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:
@@ -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 [];
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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() => [];
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user