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.
This commit is contained in:
@@ -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<AuthState> 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, ThemeMode>(
|
||||
ThemeModeNotifier.new,
|
||||
);
|
||||
|
||||
class ThemeModeNotifier extends Notifier<ThemeMode> {
|
||||
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, ThemeMode>(
|
||||
ThemeModeNotifier.new,
|
||||
);
|
||||
|
||||
class ThemeModeNotifier extends Notifier<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());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**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<Conversation, String>((
|
||||
ref,
|
||||
conversationId,
|
||||
) async {
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
if (api == null) {
|
||||
throw Exception('No API service available');
|
||||
}
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
**Recommendation:**
|
||||
|
||||
```dart
|
||||
@riverpod
|
||||
Future<Conversation> 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<bool>((ref) {
|
||||
final authState = ref.watch(authStateManagerProvider);
|
||||
return authState.maybeWhen(
|
||||
data: (state) => state.isAuthenticated,
|
||||
orElse: () => false,
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
**Better:**
|
||||
|
||||
```dart
|
||||
final isAuthenticatedProvider2 = Provider<bool>((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, bool>(
|
||||
IsLoadingConversationNotifier.new,
|
||||
);
|
||||
|
||||
class IsLoadingConversationNotifier extends Notifier<bool> {
|
||||
@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<List<ServerConfig>>((ref) async {
|
||||
final storage = ref.watch(optimizedStorageServiceProvider);
|
||||
return storage.getServerConfigs();
|
||||
});
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```dart
|
||||
@riverpod
|
||||
Future<List<ServerConfig>> 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<ChatMessage> 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.
|
||||
@@ -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<List<Conversation>>
|
||||
- **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<AppSettingsNotifier, AppSettings>
|
||||
- **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<ChatMessagesNotifier, List<ChatMessage>>
|
||||
- **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<Model?>
|
||||
- **Complexity:** 🟡 Medium
|
||||
- **Size:** ~70 lines
|
||||
- **Features:** Complex initialization with settings watchers
|
||||
- **Risk:** Medium
|
||||
- **Estimated Time:** 30 minutes
|
||||
|
||||
#### 5. voiceInputAvailableProvider
|
||||
- **Type:** FutureProvider<bool>
|
||||
- **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**
|
||||
@@ -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!"*
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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<ConversationDelta> 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.*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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, String>(MyNotifier.new);
|
||||
|
||||
class MyNotifier extends Notifier<String> {
|
||||
@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<String>((ref) async {
|
||||
return await fetchData();
|
||||
});
|
||||
|
||||
// AFTER
|
||||
@riverpod
|
||||
Future<String> my(MyRef ref) async {
|
||||
return await fetchData();
|
||||
}
|
||||
// Generated: myProvider
|
||||
```
|
||||
|
||||
**For Family Providers:**
|
||||
```dart
|
||||
// BEFORE
|
||||
final myProvider = FutureProvider.family<String, int>((ref, id) async {
|
||||
return await fetchData(id);
|
||||
});
|
||||
|
||||
// AFTER
|
||||
@riverpod
|
||||
Future<String> 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 <commit-hash>
|
||||
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 🚀
|
||||
@@ -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! 🚀**
|
||||
@@ -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<void> 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<Data> 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<Data> myData(MyDataRef ref) async {
|
||||
return await fetch();
|
||||
}
|
||||
|
||||
// Suggested (if data is short-lived)
|
||||
@riverpod
|
||||
Future<Data> 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<void> save() async {
|
||||
await someAsyncOp();
|
||||
state = newValue; // ⚠️ Might be disposed
|
||||
}
|
||||
|
||||
// Fixed
|
||||
Future<void> 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
|
||||
@@ -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*
|
||||
@@ -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, String>(
|
||||
SearchQueryNotifier.new,
|
||||
);
|
||||
|
||||
class SearchQueryNotifier extends Notifier<String> {
|
||||
@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<SearchQuery, String>.internal(
|
||||
SearchQuery.new,
|
||||
name: r'searchQueryProvider',
|
||||
debugGetCreateSourceHash: _$searchQueryHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$SearchQuery = AutoDisposeNotifier<String>;
|
||||
```
|
||||
|
||||
### 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, String>(
|
||||
SearchQueryNotifier.new,
|
||||
);
|
||||
|
||||
class SearchQueryNotifier extends Notifier<String> {
|
||||
@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, ThemeMode>(
|
||||
ThemeModeNotifier.new,
|
||||
);
|
||||
|
||||
class ThemeModeNotifier extends Notifier<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());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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<List<ServerConfig>>((ref) async {
|
||||
final storage = ref.watch(optimizedStorageServiceProvider);
|
||||
return storage.getServerConfigs();
|
||||
});
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```dart
|
||||
@riverpod
|
||||
Future<List<ServerConfig>> 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<Conversation, String>((
|
||||
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<Conversation> 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
|
||||
@@ -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
|
||||
|
||||
@@ -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<String>? 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<StreamingMarkdownWidget> {
|
||||
|
||||
@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<StreamingMarkdownWidget> {
|
||||
|
||||
/// 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
128
pubspec.lock
128
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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user