refactor: centralize conversation cache management
- Introduced a new method `refreshConversationsCache` to streamline the invalidation of the conversations provider and optionally the folders provider. - Updated various components to utilize the new cache management method, enhancing code clarity and reducing redundancy. - This refactor improves the efficiency of conversation and folder synchronization across the application.
This commit is contained in:
@@ -661,6 +661,17 @@ class _ConversationsCacheTimestamp extends _$ConversationsCacheTimestamp {
|
|||||||
void set(DateTime? timestamp) => state = timestamp;
|
void set(DateTime? timestamp) => state = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clears the in-memory timestamp cache and invalidates the conversations
|
||||||
|
/// provider so the next read forces a refetch. Optionally invalidates the
|
||||||
|
/// folders provider when folder metadata must stay in sync with conversations.
|
||||||
|
void refreshConversationsCache(dynamic ref, {bool includeFolders = false}) {
|
||||||
|
ref.read(_conversationsCacheTimestampProvider.notifier).set(null);
|
||||||
|
ref.invalidate(conversationsProvider);
|
||||||
|
if (includeFolders) {
|
||||||
|
ref.invalidate(foldersProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Conversation providers - Now using correct OpenWebUI API with caching
|
// Conversation providers - Now using correct OpenWebUI API with caching
|
||||||
// keepAlive to maintain cache during authenticated session
|
// keepAlive to maintain cache during authenticated session
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ void _scheduleConversationWarmup(Ref ref, {bool force = false}) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (existing.hasError) {
|
if (existing.hasError) {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
}
|
}
|
||||||
final conversations = await ref.read(conversationsProvider.future);
|
final conversations = await ref.read(conversationsProvider.future);
|
||||||
statusController.set(_ConversationWarmupStatus.complete);
|
statusController.set(_ConversationWarmupStatus.complete);
|
||||||
@@ -368,7 +368,7 @@ class _ForegroundRefreshObserver extends WidgetsBindingObserver {
|
|||||||
// Schedule to avoid side-effects during build frames
|
// Schedule to avoid side-effects during build frames
|
||||||
Future.microtask(() {
|
Future.microtask(() {
|
||||||
try {
|
try {
|
||||||
_ref.invalidate(conversationsProvider);
|
refreshConversationsCache(_ref);
|
||||||
_ref
|
_ref
|
||||||
.read(_conversationWarmupStatusProvider.notifier)
|
.read(_conversationWarmupStatusProvider.notifier)
|
||||||
.set(_ConversationWarmupStatus.idle);
|
.set(_ConversationWarmupStatus.idle);
|
||||||
|
|||||||
@@ -647,7 +647,7 @@ class ChatMessagesNotifier extends Notifier<List<ChatMessage>> {
|
|||||||
// can pick up updated titles and ordering once streaming completes.
|
// can pick up updated titles and ordering once streaming completes.
|
||||||
// Best-effort: ignore if ref lifecycle/context prevents invalidation.
|
// Best-effort: ignore if ref lifecycle/context prevents invalidation.
|
||||||
try {
|
try {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1373,10 +1373,10 @@ Future<void> regenerateMessage(
|
|||||||
.read(activeConversationProvider.notifier)
|
.read(activeConversationProvider.notifier)
|
||||||
.set(active.copyWith(title: newTitle));
|
.set(active.copyWith(title: newTitle));
|
||||||
}
|
}
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
},
|
},
|
||||||
onChatTagsUpdated: () {
|
onChatTagsUpdated: () {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
final active = ref.read(activeConversationProvider);
|
final active = ref.read(activeConversationProvider);
|
||||||
final api = ref.read(apiServiceProvider);
|
final api = ref.read(apiServiceProvider);
|
||||||
if (active != null && api != null) {
|
if (active != null && api != null) {
|
||||||
@@ -1523,7 +1523,7 @@ Future<void> _sendMessageInternal(
|
|||||||
try {
|
try {
|
||||||
// Guard against using ref after widget disposal
|
// Guard against using ref after widget disposal
|
||||||
if (ref.mounted == true) {
|
if (ref.mounted == true) {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// If ref doesn't support mounted or is disposed, skip
|
// If ref doesn't support mounted or is disposed, skip
|
||||||
@@ -1920,10 +1920,10 @@ Future<void> _sendMessageInternal(
|
|||||||
.read(activeConversationProvider.notifier)
|
.read(activeConversationProvider.notifier)
|
||||||
.set(active.copyWith(title: newTitle));
|
.set(active.copyWith(title: newTitle));
|
||||||
}
|
}
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
},
|
},
|
||||||
onChatTagsUpdated: () {
|
onChatTagsUpdated: () {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
final active = ref.read(activeConversationProvider);
|
final active = ref.read(activeConversationProvider);
|
||||||
final api = ref.read(apiServiceProvider);
|
final api = ref.read(apiServiceProvider);
|
||||||
if (active != null && api != null) {
|
if (active != null && api != null) {
|
||||||
@@ -2057,7 +2057,7 @@ Future<void> _saveConversationLocally(dynamic ref) async {
|
|||||||
|
|
||||||
await storage.setString('conversations', jsonEncode(conversations));
|
await storage.setString('conversations', jsonEncode(conversations));
|
||||||
ref.read(activeConversationProvider.notifier).set(updatedConversation);
|
ref.read(activeConversationProvider.notifier).set(updatedConversation);
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Handle local storage errors silently
|
// Handle local storage errors silently
|
||||||
}
|
}
|
||||||
@@ -2095,7 +2095,7 @@ Future<void> pinConversation(
|
|||||||
await api.pinConversation(conversationId, pinned);
|
await api.pinConversation(conversationId, pinned);
|
||||||
|
|
||||||
// Refresh conversations list to reflect the change
|
// Refresh conversations list to reflect the change
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
|
|
||||||
// Update active conversation if it's the one being pinned
|
// Update active conversation if it's the one being pinned
|
||||||
final activeConversation = ref.read(activeConversationProvider);
|
final activeConversation = ref.read(activeConversationProvider);
|
||||||
@@ -2134,7 +2134,7 @@ Future<void> archiveConversation(
|
|||||||
await api.archiveConversation(conversationId, archived);
|
await api.archiveConversation(conversationId, archived);
|
||||||
|
|
||||||
// Refresh conversations list to reflect the change
|
// Refresh conversations list to reflect the change
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
DebugLogger.log(
|
DebugLogger.log(
|
||||||
'Error ${archived ? 'archiving' : 'unarchiving'} conversation: $e',
|
'Error ${archived ? 'archiving' : 'unarchiving'} conversation: $e',
|
||||||
@@ -2160,7 +2160,7 @@ Future<String?> shareConversation(WidgetRef ref, String conversationId) async {
|
|||||||
final shareId = await api.shareConversation(conversationId);
|
final shareId = await api.shareConversation(conversationId);
|
||||||
|
|
||||||
// Refresh conversations list to reflect the change
|
// Refresh conversations list to reflect the change
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
|
|
||||||
return shareId;
|
return shareId;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -2183,7 +2183,7 @@ Future<void> cloneConversation(WidgetRef ref, String conversationId) async {
|
|||||||
// The ChatMessagesNotifier will automatically load messages when activeConversation changes
|
// The ChatMessagesNotifier will automatically load messages when activeConversation changes
|
||||||
|
|
||||||
// Refresh conversations list to show the new conversation
|
// Refresh conversations list to show the new conversation
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
DebugLogger.log('Error cloning conversation: $e', scope: 'chat/providers');
|
DebugLogger.log('Error cloning conversation: $e', scope: 'chat/providers');
|
||||||
rethrow;
|
rethrow;
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
|
|
||||||
// Force refresh conversations provider to ensure we get the demo conversations
|
// Force refresh conversations provider to ensure we get the demo conversations
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
|
|
||||||
// Try to load demo conversation
|
// Try to load demo conversation
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
@@ -1486,7 +1486,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
// Also refresh the conversations list to reconcile missed events
|
// Also refresh the conversations list to reconcile missed events
|
||||||
// and keep timestamps/order in sync with the server.
|
// and keep timestamps/order in sync with the server.
|
||||||
try {
|
try {
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
// Best-effort await to stabilize UI; ignore errors.
|
// Best-effort await to stabilize UI; ignore errors.
|
||||||
await ref.read(conversationsProvider.future);
|
await ref.read(conversationsProvider.future);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|||||||
@@ -1112,7 +1112,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
activeColor = null;
|
activeColor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double iconSize = IconSize.xl;
|
const double iconSize = IconSize.large;
|
||||||
|
|
||||||
final Color iconColor = !enabled
|
final Color iconColor = !enabled
|
||||||
? context.conduitTheme.textPrimary.withValues(alpha: Alpha.disabled)
|
? context.conduitTheme.textPrimary.withValues(alpha: Alpha.disabled)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import '../../../core/providers/app_providers.dart';
|
|||||||
import '../../../shared/theme/theme_extensions.dart';
|
import '../../../shared/theme/theme_extensions.dart';
|
||||||
import '../../chat/providers/chat_providers.dart' as chat;
|
import '../../chat/providers/chat_providers.dart' as chat;
|
||||||
// import '../../files/views/files_page.dart';
|
// import '../../files/views/files_page.dart';
|
||||||
import '../../../shared/utils/ui_utils.dart';
|
import '../../../core/utils/debug_logger.dart';
|
||||||
import '../../../core/services/navigation_service.dart';
|
import '../../../core/services/navigation_service.dart';
|
||||||
import '../../../shared/widgets/themed_dialogs.dart';
|
import '../../../shared/widgets/themed_dialogs.dart';
|
||||||
import 'package:conduit/l10n/app_localizations.dart';
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
@@ -55,12 +55,11 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
|
|
||||||
Future<void> _refreshChats() async {
|
Future<void> _refreshChats() async {
|
||||||
try {
|
try {
|
||||||
// Always refresh folders
|
// Always refresh folders and conversations cache
|
||||||
ref.invalidate(foldersProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
|
|
||||||
if (_query.trim().isEmpty) {
|
if (_query.trim().isEmpty) {
|
||||||
// Refresh main conversations list
|
// Refresh main conversations list
|
||||||
ref.invalidate(conversationsProvider);
|
|
||||||
try {
|
try {
|
||||||
await ref.read(conversationsProvider.future);
|
await ref.read(conversationsProvider.future);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
@@ -629,15 +628,17 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.createFolder(name: name);
|
await api.createFolder(name: name);
|
||||||
HapticFeedback.lightImpact();
|
HapticFeedback.lightImpact();
|
||||||
ref.invalidate(foldersProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
|
} catch (e, stackTrace) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
UiUtils.showMessage(context, AppLocalizations.of(context)!.folderCreated);
|
DebugLogger.error(
|
||||||
} catch (e) {
|
'create-folder-failed',
|
||||||
if (!mounted) return;
|
scope: 'drawer',
|
||||||
UiUtils.showMessage(
|
error: e,
|
||||||
context,
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
await _showDrawerError(
|
||||||
AppLocalizations.of(context)!.failedToCreateFolder,
|
AppLocalizations.of(context)!.failedToCreateFolder,
|
||||||
isError: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,22 +669,17 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.moveConversationToFolder(details.data.id, folderId);
|
await api.moveConversationToFolder(details.data.id, folderId);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
ref.invalidate(foldersProvider);
|
} catch (e, stackTrace) {
|
||||||
|
DebugLogger.error(
|
||||||
|
'move-conversation-failed',
|
||||||
|
scope: 'drawer',
|
||||||
|
error: e,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
UiUtils.showMessage(
|
await _showDrawerError(
|
||||||
context,
|
|
||||||
AppLocalizations.of(
|
|
||||||
context,
|
|
||||||
)!.movedChatToFolder(details.data.title, name),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (_) {
|
|
||||||
if (mounted) {
|
|
||||||
UiUtils.showMessage(
|
|
||||||
context,
|
|
||||||
AppLocalizations.of(context)!.failedToMoveChat,
|
AppLocalizations.of(context)!.failedToMoveChat,
|
||||||
isError: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -868,6 +864,28 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _showDrawerError(String message) async {
|
||||||
|
if (!mounted) return;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final theme = context.conduitTheme;
|
||||||
|
await ThemedDialogs.show<void>(
|
||||||
|
context,
|
||||||
|
title: l10n.errorMessage,
|
||||||
|
content: Text(
|
||||||
|
message,
|
||||||
|
style: AppTypography.bodyMediumStyle.copyWith(
|
||||||
|
color: theme.textSecondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(l10n.ok),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _showFolderContextMenu(
|
void _showFolderContextMenu(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
String folderId,
|
String folderId,
|
||||||
@@ -923,14 +941,16 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.updateFolder(folderId, name: newName);
|
await api.updateFolder(folderId, name: newName);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
ref.invalidate(foldersProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
} catch (_) {
|
} catch (e, stackTrace) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
UiUtils.showMessage(
|
DebugLogger.error(
|
||||||
this.context,
|
'rename-folder-failed',
|
||||||
'Failed to rename folder',
|
scope: 'drawer',
|
||||||
isError: true,
|
error: e,
|
||||||
|
stackTrace: stackTrace,
|
||||||
);
|
);
|
||||||
|
await _showDrawerError('Failed to rename folder');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -956,11 +976,16 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.deleteFolder(folderId);
|
await api.deleteFolder(folderId);
|
||||||
HapticFeedback.mediumImpact();
|
HapticFeedback.mediumImpact();
|
||||||
ref.invalidate(foldersProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
ref.invalidate(conversationsProvider);
|
} catch (e, stackTrace) {
|
||||||
} catch (_) {
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
UiUtils.showMessage(this.context, deleteFolderError, isError: true);
|
DebugLogger.error(
|
||||||
|
'delete-folder-failed',
|
||||||
|
scope: 'drawer',
|
||||||
|
error: e,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
await _showDrawerError(deleteFolderError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,17 +1009,16 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.moveConversationToFolder(details.data.id, null);
|
await api.moveConversationToFolder(details.data.id, null);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref, includeFolders: true);
|
||||||
ref.invalidate(foldersProvider);
|
} catch (e, stackTrace) {
|
||||||
|
DebugLogger.error(
|
||||||
|
'unfile-conversation-failed',
|
||||||
|
scope: 'drawer',
|
||||||
|
error: e,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
UiUtils.showMessage(
|
await _showDrawerError(l10n.failedToMoveChat);
|
||||||
context,
|
|
||||||
'Removed "${details.data.title}" from folder',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (_) {
|
|
||||||
if (mounted) {
|
|
||||||
UiUtils.showMessage(context, l10n.failedToMoveChat, isError: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'dart:io' show Platform;
|
|||||||
import 'package:conduit/core/providers/app_providers.dart';
|
import 'package:conduit/core/providers/app_providers.dart';
|
||||||
import 'package:conduit/l10n/app_localizations.dart';
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
import 'package:conduit/shared/theme/theme_extensions.dart';
|
import 'package:conduit/shared/theme/theme_extensions.dart';
|
||||||
import 'package:conduit/shared/utils/ui_utils.dart';
|
|
||||||
import 'package:conduit/shared/widgets/conduit_components.dart';
|
import 'package:conduit/shared/widgets/conduit_components.dart';
|
||||||
import 'package:conduit/shared/widgets/modal_safe_area.dart';
|
import 'package:conduit/shared/widgets/modal_safe_area.dart';
|
||||||
import 'package:conduit/shared/widgets/sheet_handle.dart';
|
import 'package:conduit/shared/widgets/sheet_handle.dart';
|
||||||
@@ -123,7 +122,7 @@ Future<void> showConversationContextMenu({
|
|||||||
await chat.pinConversation(ref, conversation.id, !isPinned);
|
await chat.pinConversation(ref, conversation.id, !isPinned);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
UiUtils.showMessage(context, errorMessage, isError: true);
|
await _showConversationError(context, errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +132,7 @@ Future<void> showConversationContextMenu({
|
|||||||
await chat.archiveConversation(ref, conversation.id, !isArchived);
|
await chat.archiveConversation(ref, conversation.id, !isArchived);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
UiUtils.showMessage(context, errorMessage, isError: true);
|
await _showConversationError(context, errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +220,7 @@ Future<void> _renameConversation(
|
|||||||
if (api == null) throw Exception('No API service');
|
if (api == null) throw Exception('No API service');
|
||||||
await api.updateConversation(conversationId, title: newName);
|
await api.updateConversation(conversationId, title: newName);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
final active = ref.read(activeConversationProvider);
|
final active = ref.read(activeConversationProvider);
|
||||||
if (active?.id == conversationId) {
|
if (active?.id == conversationId) {
|
||||||
ref
|
ref
|
||||||
@@ -230,7 +229,7 @@ Future<void> _renameConversation(
|
|||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
UiUtils.showMessage(context, renameError, isError: true);
|
await _showConversationError(context, renameError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,9 +261,29 @@ Future<void> _confirmAndDeleteConversation(
|
|||||||
ref.read(activeConversationProvider.notifier).clear();
|
ref.read(activeConversationProvider.notifier).clear();
|
||||||
ref.read(chat.chatMessagesProvider.notifier).clearMessages();
|
ref.read(chat.chatMessagesProvider.notifier).clearMessages();
|
||||||
}
|
}
|
||||||
ref.invalidate(conversationsProvider);
|
refreshConversationsCache(ref);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
UiUtils.showMessage(context, deleteError, isError: true);
|
await _showConversationError(context, deleteError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _showConversationError(
|
||||||
|
BuildContext context,
|
||||||
|
String message,
|
||||||
|
) async {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final theme = context.conduitTheme;
|
||||||
|
await ThemedDialogs.show<void>(
|
||||||
|
context,
|
||||||
|
title: l10n.errorMessage,
|
||||||
|
content: Text(message, style: TextStyle(color: theme.textSecondary)),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text(l10n.ok),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user