From 12a6a07043034d48aaff5e42cf05fda211565821 Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:02:34 +0530 Subject: [PATCH] chore: update dependencies and remove unused files - Replaced `flutter_highlight` with `gpt_markdown` in `pubspec.yaml`. - Updated `pubspec.lock` to reflect new dependencies and removed obsolete ones. - Deleted outdated Riverpod migration documentation files to streamline the project. - Added new configurations for GptMarkdown styling in `markdown_config.dart` and updated the streaming markdown widget implementation. --- RIVERPOD_3_ANALYSIS.md | 702 -------- RIVERPOD_MIGRATION_FINAL_SUMMARY.md | 320 ---- RIVERPOD_MIGRATION_FINAL_SUMMARY_V2.md | 239 --- RIVERPOD_MIGRATION_INDEX.md | 521 ------ RIVERPOD_MIGRATION_PROGRESS.md | 172 -- RIVERPOD_PRIORITY1_COMPLETED.md | 271 --- RIVERPOD_PRIORITY2_PLAN.md | 1473 ----------------- RIVERPOD_PRIORITY2_QUICKREF.md | 370 ----- RIVERPOD_PRIORITY2_TRACKER.md | 402 ----- RIVERPOD_QUICKSTART.md | 279 ---- RIVERPOD_SUMMARY.md | 327 ---- docs/riverpod_migration_example.md | 474 ------ .../widgets/markdown/markdown_config.dart | 205 +-- .../markdown/streaming_markdown_widget.dart | 55 +- pubspec.lock | 128 +- pubspec.yaml | 3 +- 16 files changed, 149 insertions(+), 5792 deletions(-) delete mode 100644 RIVERPOD_3_ANALYSIS.md delete mode 100644 RIVERPOD_MIGRATION_FINAL_SUMMARY.md delete mode 100644 RIVERPOD_MIGRATION_FINAL_SUMMARY_V2.md delete mode 100644 RIVERPOD_MIGRATION_INDEX.md delete mode 100644 RIVERPOD_MIGRATION_PROGRESS.md delete mode 100644 RIVERPOD_PRIORITY1_COMPLETED.md delete mode 100644 RIVERPOD_PRIORITY2_PLAN.md delete mode 100644 RIVERPOD_PRIORITY2_QUICKREF.md delete mode 100644 RIVERPOD_PRIORITY2_TRACKER.md delete mode 100644 RIVERPOD_QUICKSTART.md delete mode 100644 RIVERPOD_SUMMARY.md delete mode 100644 docs/riverpod_migration_example.md diff --git a/RIVERPOD_3_ANALYSIS.md b/RIVERPOD_3_ANALYSIS.md deleted file mode 100644 index 73d208b..0000000 --- a/RIVERPOD_3_ANALYSIS.md +++ /dev/null @@ -1,702 +0,0 @@ -# Riverpod 3.0 Alignment Analysis - -## Executive Summary - -The Conduit codebase is **well-aligned** with Riverpod 3.0 best practices. The project has already migrated to the new API and is using code generation in key areas. However, there are opportunities for improvement to achieve **full consistency** and leverage all Riverpod 3.0 features. - -**Overall Grade: B+ (85/100)** - -✅ **Strengths:** -- Already using Riverpod 3.0 packages -- No legacy providers (`StateProvider`, `StateNotifierProvider`, `ChangeNotifierProvider`) -- Using `@Riverpod` annotation with code generation for complex providers -- Proper use of `Notifier` and `AsyncNotifier` classes -- Good use of `ref.mounted` checks in async operations -- Proper `keepAlive` management for singleton providers - -⚠️ **Areas for Improvement:** -- Mixed approach (code generation vs manual providers) -- Missing `riverpod_lint` for enhanced static analysis -- Some providers could benefit from code generation -- Inconsistent provider organization - ---- - -## Current State Analysis - -### 1. Package Dependencies ✅ - -```yaml -dependencies: - flutter_riverpod: ^3.0.0 # ✅ Correct - riverpod_annotation: ^3.0.0 # ✅ Correct - -dev_dependencies: - riverpod_generator: ^3.0.0 # ✅ Correct - riverpod_lint: NOT PRESENT # ⚠️ Missing -``` - -### 2. Provider Patterns - -#### ✅ **Good: Code Generation Pattern** - -Found in: `lib/core/auth/auth_state_manager.dart`, `lib/core/providers/app_providers.dart` - -```dart -@Riverpod(keepAlive: true) -class AuthStateManager extends _$AuthStateManager { - @override - Future build() async { - await _initialize(); - return _current; - } - - // ... methods -} -``` - -**Benefits:** -- Type-safe -- Automatic provider generation -- Better refactoring support -- Family and autoDispose modifiers handled automatically - -#### ⚠️ **Mixed: Manual NotifierProvider Pattern** - -Found in: `lib/core/providers/app_providers.dart`, `lib/features/chat/providers/chat_providers.dart` - -```dart -// Manual declaration -final themeModeProvider = NotifierProvider( - ThemeModeNotifier.new, -); - -class ThemeModeNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - // ... - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} -``` - -**Issues:** -- Inconsistent with code generation approach -- More boilerplate -- Harder to add modifiers (family, autoDispose) later - -### 3. Ref.mounted Usage ✅ - -**Good usage found in multiple files:** - -```dart -// lib/core/providers/app_providers.dart -if (!ref.mounted) return; - -// lib/core/services/settings_service.dart -if (!ref.mounted) { - return; -} -``` - -**Recommendation:** Continue this pattern and apply it more broadly. - -### 4. Analysis Options ⚠️ - -Current `analysis_options.yaml` is missing Riverpod-specific lints: - -```yaml -include: package:flutter_lints/flutter.yaml - -linter: - rules: - avoid_print: true -``` - -**Missing:** -- `riverpod_lint` custom lints -- Provider-specific rules - ---- - -## Detailed Recommendations - -### 🔴 **Priority 1: Add riverpod_lint** - -**Impact:** High | **Effort:** Low | **Risk:** None - -Add the `riverpod_lint` package to catch common Riverpod mistakes at compile time. - -#### Changes Required: - -**1. Update `pubspec.yaml`:** - -```yaml -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^6.0.0 - build_runner: ^2.7.1 - freezed: ^3.2.0 - json_serializable: ^6.11.1 - flutter_native_splash: ^2.4.6 - riverpod_generator: ^3.0.0 - riverpod_lint: ^3.0.0 # ADD THIS - custom_lint: ^0.8.0 # REQUIRED FOR riverpod_lint -``` - -**2. Update `analysis_options.yaml`:** - -```yaml -include: package:flutter_lints/flutter.yaml - -analyzer: - plugins: - - custom_lint - -linter: - rules: - avoid_print: true -``` - -**3. Run:** - -```bash -dart pub get -dart run custom_lint -``` - -**Benefits:** -- Catches `ref` usage outside widgets/providers -- Warns about missing `ref.mounted` checks -- Detects provider misuse patterns -- Automatic quick-fixes for common issues - ---- - -### 🟡 **Priority 2: Standardize on Code Generation** - -**Impact:** Medium | **Effort:** Medium | **Risk:** Low - -Convert manual `NotifierProvider` declarations to use `@riverpod` annotation for consistency. - -#### Files to Refactor: - -1. **`lib/core/providers/app_providers.dart`** - - `themeModeProvider` / `ThemeModeNotifier` - - `localeProvider` / `LocaleNotifier` - - `selectedModelProvider` / `SelectedModelNotifier` - - `isManualModelSelectionProvider` / `IsManualModelSelectionNotifier` - - `searchQueryProvider` / `SearchQueryNotifier` - - `activeConversationProvider` / `ActiveConversationNotifier` - - `reviewerModeProvider` / `ReviewerModeNotifier` - -2. **`lib/features/chat/providers/chat_providers.dart`** - - `chatMessagesProvider` / `ChatMessagesNotifier` - - `isLoadingConversationProvider` / `IsLoadingConversationNotifier` - - `prefilledInputTextProvider` / `PrefilledInputTextNotifier` - - `inputFocusTriggerProvider` / `InputFocusTriggerNotifier` - - `composerHasFocusProvider` / `ComposerFocusNotifier` - - Multiple other simple notifiers - -#### Example Refactoring: - -**Before (Manual):** - -```dart -final themeModeProvider = NotifierProvider( - ThemeModeNotifier.new, -); - -class ThemeModeNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} -``` - -**After (Code Generation):** - -```dart -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'app_providers.g.dart'; - -@riverpod -class ThemeMode extends _$ThemeMode { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} - -// Usage changes from: -// ref.watch(themeModeProvider) -// ref.read(themeModeProvider.notifier).setTheme(mode) - -// To: -// ref.watch(themeModeProvider) -// ref.read(themeModeProvider.notifier).setTheme(mode) -// (Same API!) -``` - -**Benefits:** -- Consistent codebase -- Less boilerplate -- Better IDE support -- Easier to add `family` or `autoDispose` modifiers later - ---- - -### 🟡 **Priority 3: Optimize Provider Families** - -**Impact:** Medium | **Effort:** Low | **Risk:** None - -Some `FutureProvider.family` can benefit from better caching and disposal strategies. - -#### Example: `loadConversationProvider` - -**Current:** - -```dart -final loadConversationProvider = FutureProvider.family(( - ref, - conversationId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - // ... -}); -``` - -**Recommendation:** - -```dart -@riverpod -Future loadConversation( - LoadConversationRef ref, - String conversationId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - - // Automatic disposal when no longer used - // Better caching behavior - final conversation = await api.getConversation(conversationId); - - return conversation; -} -``` - ---- - -### 🟢 **Priority 4: Improve AsyncValue Handling** - -**Impact:** Low | **Effort:** Low | **Risk:** None - -Some providers use `maybeWhen` where `when` might be more appropriate for exhaustive handling. - -#### Example from `lib/features/auth/providers/unified_auth_providers.dart`: - -**Current:** - -```dart -final isAuthenticatedProvider2 = Provider((ref) { - final authState = ref.watch(authStateManagerProvider); - return authState.maybeWhen( - data: (state) => state.isAuthenticated, - orElse: () => false, - ); -}); -``` - -**Better:** - -```dart -final isAuthenticatedProvider2 = Provider((ref) { - final authState = ref.watch(authStateManagerProvider); - return authState.when( - data: (state) => state.isAuthenticated, - loading: () => false, - error: (_, __) => false, - ); -}); -``` - -**Benefits:** -- Explicit handling of all states -- Better error visibility -- Compiler-enforced exhaustiveness - ---- - -### 🟢 **Priority 5: Add Provider Documentation** - -**Impact:** Low | **Effort:** Low | **Risk:** None - -Add dartdoc comments to providers explaining their purpose and refresh behavior. - -**Example:** - -```dart -/// Manages the current theme mode (light/dark/system). -/// -/// Persists the selection using [OptimizedStorageService]. -/// This provider is kept alive for the app lifetime. -@riverpod -class ThemeMode extends _$ThemeMode { - // ... -} - -/// The currently active conversation being displayed in the chat view. -/// -/// Set to `null` when no conversation is active (e.g., on the home screen). -/// Watching this provider will trigger a rebuild when the conversation changes. -@riverpod -class ActiveConversation extends _$ActiveConversation { - // ... -} -``` - ---- - -## Migration Plan - -### Phase 1: Low-Risk Improvements (Week 1) - -1. ✅ Add `riverpod_lint` and `custom_lint` packages -2. ✅ Update `analysis_options.yaml` -3. ✅ Run linter and fix any immediate issues -4. ✅ Add provider documentation - -**Estimated Time:** 4-6 hours -**Risk Level:** 🟢 Low - -### Phase 2: Code Generation Migration (Week 2-3) - -1. ⚠️ Convert simple `Notifier` classes to `@riverpod` (low risk) - - Start with leaf nodes (no dependents) - - Test thoroughly after each conversion -2. ⚠️ Convert `Provider` declarations to `@riverpod` functions -3. ⚠️ Regenerate code with `build_runner` -4. ⚠️ Update all references (IDE should help with renames) - -**Estimated Time:** 16-24 hours -**Risk Level:** 🟡 Medium - -### Phase 3: Optimization (Week 4) - -1. 🔵 Optimize `FutureProvider.family` patterns -2. 🔵 Improve `AsyncValue` handling -3. 🔵 Add caching strategies where appropriate -4. 🔵 Review and optimize `keepAlive` usage - -**Estimated Time:** 8-12 hours -**Risk Level:** 🟢 Low - ---- - -## Testing Strategy - -### Before Each Change: - -```bash -# 1. Ensure all tests pass -flutter test - -# 2. Run code generation -dart run build_runner build --delete-conflicting-outputs - -# 3. Run custom lint -dart run custom_lint - -# 4. Analyze code -flutter analyze - -# 5. Manual testing on at least 2 platforms (iOS + Android) -flutter run -``` - -### After Migration: - -1. **Functional Testing:** - - Test all auth flows (login, logout, token refresh) - - Test chat functionality - - Test settings persistence - - Test navigation flows - -2. **Performance Testing:** - - Monitor build times - - Check app startup time - - Profile provider rebuilds (DevTools) - -3. **Regression Testing:** - - Run full test suite - - Test on physical devices - - Check for memory leaks - ---- - -## Code Examples - -### Example 1: Simple Notifier Migration - -**File:** `lib/features/chat/providers/chat_providers.dart` - -**Before:** - -```dart -final isLoadingConversationProvider = - NotifierProvider( - IsLoadingConversationNotifier.new, - ); - -class IsLoadingConversationNotifier extends Notifier { - @override - bool build() => false; - - void set(bool value) => state = value; -} -``` - -**After:** - -```dart -@riverpod -class IsLoadingConversation extends _$IsLoadingConversation { - @override - bool build() => false; - - void set(bool value) => state = value; -} - -// Usage remains the same: -// ref.watch(isLoadingConversationProvider) -// ref.read(isLoadingConversationProvider.notifier).set(true) -``` - -### Example 2: Provider to Function - -**Before:** - -```dart -final serverConfigsProvider = FutureProvider>((ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -}); -``` - -**After:** - -```dart -@riverpod -Future> serverConfigs(ServerConfigsRef ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -} - -// Usage remains identical: -// ref.watch(serverConfigsProvider) -// ref.read(serverConfigsProvider.future) -``` - -### Example 3: Keep Alive Provider - -**Before:** - -```dart -@Riverpod(keepAlive: true) -class AuthStateManager extends _$AuthStateManager { - // ... -} -``` - -**After (same - already correct!):** - -```dart -@Riverpod(keepAlive: true) -class AuthStateManager extends _$AuthStateManager { - // ... -} -``` - ---- - -## Potential Issues & Solutions - -### Issue 1: Breaking Changes - -**Problem:** Renaming providers may break existing code. - -**Solution:** -1. Use IDE's "Find and Replace" with regex -2. Create deprecation aliases during transition -3. Update incrementally, one provider at a time - -```dart -// Temporary compatibility -@Deprecated('Use themeModeProvider instead') -final oldThemeModeProvider = themeModeProvider; -``` - -### Issue 2: Complex State Logic - -**Problem:** Some `Notifier` classes have complex initialization. - -**Solution:** Code generation supports complex logic—no changes needed! - -```dart -@riverpod -class ChatMessages extends _$ChatMessages { - StreamSubscription? _messageStream; - ProviderSubscription? _conversationListener; - // ... all existing fields and initialization work fine - - @override - List build() { - if (!_initialized) { - _initialized = true; - _conversationListener = ref.listen(activeConversationProvider, /* ... */); - } - // ... existing logic - } -} -``` - -### Issue 3: Build Runner Performance - -**Problem:** Code generation might slow down development. - -**Solution:** -1. Use `watch` mode during development: - ```bash - dart run build_runner watch --delete-conflicting-outputs - ``` -2. Exclude generated files from version control (already done) -3. Consider CI/CD optimizations for parallel builds - ---- - -## Performance Considerations - -### Current Performance: ✅ Good - -The codebase already uses: -- `keepAlive` for singleton providers -- `ref.mounted` checks for async operations -- Proper disposal in `ref.onDispose` - -### After Migration: ✅ Better - -Code generation will: -- Reduce runtime overhead (compile-time generation) -- Enable better tree-shaking -- Improve IDE performance with generated code - -**Expected Impact:** -- Build time: +5-10 seconds (one-time per build) -- Runtime performance: Neutral to +2% faster -- Memory usage: Neutral -- Developer experience: Significantly better - ---- - -## Conflict with AGENTS.md Rules - -### Current Rule in AGENTS.md: - -```markdown -### State Management -* **Built-in Solutions:** Prefer Flutter's built-in state management solutions. - Do not use a third-party package unless explicitly requested. -``` - -### Recommendation: Update AGENTS.md - -The project has **already adopted Riverpod**, which contradicts this rule. The rule should be updated to reflect the current architecture: - -```markdown -### State Management -* **Riverpod:** This project uses Riverpod 3.0 for state management. -* **Code Generation:** Prefer using `@riverpod` annotation with code generation - for all new providers. -* **Notifier Classes:** Use `Notifier` and `AsyncNotifier` for mutable state. -* **Provider Functions:** Use `@riverpod` functions for computed/derived state. -* **Keep Alive:** Use `@Riverpod(keepAlive: true)` for singletons and app-wide state. -* **Ref.mounted:** Always check `ref.mounted` before state updates in async operations. -``` - ---- - -## Resources - -### Official Riverpod 3.0 Documentation - -- [Riverpod 3.0 Migration Guide](https://riverpod.dev/docs/3.0_migration) -- [Code Generation Guide](https://riverpod.dev/docs/concepts/about_code_generation) -- [Riverpod Lint Rules](https://riverpod.dev/docs/concepts/about_riverpod_lint) - -### Community Resources - -- [Riverpod 3.0 Announcement](https://medium.com/@ishuprabhakar/riverpod-3-0-1c0e247bfb2f) -- [Migration Tutorial](https://codewithandrea.com/articles/flutter-state-management-riverpod/) - ---- - -## Conclusion - -The Conduit codebase is **in good shape** regarding Riverpod 3.0 alignment. The main improvements are: - -1. **Add `riverpod_lint`** for better static analysis (Priority 1) -2. **Standardize on code generation** for consistency (Priority 2) -3. **Optimize provider patterns** where applicable (Priority 3) - -**Total Estimated Effort:** 28-42 hours -**Risk Level:** 🟡 Medium -**Expected Benefits:** High (better maintainability, consistency, developer experience) - -The migration can be done incrementally with minimal risk if following the phased approach outlined above. diff --git a/RIVERPOD_MIGRATION_FINAL_SUMMARY.md b/RIVERPOD_MIGRATION_FINAL_SUMMARY.md deleted file mode 100644 index 79c5c71..0000000 --- a/RIVERPOD_MIGRATION_FINAL_SUMMARY.md +++ /dev/null @@ -1,320 +0,0 @@ -# Riverpod 3.0 Migration - Final Summary - -**Date Completed:** September 30, 2025 -**Total Session Time:** ~3 hours -**Final Status:** 34/39 providers migrated (87%) - ---- - -## 🎉 Mission Accomplished! - -We've successfully migrated **87% of all providers** to Riverpod 3.0 code generation with: -- ✅ **Zero test failures** -- ✅ **All builds passing** -- ✅ **Minimal breaking changes** (only 2 provider renames) -- ✅ **~200 lines of code** reduced - ---- - -## ✅ Completed Phases - -### Phase 1: Simple Notifiers (100%) ✅ -**Time:** 45 minutes | **Providers:** 9/9 - -- searchQueryProvider → SearchQuery -- selectedModelProvider → SelectedModel -- isManualModelSelectionProvider → IsManualModelSelection -- reviewerModeProvider → ReviewerMode -- isLoadingConversationProvider → IsLoadingConversation -- prefilledInputTextProvider → PrefilledInputText -- inputFocusTriggerProvider → InputFocusTrigger -- composerHasFocusProvider → ComposerHasFocus -- batchModeProvider → BatchMode -- reducedMotionProvider → ReducedMotion - -### Phase 2: FutureProvider Functions (100%) ✅ -**Time:** 45 minutes | **Providers:** 15/15 - -- serverConfigsProvider, activeServerProvider, currentUserProvider -- modelsProvider, userSettingsProvider, conversationSuggestionsProvider -- userPermissionsProvider, foldersProvider, userFilesProvider -- knowledgeBasesProvider, availableVoicesProvider, imageModelsProvider -- promptsListProvider, toolsListProvider -- + Bonus: activePromptCommandProvider, selectedToolIdsProvider - -### Phase 3: Family Providers (100%) ✅ -**Time:** 30 minutes | **Providers:** 4/4 - -- loadConversationProvider(id) → loadConversation -- serverSearchProvider(query) → serverSearch -- fileContentProvider(fileId) → fileContent -- knowledgeBaseItemsProvider(kbId) → knowledgeBaseItems - -### Phase 4: Breaking Changes (100%) ✅ -**Time:** 20 minutes | **Providers:** 2/2 - -- ⚠️ themeModeProvider → appThemeModeProvider (BREAKING) -- ⚠️ localeProvider → appLocaleProvider (BREAKING) - -### Phase 6: Internal Providers (100%) ✅ -**Time:** 15 minutes | **Providers:** 2/2 - -- _conversationsCacheTimestamp → _ConversationsCacheTimestamp -- _wasOfflineProvider → _WasOffline - ---- - -## 📊 Final Statistics - -| Metric | Value | -|--------|-------| -| **Total Providers Migrated** | 34/39 (87%) | -| **Total Commits** | 17 | -| **Lines of Code Reduced** | ~200 | -| **Breaking Changes** | 2 provider renames | -| **Test Failures** | 0 | -| **Build Errors** | 0 | -| **Analyzer Warnings** | 0 new (only pre-existing) | - ---- - -## 🔄 Remaining Work (Phase 5 - 13%) - -### Not Migrated (5 providers) - -#### 1. conversationsProvider -- **Type:** FutureProvider> -- **Complexity:** 🔴 High -- **Size:** ~250 lines -- **Usages:** 33 references across 6 files -- **Features:** Complex caching, folder operations, authentication checks -- **Risk:** Medium-High -- **Estimated Time:** 2-3 hours - -#### 2. appSettingsProvider -- **Type:** NotifierProvider -- **Complexity:** 🔴 High -- **Size:** ~100 lines -- **Usages:** ~30 references -- **Features:** Large class with many settings methods -- **Risk:** High (heavily used) -- **Estimated Time:** 2-3 hours - -#### 3. chatMessagesProvider -- **Type:** NotifierProvider> -- **Complexity:** 🔴 **EXTREMELY HIGH** -- **Size:** ~2400 lines (!) -- **Usages:** ~20 references -- **Features:** Real-time streaming, WebSocket management, tool calls, batch operations -- **Risk:** **VERY HIGH** (critical app functionality) -- **Estimated Time:** 4-6 hours - -#### 4. defaultModelProvider -- **Type:** FutureProvider -- **Complexity:** 🟡 Medium -- **Size:** ~70 lines -- **Features:** Complex initialization with settings watchers -- **Risk:** Medium -- **Estimated Time:** 30 minutes - -#### 5. voiceInputAvailableProvider -- **Type:** FutureProvider -- **Complexity:** 🟢 Low -- **Size:** Small -- **Risk:** Low -- **Estimated Time:** 15 minutes - -**Total Remaining Effort:** 9-13 hours - ---- - -## ✨ Benefits Achieved - -### Code Quality -- ✅ **Consistent patterns** across 87% of providers -- ✅ **Reduced boilerplate** (~200 lines removed) -- ✅ **Better type safety** with code generation -- ✅ **Improved maintainability** with @riverpod annotation -- ✅ **Enhanced IDE support** and autocomplete - -### Developer Experience -- ✅ **Easier to add parameters** (family support automatic) -- ✅ **Better error messages** from generated code -- ✅ **Automatic dependency tracking** -- ✅ **Cleaner codebase** with less manual provider declarations - -### Technical Excellence -- ✅ **All tests passing** throughout migration -- ✅ **Zero performance regressions** -- ✅ **Minimal breaking changes** (only 2 renames needed) -- ✅ **Incremental migration** allowing safe rollback at any point - ---- - -## 📝 Recommendations - -### Option A: Deploy Current Progress (Recommended) -**Deploy the 87% migrated codebase now:** - -**Pros:** -- Massive improvement already achieved -- Low risk (all tests passing) -- Get benefits into production sooner -- Remaining providers can be migrated later -- Team can provide feedback on new patterns - -**Cons:** -- Codebase not 100% consistent (but 87% is excellent!) -- Will need another migration session later - -**Action Items:** -1. Update AGENTS.md with new patterns ✅ (already done) -2. Team review of changes -3. Test on staging environment -4. Deploy to production -5. Monitor for issues - -### Option B: Complete Phase 5 Now -**Continue migrating the remaining 5 providers:** - -**Pros:** -- 100% consistency -- Complete the work in one session -- No need for future migration - -**Cons:** -- High risk (complex providers) -- Additional 9-13 hours needed -- Requires extensive testing -- Team may be fatigued - -**Action Items:** -1. Schedule dedicated time (2-3 sessions) -2. Migrate simpler providers first (defaultModel, voiceInputAvailable) -3. Save chatMessagesProvider for last -4. Extensive testing after each -5. Consider pair programming for complex ones - -### Option C: Phased Completion -**Migrate remaining providers in smaller batches:** - -**Pros:** -- Lower risk per deployment -- Can be done over multiple sessions -- Test each migration thoroughly - -**Cons:** -- Codebase remains inconsistent longer -- Multiple deployment cycles - ---- - -## 🎓 Key Learnings - -### Technical -1. **Use `Ref` directly** in @riverpod functions, not typed refs -2. **Import order matters** - `part` directive must come after all imports -3. **Generated provider names** follow camelCase convention automatically -4. **Family parameters** become function parameters naturally -5. **Breaking changes** are minimal with proper naming - -### Process -1. **Migrate in phases** by complexity (simple → complex) -2. **Test after each provider** to catch issues early -3. **Commit frequently** for easy rollback -4. **Use bulk find-replace** carefully for breaking changes -5. **Documentation is crucial** for team understanding - -### Strategy -1. **Start with low-risk providers** to build confidence -2. **Save complex providers for last** when patterns are established -3. **Consider deployment points** between phases -4. **Monitor for issues** after each phase -5. **Team communication** is essential for breaking changes - ---- - -## 📁 Files Modified - -### Provider Files -- `lib/core/providers/app_providers.dart` (heavily modified) -- `lib/features/chat/providers/chat_providers.dart` -- `lib/features/prompts/providers/prompts_providers.dart` -- `lib/features/tools/providers/tools_providers.dart` -- `lib/core/services/animation_service.dart` -- `lib/features/chat/services/message_batch_service.dart` -- `lib/shared/widgets/offline_indicator.dart` - -### Documentation Files -- `AGENTS.md` (updated with Riverpod 3.0 patterns) -- `RIVERPOD_*.md` (multiple planning/analysis docs) -- `docs/riverpod_migration_example.md` (migration guide) - -### Usage Files (Breaking Changes) -- `lib/main.dart` -- `lib/features/profile/views/app_customization_page.dart` - ---- - -## 🚀 Next Steps - -### Immediate (Before Next Session) -1. ✅ Review all changes with the team -2. ✅ Run full test suite: `flutter test` -3. ✅ Test on physical devices (iOS + Android) -4. ✅ Check performance with DevTools -5. ✅ Review generated code for any issues - -### Short Term (1-2 weeks) -1. Deploy to staging environment -2. Conduct thorough QA testing -3. Monitor for any issues -4. Gather team feedback -5. Update documentation as needed - -### Long Term (1-2 months) -1. Schedule Phase 5 migration if desired -2. Consider refactoring chatMessagesProvider before migrating -3. Train team on new patterns -4. Update coding standards -5. Share learnings with broader team - ---- - -## 📞 Support - -### Resources -- [Riverpod 3.0 Docs](https://riverpod.dev) -- [Code Generation Guide](https://riverpod.dev/docs/concepts/about_code_generation) -- [Migration Guide](https://riverpod.dev/docs/3.0_migration) -- Project docs: `docs/riverpod_migration_example.md` - -### Questions? -Review the planning documents: -- `RIVERPOD_PRIORITY2_PLAN.md` - Full migration plan -- `RIVERPOD_PRIORITY2_QUICKREF.md` - Quick reference -- `RIVERPOD_MIGRATION_INDEX.md` - Master index - ---- - -## 🎉 Conclusion - -This migration has been **highly successful**! We've: -- ✅ Migrated 87% of providers -- ✅ Maintained 100% backward compatibility (except 2 intentional renames) -- ✅ Achieved zero test failures -- ✅ Reduced boilerplate significantly -- ✅ Improved code quality and maintainability - -The remaining 5 providers (13%) are the most complex in the codebase and can be: -- Migrated later when needed -- Left as-is (the app works perfectly with current state) -- Tackled in smaller, focused sessions - -**Recommendation:** Deploy the current progress and gather feedback before tackling the remaining complex providers. - ---- - -**Prepared by:** AI Assistant -**Session Date:** September 30, 2025 -**Status:** ✅ **READY FOR REVIEW & DEPLOYMENT** diff --git a/RIVERPOD_MIGRATION_FINAL_SUMMARY_V2.md b/RIVERPOD_MIGRATION_FINAL_SUMMARY_V2.md deleted file mode 100644 index d611071..0000000 --- a/RIVERPOD_MIGRATION_FINAL_SUMMARY_V2.md +++ /dev/null @@ -1,239 +0,0 @@ -# 🎉 Riverpod 3.0 Migration - FINAL SUMMARY V2 - -**Date Completed:** September 30, 2025 -**Total Time:** ~4 hours -**Final Status:** 38/39 providers migrated (**97%** ✅) - ---- - -## 📊 Final Statistics - -| Metric | Value | -|--------|-------| -| **Providers Migrated** | 38/39 (97%) | -| **Commits Made** | 25+ | -| **Lines Reduced** | ~250 | -| **Breaking Changes** | 2 intentional renames | -| **Test Failures** | 0 | -| **Build Errors** | 0 | -| **Success Rate** | 97% | - ---- - -## ✅ ALL COMPLETED PHASES - -### Phase 1: Simple Notifiers (9/9) ✅ -- searchQueryProvider → searchQueryProvider -- selectedModelProvider → selectedModelProvider -- isManualModelSelectionProvider → isManualModelSelectionProvider -- reviewerModeProvider → reviewerModeProvider -- isLoadingConversationProvider → isLoadingConversationProvider -- prefilledInputTextProvider → prefilledInputTextProvider -- inputFocusTriggerProvider → inputFocusTriggerProvider -- composerHasFocusProvider → composerHasFocusProvider -- batchModeProvider → batchModeProvider -- reducedMotionProvider → reducedMotionProvider - -### Phase 2: FutureProvider Functions (15/15) ✅ -- serverConfigsProvider → serverConfigs -- activeServerProvider → activeServer -- currentUserProvider → currentUser -- modelsProvider → models -- userSettingsProvider → userSettings -- conversationSuggestionsProvider → conversationSuggestions -- userPermissionsProvider → userPermissions -- foldersProvider → folders -- userFilesProvider → userFiles -- knowledgeBasesProvider → knowledgeBases -- availableVoicesProvider → availableVoices -- imageModelsProvider → imageModels -- promptsListProvider → promptsList -- toolsListProvider → toolsList -- + activePromptCommandProvider, selectedToolIdsProvider - -### Phase 3: Family Providers (4/4) ✅ -- loadConversationProvider(id) → loadConversation -- serverSearchProvider(query) → serverSearch -- fileContentProvider(fileId) → fileContent -- knowledgeBaseItemsProvider(kbId) → knowledgeBaseItems - -### Phase 4: Breaking Changes (2/2) ✅ -- ⚠️ themeModeProvider → appThemeModeProvider -- ⚠️ localeProvider → appLocaleProvider - -### Phase 5: Complex Providers (4/5) ✅ -- ✅ voiceInputAvailableProvider → voiceInputAvailable -- ✅ defaultModelProvider → defaultModel -- ✅ conversationsProvider → conversations (complex caching!) -- ✅ appSettingsProvider → appSettingsNotifierProvider -- ⏸️ chatMessagesProvider - **DEFERRED** (see below) - -### Phase 6: Internal Providers (2/2) ✅ -- _conversationsCacheTimestamp → _ConversationsCacheTimestamp -- _wasOfflineProvider → _WasOffline - ---- - -## ⏸️ Deferred: chatMessagesProvider - -### Why Deferred? -- **Extreme Complexity:** 2400+ lines of code -- **Critical Functionality:** Real-time streaming, WebSockets, tool calls -- **High Risk:** Core chat functionality, heavily used -- **Time Required:** Estimated 6-8 hours for careful migration + testing - -### Current Status: -- Provider remains as `NotifierProvider` (Riverpod 2.x style) -- **Works perfectly** alongside migrated 3.0 providers -- No issues with mixed provider types -- Can be migrated later when dedicated time is available - -### Recommendation: -**Leave as-is** until: -1. A dedicated migration session can be scheduled -2. Comprehensive testing resources are available -3. The team has more familiarity with Riverpod 3.0 patterns - ---- - -## 🎯 Impact & Benefits - -### Code Quality Improvements -✅ **97% consistent patterns** across all providers -✅ **~250 lines** of boilerplate removed -✅ **Enhanced type safety** with code generation -✅ **Better IDE support** and autocomplete -✅ **Cleaner codebase** with declarative syntax - -### Developer Experience -✅ **Easier to add parameters** - family support automatic -✅ **Better error messages** from generated code -✅ **Faster development** with less boilerplate -✅ **Improved maintainability** for future changes - -### Technical Excellence -✅ **Zero test failures** throughout migration -✅ **Zero performance regressions** -✅ **Minimal breaking changes** (only 2 intentional renames) -✅ **Safe incremental approach** allowing rollback at any point - ---- - -## 📁 Modified Files Summary - -### Core Provider Files -- `lib/core/providers/app_providers.dart` - Heavily modified (32 providers) -- `lib/features/chat/providers/chat_providers.dart` - Modified (5 providers) -- `lib/features/prompts/providers/prompts_providers.dart` - Modified (2 providers) -- `lib/features/tools/providers/tools_providers.dart` - Modified (2 providers) -- `lib/core/services/settings_service.dart` - Modified (1 provider) -- `lib/core/services/animation_service.dart` - Modified (1 provider) -- `lib/features/chat/services/message_batch_service.dart` - Modified (1 provider) -- `lib/features/chat/services/voice_input_service.dart` - Modified (1 provider) -- `lib/shared/widgets/offline_indicator.dart` - Modified (1 provider) - -### Configuration Files -- `pubspec.yaml` - Added riverpod_lint, custom_lint -- `analysis_options.yaml` - Added custom_lint plugin - -### Documentation -- `AGENTS.md` - Updated with Riverpod 3.0 best practices -- `RIVERPOD_*.md` - Multiple planning and tracking documents -- `docs/riverpod_migration_example.md` - Migration guide - ---- - -## 🚀 Deployment Readiness - -### ✅ Ready to Deploy -- All 38 migrated providers are production-ready -- Zero breaking changes (except 2 intentional renames) -- All tests passing -- Build successful -- No analyzer warnings - -### 📋 Pre-Deployment Checklist -- [ ] Final code review by team -- [ ] Run full test suite: `flutter test` -- [ ] Test on physical devices (iOS + Android) -- [ ] Performance check with DevTools -- [ ] Update team documentation - -### 🎯 Recommended Next Steps -1. **Deploy immediately** - 97% is excellent! -2. **Monitor for issues** - though none expected -3. **Gather feedback** from team -4. **Plan chatMessagesProvider** migration for future (optional) - ---- - -## 🎓 Key Learnings - -### What Went Well ✅ -1. **Phased approach** worked perfectly - simple to complex -2. **Frequent commits** enabled safe rollback points -3. **Code generation** caught errors early -4. **Documentation** made the process smooth -5. **Testing after each phase** prevented issues - -### Technical Insights -1. Use `Ref` directly in @riverpod functions, not typed refs -2. Import order critical - `part` directive must be last -3. Generated provider names follow automatic conventions -4. Family parameters become function parameters naturally -5. Breaking changes minimal with careful naming - -### Process Wisdom -1. Start with low-risk providers to build confidence -2. Save complex providers for last -3. Don't be afraid to defer extremely complex migrations -4. 97% completion is better than 100% with high risk -5. Mixed Riverpod 2.x/3.x works perfectly fine - ---- - -## 🏆 Success Metrics - -| Goal | Target | Achieved | -|------|--------|----------| -| Providers Migrated | 80%+ | **97%** ✅ | -| Test Failures | 0 | **0** ✅ | -| Breaking Changes | <5 | **2** ✅ | -| Build Errors | 0 | **0** ✅ | -| Code Reduction | 100+ lines | **~250** ✅ | - -### Overall Grade: **A+ (97/100)** - ---- - -## 💬 Conclusion - -This migration has been **extraordinarily successful**! - -### Achievements: -- ✅ 97% of providers migrated -- ✅ Zero technical debt introduced -- ✅ All tests passing -- ✅ Significant code quality improvements -- ✅ Team can start using Riverpod 3.0 patterns immediately - -### The Remaining 3%: -- The deferred `chatMessagesProvider` is extremely complex -- It works perfectly in its current state -- Can be migrated later if/when needed -- **No urgency** - mixed provider styles are fully supported - -### Final Recommendation: -**🚀 DEPLOY NOW!** - -The migration is complete enough to provide all benefits of Riverpod 3.0 while maintaining stability. The remaining provider can stay as-is indefinitely without any issues. - ---- - -**Prepared by:** AI Assistant -**Session Date:** September 30, 2025 -**Status:** ✅ **MIGRATION COMPLETE - READY FOR PRODUCTION** - ---- - -*"Perfect is the enemy of good. 97% is excellent!"* diff --git a/RIVERPOD_MIGRATION_INDEX.md b/RIVERPOD_MIGRATION_INDEX.md deleted file mode 100644 index 37cc517..0000000 --- a/RIVERPOD_MIGRATION_INDEX.md +++ /dev/null @@ -1,521 +0,0 @@ -# Riverpod 3.0 Migration - Complete Guide - -**Comprehensive index for the Conduit Riverpod 3.0 migration** - ---- - -## 📚 Documentation Overview - -This repository contains a complete migration plan for upgrading the Conduit codebase to use Riverpod 3.0 best practices with code generation. - -### Document Structure - -``` -Migration Documentation -├── Analysis & Planning -│ ├── RIVERPOD_3_ANALYSIS.md .................. Initial codebase analysis -│ ├── RIVERPOD_SUMMARY.md ..................... Executive summary -│ └── RIVERPOD_QUICKSTART.md .................. Quick start guide -│ -├── Implementation -│ ├── Priority 1 (COMPLETED ✅) -│ │ └── RIVERPOD_PRIORITY1_COMPLETED.md ..... Linting setup (done) -│ │ -│ └── Priority 2 (PLANNED 📋) -│ ├── RIVERPOD_PRIORITY2_PLAN.md .......... Detailed migration plan -│ ├── RIVERPOD_PRIORITY2_QUICKREF.md ...... Quick reference guide -│ └── RIVERPOD_PRIORITY2_TRACKER.md ....... Progress tracker -│ -└── Examples & Reference - └── docs/riverpod_migration_example.md ...... Step-by-step examples -``` - ---- - -## 🎯 Quick Start - -### For New Developers - -1. Read **RIVERPOD_SUMMARY.md** for overview -2. Review **RIVERPOD_QUICKSTART.md** for patterns -3. Check **docs/riverpod_migration_example.md** for examples - -### For Migration Contributors - -1. Start with **RIVERPOD_PRIORITY2_PLAN.md** for full context -2. Use **RIVERPOD_PRIORITY2_QUICKREF.md** as daily reference -3. Track progress in **RIVERPOD_PRIORITY2_TRACKER.md** - -### For Project Leads - -1. Review **RIVERPOD_3_ANALYSIS.md** for technical assessment -2. Check **RIVERPOD_PRIORITY1_COMPLETED.md** for completed work -3. Evaluate **RIVERPOD_PRIORITY2_PLAN.md** for timeline and resources - ---- - -## 📖 Document Descriptions - -### Analysis Documents - -#### [RIVERPOD_3_ANALYSIS.md](./RIVERPOD_3_ANALYSIS.md) -**Purpose:** Initial technical analysis of Riverpod 3.0 alignment -**Audience:** Technical leads, architects -**Key Content:** -- Current state assessment -- Detailed recommendations -- Migration phases overview -- Testing strategy -- Performance considerations - -**When to Read:** Before starting any migration work - ---- - -#### [RIVERPOD_SUMMARY.md](./RIVERPOD_SUMMARY.md) -**Purpose:** High-level executive summary -**Audience:** All team members, stakeholders -**Key Content:** -- Quick overview of migration -- Key benefits -- High-level timeline -- Risk assessment - -**When to Read:** For a quick understanding of the migration - ---- - -#### [RIVERPOD_QUICKSTART.md](./RIVERPOD_QUICKSTART.md) -**Purpose:** Quick reference for Riverpod 3.0 patterns -**Audience:** All developers -**Key Content:** -- Common patterns -- Code examples -- Best practices -- Quick tips - -**When to Read:** When writing new Riverpod code - ---- - -### Implementation Documents - -#### [RIVERPOD_PRIORITY1_COMPLETED.md](./RIVERPOD_PRIORITY1_COMPLETED.md) ✅ -**Purpose:** Documentation of completed Priority 1 work -**Audience:** All team members -**Key Content:** -- Linting setup (riverpod_lint, custom_lint) -- AGENTS.md updates -- Issues found and fixed -- Validation results - -**Status:** ✅ **COMPLETE** -**When to Read:** To understand what's already been done - ---- - -#### [RIVERPOD_PRIORITY2_PLAN.md](./RIVERPOD_PRIORITY2_PLAN.md) 📋 -**Purpose:** Comprehensive migration plan for Priority 2 -**Audience:** Migration contributors, technical leads -**Key Content:** -- All 39 providers to migrate -- 6 migration phases -- Detailed step-by-step instructions -- Testing plan -- Rollback procedures -- Risk mitigation - -**Status:** 📋 **READY FOR IMPLEMENTATION** -**When to Read:** Before starting Priority 2 migration -**Size:** 33 KB, comprehensive guide - ---- - -#### [RIVERPOD_PRIORITY2_QUICKREF.md](./RIVERPOD_PRIORITY2_QUICKREF.md) 📋 -**Purpose:** Quick reference for daily migration work -**Audience:** Migration contributors -**Key Content:** -- Phase checklists -- Standard migration process -- Common commands -- Issue troubleshooting -- Quick examples - -**Status:** 📋 **READY FOR USE** -**When to Read:** During active migration work -**Size:** 8 KB, concise reference - ---- - -#### [RIVERPOD_PRIORITY2_TRACKER.md](./RIVERPOD_PRIORITY2_TRACKER.md) 📋 -**Purpose:** Track migration progress -**Audience:** Migration contributors, project managers -**Key Content:** -- Progress charts -- Phase-by-phase checklists -- Testing checklists -- Issues log -- Time tracking -- Commit log - -**Status:** 📋 **READY FOR USE** -**When to Read:** Daily during migration -**Size:** 11 KB, interactive tracker - ---- - -### Example Documents - -#### [docs/riverpod_migration_example.md](./docs/riverpod_migration_example.md) -**Purpose:** Step-by-step migration examples -**Audience:** All developers -**Key Content:** -- Before/after code comparisons -- Simple to complex examples -- Family provider examples -- Testing examples -- Common pitfalls -- IDE setup - -**When to Read:** When migrating specific provider types -**Size:** Detailed examples with explanations - ---- - -## 🚀 Migration Status - -### Overview - -``` -Priority 1: ✅ COMPLETE -├── riverpod_lint added -├── custom_lint added -├── AGENTS.md updated -└── 1 safety issue fixed - -Priority 2: 📋 PLANNED -├── Phase 1: 10 simple notifiers (4-6h) -├── Phase 2: 15 future providers (6-8h) -├── Phase 3: 4 family providers (2-3h) -├── Phase 4: 2 name-changing providers (4-6h) -├── Phase 5: 3 complex providers (6-8h) -└── Phase 6: 2 internal providers (1-2h) - -Total Effort: 23-33 hours (4 weeks) -``` - -### Completed Work - -✅ **Priority 1 Complete** (September 30, 2025) -- Linting infrastructure -- Documentation alignment -- Safety fixes -- Zero breaking changes -- All tests passing - -### Upcoming Work - -📋 **Priority 2 Ready** (Scheduled: October 2025) -- 39 providers to migrate -- 6 phases planned -- Comprehensive testing plan -- Clear rollback procedures - ---- - -## 📊 Provider Migration Breakdown - -### By Complexity - -| Complexity | Count | Estimated Hours | Risk Level | -|------------|-------|-----------------|------------| -| 🟢 Simple | 28 | 12-16 | Low | -| 🟡 Medium | 8 | 7-10 | Medium | -| 🔴 Complex | 3 | 6-8 | High | -| **Total** | **39** | **25-34** | **Medium** | - -### By Phase - -| Phase | Providers | Hours | Risk | Status | -|-------|-----------|-------|------|--------| -| Phase 1 | 10 | 4-6 | 🟢 Low | Not Started | -| Phase 2 | 15 | 6-8 | 🟢 Low | Not Started | -| Phase 3 | 4 | 2-3 | 🟡 Medium | Not Started | -| Phase 4 | 2 | 4-6 | 🟡 Medium | Not Started | -| Phase 5 | 3 | 6-8 | 🔴 High | Not Started | -| Phase 6 | 2 | 1-2 | 🟢 Low | Not Started | - -### By File - -| File | Providers | Priority | -|------|-----------|----------| -| `lib/core/providers/app_providers.dart` | 26 | High | -| `lib/features/chat/providers/chat_providers.dart` | 5 | Medium | -| `lib/core/services/settings_service.dart` | 1 | High | -| Other files | 7 | Low | - ---- - -## 🎓 Learning Path - -### For New Contributors - -1. **Day 1: Understand Riverpod 3.0** - - Read: RIVERPOD_SUMMARY.md - - Read: RIVERPOD_QUICKSTART.md - - Review: docs/riverpod_migration_example.md - -2. **Day 2: Understand the Codebase** - - Read: RIVERPOD_3_ANALYSIS.md - - Review: RIVERPOD_PRIORITY1_COMPLETED.md - - Explore: Existing @riverpod providers in codebase - -3. **Day 3: Prepare for Migration** - - Read: RIVERPOD_PRIORITY2_PLAN.md - - Familiarize: RIVERPOD_PRIORITY2_QUICKREF.md - - Setup: Development environment - -4. **Day 4+: Start Migrating** - - Follow: Phase 1 checklist - - Use: RIVERPOD_PRIORITY2_QUICKREF.md - - Track: RIVERPOD_PRIORITY2_TRACKER.md - ---- - -## 🛠️ Essential Commands - -### Development - -```bash -# Start watch mode (recommended) -dart run build_runner watch --delete-conflicting-outputs - -# Run all checks -flutter analyze && dart run custom_lint && flutter test - -# Manual test -flutter run -``` - -### Migration - -```bash -# Check provider usage -grep -r "providerName" lib/ --exclude="*.g.dart" | wc -l - -# Generate code -dart run build_runner build --delete-conflicting-outputs - -# Run tests -flutter test -``` - -### Tracking - -```bash -# View progress -cat RIVERPOD_PRIORITY2_TRACKER.md - -# Update tracker (edit the file after each migration) -# Mark providers as complete: ⬜ → ✅ -``` - ---- - -## 📋 Quick Decision Tree - -### "Which document should I read?" - -``` -Are you new to the project? -├─ Yes → Start with RIVERPOD_SUMMARY.md -└─ No - │ - Are you migrating providers today? - ├─ Yes - │ ├─ First time? → Read RIVERPOD_PRIORITY2_PLAN.md - │ └─ Continuing? → Use RIVERPOD_PRIORITY2_QUICKREF.md - │ - └─ No - │ - Need code examples? - ├─ Yes → See docs/riverpod_migration_example.md - └─ No - │ - Want to understand decisions? - ├─ Yes → Read RIVERPOD_3_ANALYSIS.md - └─ No → Check RIVERPOD_QUICKSTART.md -``` - ---- - -## ⚠️ Important Notes - -### Before Starting Migration - -1. ✅ **Verify Priority 1 is complete** - - Check: `pubspec.yaml` has `riverpod_lint` and `custom_lint` - - Check: `analysis_options.yaml` has `custom_lint` plugin - - Check: `dart run custom_lint` runs without errors - -2. ✅ **Ensure clean git state** - - No uncommitted changes - - All tests passing - - On main branch (or feature branch) - -3. ✅ **Read the plan** - - RIVERPOD_PRIORITY2_PLAN.md - - Understand the phase structure - - Know the rollback procedures - -### During Migration - -1. ✅ **Follow the phases in order** - - Don't skip ahead to complex providers - - Complete all providers in a phase before moving on - -2. ✅ **Test frequently** - - After each provider migration - - Before committing - - After each phase - -3. ✅ **Track progress** - - Update RIVERPOD_PRIORITY2_TRACKER.md - - Document issues - - Record learnings - -4. ✅ **Commit frequently** - - One provider per commit (for simple ones) - - One phase per commit (for batches) - - Clear commit messages - ---- - -## 🎯 Success Criteria - -### Per Provider - -- ✅ Code compiles without errors -- ✅ No lint warnings -- ✅ Tests pass -- ✅ Manual test successful -- ✅ Committed with clear message - -### Per Phase - -- ✅ All phase providers complete -- ✅ Full test suite passes -- ✅ Integration tests pass -- ✅ Multi-platform verification - -### Overall Migration - -- ✅ All 39 providers migrated -- ✅ Consistent code generation usage -- ✅ Zero regressions -- ✅ Documentation updated -- ✅ Team trained - ---- - -## 📞 Getting Help - -### If You're Stuck - -1. **Check the troubleshooting section** - - RIVERPOD_PRIORITY2_QUICKREF.md has common issues - -2. **Review examples** - - docs/riverpod_migration_example.md has similar cases - -3. **Search the codebase** - - Look for existing @riverpod providers - - Find patterns that work - -4. **Consult official docs** - - [Riverpod Code Generation](https://riverpod.dev/docs/concepts/about_code_generation) - - [Riverpod Migration Guide](https://riverpod.dev/docs/3.0_migration) - ---- - -## 📈 Timeline - -### Completed - -- **September 30, 2025:** Priority 1 complete (linting setup) ✅ - -### Planned - -- **Week 1 (Oct 1-5):** Phase 1 - Simple notifiers -- **Week 2 (Oct 8-12):** Phase 2 & 3 - Functions and families -- **Week 3 (Oct 15-19):** Phase 4 - Breaking changes -- **Week 4 (Oct 22-26):** Phase 5 & 6 - Complex providers - -**Target Completion:** End of October 2025 - ---- - -## 📝 Contributing - -When updating these documents: - -1. **Keep them in sync** - - Update all relevant documents - - Maintain consistent information - -2. **Document changes** - - Add date stamps - - Note what changed - -3. **Update the index** - - Add new documents here - - Update status information - ---- - -## 🔗 External Resources - -### Official Documentation - -- [Riverpod 3.0 Docs](https://riverpod.dev) -- [Code Generation Guide](https://riverpod.dev/docs/concepts/about_code_generation) -- [Migration Guide](https://riverpod.dev/docs/3.0_migration) -- [Riverpod Lint](https://riverpod.dev/docs/concepts/about_riverpod_lint) - -### Community Resources - -- [Riverpod Examples](https://github.com/rrousselGit/riverpod/tree/master/examples) -- [Flutter Community](https://flutter.dev/community) - ---- - -## 📅 Document History - -| Date | Document | Change | Author | -|------|----------|--------|--------| -| Sep 30, 2025 | RIVERPOD_PRIORITY1_COMPLETED.md | Created, Priority 1 complete | AI Assistant | -| Sep 30, 2025 | RIVERPOD_PRIORITY2_PLAN.md | Created, detailed plan | AI Assistant | -| Sep 30, 2025 | RIVERPOD_PRIORITY2_QUICKREF.md | Created, quick reference | AI Assistant | -| Sep 30, 2025 | RIVERPOD_PRIORITY2_TRACKER.md | Created, progress tracker | AI Assistant | -| Sep 30, 2025 | RIVERPOD_MIGRATION_INDEX.md | Created, master index | AI Assistant | - ---- - -## 🎉 Conclusion - -This comprehensive documentation suite provides everything needed for a successful Riverpod 3.0 migration. With clear plans, examples, and tracking tools, the migration can proceed smoothly and safely. - -**Remember:** -- 📖 Read the docs -- 🧪 Test frequently -- 📝 Track progress -- 🤝 Ask for help -- 🎯 Stay focused - -**Good luck with the migration! 🚀** - ---- - -**Last Updated:** September 30, 2025 -**Status:** Priority 1 Complete ✅ | Priority 2 Ready 📋 -**Next Action:** Begin Phase 1 of Priority 2 migration diff --git a/RIVERPOD_MIGRATION_PROGRESS.md b/RIVERPOD_MIGRATION_PROGRESS.md deleted file mode 100644 index 4c894a1..0000000 --- a/RIVERPOD_MIGRATION_PROGRESS.md +++ /dev/null @@ -1,172 +0,0 @@ -# Riverpod Migration Progress Report - -**Date:** September 30, 2025 -**Session Duration:** ~2 hours -**Status:** 30/39 providers migrated (77%) - ---- - -## ✅ Completed Phases - -### Phase 1: Simple Notifiers (COMPLETE) -**Time:** ~45 minutes -**Providers:** 9/9 migrated - -- searchQueryProvider → SearchQuery -- selectedModelProvider → SelectedModel -- isManualModelSelectionProvider → IsManualModelSelection -- reviewerModeProvider → ReviewerMode -- isLoadingConversationProvider → IsLoadingConversation -- prefilledInputTextProvider → PrefilledInputText -- inputFocusTriggerProvider → InputFocusTrigger -- composerHasFocusProvider → ComposerHasFocus -- batchModeProvider → BatchMode -- reducedMotionProvider → ReducedMotion - -### Phase 2: FutureProvider Functions (COMPLETE) -**Time:** ~45 minutes -**Providers:** 15/15 migrated - -Core: -- serverConfigsProvider → serverConfigs -- activeServerProvider → activeServer -- currentUserProvider → currentUser -- modelsProvider → models -- userSettingsProvider → userSettings -- conversationSuggestionsProvider → conversationSuggestions -- userPermissionsProvider → userPermissions -- foldersProvider → folders -- userFilesProvider → userFiles -- knowledgeBasesProvider → knowledgeBases -- availableVoicesProvider → availableVoices -- imageModelsProvider → imageModels - -Features: -- promptsListProvider → promptsList -- toolsListProvider → toolsList - -Bonus: -- activePromptCommandProvider → ActivePromptCommand -- selectedToolIdsProvider → SelectedToolIds - -### Phase 3: Family Providers (COMPLETE) -**Time:** ~30 minutes -**Providers:** 4/4 migrated - -- loadConversationProvider(id) → loadConversation -- serverSearchProvider(query) → serverSearch -- fileContentProvider(fileId) → fileContent -- knowledgeBaseItemsProvider(kbId) → knowledgeBaseItems - ---- - -## 📊 Statistics - -**Total Migrated:** 30/39 providers (77%) -**Commits:** 11 total -**Breaking Changes:** 0 (so far) -**Build Errors:** 0 -**Test Failures:** 0 - -**Key Learning:** Use `Ref` directly in @riverpod functions, not typed refs - ---- - -## 🔄 Remaining Work - -### Phase 4: Name-Changing Providers (2 providers) -**Risk:** 🟡 Medium (breaking changes) -**Estimated:** 2-3 hours - -- themeModeProvider → appThemeModeProvider ⚠️ BREAKING -- localeProvider → appLocaleProvider ⚠️ BREAKING - -### Phase 5: Complex Providers (3 providers) -**Risk:** 🔴 High (complex logic, high usage) -**Estimated:** 4-6 hours - -- conversationsProvider (complex caching) -- appSettingsProvider (large class, ~30 usages) -- chatMessagesProvider (2500+ lines, very complex) - -### Phase 6: Internal Providers (2 providers) -**Risk:** 🟢 Low (internal use only) -**Estimated:** 30 minutes - -- _wasOfflineProvider (private) -- _conversationsCacheTimestampProvider (private) - -**Remaining:** 9/39 providers (23%) - ---- - -## ✨ Benefits Achieved - -### Code Quality -- ✅ Consistent provider patterns across codebase -- ✅ Less boilerplate (reduced code by ~150 lines) -- ✅ Better type safety with code generation -- ✅ Improved IDE support and autocomplete - -### Developer Experience -- ✅ Easier to add family parameters -- ✅ Automatic dependency tracking -- ✅ Better error messages -- ✅ Cleaner, more maintainable code - -### Technical -- ✅ All tests passing -- ✅ Zero breaking changes (so far) -- ✅ No performance regressions -- ✅ Analyzer clean (only pre-existing warnings) - ---- - -## 🎯 Next Session Plan - -### Option A: Complete All Phases (Recommended) -Continue with Phases 4-6 to complete the migration. - -**Pros:** -- Full consistency -- Get breaking changes out of the way -- Complete the work - -**Cons:** -- Requires careful testing -- Breaking changes need communication - -### Option B: Test & Deploy Phases 1-3 -Deploy current progress before tackling complex providers. - -**Pros:** -- Lower risk deployment -- Get feedback early -- Test in production - -**Cons:** -- Codebase remains inconsistent -- Need another migration session later - ---- - -## 📝 Recommendations - -1. **Continue with Phase 4 & 6 first** (low-medium risk) - - Get breaking changes done together - - Migrate internal providers (quick wins) - -2. **Test thoroughly** before Phase 5 - - Run full test suite - - Manual testing on all platforms - - Check for regressions - -3. **Phase 5 in separate PR** - - Complex providers need careful review - - High usage means high impact - - Consider pair programming - ---- - -**Prepared by:** AI Assistant -**Review Status:** Ready for team review diff --git a/RIVERPOD_PRIORITY1_COMPLETED.md b/RIVERPOD_PRIORITY1_COMPLETED.md deleted file mode 100644 index 2d1bf1f..0000000 --- a/RIVERPOD_PRIORITY1_COMPLETED.md +++ /dev/null @@ -1,271 +0,0 @@ -# Priority 1 Implementation - Completed ✅ - -**Date:** September 30, 2025 -**Time Taken:** ~10 minutes -**Status:** Successfully Completed - ---- - -## Changes Made - -### 1. ✅ Updated `pubspec.yaml` - -Added Riverpod linting packages: - -```yaml -dev_dependencies: - # ... existing dependencies ... - riverpod_generator: ^3.0.0 - riverpod_lint: ^3.0.0 # NEW - custom_lint: ^0.8.0 # NEW -``` - -**Note:** Required version upgrades due to dependency constraints: -- `riverpod_lint` upgraded from recommended `^2.3.10` to `^3.0.0` (compatible with Riverpod 3.0) -- `custom_lint` set to `^0.8.0` (compatible with `riverpod_generator` 3.0.0) - -### 2. ✅ Updated `analysis_options.yaml` - -Added custom_lint plugin: - -```yaml -analyzer: - plugins: - - custom_lint -``` - -### 3. ✅ Updated `AGENTS.md` - -Replaced generic state management guidelines with Riverpod 3.0 specific best practices: -- Added code generation examples -- Added `@riverpod` annotation patterns -- Added `Notifier` and `AsyncNotifier` usage -- Added `ref.mounted` safety checks -- Added lint rules guidance - -### 4. ✅ Installed Packages - -```bash -flutter pub get -``` - -Successfully resolved all dependencies. - -### 5. ✅ Ran Linter and Fixed Issues - -**Initial Issues Found:** 3 -- 1 WARNING: Using `ref` in `State.dispose()` -- 2 INFO: Public properties in stream-based Notifiers - -**Actions Taken:** -- ✅ Fixed WARNING in `lib/features/chat/widgets/modern_chat_input.dart` - - Removed `ref.read()` call from `dispose()` method - - Added explanatory comment about Riverpod best practices -- ℹ️ Kept INFO warnings (valid patterns for stream management) - -**Final Result:** -```bash -dart run custom_lint -# 2 INFO items (acceptable stream patterns) -# 0 WARNINGS -# 0 ERRORS -``` - -### 6. ✅ Verified with Flutter Analyze - -```bash -flutter analyze -# No issues found! ✅ -``` - ---- - -## Results - -### Before Priority 1 - -- ❌ No compile-time Riverpod checks -- ❌ Could use `ref` in unsafe contexts -- ❌ No automatic detection of provider misuse -- ⚠️ AGENTS.md had conflicting guidance - -### After Priority 1 - -- ✅ Compile-time Riverpod safety checks enabled -- ✅ Automatic detection of unsafe `ref` usage -- ✅ IDE integration for Riverpod-specific lints -- ✅ AGENTS.md aligned with actual codebase architecture -- ✅ All existing code passing lint checks - ---- - -## Remaining INFO Items (Acceptable) - -Two INFO-level notifications remain in `lib/core/providers/app_providers.dart`: - -1. **Line 407:** `SocketConnectionState get latest` - - **Status:** Acceptable - provides imperative access to cached stream state - - **Pattern:** Valid for stream-based providers - -2. **Line 502:** `Stream get stream` - - **Status:** Acceptable - exposes the underlying stream for consumption - - **Pattern:** Standard stream provider pattern - -These are informational suggestions, not errors. The code follows appropriate patterns for stream management in Riverpod. - ---- - -## Benefits Achieved - -### Immediate Benefits - -1. **Compile-time Safety** - - Riverpod mistakes caught before runtime - - IDE shows warnings/errors as you type - -2. **Better Developer Experience** - - Quick fixes available in IDE - - Better autocomplete for Riverpod patterns - - Inline documentation for best practices - -3. **Code Quality** - - Fixed unsafe `ref` usage in dispose - - Documentation aligned with implementation - - Clear guidelines for future development - -4. **Team Onboarding** - - AGENTS.md now has correct Riverpod examples - - New developers get accurate guidance - - Consistent patterns documented - -### Metrics - -- **Lint errors fixed:** 1 WARNING -- **Documentation updated:** 1 file (AGENTS.md) -- **Configuration files updated:** 2 files -- **New dependencies added:** 2 packages -- **Breaking changes:** 0 -- **Test failures:** 0 - ---- - -## Validation - -All validation checks passed: - -```bash -# ✅ Packages installed -flutter pub get - -# ✅ Custom lint passed (only INFO items) -dart run custom_lint - -# ✅ Flutter analyze passed -flutter analyze - -# ✅ No breaking changes -# (existing code continues to work) -``` - ---- - -## Next Steps - -### Recommended (Optional) - -1. **Run tests** to ensure no regressions: - ```bash - flutter test - ``` - -2. **Test app manually** on at least one platform: - ```bash - flutter run - ``` - -3. **Review Priority 2** changes: - - See `RIVERPOD_3_ANALYSIS.md` for detailed migration plan - - Start with simple providers (low risk) - - Schedule for next sprint - -4. **Enable IDE integration**: - - Restart IDE/analysis server to pick up new lints - - VS Code: Cmd+Shift+P → "Dart: Restart Analysis Server" - - Android Studio: File → Invalidate Caches / Restart - ---- - -## Files Modified - -### Configuration Files -- ✅ `pubspec.yaml` - Added linting dependencies -- ✅ `analysis_options.yaml` - Added custom_lint plugin - -### Documentation Files -- ✅ `AGENTS.md` - Updated state management section -- ✅ `RIVERPOD_QUICKSTART.md` - Updated with correct versions -- ✅ `RIVERPOD_3_ANALYSIS.md` - Updated with correct versions - -### Source Files -- ✅ `lib/features/chat/widgets/modern_chat_input.dart` - Fixed unsafe ref usage - ---- - -## Troubleshooting Notes - -### Dependency Resolution - -Initial version recommendations had conflicts: -- `custom_lint: ^0.6.0` → incompatible with `freezed_annotation: ^3.0.0` -- `custom_lint: ^0.7.0` → incompatible with `riverpod_generator: ^3.0.0` -- `riverpod_lint: ^2.3.10` → incompatible with `custom_lint: ^0.8.0` - -**Solution:** Use compatible versions: -- `riverpod_lint: ^3.0.0` (matches Riverpod 3.0) -- `custom_lint: ^0.8.0` (compatible with all dependencies) - -### Key Learnings - -1. Always check `riverpod_lint` version matches your Riverpod version -2. `custom_lint_core` version must match between packages -3. `freezed_annotation` version affects `custom_lint` compatibility -4. Use `flutter pub get` to verify dependency resolution before committing - ---- - -## Risk Assessment - -**Risk Level:** 🟢 **NONE** - -Changes are purely additive: -- No existing code modified (except 1 bug fix) -- No runtime behavior changes -- Only added static analysis -- Can be reverted easily if needed - -**Rollback Plan:** -1. Revert changes to `pubspec.yaml` -2. Run `flutter pub get` -3. Revert changes to `analysis_options.yaml` -4. Done (app continues to work) - ---- - -## Conclusion - -Priority 1 implementation is **complete and successful**. The codebase now has: - -✅ Riverpod-specific compile-time checks -✅ Better IDE support for Riverpod development -✅ Accurate documentation for developers -✅ One safety issue fixed -✅ Zero breaking changes -✅ All tests passing - -The foundation is now in place for Priority 2 migrations (code generation standardization) if desired. - ---- - -**Status:** READY FOR PRODUCTION ✅ - -*No additional testing required beyond standard PR validation.* diff --git a/RIVERPOD_PRIORITY2_PLAN.md b/RIVERPOD_PRIORITY2_PLAN.md deleted file mode 100644 index 9637f0c..0000000 --- a/RIVERPOD_PRIORITY2_PLAN.md +++ /dev/null @@ -1,1473 +0,0 @@ -# Priority 2 Migration Plan - Code Generation Standardization - -**Created:** September 30, 2025 -**Status:** 📋 Planning Phase -**Estimated Effort:** 16-24 hours -**Risk Level:** 🟡 Medium - ---- - -## Table of Contents - -1. [Overview](#overview) -2. [Providers to Migrate](#providers-to-migrate) -3. [Migration Strategy](#migration-strategy) -4. [Step-by-Step Instructions](#step-by-step-instructions) -5. [Testing Plan](#testing-plan) -6. [Rollback Plan](#rollback-plan) - ---- - -## Overview - -### Goals - -Convert all manual `NotifierProvider` and `FutureProvider` declarations to use `@riverpod` annotation for: -- ✅ Consistency across the codebase -- ✅ Less boilerplate -- ✅ Better IDE support and type safety -- ✅ Easier future modifications (family, autoDispose, etc.) -- ✅ Automatic dependency tracking - -### Scope - -**Total Providers to Migrate:** 39 providers across 7 files - -**Files Affected:** -1. `lib/core/providers/app_providers.dart` (26 providers) -2. `lib/features/chat/providers/chat_providers.dart` (5 providers) -3. `lib/core/services/settings_service.dart` (1 provider) -4. `lib/core/services/animation_service.dart` (1 provider) -5. `lib/features/chat/services/message_batch_service.dart` (1 provider) -6. `lib/features/prompts/providers/prompts_providers.dart` (1 provider) -7. `lib/features/tools/providers/tools_providers.dart` (1 provider) -8. `lib/shared/widgets/offline_indicator.dart` (1 provider) -9. `lib/features/chat/services/voice_input_service.dart` (1 provider) - ---- - -## Providers to Migrate - -### Category A: Simple Notifier Classes (Low Risk, High Priority) - -These are straightforward state holders with minimal logic. - -#### 1. `searchQueryProvider` / `SearchQueryNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 1200-1209) -**Complexity:** 🟢 Simple -**Usage Count:** ~5-10 files -**Dependencies:** None - -**Current:** -```dart -final searchQueryProvider = NotifierProvider( - SearchQueryNotifier.new, -); - -class SearchQueryNotifier extends Notifier { - @override - String build() => ''; - - void set(String query) => state = query; -} -``` - -**After:** -```dart -@riverpod -class SearchQuery extends _$SearchQuery { - @override - String build() => ''; - - void set(String query) => state = query; -} - -// Generated provider name: searchQueryProvider ✅ (same!) -``` - -**Migration Notes:** -- Class renamed from `SearchQueryNotifier` to `SearchQuery` (convention) -- Provider name stays identical -- No usage changes required - ---- - -#### 2. `selectedModelProvider` / `SelectedModelNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 618-635) -**Complexity:** 🟢 Simple -**Usage Count:** ~15-20 files -**Dependencies:** None - -**Current:** -```dart -final selectedModelProvider = NotifierProvider( - SelectedModelNotifier.new, -); - -class SelectedModelNotifier extends Notifier { - @override - Model? build() => null; - - void set(Model? model) => state = model; - - void clear() => state = null; -} -``` - -**After:** -```dart -@riverpod -class SelectedModel extends _$SelectedModel { - @override - Model? build() => null; - - void set(Model? model) => state = model; - - void clear() => state = null; -} - -// Generated provider name: selectedModelProvider ✅ -``` - ---- - -#### 3. `isManualModelSelectionProvider` / `IsManualModelSelectionNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 623-642) -**Complexity:** 🟢 Simple -**Usage Count:** ~3-5 files -**Dependencies:** None - -**Current:** -```dart -final isManualModelSelectionProvider = - NotifierProvider( - IsManualModelSelectionNotifier.new, - ); - -class IsManualModelSelectionNotifier extends Notifier { - @override - bool build() => false; - - void set(bool value) => state = value; -} -``` - -**After:** -```dart -@riverpod -class IsManualModelSelection extends _$IsManualModelSelection { - @override - bool build() => false; - - void set(bool value) => state = value; -} - -// Generated provider name: isManualModelSelectionProvider ✅ -``` - ---- - -#### 4. `reviewerModeProvider` / `ReviewerModeNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 1415-1430) -**Complexity:** 🟢 Simple (has storage dependency) -**Usage Count:** ~5-8 files -**Dependencies:** `optimizedStorageServiceProvider` - -**Current:** -```dart -final reviewerModeProvider = NotifierProvider( - ReviewerModeNotifier.new, -); - -class ReviewerModeNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - bool build() { - _storage = ref.watch(optimizedStorageServiceProvider); - return _storage.getReviewerMode(); - } - - void set(bool value) { - state = value; - _storage.setReviewerMode(value); - } -} -``` - -**After:** -```dart -@riverpod -class ReviewerMode extends _$ReviewerMode { - late final OptimizedStorageService _storage; - - @override - bool build() { - _storage = ref.watch(optimizedStorageServiceProvider); - return _storage.getReviewerMode(); - } - - void set(bool value) { - state = value; - _storage.setReviewerMode(value); - } -} - -// Generated provider name: reviewerModeProvider ✅ -``` - ---- - -#### 5. `batchModeProvider` / `BatchModeNotifier` -**File:** `lib/features/chat/services/message_batch_service.dart` (lines 532-540) -**Complexity:** 🟢 Simple -**Usage Count:** ~3-5 files -**Dependencies:** None - ---- - -#### 6. `reducedMotionProvider` / `ReducedMotionNotifier` -**File:** `lib/core/services/animation_service.dart` (lines 211-225) -**Complexity:** 🟢 Simple (has storage dependency) -**Usage Count:** ~5-10 files -**Dependencies:** `optimizedStorageServiceProvider` - ---- - -### Category B: Storage-Backed Notifiers (Low-Medium Risk) - -These manage persistent state with storage dependencies. - -#### 7. `themeModeProvider` / `ThemeModeNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 71-95) -**Complexity:** 🟡 Medium -**Usage Count:** ~10-15 files -**Dependencies:** `optimizedStorageServiceProvider` - -**Current:** -```dart -final themeModeProvider = NotifierProvider( - ThemeModeNotifier.new, -); - -class ThemeModeNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} -``` - -**After:** -```dart -@riverpod -class AppThemeMode extends _$AppThemeMode { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} - -// Generated provider name: appThemeModeProvider -``` - -**⚠️ Important:** -- Class renamed from `ThemeModeNotifier` to `AppThemeMode` to avoid conflict with Flutter's `ThemeMode` enum -- Provider name changes from `themeModeProvider` to `appThemeModeProvider` -- **Requires bulk find-replace across codebase** - -**Migration Command:** -```bash -# Find all usages first -grep -r "themeModeProvider" lib/ --exclude="*.g.dart" | wc -l - -# Replace (use IDE refactoring or sed) -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/themeModeProvider/appThemeModeProvider/g' {} + -``` - ---- - -#### 8. `localeProvider` / `LocaleNotifier` -**File:** `lib/core/providers/app_providers.dart` (lines 98-119) -**Complexity:** 🟢 Simple (async method) -**Usage Count:** ~8-12 files -**Dependencies:** `optimizedStorageServiceProvider` - -**Current:** -```dart -final localeProvider = NotifierProvider( - LocaleNotifier.new, -); - -class LocaleNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - Locale? build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final code = _storage.getLocaleCode(); - if (code != null && code.isNotEmpty) { - return Locale(code); - } - return null; // system default - } - - Future setLocale(Locale? locale) async { - state = locale; - await _storage.setLocaleCode(locale?.languageCode); - } -} -``` - -**After:** -```dart -@riverpod -class AppLocale extends _$AppLocale { - late final OptimizedStorageService _storage; - - @override - Locale? build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final code = _storage.getLocaleCode(); - if (code != null && code.isNotEmpty) { - return Locale(code); - } - return null; // system default - } - - Future setLocale(Locale? locale) async { - state = locale; - await _storage.setLocaleCode(locale?.languageCode); - } -} - -// Generated provider name: appLocaleProvider -``` - -**⚠️ Important:** -- Class renamed from `LocaleNotifier` to `AppLocale` to avoid potential conflicts -- Provider name changes from `localeProvider` to `appLocaleProvider` -- **Requires bulk find-replace across codebase** - ---- - -#### 9. `appSettingsProvider` / `AppSettingsNotifier` -**File:** `lib/core/services/settings_service.dart` (lines 407-500+) -**Complexity:** 🔴 Complex (large class with many methods) -**Usage Count:** ~20-30 files (high usage!) -**Dependencies:** `optimizedStorageServiceProvider`, `apiServiceProvider` - -**Migration Strategy:** -- ⚠️ Save for **last** due to high complexity and usage -- Test extensively before committing -- Consider splitting into smaller providers if possible - ---- - -### Category C: Chat-Specific Notifiers (Medium Risk) - -#### 10. `isLoadingConversationProvider` / `IsLoadingConversationNotifier` -**File:** `lib/features/chat/providers/chat_providers.dart` (lines 30-57) -**Complexity:** 🟢 Simple -**Usage Count:** ~5-8 files - -**After:** -```dart -@riverpod -class IsLoadingConversation extends _$IsLoadingConversation { - @override - bool build() => false; - - void set(bool value) => state = value; -} - -// Generated provider name: isLoadingConversationProvider ✅ -``` - ---- - -#### 11. `prefilledInputTextProvider` / `PrefilledInputTextNotifier` -**File:** `lib/features/chat/providers/chat_providers.dart` (lines 36-66) -**Complexity:** 🟢 Simple -**Usage Count:** ~3-5 files - -**After:** -```dart -@riverpod -class PrefilledInputText extends _$PrefilledInputText { - @override - String? build() => null; - - void set(String? value) => state = value; - - void clear() => state = null; -} - -// Generated provider name: prefilledInputTextProvider ✅ -``` - ---- - -#### 12. `inputFocusTriggerProvider` / `InputFocusTriggerNotifier` -**File:** `lib/features/chat/providers/chat_providers.dart` (lines 42-79) -**Complexity:** 🟢 Simple -**Usage Count:** ~3-5 files - -**After:** -```dart -@riverpod -class InputFocusTrigger extends _$InputFocusTrigger { - @override - int build() => 0; - - void set(int value) => state = value; - - int increment() { - final next = state + 1; - state = next; - return next; - } -} - -// Generated provider name: inputFocusTriggerProvider ✅ -``` - ---- - -#### 13. `composerHasFocusProvider` / `ComposerFocusNotifier` -**File:** `lib/features/chat/providers/chat_providers.dart` (lines 48-86) -**Complexity:** 🟢 Simple -**Usage Count:** ~3-5 files - -**After:** -```dart -@riverpod -class ComposerHasFocus extends _$ComposerHasFocus { - @override - bool build() => false; - - void set(bool value) => state = value; -} - -// Generated provider name: composerHasFocusProvider ✅ -``` - ---- - -#### 14. `chatMessagesProvider` / `ChatMessagesNotifier` -**File:** `lib/features/chat/providers/chat_providers.dart` (lines 24-2532) -**Complexity:** 🔴 Very Complex (2500+ lines!) -**Usage Count:** ~15-20 files (high usage!) -**Dependencies:** Many (socket, API, storage, etc.) - -**Migration Strategy:** -- ⚠️ Save for **last** due to extreme complexity -- Consider refactoring into smaller providers first -- Extensive testing required - ---- - -### Category D: FutureProvider Functions (Low-Medium Risk) - -These are stateless async computations that can be easily converted. - -#### 15. `serverConfigsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 122-125) -**Complexity:** 🟢 Simple -**Usage Count:** ~5-10 files - -**Current:** -```dart -final serverConfigsProvider = FutureProvider>((ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -}); -``` - -**After:** -```dart -@riverpod -Future> serverConfigs(ServerConfigsRef ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -} - -// Generated provider name: serverConfigsProvider ✅ -``` - ---- - -#### 16. `activeServerProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 127-141) -**Complexity:** 🟢 Simple - -**After:** -```dart -@riverpod -Future activeServer(ActiveServerRef ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - final configs = await ref.watch(serverConfigsProvider.future); - final activeId = await storage.getActiveServerId(); - - if (activeId == null || configs.isEmpty) return null; - - for (final config in configs) { - if (config.id == activeId) { - return config; - } - } - - return null; -} - -// Generated provider name: activeServerProvider ✅ -``` - ---- - -#### 17. `currentUserProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 549-568) -**Complexity:** 🟢 Simple - -**After:** -```dart -@riverpod -Future currentUser(CurrentUserRef ref) async { - final api = ref.watch(apiServiceProvider); - if (api == null) return null; - - try { - final user = await api.getCurrentUser(); - return user; - } catch (e) { - DebugLogger.error('current-user-failed', scope: 'user', error: e); - return null; - } -} - -// Generated provider name: currentUserProvider ✅ -``` - ---- - -#### 18. `modelsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 570-615) -**Complexity:** 🟡 Medium (has caching logic) - -**After:** -```dart -@riverpod -Future> models(ModelsRef ref) async { - final api = ref.watch(apiServiceProvider); - if (api == null) return []; - - try { - final models = await api.getModels(); - DebugLogger.log('models-fetched', scope: 'models', data: {'count': models.length}); - return models; - } catch (e) { - DebugLogger.error('models-fetch-failed', scope: 'models', error: e); - return []; - } -} - -// Generated provider name: modelsProvider ✅ -``` - ---- - -#### 19. `conversationsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 722-990+) -**Complexity:** 🔴 Complex (has custom caching, listeners) -**Usage Count:** ~10-15 files - -**Migration Strategy:** -- ⚠️ Medium priority (moderate complexity) -- Keep caching behavior intact -- Test conversation list loading thoroughly - ---- - -#### 20. `defaultModelProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1020-1050) -**Complexity:** 🟢 Simple - ---- - -#### 21. `userSettingsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1450-1465) -**Complexity:** 🟢 Simple - -**After:** -```dart -@riverpod -Future userSettings(UserSettingsRef ref) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - return UserSettings.empty(); - } - - try { - return await api.getUserSettings(); - } catch (e) { - DebugLogger.error('user-settings-fetch-failed', scope: 'settings', error: e); - return UserSettings.empty(); - } -} - -// Generated provider name: userSettingsProvider ✅ -``` - ---- - -#### 22. `conversationSuggestionsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1468-1480) -**Complexity:** 🟢 Simple - ---- - -#### 23. `userPermissionsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1483-1500) -**Complexity:** 🟢 Simple - ---- - -#### 24. `foldersProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1530-1555) -**Complexity:** 🟢 Simple - ---- - -#### 25. `userFilesProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1560-1575) -**Complexity:** 🟢 Simple - ---- - -#### 26. `knowledgeBasesProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1605-1625) -**Complexity:** 🟢 Simple - ---- - -#### 27. `availableVoicesProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1649-1665) -**Complexity:** 🟢 Simple - ---- - -#### 28. `imageModelsProvider` -**File:** `lib/core/providers/app_providers.dart` (lines 1667-1680) -**Complexity:** 🟢 Simple - ---- - -### Category E: Family Providers (Medium Risk) - -#### 29. `loadConversationProvider` (family) -**File:** `lib/core/providers/app_providers.dart` (lines 995-1015) -**Complexity:** 🟡 Medium -**Usage Count:** ~5-10 files - -**Current:** -```dart -final loadConversationProvider = FutureProvider.family(( - ref, - conversationId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - // ... fetch logic -}); -``` - -**After:** -```dart -@riverpod -Future loadConversation( - LoadConversationRef ref, - String conversationId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - // ... fetch logic -} - -// Usage stays the same: -// ref.watch(loadConversationProvider(conversationId)) -``` - ---- - -#### 30. `serverSearchProvider` (family) -**File:** `lib/core/providers/app_providers.dart` (lines 1212-1250) -**Complexity:** 🟢 Simple - -**After:** -```dart -@riverpod -Future> serverSearch( - ServerSearchRef ref, - String query, -) async { - if (query.trim().isEmpty) { - return []; - } - - final api = ref.watch(apiServiceProvider); - if (api == null) return []; - - try { - final trimmedQuery = query.trim(); - DebugLogger.log('server-search', scope: 'search', data: {'query': trimmedQuery}); - final results = await api.searchConversations(trimmedQuery); - return results; - } catch (e) { - DebugLogger.error('server-search-failed', scope: 'search', error: e); - return []; - } -} - -// Generated provider name: serverSearchProvider ✅ -``` - ---- - -#### 31. `fileContentProvider` (family) -**File:** `lib/core/providers/app_providers.dart` (lines 1579-1600) -**Complexity:** 🟢 Simple - -**After:** -```dart -@riverpod -Future fileContent( - FileContentRef ref, - String fileId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) return ''; - - try { - return await api.getFileContent(fileId); - } catch (e) { - DebugLogger.error('file-content-fetch-failed', scope: 'files', error: e); - return ''; - } -} - -// Generated provider name: fileContentProvider ✅ -``` - ---- - -### Category F: Feature-Specific Providers (Low Risk) - -#### 32. `promptsListProvider` -**File:** `lib/features/prompts/providers/prompts_providers.dart` (lines 6-15) -**Complexity:** 🟢 Simple -**Usage Count:** ~2-3 files - -**After:** -```dart -@riverpod -Future> promptsList(PromptsListRef ref) async { - final api = ref.watch(apiServiceProvider); - if (api == null) return []; - - try { - return await api.getPrompts(); - } catch (e) { - return []; - } -} - -// Generated provider name: promptsListProvider ✅ -``` - ---- - -#### 33. `toolsListProvider` -**File:** `lib/features/tools/providers/tools_providers.dart` (lines 5-15) -**Complexity:** 🟢 Simple -**Usage Count:** ~2-3 files - -**After:** -```dart -@riverpod -Future> toolsList(ToolsListRef ref) async { - final api = ref.watch(apiServiceProvider); - if (api == null) return []; - - try { - return await api.getTools(); - } catch (e) { - return []; - } -} - -// Generated provider name: toolsListProvider ✅ -``` - ---- - -#### 34. `voiceInputAvailableProvider` -**File:** `lib/features/chat/services/voice_input_service.dart` (lines 325-330) -**Complexity:** 🟢 Simple -**Usage Count:** ~2-3 files - ---- - -### Category G: Private/Internal Providers (Low Risk) - -#### 35. `_wasOfflineProvider` / `_WasOfflineNotifier` -**File:** `lib/shared/widgets/offline_indicator.dart` (lines 55-65) -**Complexity:** 🟢 Simple -**Usage Count:** 1 file (internal) - -**Note:** This is a private provider (starts with `_`). Can migrate but low priority. - ---- - -#### 36. `_conversationsCacheTimestampProvider` (internal) -**File:** `lib/core/providers/app_providers.dart` (lines 709-718) -**Complexity:** 🟢 Simple -**Usage Count:** 1-2 files (internal) - -**Note:** Internal caching helper. Can migrate alongside `conversationsProvider`. - ---- - -## Migration Strategy - -### Phase 1: Simple Wins (Week 1, 4-6 hours) - -Migrate simple, low-usage providers to build confidence and establish patterns. - -**Targets (10 providers):** -1. ✅ `searchQueryProvider` -2. ✅ `selectedModelProvider` -3. ✅ `isManualModelSelectionProvider` -4. ✅ `reviewerModeProvider` -5. ✅ `batchModeProvider` -6. ✅ `isLoadingConversationProvider` -7. ✅ `prefilledInputTextProvider` -8. ✅ `inputFocusTriggerProvider` -9. ✅ `composerHasFocusProvider` -10. ✅ `reducedMotionProvider` - -**Process:** -1. Migrate one provider -2. Run `build_runner` -3. Test manually -4. Commit -5. Repeat - -**Exit Criteria:** -- All 10 providers migrated -- All tests passing -- No regressions in functionality - ---- - -### Phase 2: FutureProvider Functions (Week 2, 6-8 hours) - -Convert simple async functions to @riverpod functions. - -**Targets (15 providers):** -1. ✅ `serverConfigsProvider` -2. ✅ `activeServerProvider` -3. ✅ `currentUserProvider` -4. ✅ `modelsProvider` -5. ✅ `defaultModelProvider` -6. ✅ `userSettingsProvider` -7. ✅ `conversationSuggestionsProvider` -8. ✅ `userPermissionsProvider` -9. ✅ `foldersProvider` -10. ✅ `userFilesProvider` -11. ✅ `knowledgeBasesProvider` -12. ✅ `availableVoicesProvider` -13. ✅ `imageModelsProvider` -14. ✅ `promptsListProvider` -15. ✅ `toolsListProvider` - -**Process:** -1. Migrate in batches of 3-5 providers -2. Run `build_runner` after each batch -3. Test affected features -4. Commit batch - ---- - -### Phase 3: Family Providers (Week 2, 2-3 hours) - -Convert family providers to @riverpod functions with parameters. - -**Targets (4 providers):** -1. ✅ `loadConversationProvider` -2. ✅ `serverSearchProvider` -3. ✅ `fileContentProvider` -4. ✅ `voiceInputAvailableProvider` - -**Process:** -1. Migrate one at a time -2. Pay attention to parameter types -3. Test with different parameter values -4. Commit individually - ---- - -### Phase 4: Storage-Backed Notifiers (Week 3, 4-6 hours) - -Migrate providers that require provider name changes (breaking changes). - -**Targets (2 providers + bulk replace):** -1. ⚠️ `themeModeProvider` → `appThemeModeProvider` -2. ⚠️ `localeProvider` → `appLocaleProvider` - -**Process:** -1. Migrate provider definition -2. Run `build_runner` -3. **Find and replace all usages** (use IDE refactoring) -4. Run tests -5. Manual testing on all platforms -6. Commit with clear message about breaking change - -**Find/Replace Commands:** -```bash -# ThemeMode migration -grep -r "themeModeProvider" lib/ --exclude="*.g.dart" | wc -l -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/themeModeProvider/appThemeModeProvider/g' {} + - -# Locale migration -grep -r "localeProvider" lib/ --exclude="*.g.dart" | wc -l -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/localeProvider/appLocaleProvider/g' {} + -``` - ---- - -### Phase 5: Complex Providers (Week 4, 6-8 hours) - -Migrate complex, high-usage providers with extensive testing. - -**Targets (3 providers):** -1. 🔴 `conversationsProvider` (complex caching) -2. 🔴 `appSettingsProvider` (large class, high usage) -3. 🔴 `chatMessagesProvider` (extremely complex, 2500+ lines) - -**Process:** -1. **Read the entire class** to understand all dependencies -2. Create a test plan covering all methods -3. Migrate the provider -4. Run `build_runner` -5. Run all tests -6. Manual testing of all affected features -7. Commit with detailed migration notes - -**Extra Caution:** -- Test on physical devices (iOS + Android) -- Check for memory leaks -- Monitor performance -- Have rollback plan ready - ---- - -### Phase 6: Internal/Private Providers (Optional, 1-2 hours) - -Migrate internal providers for completeness. - -**Targets (2 providers):** -1. ✅ `_wasOfflineProvider` -2. ✅ `_conversationsCacheTimestampProvider` - -**Process:** -- Low priority -- Can be done as cleanup task -- No external dependencies to worry about - ---- - -## Step-by-Step Instructions - -### For Each Provider Migration - -#### Step 1: Prepare - -```bash -# Ensure clean git state -git status - -# Ensure packages are up to date -flutter pub get - -# Run tests to establish baseline -flutter test - -# (Optional) Find usage count -grep -r "providerName" lib/ --exclude="*.g.dart" | wc -l -``` - ---- - -#### Step 2: Migrate the Provider - -**For Notifier Classes:** - -1. Add `@riverpod` annotation -2. Change class name (remove `Notifier` suffix, handle conflicts) -3. Extend `_$ClassName` -4. Remove manual provider declaration -5. Keep all methods unchanged - -**For FutureProvider Functions:** - -1. Add `@riverpod` annotation -2. Convert to function with `Ref` parameter -3. Add family parameters as function parameters (if applicable) -4. Keep logic unchanged - ---- - -#### Step 3: Generate Code - -```bash -dart run build_runner build --delete-conflicting-outputs -``` - -**Watch for:** -- Build errors (fix immediately) -- Generated file created (`.g.dart`) -- Provider name in generated code (check if it matches expected) - ---- - -#### Step 4: Update Usages (if needed) - -**For providers with name changes only:** - -```bash -# Example: themeModeProvider → appThemeModeProvider -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/themeModeProvider/appThemeModeProvider/g' {} + -``` - -**Or use IDE:** -1. Right-click on provider name -2. Refactor → Rename -3. Enter new name -4. Preview changes -5. Apply - ---- - -#### Step 5: Verify - -```bash -# Check for compilation errors -flutter analyze - -# Run linter -dart run custom_lint - -# Run tests -flutter test - -# Manual smoke test -flutter run -``` - ---- - -#### Step 6: Commit - -```bash -git add . -git commit -m "refactor: migrate providerName to @riverpod code generation - -- Converted ProviderClass to use @riverpod annotation -- Provider name remains: providerNameProvider -- No breaking changes -- Tests passing ✅" -``` - -**For breaking changes:** - -```bash -git commit -m "refactor!: migrate themeModeProvider to @riverpod - -BREAKING CHANGE: Provider renamed from themeModeProvider to appThemeModeProvider - -- Converted ThemeModeNotifier to AppThemeMode -- Updated all usages across codebase (N files) -- Tests passing ✅" -``` - ---- - -## Testing Plan - -### Per-Provider Testing - -After migrating each provider, perform: - -1. **Compilation Check** - ```bash - flutter analyze - ``` - -2. **Lint Check** - ```bash - dart run custom_lint - ``` - -3. **Unit Tests** - ```bash - flutter test - ``` - -4. **Manual Smoke Test** - - Launch app - - Navigate to feature using the provider - - Verify behavior is unchanged - ---- - -### Phase Testing - -After completing each phase: - -1. **Full Test Suite** - ```bash - flutter test --coverage - ``` - -2. **Integration Testing** - - Test all major user flows - - Auth flow (login, logout, token refresh) - - Chat flow (create, send, receive) - - Settings (change theme, locale, models) - - Navigation (all routes) - -3. **Platform Testing** - - iOS simulator - - Android emulator - - (Optional) Web browser - - (Optional) Physical devices - -4. **Performance Check** - - App startup time - - Navigation performance - - Memory usage (DevTools) - - Provider rebuild counts (DevTools) - ---- - -### Final Testing (After All Phases) - -1. **Regression Testing** - - Run full test suite - - Manual testing of all features - - Test on multiple platforms - - Check for memory leaks - -2. **Code Quality** - - Run analyzer - - Run linter - - Check code coverage - - Review generated files - -3. **Documentation** - - Update README if needed - - Update AGENTS.md if needed - - Add migration notes to commits - ---- - -## Rollback Plan - -### Per-Provider Rollback - -If a single provider migration causes issues: - -```bash -# Revert the last commit -git revert HEAD - -# Or reset to before migration -git reset --hard HEAD~1 - -# Regenerate code -dart run build_runner build --delete-conflicting-outputs - -# Test -flutter test -``` - ---- - -### Phase Rollback - -If an entire phase needs to be rolled back: - -```bash -# Find the commit before phase started -git log --oneline - -# Reset to that commit -git reset --hard - -# Regenerate code -dart run build_runner build --delete-conflicting-outputs - -# Test -flutter test -``` - ---- - -### Emergency Rollback - -If production issues arise after deployment: - -1. **Immediate:** - ```bash - # Revert to last known good state - git revert - git push - ``` - -2. **Rebuild and Deploy:** - ```bash - flutter clean - flutter pub get - dart run build_runner build --delete-conflicting-outputs - flutter build - # Deploy to stores - ``` - ---- - -## Risk Mitigation - -### Low-Risk Providers (Categories A, D, F) - -**Mitigation:** -- Migrate in small batches -- Commit frequently -- Test after each migration - -**Rollback:** -- Easy (single commit revert) - ---- - -### Medium-Risk Providers (Categories B, C, E) - -**Mitigation:** -- Migrate individually -- Extensive manual testing -- Update documentation - -**Rollback:** -- Straightforward (commit revert) -- May need to update usages - ---- - -### High-Risk Providers (appSettingsProvider, chatMessagesProvider, conversationsProvider) - -**Mitigation:** -- Create detailed test plan -- Test on multiple platforms -- Have team review changes -- Deploy to staging first -- Monitor production closely - -**Rollback:** -- More complex (many dependencies) -- May need coordinated revert -- Keep backup branch - ---- - -## Success Criteria - -### Phase Completion - -Each phase is complete when: -- ✅ All targeted providers migrated -- ✅ All tests passing -- ✅ No analyzer/lint errors -- ✅ Manual testing successful -- ✅ Performance unchanged or improved -- ✅ Changes committed with clear messages - ---- - -### Overall Completion - -Priority 2 migration is complete when: -- ✅ All 39 providers migrated to @riverpod -- ✅ Codebase uses consistent provider pattern -- ✅ All tests passing -- ✅ No regressions identified -- ✅ Documentation updated -- ✅ Team trained on new patterns - ---- - -## Timeline - -### Estimated Schedule - -| Phase | Providers | Effort | Timeline | -|-------|-----------|--------|----------| -| Phase 1 | 10 simple notifiers | 4-6 hours | Week 1 | -| Phase 2 | 15 future providers | 6-8 hours | Week 2 | -| Phase 3 | 4 family providers | 2-3 hours | Week 2 | -| Phase 4 | 2 storage notifiers | 4-6 hours | Week 3 | -| Phase 5 | 3 complex providers | 6-8 hours | Week 4 | -| Phase 6 | 2 private providers | 1-2 hours | Week 4 | -| **Total** | **36 providers** | **23-33 hours** | **4 weeks** | - -**Note:** 3 providers (`activeConversationProvider`, `socketConnectionStreamProvider`, `conversationStreamProvider`) are already using @riverpod and don't need migration. - -**Recommended Pace:** -- 1-2 hours per day -- 5-10 providers per week -- Don't rush high-risk migrations - ---- - -## Resources - -### Documentation - -- [Riverpod 3.0 Code Generation Guide](https://riverpod.dev/docs/concepts/about_code_generation) -- [Riverpod Migration Guide](https://riverpod.dev/docs/3.0_migration) -- [docs/riverpod_migration_example.md](./docs/riverpod_migration_example.md) (this repo) - -### Tools - -- VS Code Riverpod snippets -- Android Studio Riverpod plugin -- `dart run build_runner watch` (auto-regenerate) - -### Commands - -```bash -# Build once -dart run build_runner build --delete-conflicting-outputs - -# Watch mode (recommended during development) -dart run build_runner watch --delete-conflicting-outputs - -# Clean generated files -flutter clean -dart run build_runner clean - -# Run all checks -flutter analyze && dart run custom_lint && flutter test -``` - ---- - -## Notes - -### Naming Conventions - -**Class Names:** -- Remove `Notifier` suffix -- Use descriptive names -- Avoid conflicts with existing types (e.g., `AppThemeMode` instead of `ThemeMode`) - -**Provider Names:** -- Auto-generated from class/function name -- Camel case with `Provider` suffix -- Examples: - - Class `SearchQuery` → `searchQueryProvider` - - Function `serverConfigs` → `serverConfigsProvider` - -### Common Issues - -**Issue 1: "_$ClassName not found"** -```bash -# Solution: Run build_runner -dart run build_runner build --delete-conflicting-outputs -``` - -**Issue 2: "Provider name already exists"** -```dart -// Solution: Rename the class to avoid conflicts -@riverpod -class AppThemeMode extends _$AppThemeMode { // ✅ Not 'ThemeMode' - // ... -} -``` - -**Issue 3: "Tests failing after migration"** -```bash -# Solution: Check if provider name changed -# Update test imports and usages -``` - ---- - -## Conclusion - -This Priority 2 migration plan provides a systematic approach to standardizing all providers in the Conduit codebase to use Riverpod 3.0 code generation. - -**Key Principles:** -1. **Incremental:** Small, focused changes -2. **Safe:** Test after every change -3. **Reversible:** Clear commits, easy rollback -4. **Documented:** Clear migration notes - -**Expected Benefits:** -- ✅ Consistent codebase -- ✅ Better IDE support -- ✅ Reduced boilerplate -- ✅ Easier future modifications -- ✅ Improved developer experience - -**Risk Level:** 🟡 Medium (manageable with careful execution) - -**Recommendation:** Proceed with Phase 1 to build confidence, then continue incrementally based on results. - ---- - -**Status:** 📋 Ready for Implementation -**Next Action:** Begin Phase 1 migrations - diff --git a/RIVERPOD_PRIORITY2_QUICKREF.md b/RIVERPOD_PRIORITY2_QUICKREF.md deleted file mode 100644 index 24edc1f..0000000 --- a/RIVERPOD_PRIORITY2_QUICKREF.md +++ /dev/null @@ -1,370 +0,0 @@ -# Priority 2 Migration Quick Reference - -**Quick access guide for Priority 2 migration tasks** - ---- - -## Quick Stats - -- **Total Providers:** 39 providers to migrate -- **Estimated Effort:** 23-33 hours (4 weeks at 1-2 hours/day) -- **Risk Level:** 🟡 Medium -- **Phases:** 6 phases - ---- - -## Migration Checklist by Phase - -### Phase 1: Simple Notifiers (4-6 hours) 🟢 - -- [ ] `searchQueryProvider` → `SearchQuery` -- [ ] `selectedModelProvider` → `SelectedModel` -- [ ] `isManualModelSelectionProvider` → `IsManualModelSelection` -- [ ] `reviewerModeProvider` → `ReviewerMode` -- [ ] `batchModeProvider` → `BatchMode` -- [ ] `isLoadingConversationProvider` → `IsLoadingConversation` -- [ ] `prefilledInputTextProvider` → `PrefilledInputText` -- [ ] `inputFocusTriggerProvider` → `InputFocusTrigger` -- [ ] `composerHasFocusProvider` → `ComposerHasFocus` -- [ ] `reducedMotionProvider` → `ReducedMotion` - -**File:** Various -**Risk:** 🟢 Low -**Provider Names:** Unchanged ✅ - ---- - -### Phase 2: FutureProvider Functions (6-8 hours) 🟢 - -- [ ] `serverConfigsProvider` -- [ ] `activeServerProvider` -- [ ] `currentUserProvider` -- [ ] `modelsProvider` -- [ ] `defaultModelProvider` -- [ ] `userSettingsProvider` -- [ ] `conversationSuggestionsProvider` -- [ ] `userPermissionsProvider` -- [ ] `foldersProvider` -- [ ] `userFilesProvider` -- [ ] `knowledgeBasesProvider` -- [ ] `availableVoicesProvider` -- [ ] `imageModelsProvider` -- [ ] `promptsListProvider` -- [ ] `toolsListProvider` - -**File:** Mostly `app_providers.dart` -**Risk:** 🟢 Low -**Provider Names:** Unchanged ✅ - ---- - -### Phase 3: Family Providers (2-3 hours) 🟢 - -- [ ] `loadConversationProvider(id)` -- [ ] `serverSearchProvider(query)` -- [ ] `fileContentProvider(fileId)` -- [ ] `voiceInputAvailableProvider` - -**File:** Various -**Risk:** 🟡 Medium -**Provider Names:** Unchanged ✅ - ---- - -### Phase 4: Name-Changing Providers (4-6 hours) ⚠️ - -- [ ] `themeModeProvider` → `appThemeModeProvider` ⚠️ BREAKING -- [ ] `localeProvider` → `appLocaleProvider` ⚠️ BREAKING - -**File:** `app_providers.dart` -**Risk:** 🟡 Medium -**Provider Names:** CHANGED - requires bulk find/replace - -**Migration Commands:** -```bash -# ThemeMode -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/themeModeProvider/appThemeModeProvider/g' {} + - -# Locale -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/localeProvider/appLocaleProvider/g' {} + -``` - ---- - -### Phase 5: Complex Providers (6-8 hours) 🔴 - -- [ ] `conversationsProvider` (complex caching) -- [ ] `appSettingsProvider` (large class, high usage) -- [ ] `chatMessagesProvider` (2500+ lines, very complex) - -**File:** Various -**Risk:** 🔴 High -**Strategy:** One at a time, extensive testing - ---- - -### Phase 6: Internal Providers (1-2 hours) 🟢 - -- [ ] `_wasOfflineProvider` (private) -- [ ] `_conversationsCacheTimestampProvider` (private) - -**File:** Various -**Risk:** 🟢 Low (internal use only) - ---- - -## Standard Migration Process - -### 1. Preparation -```bash -git status # Clean state -flutter pub get # Dependencies -flutter test # Baseline -grep -r "providerName" lib/ # Usage count -``` - -### 2. Code Changes - -**For Notifier Classes:** -```dart -// BEFORE -final myProvider = NotifierProvider(MyNotifier.new); - -class MyNotifier extends Notifier { - @override - String build() => ''; - void set(String value) => state = value; -} - -// AFTER -@riverpod -class My extends _$My { - @override - String build() => ''; - void set(String value) => state = value; -} -// Generated: myProvider -``` - -**For FutureProvider Functions:** -```dart -// BEFORE -final myProvider = FutureProvider((ref) async { - return await fetchData(); -}); - -// AFTER -@riverpod -Future my(MyRef ref) async { - return await fetchData(); -} -// Generated: myProvider -``` - -**For Family Providers:** -```dart -// BEFORE -final myProvider = FutureProvider.family((ref, id) async { - return await fetchData(id); -}); - -// AFTER -@riverpod -Future my(MyRef ref, int id) async { - return await fetchData(id); -} -// Usage: ref.watch(myProvider(123)) -``` - -### 3. Generate Code -```bash -dart run build_runner build --delete-conflicting-outputs -``` - -### 4. Verify -```bash -flutter analyze -dart run custom_lint -flutter test -flutter run # Manual test -``` - -### 5. Commit -```bash -git add . -git commit -m "refactor: migrate myProvider to @riverpod - -- Converted MyNotifier to My -- Provider name unchanged: myProvider -- Tests passing ✅" -``` - ---- - -## Quick Commands - -### Build Runner -```bash -# One-time build -dart run build_runner build --delete-conflicting-outputs - -# Watch mode (recommended) -dart run build_runner watch --delete-conflicting-outputs - -# Clean -dart run build_runner clean -``` - -### Testing -```bash -# All checks -flutter analyze && dart run custom_lint && flutter test - -# With coverage -flutter test --coverage - -# Single file -flutter test test/path/to/test.dart -``` - -### Finding Usages -```bash -# Count usages -grep -r "providerName" lib/ --exclude="*.g.dart" | wc -l - -# Find files -grep -r "providerName" lib/ --exclude="*.g.dart" -l - -# Show context -grep -r "providerName" lib/ --exclude="*.g.dart" -C 2 -``` - -### Bulk Replace -```bash -# Preview (dry run) -grep -r "oldName" lib/ --exclude="*.g.dart" - -# Replace (macOS) -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i '' 's/oldName/newName/g' {} + - -# Replace (Linux) -find lib -type f -name "*.dart" ! -name "*.g.dart" -exec sed -i 's/oldName/newName/g' {} + -``` - ---- - -## Common Issues & Solutions - -### Issue: "_$ClassName not found" -```bash -# Run build_runner -dart run build_runner build --delete-conflicting-outputs -``` - -### Issue: "Provider name conflict" -```dart -// Rename class to avoid conflicts -@riverpod -class AppThemeMode extends _$AppThemeMode { // Not 'ThemeMode' - // ... -} -``` - -### Issue: "Build runner errors" -```bash -# Clean and rebuild -flutter clean -flutter pub get -dart run build_runner clean -dart run build_runner build --delete-conflicting-outputs -``` - -### Issue: "Tests failing" -```dart -// Check if provider name changed -// Update imports: -// OLD: import 'old_file.dart'; -// NEW: import 'new_file.dart'; (if moved) -``` - ---- - -## Risk Levels - -| Symbol | Risk | Description | Strategy | -|--------|------|-------------|----------| -| 🟢 | Low | Simple, low usage | Batch migrate, quick test | -| 🟡 | Medium | Breaking changes or moderate complexity | Migrate individually, thorough test | -| 🔴 | High | Complex, high usage | Extensive planning, staging deployment | - ---- - -## Success Metrics - -After each migration: -- ✅ Code compiles without errors -- ✅ No lint warnings -- ✅ All tests pass -- ✅ Manual test successful -- ✅ Performance unchanged - -After each phase: -- ✅ All phase targets complete -- ✅ Full test suite passes -- ✅ Integration tests pass -- ✅ Multi-platform verification - ---- - -## Rollback - -### Single Provider -```bash -git revert HEAD -dart run build_runner build --delete-conflicting-outputs -flutter test -``` - -### Multiple Commits -```bash -git log --oneline -git reset --hard -dart run build_runner build --delete-conflicting-outputs -flutter test -``` - ---- - -## Phase Progression - -``` -Phase 1 (Simple) ──→ Phase 2 (Functions) ──→ Phase 3 (Family) - ↓ -Phase 6 (Private) ←── Phase 5 (Complex) ←── Phase 4 (Breaking) -``` - -**Recommendation:** Complete phases in order. Don't skip ahead to complex providers. - ---- - -## Next Steps - -1. **Review** the detailed plan: `RIVERPOD_PRIORITY2_PLAN.md` -2. **Start** with Phase 1: Simple notifiers -3. **Test** after each migration -4. **Commit** frequently -5. **Document** any issues or learnings - ---- - -## References - -- **Detailed Plan:** [RIVERPOD_PRIORITY2_PLAN.md](./RIVERPOD_PRIORITY2_PLAN.md) -- **Example Guide:** [docs/riverpod_migration_example.md](./docs/riverpod_migration_example.md) -- **Analysis:** [RIVERPOD_3_ANALYSIS.md](./RIVERPOD_3_ANALYSIS.md) -- **Priority 1:** [RIVERPOD_PRIORITY1_COMPLETED.md](./RIVERPOD_PRIORITY1_COMPLETED.md) - ---- - -**Last Updated:** September 30, 2025 -**Status:** Ready for Implementation 🚀 diff --git a/RIVERPOD_PRIORITY2_TRACKER.md b/RIVERPOD_PRIORITY2_TRACKER.md deleted file mode 100644 index 5c74c63..0000000 --- a/RIVERPOD_PRIORITY2_TRACKER.md +++ /dev/null @@ -1,402 +0,0 @@ -# Priority 2 Migration Progress Tracker - -**Track your progress through the Priority 2 migration** - -Last Updated: September 30, 2025 - ---- - -## Overall Progress - -``` -Total: 39 providers -├── Phase 1: 0/10 providers ░░░░░░░░░░ 0% -├── Phase 2: 0/15 providers ░░░░░░░░░░ 0% -├── Phase 3: 0/4 providers ░░░░░░░░░░ 0% -├── Phase 4: 0/2 providers ░░░░░░░░░░ 0% -├── Phase 5: 0/3 providers ░░░░░░░░░░ 0% -└── Phase 6: 0/2 providers ░░░░░░░░░░ 0% - -Overall: 0/36 providers (0%) -``` - -**Note:** 3 providers already use @riverpod and don't need migration: -- ✅ `activeConversationProvider` -- ✅ `socketConnectionStreamProvider` -- ✅ `conversationStreamProvider` - ---- - -## Phase 1: Simple Notifiers 🟢 - -**Status:** Not Started -**Progress:** 0/10 (0%) -**Estimated Time:** 4-6 hours -**Files Modified:** 0/5 - -### Providers - -| # | Provider | Class | File | Status | Notes | -|---|----------|-------|------|--------|-------| -| 1 | `searchQueryProvider` | `SearchQuery` | `app_providers.dart` | ⬜ Not Started | | -| 2 | `selectedModelProvider` | `SelectedModel` | `app_providers.dart` | ⬜ Not Started | | -| 3 | `isManualModelSelectionProvider` | `IsManualModelSelection` | `app_providers.dart` | ⬜ Not Started | | -| 4 | `reviewerModeProvider` | `ReviewerMode` | `app_providers.dart` | ⬜ Not Started | | -| 5 | `batchModeProvider` | `BatchMode` | `message_batch_service.dart` | ⬜ Not Started | | -| 6 | `isLoadingConversationProvider` | `IsLoadingConversation` | `chat_providers.dart` | ⬜ Not Started | | -| 7 | `prefilledInputTextProvider` | `PrefilledInputText` | `chat_providers.dart` | ⬜ Not Started | | -| 8 | `inputFocusTriggerProvider` | `InputFocusTrigger` | `chat_providers.dart` | ⬜ Not Started | | -| 9 | `composerHasFocusProvider` | `ComposerHasFocus` | `chat_providers.dart` | ⬜ Not Started | | -| 10 | `reducedMotionProvider` | `ReducedMotion` | `animation_service.dart` | ⬜ Not Started | | - -### Checklist - -- [ ] All providers migrated -- [ ] Build runner completed successfully -- [ ] All tests passing -- [ ] Manual testing completed -- [ ] No lint errors -- [ ] Changes committed - ---- - -## Phase 2: FutureProvider Functions 🟢 - -**Status:** Not Started -**Progress:** 0/15 (0%) -**Estimated Time:** 6-8 hours -**Files Modified:** 0/5 - -### Batch 1: Core Providers - -| # | Provider | File | Status | Notes | -|---|----------|------|--------|-------| -| 1 | `serverConfigsProvider` | `app_providers.dart` | ⬜ Not Started | | -| 2 | `activeServerProvider` | `app_providers.dart` | ⬜ Not Started | | -| 3 | `currentUserProvider` | `app_providers.dart` | ⬜ Not Started | | -| 4 | `modelsProvider` | `app_providers.dart` | ⬜ Not Started | | -| 5 | `defaultModelProvider` | `app_providers.dart` | ⬜ Not Started | | - -### Batch 2: Settings & User Data - -| # | Provider | File | Status | Notes | -|---|----------|------|--------|-------| -| 6 | `userSettingsProvider` | `app_providers.dart` | ⬜ Not Started | | -| 7 | `conversationSuggestionsProvider` | `app_providers.dart` | ⬜ Not Started | | -| 8 | `userPermissionsProvider` | `app_providers.dart` | ⬜ Not Started | | - -### Batch 3: Resources - -| # | Provider | File | Status | Notes | -|---|----------|------|--------|-------| -| 9 | `foldersProvider` | `app_providers.dart` | ⬜ Not Started | | -| 10 | `userFilesProvider` | `app_providers.dart` | ⬜ Not Started | | -| 11 | `knowledgeBasesProvider` | `app_providers.dart` | ⬜ Not Started | | -| 12 | `availableVoicesProvider` | `app_providers.dart` | ⬜ Not Started | | -| 13 | `imageModelsProvider` | `app_providers.dart` | ⬜ Not Started | | - -### Batch 4: Feature Providers - -| # | Provider | File | Status | Notes | -|---|----------|------|--------|-------| -| 14 | `promptsListProvider` | `prompts_providers.dart` | ⬜ Not Started | | -| 15 | `toolsListProvider` | `tools_providers.dart` | ⬜ Not Started | | - -### Checklist - -- [ ] Batch 1 complete (5 providers) -- [ ] Batch 2 complete (3 providers) -- [ ] Batch 3 complete (5 providers) -- [ ] Batch 4 complete (2 providers) -- [ ] All tests passing -- [ ] Manual testing completed -- [ ] Changes committed - ---- - -## Phase 3: Family Providers 🟡 - -**Status:** Not Started -**Progress:** 0/4 (0%) -**Estimated Time:** 2-3 hours -**Files Modified:** 0/3 - -### Providers - -| # | Provider | Parameters | File | Status | Notes | -|---|----------|------------|------|--------|-------| -| 1 | `loadConversationProvider` | `String id` | `app_providers.dart` | ⬜ Not Started | | -| 2 | `serverSearchProvider` | `String query` | `app_providers.dart` | ⬜ Not Started | | -| 3 | `fileContentProvider` | `String fileId` | `app_providers.dart` | ⬜ Not Started | | -| 4 | `voiceInputAvailableProvider` | (none) | `voice_input_service.dart` | ⬜ Not Started | | - -### Checklist - -- [ ] All providers migrated -- [ ] Parameter types verified -- [ ] Usage patterns tested -- [ ] All tests passing -- [ ] Changes committed - ---- - -## Phase 4: Name-Changing Providers ⚠️ - -**Status:** Not Started -**Progress:** 0/2 (0%) -**Estimated Time:** 4-6 hours -**Files Modified:** 0/1 - -### Providers - -| # | Old Name | New Name | Class | Usages | Status | Notes | -|---|----------|----------|-------|--------|--------|-------| -| 1 | `themeModeProvider` | `appThemeModeProvider` | `AppThemeMode` | ~10-15 | ⬜ Not Started | Breaking change | -| 2 | `localeProvider` | `appLocaleProvider` | `AppLocale` | ~8-12 | ⬜ Not Started | Breaking change | - -### Checklist - -- [ ] `themeModeProvider` migrated - - [ ] Class renamed to `AppThemeMode` - - [ ] Generated code verified - - [ ] All usages found (run: `grep -r "themeModeProvider" lib/`) - - [ ] Bulk replace completed - - [ ] Tests passing - - [ ] Manual testing on iOS - - [ ] Manual testing on Android -- [ ] `localeProvider` migrated - - [ ] Class renamed to `AppLocale` - - [ ] Generated code verified - - [ ] All usages found (run: `grep -r "localeProvider" lib/`) - - [ ] Bulk replace completed - - [ ] Tests passing - - [ ] Manual testing on iOS - - [ ] Manual testing on Android -- [ ] Integration testing -- [ ] Changes committed with BREAKING CHANGE message - ---- - -## Phase 5: Complex Providers 🔴 - -**Status:** Not Started -**Progress:** 0/3 (0%) -**Estimated Time:** 6-8 hours -**Files Modified:** 0/3 - -### Providers - -| # | Provider | Complexity | Lines | Usages | Status | Notes | -|---|----------|------------|-------|--------|--------|-------| -| 1 | `conversationsProvider` | High | ~300 | ~10-15 | ⬜ Not Started | Complex caching | -| 2 | `appSettingsProvider` | High | ~100 | ~20-30 | ⬜ Not Started | Large class, high usage | -| 3 | `chatMessagesProvider` | Very High | ~2500 | ~15-20 | ⬜ Not Started | Extremely complex | - -### `conversationsProvider` Checklist - -- [ ] Code review completed -- [ ] Test plan created -- [ ] Migration completed -- [ ] Build runner successful -- [ ] Unit tests passing -- [ ] Integration tests passing -- [ ] Manual testing: - - [ ] List conversations - - [ ] Create conversation - - [ ] Delete conversation - - [ ] Search conversations - - [ ] Folder operations -- [ ] Performance check (DevTools) -- [ ] Committed - -### `appSettingsProvider` Checklist - -- [ ] Code review completed -- [ ] Test plan created -- [ ] Migration completed -- [ ] Build runner successful -- [ ] Unit tests passing -- [ ] Manual testing: - - [ ] Read settings - - [ ] Update settings - - [ ] Persist settings - - [ ] Default model selection - - [ ] Theme changes - - [ ] Voice settings -- [ ] Committed - -### `chatMessagesProvider` Checklist - -- [ ] Code review completed (entire 2500 lines!) -- [ ] All dependencies documented -- [ ] Test plan created (comprehensive) -- [ ] Migration completed -- [ ] Build runner successful -- [ ] Unit tests passing -- [ ] Integration tests passing -- [ ] Manual testing: - - [ ] Load conversation - - [ ] Send message - - [ ] Receive message - - [ ] Stream processing - - [ ] Tool calls - - [ ] Attachments - - [ ] Error handling - - [ ] Typing indicators - - [ ] Message regeneration - - [ ] Batch operations -- [ ] Performance check (memory, rebuilds) -- [ ] Memory leak check -- [ ] Committed -- [ ] Team review - ---- - -## Phase 6: Internal Providers 🟢 - -**Status:** Not Started -**Progress:** 0/2 (0%) -**Estimated Time:** 1-2 hours -**Files Modified:** 0/2 - -### Providers - -| # | Provider | Visibility | File | Status | Notes | -|---|----------|------------|------|--------|-------| -| 1 | `_wasOfflineProvider` | Private | `offline_indicator.dart` | ⬜ Not Started | Internal only | -| 2 | `_conversationsCacheTimestampProvider` | Private | `app_providers.dart` | ⬜ Not Started | Internal only | - -### Checklist - -- [ ] Both providers migrated -- [ ] Tests passing -- [ ] Changes committed - ---- - -## Testing Checklist - -### Per-Provider Testing - -After each provider migration: - -- [ ] Compilation check: `flutter analyze` -- [ ] Lint check: `dart run custom_lint` -- [ ] Unit tests: `flutter test` -- [ ] Manual smoke test: `flutter run` - -### Phase Testing - -After each phase: - -- [ ] Full test suite: `flutter test --coverage` -- [ ] Integration testing (all major flows) -- [ ] iOS simulator testing -- [ ] Android emulator testing -- [ ] Performance check (DevTools) -- [ ] Memory check (DevTools) - -### Final Testing - -After all phases: - -- [ ] Full regression testing -- [ ] All platforms tested -- [ ] Performance benchmarked -- [ ] Memory profiled -- [ ] Code coverage checked -- [ ] Documentation updated - ---- - -## Issues Log - -Track any issues encountered during migration: - -| Date | Provider | Issue | Solution | Time Lost | -|------|----------|-------|----------|-----------| -| | | | | | - ---- - -## Notes & Learnings - -Document any insights or patterns discovered: - -### Patterns Discovered - -- - -### Common Mistakes to Avoid - -- - -### Tips & Tricks - -- - ---- - -## Time Tracking - -| Phase | Estimated | Actual | Difference | Notes | -|-------|-----------|--------|------------|-------| -| Phase 1 | 4-6h | | | | -| Phase 2 | 6-8h | | | | -| Phase 3 | 2-3h | | | | -| Phase 4 | 4-6h | | | | -| Phase 5 | 6-8h | | | | -| Phase 6 | 1-2h | | | | -| **Total** | **23-33h** | | | | - ---- - -## Commit Log - -Track commits for easy rollback: - -| Date | Phase | Providers | Commit Hash | Notes | -|------|-------|-----------|-------------|-------| -| | | | | | - ---- - -## Status Legend - -- ⬜ Not Started -- 🔄 In Progress -- ✅ Complete -- ⚠️ Blocked -- ❌ Failed/Rolled Back - ---- - -## Quick Commands Reference - -```bash -# Start working -git status -flutter pub get -dart run build_runner watch --delete-conflicting-outputs - -# After migration -flutter analyze && dart run custom_lint && flutter test - -# Find usages -grep -r "providerName" lib/ --exclude="*.g.dart" | wc -l - -# Commit -git add . -git commit -m "refactor: migrate providerName to @riverpod" -``` - ---- - -**Remember:** -1. ✅ Test after each migration -2. ✅ Commit frequently -3. ✅ Take breaks between complex providers -4. ✅ Ask for help if stuck -5. ✅ Document any issues or learnings - -**Good luck! 🚀** diff --git a/RIVERPOD_QUICKSTART.md b/RIVERPOD_QUICKSTART.md deleted file mode 100644 index 32cca1a..0000000 --- a/RIVERPOD_QUICKSTART.md +++ /dev/null @@ -1,279 +0,0 @@ -# Riverpod 3.0 Quick Start Guide - -## Immediate Actions (30 minutes) - -### Step 1: Add riverpod_lint (5 minutes) - -1. **Update `pubspec.yaml`:** - -```bash -cd /Users/cogwheel/Documents/conduit -``` - -Add to `dev_dependencies` section: - -```yaml -dev_dependencies: - # ... existing dependencies ... - riverpod_lint: ^3.0.0 - custom_lint: ^0.8.0 -``` - -2. **Install packages:** - -```bash -flutter pub get -``` - -3. **Update `analysis_options.yaml`:** - -Add this at the top level (same level as `linter:`): - -```yaml -analyzer: - plugins: - - custom_lint -``` - -Full file should look like: - -```yaml -include: package:flutter_lints/flutter.yaml - -analyzer: - plugins: - - custom_lint - -linter: - rules: - avoid_print: true -``` - -4. **Run the linter:** - -```bash -dart run custom_lint -``` - -This will show Riverpod-specific issues if any exist. - ---- - -### Step 2: Fix Any Linter Issues (10 minutes) - -The linter will identify issues like: - -- ❌ Using `ref` outside of widgets/providers -- ❌ Missing `ref.mounted` checks -- ❌ Incorrect provider usage patterns - -**Example Fix:** - -If you see: `"ref should not be used outside of a widget/provider"` - -```dart -// ❌ Bad -class MyService { - void doSomething(WidgetRef ref) { // ref as parameter - ref.read(someProvider); - } -} - -// ✅ Good -@riverpod -class MyService extends _$MyService { - @override - void build() {} - - void doSomething() { - ref.read(someProvider); // ref is available in Notifier - } -} -``` - ---- - -### Step 3: Update AGENTS.md (5 minutes) - -Replace the state management section in `AGENTS.md`: - -**Find (around line 166):** - -```markdown -### State Management -* **Built-in Solutions:** Prefer Flutter's built-in state management solutions. - Do not use a third-party package unless explicitly requested. -``` - -**Replace with:** - -```markdown -### State Management -* **Riverpod 3.0:** This project uses Riverpod 3.0 for state management. -* **Code Generation:** Always use `@riverpod` annotation with code generation - for new providers. See existing examples in `lib/core/providers/`. -* **Notifier Classes:** Use `Notifier` and `AsyncNotifier` for mutable state: - ```dart - @riverpod - class Counter extends _$Counter { - @override - int build() => 0; - - void increment() => state++; - } - ``` -* **Provider Functions:** Use `@riverpod` functions for computed/derived state: - ```dart - @riverpod - int doubled(DoubledRef ref) { - final count = ref.watch(counterProvider); - return count * 2; - } - ``` -* **Keep Alive:** Use `@Riverpod(keepAlive: true)` for singletons: - ```dart - @Riverpod(keepAlive: true) - class AuthManager extends _$AuthManager { ... } - ``` -* **Async Safety:** Always check `ref.mounted` before state updates in async ops: - ```dart - Future loadData() async { - final data = await fetchData(); - if (!ref.mounted) return; // ✅ Prevent updates after disposal - state = data; - } - ``` -* **Automatic Retry:** Providers automatically retry on failure with exponential - backoff. Customize if needed: - ```dart - @riverpod - Future myData(MyDataRef ref) async { - ref.onDispose(() { - // Cleanup - }); - return await fetchData(); - } - ``` -* **Lint Rules:** Use `custom_lint` with `riverpod_lint` to catch common mistakes. - Run `dart run custom_lint` before committing. -``` - ---- - -## Validation (10 minutes) - -### 1. Run All Checks - -```bash -# Code generation (if needed) -dart run build_runner build --delete-conflicting-outputs - -# Custom lint -dart run custom_lint - -# Standard analysis -flutter analyze - -# Tests -flutter test -``` - -### 2. Expected Results - -All should pass ✅ without new errors. You may see some warnings from `riverpod_lint` which are informational. - -### 3. Common Warnings and Fixes - -#### Warning: "Provider could use autoDispose" - -```dart -// Current -@riverpod -Future myData(MyDataRef ref) async { - return await fetch(); -} - -// Suggested (if data is short-lived) -@riverpod -Future myData(MyDataRef ref) async { - ref.cacheFor(const Duration(minutes: 5)); // Auto-dispose after 5 min - return await fetch(); -} -``` - -#### Warning: "Missing ref.mounted check" - -```dart -// Current -Future save() async { - await someAsyncOp(); - state = newValue; // ⚠️ Might be disposed -} - -// Fixed -Future save() async { - await someAsyncOp(); - if (!ref.mounted) return; // ✅ - state = newValue; -} -``` - ---- - -## Next Steps (Optional) - -After completing the quick start, you can: - -1. **Read the full analysis:** See `RIVERPOD_3_ANALYSIS.md` -2. **Start migration:** Follow Phase 2 in the analysis document -3. **Add provider docs:** Document provider purposes with dartdoc - ---- - -## Troubleshooting - -### Issue: `custom_lint` not found - -```bash -# Reinstall -flutter pub get -flutter pub global activate custom_lint -``` - -### Issue: Analysis takes too long - -```bash -# Restart Dart analysis server -# In VS Code: Cmd+Shift+P -> "Dart: Restart Analysis Server" -# In Android Studio: File -> Invalidate Caches / Restart -``` - -### Issue: Generated files out of sync - -```bash -# Clean and rebuild -flutter clean -flutter pub get -dart run build_runner build --delete-conflicting-outputs -``` - ---- - -## Benefits You'll See Immediately - -After adding `riverpod_lint`: - -✅ **Compile-time safety** - Catch errors before runtime -✅ **Better autocomplete** - IDE knows provider types -✅ **Quick fixes** - Automatic solutions for common issues -✅ **Consistency checks** - Enforced best practices -✅ **Refactoring confidence** - Compiler catches all usages - ---- - -## Questions? - -Refer to: -- Full analysis: `RIVERPOD_3_ANALYSIS.md` -- Official docs: https://riverpod.dev -- Linter docs: https://riverpod.dev/docs/concepts/about_riverpod_lint diff --git a/RIVERPOD_SUMMARY.md b/RIVERPOD_SUMMARY.md deleted file mode 100644 index 8a4a2de..0000000 --- a/RIVERPOD_SUMMARY.md +++ /dev/null @@ -1,327 +0,0 @@ -# Riverpod 3.0 Review - Executive Summary - -## Quick Assessment - -**Current State:** ✅ **Well-Aligned with Riverpod 3.0** -**Grade:** B+ (85/100) -**Recommendation:** Implement Priority 1 changes immediately, schedule Priority 2-3 for next sprint - ---- - -## Three Key Documents - -1. **`RIVERPOD_3_ANALYSIS.md`** - Full technical analysis with examples -2. **`RIVERPOD_QUICKSTART.md`** - 30-minute setup guide for immediate improvements -3. **`docs/riverpod_migration_example.md`** - Detailed migration examples with code - ---- - -## What's Working Well ✅ - -1. **Already using Riverpod 3.0** - Latest packages installed -2. **No legacy providers** - No `StateProvider`, `StateNotifierProvider`, or `ChangeNotifierProvider` -3. **Code generation in use** - `@Riverpod` annotation used for complex providers -4. **Modern patterns** - `Notifier`, `AsyncNotifier`, and proper lifecycle management -5. **Safety checks** - `ref.mounted` used in async operations -6. **Keep alive** - Proper singleton management with `@Riverpod(keepAlive: true)` - ---- - -## What Needs Improvement ⚠️ - -### Priority 1: Critical (30 minutes, low risk) - -**Add `riverpod_lint` for compile-time safety** - -```bash -# 1. Update pubspec.yaml -flutter pub add --dev riverpod_lint custom_lint - -# 2. Update analysis_options.yaml -# Add: analyzer.plugins: - custom_lint - -# 3. Run -dart run custom_lint -flutter analyze -``` - -**Impact:** Catch Riverpod mistakes at compile-time -**Effort:** 30 minutes -**Risk:** 🟢 None - -### Priority 2: Important (1-2 weeks, medium risk) - -**Standardize on code generation** - -- Convert ~30-40 manual `NotifierProvider` declarations to `@riverpod` -- Benefits: Consistency, less boilerplate, better IDE support -- See `docs/riverpod_migration_example.md` for step-by-step guide - -**Impact:** Improved maintainability and consistency -**Effort:** 16-24 hours -**Risk:** 🟡 Medium (requires testing) - -### Priority 3: Nice-to-have (optional) - -- Optimize `FutureProvider.family` patterns -- Improve `AsyncValue` handling (use `when` instead of `maybeWhen`) -- Add provider documentation - ---- - -## Immediate Action Items - -### Today (30 minutes) - -1. ✅ **Add linter packages:** - ```bash - cd /Users/cogwheel/Documents/conduit - flutter pub add --dev riverpod_lint custom_lint - ``` - -2. ✅ **Update analysis_options.yaml:** - ```yaml - analyzer: - plugins: - - custom_lint - ``` - -3. ✅ **Run checks:** - ```bash - dart run custom_lint - flutter analyze - ``` - -4. ✅ **Update AGENTS.md:** - - Replace state management section with Riverpod-specific guidelines - - See `RIVERPOD_QUICKSTART.md` for exact text - -### This Week (2-3 hours) - -1. ⚠️ **Fix any issues found by `riverpod_lint`** - - Add missing `ref.mounted` checks - - Fix incorrect provider usage - -2. ⚠️ **Document providers:** - - Add dartdoc comments to all providers - - Explain purpose and usage - -### Next Sprint (16-24 hours) - -1. 🔵 **Migrate simple providers:** - - Start with leaf nodes (no dependents) - - Use `docs/riverpod_migration_example.md` as guide - - Test thoroughly after each migration - -2. 🔵 **Update tests:** - - Verify all tests pass after migration - - Add new tests where coverage is lacking - ---- - -## Files to Modify - -### Immediate Changes (Priority 1) - -- ✅ `pubspec.yaml` - Add `riverpod_lint` and `custom_lint` -- ✅ `analysis_options.yaml` - Add custom_lint plugin -- ✅ `AGENTS.md` - Update state management section - -### Future Changes (Priority 2) - -- ⚠️ `lib/core/providers/app_providers.dart` - ~15 providers to migrate -- ⚠️ `lib/features/chat/providers/chat_providers.dart` - ~10 providers to migrate -- ⚠️ `lib/features/auth/providers/unified_auth_providers.dart` - Review AsyncValue usage -- ⚠️ Other provider files across features - ---- - -## Expected Benefits - -### Short-term (after Priority 1) - -- ✅ Catch errors at compile-time instead of runtime -- ✅ Better IDE autocomplete and navigation -- ✅ Automatic quick-fixes for common mistakes -- ✅ Enforced best practices - -### Long-term (after Priority 2) - -- ✅ Consistent codebase (easier onboarding) -- ✅ Less boilerplate (~20% reduction) -- ✅ Better refactoring support -- ✅ Easier to add features (family, autoDispose) -- ✅ Improved developer experience - ---- - -## Risk Assessment - -### Priority 1 Changes - -**Risk:** 🟢 **Low** -- Adding linter has no runtime impact -- Only improves static analysis -- Can be reverted easily if issues arise - -### Priority 2 Changes - -**Risk:** 🟡 **Medium** -- Requires updating provider usage across codebase -- Needs thorough testing -- Should be done incrementally -- Can be rolled back per-provider if needed - -**Mitigation:** -- Migrate one provider at a time -- Run full test suite after each migration -- Use feature flags for risky changes -- Keep old provider as deprecated alias during transition - ---- - -## Performance Impact - -### Build Time - -- **Before:** ~30-45 seconds (clean build) -- **After:** ~35-50 seconds (clean build) -- **Impact:** +5-10 seconds due to code generation -- **Mitigation:** Use `watch` mode during development - -### Runtime Performance - -- **Impact:** Neutral to slightly positive -- Code generation produces optimized code -- Better tree-shaking with generated providers -- No additional runtime dependencies - -### Developer Experience - -- **Before:** Manual provider declarations, occasional mistakes -- **After:** Auto-generated providers, compile-time safety -- **Impact:** ✅ Significantly better - ---- - -## Testing Strategy - -### Before Each Change - -```bash -# 1. Backup -git checkout -b riverpod-migration-backup - -# 2. Run tests -flutter test - -# 3. Verify app works -flutter run --release -``` - -### After Each Change - -```bash -# 1. Regenerate code -dart run build_runner build --delete-conflicting-outputs - -# 2. Run linter -dart run custom_lint - -# 3. Analyze -flutter analyze - -# 4. Test -flutter test - -# 5. Manual testing -flutter run -``` - ---- - -## Success Metrics - -Track these metrics before and after migration: - -1. **Code coverage:** Should remain same or improve -2. **Build time:** May increase slightly (acceptable) -3. **Lines of code:** Should decrease by ~10-20% -4. **Linter warnings:** Should decrease significantly -5. **Developer velocity:** Should improve after learning curve - ---- - -## Support & Resources - -### Documentation - -- 📄 Full analysis: `RIVERPOD_3_ANALYSIS.md` -- 🚀 Quick start: `RIVERPOD_QUICKSTART.md` -- 📝 Examples: `docs/riverpod_migration_example.md` - -### External Resources - -- [Official Riverpod Docs](https://riverpod.dev) -- [Migration Guide](https://riverpod.dev/docs/3.0_migration) -- [Riverpod Lint](https://riverpod.dev/docs/concepts/about_riverpod_lint) - -### Questions? - -Common questions answered in the full documentation: - -- Q: Will this break existing code? - - A: No for Priority 1, minimal risk for Priority 2 with proper testing - -- Q: How long will migration take? - - A: 30 min for Priority 1, 16-24 hours for Priority 2 (can be spread out) - -- Q: What if we find issues? - - A: Each provider can be rolled back independently - -- Q: Do we need to migrate everything at once? - - A: No! Can be done incrementally, one provider at a time - ---- - -## Recommendation - -### Immediate (This Week) - -✅ **DO:** Implement Priority 1 changes -- Low risk, high reward -- 30 minutes of work -- Immediate benefits - -### Short-term (Next Sprint) - -⚠️ **CONSIDER:** Start Priority 2 migration -- Medium risk, high reward -- Plan for 16-24 hours over 2-3 weeks -- Migrate incrementally - -### Long-term (Future Sprints) - -🔵 **OPTIONAL:** Priority 3 optimizations -- Low risk, medium reward -- Nice-to-have improvements -- Can be done as time permits - ---- - -## Conclusion - -The Conduit project is **already using Riverpod 3.0 correctly** for the most part. The main improvements are: - -1. **Add static analysis** (`riverpod_lint`) for compile-time safety -2. **Standardize on code generation** for consistency -3. **Optimize patterns** where applicable - -The migration can be done **incrementally with minimal risk**. Priority 1 changes should be implemented immediately (30 minutes), while Priority 2 can be planned for the next sprint. - -**Overall assessment:** 🟢 Good foundation, ready for optimization - ---- - -*Last updated: September 30, 2025* -*Codebase version: 1.1.6+20* diff --git a/docs/riverpod_migration_example.md b/docs/riverpod_migration_example.md deleted file mode 100644 index 0740d67..0000000 --- a/docs/riverpod_migration_example.md +++ /dev/null @@ -1,474 +0,0 @@ -# Riverpod Migration Example - -## Example: Migrating SearchQueryNotifier - -This example shows step-by-step how to migrate a simple provider from manual declaration to code generation. - ---- - -## Current Code (Manual NotifierProvider) - -**File:** `lib/core/providers/app_providers.dart` (lines ~1200-1209) - -```dart -// Manual provider declaration -final searchQueryProvider = NotifierProvider( - SearchQueryNotifier.new, -); - -class SearchQueryNotifier extends Notifier { - @override - String build() => ''; - - void set(String query) => state = query; -} -``` - -**Usage in code:** - -```dart -// Reading value -final query = ref.watch(searchQueryProvider); - -// Updating value -ref.read(searchQueryProvider.notifier).set('new search'); -``` - ---- - -## Migrated Code (Code Generation) - -**File:** `lib/core/providers/app_providers.dart` - -### Step 1: Add annotation and extend generated class - -```dart -@riverpod -class SearchQuery extends _$SearchQuery { // Note: Class name changes - @override - String build() => ''; - - void set(String query) => state = query; -} -``` - -### Step 2: Run build_runner - -```bash -dart run build_runner build --delete-conflicting-outputs -``` - -This generates `app_providers.g.dart` with: - -```dart -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$searchQueryHash() => r'...'; - -/// See also [SearchQuery]. -@ProviderFor(SearchQuery) -final searchQueryProvider = AutoDisposeNotifierProvider.internal( - SearchQuery.new, - name: r'searchQueryProvider', - debugGetCreateSourceHash: _$searchQueryHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$SearchQuery = AutoDisposeNotifier; -``` - -### Step 3: Update imports (if needed) - -No changes needed! The provider name stays the same: `searchQueryProvider` - -### Step 4: Usage remains identical - -```dart -// Reading value - NO CHANGE -final query = ref.watch(searchQueryProvider); - -// Updating value - NO CHANGE -ref.read(searchQueryProvider.notifier).set('new search'); -``` - ---- - -## Benefits of Migration - -### Before (Manual) - -```dart -// 8 lines of boilerplate -final searchQueryProvider = NotifierProvider( - SearchQueryNotifier.new, -); - -class SearchQueryNotifier extends Notifier { - @override - String build() => ''; - - void set(String query) => state = query; -} -``` - -**Issues:** -- ❌ More verbose -- ❌ Need to manually create provider variable -- ❌ Easy to forget to update provider declaration when class changes -- ❌ No automatic dependency tracking - -### After (Code Generation) - -```dart -// 6 lines, cleaner -@riverpod -class SearchQuery extends _$SearchQuery { - @override - String build() => ''; - - void set(String query) => state = query; -} -``` - -**Benefits:** -- ✅ Less boilerplate -- ✅ Provider auto-generated -- ✅ Type-safe -- ✅ Better IDE support -- ✅ Automatic dependency tracking -- ✅ Easier to add `family` or modifiers later - ---- - -## More Complex Example: ThemeModeNotifier - -### Current Code (Manual) - -```dart -final themeModeProvider = NotifierProvider( - ThemeModeNotifier.new, -); - -class ThemeModeNotifier extends Notifier { - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} -``` - -### Migrated Code (Code Generation) - -```dart -@riverpod -class AppThemeMode extends _$AppThemeMode { // Renamed to avoid conflict with ThemeMode enum - late final OptimizedStorageService _storage; - - @override - ThemeMode build() { - _storage = ref.watch(optimizedStorageServiceProvider); - final storedMode = _storage.getThemeMode(); - if (storedMode != null) { - return ThemeMode.values.firstWhere( - (e) => e.toString() == storedMode, - orElse: () => ThemeMode.system, - ); - } - return ThemeMode.system; - } - - void setTheme(ThemeMode mode) { - state = mode; - _storage.setThemeMode(mode.toString()); - } -} - -// Generated provider will be: appThemeModeProvider -``` - -**Important:** Class renamed from `ThemeModeNotifier` to `AppThemeMode` to avoid name conflict with the `ThemeMode` enum from Flutter. - -### Update Usage - -```dart -// Before -final mode = ref.watch(themeModeProvider); -ref.read(themeModeProvider.notifier).setTheme(ThemeMode.dark); - -// After -final mode = ref.watch(appThemeModeProvider); -ref.read(appThemeModeProvider.notifier).setTheme(ThemeMode.dark); -``` - -**Migration tool can help:** - -```bash -# Find all usages -grep -r "themeModeProvider" lib/ - -# Replace with IDE refactoring or: -find lib -type f -name "*.dart" -exec sed -i '' 's/themeModeProvider/appThemeModeProvider/g' {} + -``` - ---- - -## Provider Function Example - -### FutureProvider to @riverpod function - -**Before:** - -```dart -final serverConfigsProvider = FutureProvider>((ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -}); -``` - -**After:** - -```dart -@riverpod -Future> serverConfigs(ServerConfigsRef ref) async { - final storage = ref.watch(optimizedStorageServiceProvider); - return storage.getServerConfigs(); -} - -// Generated provider name: serverConfigsProvider (same!) -``` - -**Usage - NO CHANGE:** - -```dart -final configs = ref.watch(serverConfigsProvider); -// or -final configs = await ref.read(serverConfigsProvider.future); -``` - ---- - -## Family Provider Example - -### Before (Manual) - -```dart -final loadConversationProvider = FutureProvider.family(( - ref, - conversationId, -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - return await api.getConversation(conversationId); -}); -``` - -### After (Code Generation) - -```dart -@riverpod -Future loadConversation( - LoadConversationRef ref, - String conversationId, // Family parameter -) async { - final api = ref.watch(apiServiceProvider); - if (api == null) { - throw Exception('No API service available'); - } - return await api.getConversation(conversationId); -} - -// Usage stays the same! -// ref.watch(loadConversationProvider(conversationId)) -``` - -**Benefits:** -- ✅ Automatic `.family` modifier handling -- ✅ Type-safe parameters -- ✅ Better parameter completion in IDE -- ✅ Can add multiple parameters easily - ---- - -## Keep Alive Example - -### Before - -```dart -@Riverpod(keepAlive: true) -class AuthStateManager extends _$AuthStateManager { - // ... -} -``` - -### After - -**No change needed!** Already using code generation correctly. ✅ - ---- - -## Migration Checklist - -For each provider to migrate: - -- [ ] Identify the provider type (Notifier, AsyncNotifier, function) -- [ ] Check for name conflicts (e.g., `ThemeModeNotifier` vs `ThemeMode`) -- [ ] Add `@riverpod` annotation -- [ ] Change class to extend `_$ClassName` -- [ ] Remove manual provider declaration -- [ ] Run `dart run build_runner build` -- [ ] Update all usages (IDE refactoring recommended) -- [ ] Test the provider functionality -- [ ] Commit the change - ---- - -## Testing After Migration - -### Unit Test Example - -**Before:** - -```dart -test('searchQuery updates correctly', () { - final container = ProviderContainer(); - - expect(container.read(searchQueryProvider), ''); - - container.read(searchQueryProvider.notifier).set('test'); - - expect(container.read(searchQueryProvider), 'test'); -}); -``` - -**After:** - -```dart -test('searchQuery updates correctly', () { - final container = ProviderContainer(); - - // Same test code - no changes needed! - expect(container.read(searchQueryProvider), ''); - - container.read(searchQueryProvider.notifier).set('test'); - - expect(container.read(searchQueryProvider), 'test'); -}); -``` - -Tests remain identical! ✅ - ---- - -## Common Pitfalls - -### 1. Class Name Conflicts - -**Problem:** - -```dart -@riverpod -class ThemeMode extends _$ThemeMode { // ❌ Conflicts with Flutter's ThemeMode - // ... -} -``` - -**Solution:** - -```dart -@riverpod -class AppThemeMode extends _$AppThemeMode { // ✅ Unique name - // ... -} -``` - -### 2. Forgetting to Run Build Runner - -**Problem:** After adding `@riverpod`, code doesn't compile. - -``` -Error: The getter '_$SearchQuery' isn't defined for the class 'SearchQuery'. -``` - -**Solution:** - -```bash -dart run build_runner build --delete-conflicting-outputs -``` - -### 3. Mixing Manual and Generated Providers - -**Problem:** Some providers use `@riverpod`, others use manual `NotifierProvider`. - -**Solution:** Be consistent! Migrate all providers in a file together to maintain consistency. - ---- - -## IDE Support - -### VS Code - -Add to `.vscode/tasks.json`: - -```json -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build_runner watch", - "type": "shell", - "command": "dart run build_runner watch --delete-conflicting-outputs", - "isBackground": true, - "problemMatcher": [] - } - ] -} -``` - -Run with `Cmd+Shift+P` → "Tasks: Run Task" → "build_runner watch" - -### Android Studio / IntelliJ - -1. Run → Edit Configurations -2. Add new "Shell Script" configuration -3. Script text: `dart run build_runner watch --delete-conflicting-outputs` -4. Working directory: `$ProjectFileDir$` - ---- - -## Summary - -**Effort per provider:** ~5-10 minutes -**Risk level:** 🟢 Low (tests verify behavior) -**Benefit:** High (consistency, maintainability, developer experience) - -**Recommended order:** - -1. Start with simple `Notifier` classes (like `SearchQueryNotifier`) -2. Move to `FutureProvider` functions -3. Then tackle complex `AsyncNotifier` classes -4. Keep `@Riverpod(keepAlive: true)` providers for last (already correct) - -**Total providers to migrate:** ~30-40 (based on codebase analysis) -**Estimated total time:** 5-8 hours spread across multiple sessions diff --git a/lib/shared/widgets/markdown/markdown_config.dart b/lib/shared/widgets/markdown/markdown_config.dart index 9da1e91..aa9125a 100644 --- a/lib/shared/widgets/markdown/markdown_config.dart +++ b/lib/shared/widgets/markdown/markdown_config.dart @@ -1,161 +1,32 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:markdown_widget/markdown_widget.dart'; -import 'package:flutter_highlight/themes/atom-one-dark.dart'; -import 'package:flutter_highlight/themes/atom-one-light.dart'; import 'package:cached_network_image/cached_network_image.dart'; -import 'package:url_launcher/url_launcher_string.dart'; import 'package:conduit/shared/theme/theme_extensions.dart'; import 'package:conduit/l10n/app_localizations.dart'; +/// Configuration for GptMarkdown styling +class ConduitMarkdownStyleConfig { + final TextStyle textStyle; + + const ConduitMarkdownStyleConfig({required this.textStyle}); +} + class ConduitMarkdownConfig { - static MarkdownConfig getConfig({ - required bool isDark, + static ConduitMarkdownStyleConfig getStyleConfig({ required BuildContext context, - bool isStreaming = false, }) { final theme = context.conduitTheme; - return (isDark ? MarkdownConfig.darkConfig : MarkdownConfig.defaultConfig).copy( - configs: [ - // Code block config - PreConfig( - theme: isDark ? atomOneDarkTheme : atomOneLightTheme, - decoration: BoxDecoration( - color: theme.surfaceBackground.withValues(alpha: 0.06), - borderRadius: BorderRadius.circular(AppBorderRadius.md), - border: Border.all( - color: theme.dividerColor.withValues(alpha: 0.7), - width: BorderWidth.thin, - ), - ), - padding: const EdgeInsets.all(Spacing.md), - textStyle: AppTypography.chatCodeStyle, - wrapper: (child, text, language) => CodeBlockWrapper( - code: text, - language: language, - theme: theme, - child: child, - ), - ), - - // Link config - LinkConfig( - style: TextStyle( - color: theme.buttonPrimary, - decoration: TextDecoration.none, - ), - onTap: (url) async { - if (await canLaunchUrlString(url)) { - launchUrlString(url, mode: LaunchMode.inAppWebView); - } - }, - ), - - // Image config - optimized for mobile with support for base64 and network images - ImgConfig( - builder: (url, attributes) { - // Check if it's a base64 data URL - if (url.startsWith('data:')) { - return _buildBase64Image(url, context, theme); - } - // Network image - return CachedNetworkImage( - imageUrl: url, - placeholder: (context, url) => Container( - height: 200, - decoration: BoxDecoration( - color: theme.surfaceBackground.withValues(alpha: 0.5), - borderRadius: BorderRadius.circular(AppBorderRadius.md), - ), - child: Center( - child: CircularProgressIndicator( - color: theme.loadingIndicator, - strokeWidth: 2, - ), - ), - ), - errorWidget: (context, url, error) => Container( - height: 100, - decoration: BoxDecoration( - color: theme.surfaceBackground.withValues(alpha: 0.3), - borderRadius: BorderRadius.circular(AppBorderRadius.md), - border: Border.all( - color: theme.error.withValues(alpha: 0.3), - width: BorderWidth.thin, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.broken_image_outlined, - color: theme.error, - size: 32, - ), - const SizedBox(height: Spacing.xs), - Text( - AppLocalizations.of(context)!.failedToLoadImage(''), - style: TextStyle(color: theme.error, fontSize: 12), - ), - ], - ), - ), - ); - }, - ), - - // Table config - mobile responsive - TableConfig( - wrapper: (table) => SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: table, - ), - ), - - // Paragraphs — improve readability and spacing on mobile - PConfig( - textStyle: AppTypography.chatMessageStyle.copyWith( - color: theme.textPrimary, - height: 1.45, - ), - ), - - // Headers - H1Config( - style: AppTypography.headlineLargeStyle.copyWith( - color: theme.textPrimary, - height: 1.25, - ), - ), - H2Config( - style: AppTypography.headlineMediumStyle.copyWith( - color: theme.textPrimary, - height: 1.25, - ), - ), - H3Config( - style: AppTypography.headlineSmallStyle.copyWith( - color: theme.textPrimary, - height: 1.3, - ), - ), - - // Blockquote — keep default rendering for compatibility - BlockquoteConfig(), - - // Code inline - CodeConfig( - style: AppTypography.chatCodeStyle.copyWith( - color: theme.textPrimary, - backgroundColor: theme.surfaceBackground.withValues(alpha: 0.1), - ), - ), - ], + return ConduitMarkdownStyleConfig( + textStyle: AppTypography.chatMessageStyle.copyWith( + color: theme.textPrimary, + height: 1.45, + ), ); } - static Widget _buildBase64Image( + /// Legacy method for base64 image support (if needed elsewhere) + static Widget buildBase64Image( String dataUrl, BuildContext context, ConduitThemeExtension theme, @@ -221,6 +92,52 @@ class ConduitMarkdownConfig { ); } } + + /// Build a cached network image widget + static Widget buildNetworkImage( + String url, + BuildContext context, + ConduitThemeExtension theme, + ) { + return CachedNetworkImage( + imageUrl: url, + placeholder: (context, url) => Container( + height: 200, + decoration: BoxDecoration( + color: theme.surfaceBackground.withValues(alpha: 0.5), + borderRadius: BorderRadius.circular(AppBorderRadius.md), + ), + child: Center( + child: CircularProgressIndicator( + color: theme.loadingIndicator, + strokeWidth: 2, + ), + ), + ), + errorWidget: (context, url, error) => Container( + height: 100, + decoration: BoxDecoration( + color: theme.surfaceBackground.withValues(alpha: 0.3), + borderRadius: BorderRadius.circular(AppBorderRadius.md), + border: Border.all( + color: theme.error.withValues(alpha: 0.3), + width: BorderWidth.thin, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.broken_image_outlined, color: theme.error, size: 32), + const SizedBox(height: Spacing.xs), + Text( + AppLocalizations.of(context)!.failedToLoadImage(''), + style: TextStyle(color: theme.error, fontSize: 12), + ), + ], + ), + ), + ); + } } /// Custom wrapper for code blocks with copy functionality diff --git a/lib/shared/widgets/markdown/streaming_markdown_widget.dart b/lib/shared/widgets/markdown/streaming_markdown_widget.dart index 4f5525e..3f8d37d 100644 --- a/lib/shared/widgets/markdown/streaming_markdown_widget.dart +++ b/lib/shared/widgets/markdown/streaming_markdown_widget.dart @@ -1,22 +1,18 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:markdown_widget/markdown_widget.dart'; +import 'package:gpt_markdown/gpt_markdown.dart'; import 'package:conduit/shared/widgets/markdown/markdown_config.dart'; class StreamingMarkdownWidget extends StatefulWidget { final Stream? contentStream; final String? staticContent; final bool isStreaming; - final ScrollController? scrollController; - final EdgeInsetsGeometry? padding; const StreamingMarkdownWidget({ super.key, this.contentStream, this.staticContent, required this.isStreaming, - this.scrollController, - this.padding, }); @override @@ -110,36 +106,14 @@ class _StreamingMarkdownWidgetState extends State { @override Widget build(BuildContext context) { - final isDark = Theme.of(context).brightness == Brightness.dark; - final config = ConduitMarkdownConfig.getConfig( - isDark: isDark, - context: context, - isStreaming: widget.isStreaming, - ); + final config = ConduitMarkdownConfig.getStyleConfig(context: context); if (_renderedContent.isEmpty) { return const SizedBox.shrink(); } - if (widget.isStreaming && _renderedContent.isNotEmpty) { - // Use MarkdownBlock for streaming - it's optimized for live updates - return MarkdownBlock( - data: _renderedContent, - config: config, - selectable: true, - ); - } else { - // Use MarkdownWidget for completed messages - // This provides better interactivity and selection - return MarkdownWidget( - data: _renderedContent, - config: config, - selectable: true, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - ); - } + // GptMarkdown handles both streaming and static content elegantly + return GptMarkdown(_renderedContent, style: config.textStyle); } @override @@ -152,15 +126,10 @@ class _StreamingMarkdownWidgetState extends State { /// Extension to provide easy access to streaming markdown extension StreamingMarkdownExtension on String { - Widget toMarkdown({ - required BuildContext context, - bool isStreaming = false, - EdgeInsetsGeometry? padding, - }) { + Widget toMarkdown({required BuildContext context, bool isStreaming = false}) { return StreamingMarkdownWidget( staticContent: this, isStreaming: isStreaming, - padding: padding, ); } } @@ -169,28 +138,18 @@ extension StreamingMarkdownExtension on String { class MarkdownWithLoading extends StatelessWidget { final String? content; final bool isLoading; - final EdgeInsetsGeometry? padding; - const MarkdownWithLoading({ - super.key, - this.content, - required this.isLoading, - this.padding, - }); + const MarkdownWithLoading({super.key, this.content, required this.isLoading}); @override Widget build(BuildContext context) { if (isLoading && (content == null || content!.isEmpty)) { - return Container( - padding: padding ?? const EdgeInsets.all(16), - child: const Center(child: CircularProgressIndicator()), - ); + return const Center(child: CircularProgressIndicator()); } return StreamingMarkdownWidget( staticContent: content ?? '', isStreaming: isLoading, - padding: padding, ); } } diff --git a/pubspec.lock b/pubspec.lock index d906b9f..a134d2b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -430,14 +430,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" - flutter_highlight: - dependency: "direct main" - description: - name: flutter_highlight - sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" - url: "https://pub.dev" - source: hosted - version: "0.7.0" flutter_lints: dependency: "direct dev" description: @@ -451,6 +443,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_math_fork: + dependency: transitive + description: + name: flutter_math_fork + sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407" + url: "https://pub.dev" + source: hosted + version: "0.7.4" flutter_native_splash: dependency: "direct dev" description: @@ -531,6 +531,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.3" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678 + url: "https://pub.dev" + source: hosted + version: "2.2.1" flutter_test: dependency: "direct dev" description: flutter @@ -589,6 +597,14 @@ packages: url: "https://pub.dev" source: hosted version: "14.8.1" + gpt_markdown: + dependency: "direct main" + description: + name: gpt_markdown + sha256: "8174983f2ed7d8576d25810913e3afe3f8ffdaa3172c0c823b7cfc289b67f380" + url: "https://pub.dev" + source: hosted + version: "1.1.4" graphs: dependency: transitive description: @@ -597,14 +613,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" - highlight: - dependency: transitive - description: - name: highlight - sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" - url: "https://pub.dev" - source: hosted - version: "0.7.0" hotreloader: dependency: transitive description: @@ -797,22 +805,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" - url: "https://pub.dev" - source: hosted - version: "7.3.0" - markdown_widget: - dependency: "direct main" - description: - name: markdown_widget - sha256: b52c13d3ee4d0e60c812e15b0593f142a3b8a2003cde1babb271d001a1dbdc1c - url: "https://pub.dev" - source: hosted - version: "2.3.2+8" matcher: dependency: transitive description: @@ -853,6 +845,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.5.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" node_preamble: dependency: transitive description: @@ -901,6 +901,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: "direct main" description: @@ -989,6 +997,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.3" + provider: + dependency: transitive + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" pub_semver: dependency: transitive description: @@ -1117,14 +1133,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.28.0" - scroll_to_index: - dependency: transitive - description: - name: scroll_to_index - sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 - url: "https://pub.dev" - source: hosted - version: "3.0.1" share_handler: dependency: "direct main" description: @@ -1482,6 +1490,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" typed_data: dependency: transitive description: @@ -1570,6 +1586,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc + url: "https://pub.dev" + source: hosted + version: "1.1.19" vector_math: dependency: transitive description: @@ -1578,14 +1618,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" - visibility_detector: - dependency: transitive - description: - name: visibility_detector - sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 - url: "https://pub.dev" - source: hosted - version: "0.4.0+2" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b8338d4..530edb3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,8 +28,7 @@ dependencies: shared_preferences: ^2.3.2 # UI Components - Enhanced Markdown - markdown_widget: ^2.3.2+8 - flutter_highlight: ^0.7.0 + gpt_markdown: ^1.1.4 cached_network_image: ^3.3.1 socket_io_client: ^3.1.2 yaml: ^3.1.2