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.
This commit is contained in:
cogwheel0
2025-10-01 18:32:16 +05:30
parent 28dc16a6e3
commit 8a8ba76298
8 changed files with 23 additions and 60 deletions

View File

@@ -55,7 +55,7 @@ final optimizedStorageServiceProvider = Provider<OptimizedStorageService>((
}); });
// Theme provider // Theme provider
@riverpod @Riverpod(keepAlive: true)
class AppThemeMode extends _$AppThemeMode { class AppThemeMode extends _$AppThemeMode {
late final OptimizedStorageService _storage; late final OptimizedStorageService _storage;
@@ -79,7 +79,7 @@ class AppThemeMode extends _$AppThemeMode {
} }
// Locale provider // Locale provider
@riverpod @Riverpod(keepAlive: true)
class AppLocale extends _$AppLocale { class AppLocale extends _$AppLocale {
late final OptimizedStorageService _storage; late final OptimizedStorageService _storage;
@@ -370,24 +370,6 @@ class SocketConnectionStream extends _$SocketConnectionStream {
_cancelConnectListener = null; _cancelConnectListener = null;
_cancelDisconnectListener = 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<void> 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) @Riverpod(keepAlive: true)
@@ -480,27 +462,8 @@ class ConversationDeltaStream extends _$ConversationDeltaStream {
_socketSubscription?.dispose(); _socketSubscription?.dispose();
_socketSubscription = null; _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<ConversationDelta> get stream =>
_controller?.stream ?? const Stream<ConversationDelta>.empty();
} }
final conversationDeltaEventsProvider =
StreamProvider.family<ConversationDelta, ConversationDeltaRequest>((
ref,
request,
) {
final notifier = ref.watch(
conversationDeltaStreamProvider(request).notifier,
);
return notifier.stream;
});
// Attachment upload queue provider // Attachment upload queue provider
final attachmentUploadQueueProvider = Provider<AttachmentUploadQueue?>((ref) { final attachmentUploadQueueProvider = Provider<AttachmentUploadQueue?>((ref) {
final api = ref.watch(apiServiceProvider); final api = ref.watch(apiServiceProvider);
@@ -533,7 +496,7 @@ final apiTokenUpdaterProvider = Provider<void>((ref) {
}); });
}); });
@riverpod @Riverpod(keepAlive: true)
Future<User?> currentUser(Ref ref) async { Future<User?> currentUser(Ref ref) async {
final api = ref.read(apiServiceProvider); final api = ref.read(apiServiceProvider);
final isAuthenticated = ref.watch(isAuthenticatedProvider2); final isAuthenticated = ref.watch(isAuthenticatedProvider2);
@@ -1243,7 +1206,7 @@ final backgroundModelLoadProvider = Provider<void>((ref) {
}); });
// Search query provider // Search query provider
@riverpod @Riverpod(keepAlive: true)
class SearchQuery extends _$SearchQuery { class SearchQuery extends _$SearchQuery {
@override @override
String build() => ''; String build() => '';
@@ -1485,7 +1448,7 @@ class ReviewerMode extends _$ReviewerMode {
} }
// User Settings providers // User Settings providers
@riverpod @Riverpod(keepAlive: true)
Future<UserSettings> userSettings(Ref ref) async { Future<UserSettings> userSettings(Ref ref) async {
final api = ref.watch(apiServiceProvider); final api = ref.watch(apiServiceProvider);
if (api == null) { if (api == null) {
@@ -1504,7 +1467,7 @@ Future<UserSettings> userSettings(Ref ref) async {
} }
// Conversation Suggestions provider // Conversation Suggestions provider
@riverpod @Riverpod(keepAlive: true)
Future<List<String>> conversationSuggestions(Ref ref) async { Future<List<String>> conversationSuggestions(Ref ref) async {
final api = ref.watch(apiServiceProvider); final api = ref.watch(apiServiceProvider);
if (api == null) return []; if (api == null) return [];
@@ -1518,7 +1481,7 @@ Future<List<String>> conversationSuggestions(Ref ref) async {
} }
// Server features and permissions // Server features and permissions
@riverpod @Riverpod(keepAlive: true)
Future<Map<String, dynamic>> userPermissions(Ref ref) async { Future<Map<String, dynamic>> userPermissions(Ref ref) async {
final api = ref.watch(apiServiceProvider); final api = ref.watch(apiServiceProvider);
if (api == null) return {}; if (api == null) return {};
@@ -1595,7 +1558,7 @@ Future<List<Folder>> folders(Ref ref) async {
} }
// Files provider // Files provider
@riverpod @Riverpod(keepAlive: true)
Future<List<FileInfo>> userFiles(Ref ref) async { Future<List<FileInfo>> userFiles(Ref ref) async {
// Protected: require authentication // Protected: require authentication
if (!ref.read(isAuthenticatedProvider2)) { if (!ref.read(isAuthenticatedProvider2)) {
@@ -1639,7 +1602,7 @@ Future<String> fileContent(Ref ref, String fileId) async {
} }
// Knowledge Base providers // Knowledge Base providers
@riverpod @Riverpod(keepAlive: true)
Future<List<KnowledgeBase>> knowledgeBases(Ref ref) async { Future<List<KnowledgeBase>> knowledgeBases(Ref ref) async {
// Protected: require authentication // Protected: require authentication
if (!ref.read(isAuthenticatedProvider2)) { if (!ref.read(isAuthenticatedProvider2)) {
@@ -1678,7 +1641,7 @@ Future<List<KnowledgeBaseItem>> knowledgeBaseItems(Ref ref, String kbId) async {
} }
// Audio providers // Audio providers
@riverpod @Riverpod(keepAlive: true)
Future<List<String>> availableVoices(Ref ref) async { Future<List<String>> availableVoices(Ref ref) async {
// Protected: require authentication // Protected: require authentication
if (!ref.read(isAuthenticatedProvider2)) { if (!ref.read(isAuthenticatedProvider2)) {
@@ -1697,7 +1660,7 @@ Future<List<String>> availableVoices(Ref ref) async {
} }
// Image Generation providers // Image Generation providers
@riverpod @Riverpod(keepAlive: true)
Future<List<Map<String, dynamic>>> imageModels(Ref ref) async { Future<List<Map<String, dynamic>>> imageModels(Ref ref) async {
final api = ref.watch(apiServiceProvider); final api = ref.watch(apiServiceProvider);
if (api == null) return []; if (api == null) return [];

View File

@@ -212,7 +212,7 @@ class AnimationService {
enum PageTransitionType { fade, slide, scale } enum PageTransitionType { fade, slide, scale }
/// Provider for reduced motion preference /// Provider for reduced motion preference
@riverpod @Riverpod(keepAlive: true)
class ReducedMotion extends _$ReducedMotion { class ReducedMotion extends _$ReducedMotion {
@override @override
bool build() => false; bool build() => false;

View File

@@ -33,7 +33,7 @@ final chatMessagesProvider =
); );
// Loading state for conversation (used to show chat skeletons during fetch) // Loading state for conversation (used to show chat skeletons during fetch)
@riverpod @Riverpod(keepAlive: true)
class IsLoadingConversation extends _$IsLoadingConversation { class IsLoadingConversation extends _$IsLoadingConversation {
@override @override
bool build() => false; bool build() => false;
@@ -42,7 +42,7 @@ class IsLoadingConversation extends _$IsLoadingConversation {
} }
// Prefilled input text (e.g., when sharing text from other apps) // Prefilled input text (e.g., when sharing text from other apps)
@riverpod @Riverpod(keepAlive: true)
class PrefilledInputText extends _$PrefilledInputText { class PrefilledInputText extends _$PrefilledInputText {
@override @override
String? build() => null; String? build() => null;
@@ -53,7 +53,7 @@ class PrefilledInputText extends _$PrefilledInputText {
} }
// Trigger to request focus on the chat input (increment to signal) // Trigger to request focus on the chat input (increment to signal)
@riverpod @Riverpod(keepAlive: true)
class InputFocusTrigger extends _$InputFocusTrigger { class InputFocusTrigger extends _$InputFocusTrigger {
@override @override
int build() => 0; int build() => 0;
@@ -68,7 +68,7 @@ class InputFocusTrigger extends _$InputFocusTrigger {
} }
// Whether the chat composer currently has focus // Whether the chat composer currently has focus
@riverpod @Riverpod(keepAlive: true)
class ComposerHasFocus extends _$ComposerHasFocus { class ComposerHasFocus extends _$ComposerHasFocus {
@override @override
bool build() => false; bool build() => false;

View File

@@ -534,7 +534,7 @@ final selectedMessagesProvider =
); );
/// Provider for batch operation mode /// Provider for batch operation mode
@riverpod @Riverpod(keepAlive: true)
class BatchMode extends _$BatchMode { class BatchMode extends _$BatchMode {
@override @override
bool build() => false; bool build() => false;

View File

@@ -326,7 +326,7 @@ final voiceInputServiceProvider = Provider<VoiceInputService>((ref) {
return VoiceInputService(); return VoiceInputService();
}); });
@riverpod @Riverpod(keepAlive: true)
Future<bool> voiceInputAvailable(Ref ref) async { Future<bool> voiceInputAvailable(Ref ref) async {
final service = ref.watch(voiceInputServiceProvider); final service = ref.watch(voiceInputServiceProvider);
if (!service.isSupportedPlatform) return false; if (!service.isSupportedPlatform) return false;

View File

@@ -5,14 +5,14 @@ import 'package:conduit/core/services/prompts_service.dart';
part 'prompts_providers.g.dart'; part 'prompts_providers.g.dart';
@riverpod @Riverpod(keepAlive: true)
Future<List<Prompt>> promptsList(Ref ref) async { Future<List<Prompt>> promptsList(Ref ref) async {
final promptsService = ref.watch(promptsServiceProvider); final promptsService = ref.watch(promptsServiceProvider);
if (promptsService == null) return const <Prompt>[]; if (promptsService == null) return const <Prompt>[];
return promptsService.getPrompts(); return promptsService.getPrompts();
} }
@riverpod @Riverpod(keepAlive: true)
class ActivePromptCommand extends _$ActivePromptCommand { class ActivePromptCommand extends _$ActivePromptCommand {
@override @override
String? build() => null; String? build() => null;

View File

@@ -5,14 +5,14 @@ import 'package:conduit/core/services/tools_service.dart';
part 'tools_providers.g.dart'; part 'tools_providers.g.dart';
@riverpod @Riverpod(keepAlive: true)
Future<List<Tool>> toolsList(Ref ref) async { Future<List<Tool>> toolsList(Ref ref) async {
final toolsService = ref.watch(toolsServiceProvider); final toolsService = ref.watch(toolsServiceProvider);
if (toolsService == null) return []; if (toolsService == null) return [];
return await toolsService.getTools(); return await toolsService.getTools();
} }
@riverpod @Riverpod(keepAlive: true)
class SelectedToolIds extends _$SelectedToolIds { class SelectedToolIds extends _$SelectedToolIds {
@override @override
List<String> build() => []; List<String> build() => [];

View File

@@ -57,7 +57,7 @@ class OfflineIndicator extends ConsumerWidget {
} }
// Tracks if the app was recently offline to enable a one-shot back-online toast // Tracks if the app was recently offline to enable a one-shot back-online toast
@riverpod @Riverpod(keepAlive: true)
class _WasOffline extends _$WasOffline { class _WasOffline extends _$WasOffline {
@override @override
bool build() { bool build() {