From 8a8ba76298bd9ca0e30f8ac4dd55bc72d94ccfc1 Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:32:16 +0530 Subject: [PATCH] refactor: update providers to use keepAlive for enhanced state management - Changed multiple provider annotations to `@Riverpod(keepAlive: true)` to improve state retention and management across the application. - This update aligns with recent enhancements in state management practices, ensuring better performance and user experience throughout the app. --- lib/core/providers/app_providers.dart | 59 ++++--------------- lib/core/services/animation_service.dart | 2 +- .../chat/providers/chat_providers.dart | 8 +-- .../chat/services/message_batch_service.dart | 2 +- .../chat/services/voice_input_service.dart | 2 +- .../prompts/providers/prompts_providers.dart | 4 +- .../tools/providers/tools_providers.dart | 4 +- lib/shared/widgets/offline_indicator.dart | 2 +- 8 files changed, 23 insertions(+), 60 deletions(-) diff --git a/lib/core/providers/app_providers.dart b/lib/core/providers/app_providers.dart index 09965bf..d068a8c 100644 --- a/lib/core/providers/app_providers.dart +++ b/lib/core/providers/app_providers.dart @@ -55,7 +55,7 @@ final optimizedStorageServiceProvider = Provider(( }); // Theme provider -@riverpod +@Riverpod(keepAlive: true) class AppThemeMode extends _$AppThemeMode { late final OptimizedStorageService _storage; @@ -79,7 +79,7 @@ class AppThemeMode extends _$AppThemeMode { } // Locale provider -@riverpod +@Riverpod(keepAlive: true) class AppLocale extends _$AppLocale { late final OptimizedStorageService _storage; @@ -370,24 +370,6 @@ class SocketConnectionStream extends _$SocketConnectionStream { _cancelConnectListener = null; _cancelDisconnectListener = null; } - - /// Forces a best-effort reconnect of the underlying socket service. - /// This is an action method, not state exposure. - // ignore: avoid_public_notifier_properties - Future reconnect({ - Duration timeout = const Duration(seconds: 2), - }) async { - final service = ref.read(socketServiceProvider); - if (service == null) { - return; - } - final connected = await service.ensureConnected(timeout: timeout); - _emit( - connected - ? SocketConnectionState.connected - : SocketConnectionState.connecting, - ); - } } @Riverpod(keepAlive: true) @@ -480,27 +462,8 @@ class ConversationDeltaStream extends _$ConversationDeltaStream { _socketSubscription?.dispose(); _socketSubscription = null; } - - /// Provides direct access to the underlying stream. - /// Note: This getter is necessary for compatibility with StreamProvider. - /// While Riverpod 3 discourages public getters on Notifiers, this is a - /// pragmatic exception for stream delegation patterns. - // ignore: avoid_public_notifier_properties - Stream get stream => - _controller?.stream ?? const Stream.empty(); } -final conversationDeltaEventsProvider = - StreamProvider.family(( - ref, - request, - ) { - final notifier = ref.watch( - conversationDeltaStreamProvider(request).notifier, - ); - return notifier.stream; - }); - // Attachment upload queue provider final attachmentUploadQueueProvider = Provider((ref) { final api = ref.watch(apiServiceProvider); @@ -533,7 +496,7 @@ final apiTokenUpdaterProvider = Provider((ref) { }); }); -@riverpod +@Riverpod(keepAlive: true) Future currentUser(Ref ref) async { final api = ref.read(apiServiceProvider); final isAuthenticated = ref.watch(isAuthenticatedProvider2); @@ -1243,7 +1206,7 @@ final backgroundModelLoadProvider = Provider((ref) { }); // Search query provider -@riverpod +@Riverpod(keepAlive: true) class SearchQuery extends _$SearchQuery { @override String build() => ''; @@ -1485,7 +1448,7 @@ class ReviewerMode extends _$ReviewerMode { } // User Settings providers -@riverpod +@Riverpod(keepAlive: true) Future userSettings(Ref ref) async { final api = ref.watch(apiServiceProvider); if (api == null) { @@ -1504,7 +1467,7 @@ Future userSettings(Ref ref) async { } // Conversation Suggestions provider -@riverpod +@Riverpod(keepAlive: true) Future> conversationSuggestions(Ref ref) async { final api = ref.watch(apiServiceProvider); if (api == null) return []; @@ -1518,7 +1481,7 @@ Future> conversationSuggestions(Ref ref) async { } // Server features and permissions -@riverpod +@Riverpod(keepAlive: true) Future> userPermissions(Ref ref) async { final api = ref.watch(apiServiceProvider); if (api == null) return {}; @@ -1595,7 +1558,7 @@ Future> folders(Ref ref) async { } // Files provider -@riverpod +@Riverpod(keepAlive: true) Future> userFiles(Ref ref) async { // Protected: require authentication if (!ref.read(isAuthenticatedProvider2)) { @@ -1639,7 +1602,7 @@ Future fileContent(Ref ref, String fileId) async { } // Knowledge Base providers -@riverpod +@Riverpod(keepAlive: true) Future> knowledgeBases(Ref ref) async { // Protected: require authentication if (!ref.read(isAuthenticatedProvider2)) { @@ -1678,7 +1641,7 @@ Future> knowledgeBaseItems(Ref ref, String kbId) async { } // Audio providers -@riverpod +@Riverpod(keepAlive: true) Future> availableVoices(Ref ref) async { // Protected: require authentication if (!ref.read(isAuthenticatedProvider2)) { @@ -1697,7 +1660,7 @@ Future> availableVoices(Ref ref) async { } // Image Generation providers -@riverpod +@Riverpod(keepAlive: true) Future>> imageModels(Ref ref) async { final api = ref.watch(apiServiceProvider); if (api == null) return []; diff --git a/lib/core/services/animation_service.dart b/lib/core/services/animation_service.dart index 68da430..5e8a316 100644 --- a/lib/core/services/animation_service.dart +++ b/lib/core/services/animation_service.dart @@ -212,7 +212,7 @@ class AnimationService { enum PageTransitionType { fade, slide, scale } /// Provider for reduced motion preference -@riverpod +@Riverpod(keepAlive: true) class ReducedMotion extends _$ReducedMotion { @override bool build() => false; diff --git a/lib/features/chat/providers/chat_providers.dart b/lib/features/chat/providers/chat_providers.dart index 07a99b6..6431a53 100644 --- a/lib/features/chat/providers/chat_providers.dart +++ b/lib/features/chat/providers/chat_providers.dart @@ -33,7 +33,7 @@ final chatMessagesProvider = ); // Loading state for conversation (used to show chat skeletons during fetch) -@riverpod +@Riverpod(keepAlive: true) class IsLoadingConversation extends _$IsLoadingConversation { @override bool build() => false; @@ -42,7 +42,7 @@ class IsLoadingConversation extends _$IsLoadingConversation { } // Prefilled input text (e.g., when sharing text from other apps) -@riverpod +@Riverpod(keepAlive: true) class PrefilledInputText extends _$PrefilledInputText { @override String? build() => null; @@ -53,7 +53,7 @@ class PrefilledInputText extends _$PrefilledInputText { } // Trigger to request focus on the chat input (increment to signal) -@riverpod +@Riverpod(keepAlive: true) class InputFocusTrigger extends _$InputFocusTrigger { @override int build() => 0; @@ -68,7 +68,7 @@ class InputFocusTrigger extends _$InputFocusTrigger { } // Whether the chat composer currently has focus -@riverpod +@Riverpod(keepAlive: true) class ComposerHasFocus extends _$ComposerHasFocus { @override bool build() => false; diff --git a/lib/features/chat/services/message_batch_service.dart b/lib/features/chat/services/message_batch_service.dart index 2973f4b..af3c767 100644 --- a/lib/features/chat/services/message_batch_service.dart +++ b/lib/features/chat/services/message_batch_service.dart @@ -534,7 +534,7 @@ final selectedMessagesProvider = ); /// Provider for batch operation mode -@riverpod +@Riverpod(keepAlive: true) class BatchMode extends _$BatchMode { @override bool build() => false; diff --git a/lib/features/chat/services/voice_input_service.dart b/lib/features/chat/services/voice_input_service.dart index caa9924..1c30c63 100644 --- a/lib/features/chat/services/voice_input_service.dart +++ b/lib/features/chat/services/voice_input_service.dart @@ -326,7 +326,7 @@ final voiceInputServiceProvider = Provider((ref) { return VoiceInputService(); }); -@riverpod +@Riverpod(keepAlive: true) Future voiceInputAvailable(Ref ref) async { final service = ref.watch(voiceInputServiceProvider); if (!service.isSupportedPlatform) return false; diff --git a/lib/features/prompts/providers/prompts_providers.dart b/lib/features/prompts/providers/prompts_providers.dart index 708c46a..b73f8dd 100644 --- a/lib/features/prompts/providers/prompts_providers.dart +++ b/lib/features/prompts/providers/prompts_providers.dart @@ -5,14 +5,14 @@ import 'package:conduit/core/services/prompts_service.dart'; part 'prompts_providers.g.dart'; -@riverpod +@Riverpod(keepAlive: true) Future> promptsList(Ref ref) async { final promptsService = ref.watch(promptsServiceProvider); if (promptsService == null) return const []; return promptsService.getPrompts(); } -@riverpod +@Riverpod(keepAlive: true) class ActivePromptCommand extends _$ActivePromptCommand { @override String? build() => null; diff --git a/lib/features/tools/providers/tools_providers.dart b/lib/features/tools/providers/tools_providers.dart index f0f5549..d16979c 100644 --- a/lib/features/tools/providers/tools_providers.dart +++ b/lib/features/tools/providers/tools_providers.dart @@ -5,14 +5,14 @@ import 'package:conduit/core/services/tools_service.dart'; part 'tools_providers.g.dart'; -@riverpod +@Riverpod(keepAlive: true) Future> toolsList(Ref ref) async { final toolsService = ref.watch(toolsServiceProvider); if (toolsService == null) return []; return await toolsService.getTools(); } -@riverpod +@Riverpod(keepAlive: true) class SelectedToolIds extends _$SelectedToolIds { @override List build() => []; diff --git a/lib/shared/widgets/offline_indicator.dart b/lib/shared/widgets/offline_indicator.dart index ea247a8..ff82b8f 100644 --- a/lib/shared/widgets/offline_indicator.dart +++ b/lib/shared/widgets/offline_indicator.dart @@ -57,7 +57,7 @@ class OfflineIndicator extends ConsumerWidget { } // Tracks if the app was recently offline to enable a one-shot back-online toast -@riverpod +@Riverpod(keepAlive: true) class _WasOffline extends _$WasOffline { @override bool build() {