refactor: optimize chat drawer state management by using a detached provider container for improved performance and loading state handling

This commit is contained in:
cogwheel0
2025-08-26 13:42:46 +05:30
parent 807dc01e8e
commit 69c4b4c484

View File

@@ -1098,31 +1098,49 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
if (_isLoadingConversation) return; if (_isLoadingConversation) return;
setState(() => _isLoadingConversation = true); setState(() => _isLoadingConversation = true);
final navigator = Navigator.of(context); final navigator = Navigator.of(context);
// Capture a provider container detached from this widget's lifecycle so
// we can continue to read/write providers after the drawer is closed.
final container = ProviderScope.containerOf(context, listen: false);
try { try {
// Mark global loading to show skeletons in chat // Mark global loading to show skeletons in chat
ref.read(chat.isLoadingConversationProvider.notifier).state = true; container.read(chat.isLoadingConversationProvider.notifier).state = true;
_pendingConversationId = id; _pendingConversationId = id;
final api = ref.read(apiServiceProvider); // Immediately clear current chat to show loading skeleton in the chat view
container.read(activeConversationProvider.notifier).state = null;
container.read(chat.chatMessagesProvider.notifier).clearMessages();
// Close the drawer immediately for faster perceived performance
if (mounted) {
// Prefer closing the Scaffold's drawer to avoid popping other routes
final scaffold = Scaffold.maybeOf(context);
if (scaffold?.isDrawerOpen == true) {
scaffold!.closeDrawer();
} else {
navigator.maybePop();
}
}
// Load the full conversation details in the background
final api = container.read(apiServiceProvider);
if (api != null) { if (api != null) {
final full = await api.getConversation(id); final full = await api.getConversation(id);
ref.read(activeConversationProvider.notifier).state = full; container.read(activeConversationProvider.notifier).state = full;
} else { } else {
// Fallback: let ChatPage handle if API missing // Fallback: use the lightweight item to update the active conversation
ref.read(activeConversationProvider.notifier).state = (await ref.read( container
.read(activeConversationProvider.notifier)
.state = (await container.read(
conversationsProvider.future, conversationsProvider.future,
)).firstWhere((c) => c.id == id); )).firstWhere((c) => c.id == id);
} }
// Clear global loading before closing drawer // Clear loading after data is ready
ref.read(chat.isLoadingConversationProvider.notifier).state = false; container.read(chat.isLoadingConversationProvider.notifier).state = false;
_pendingConversationId = null; _pendingConversationId = null;
if (mounted) navigator.maybePop();
} catch (_) { } catch (_) {
ref.read(chat.isLoadingConversationProvider.notifier).state = false; container.read(chat.isLoadingConversationProvider.notifier).state = false;
_pendingConversationId = null; _pendingConversationId = null;
if (mounted) navigator.maybePop();
} finally { } finally {
if (mounted) setState(() => _isLoadingConversation = false); if (mounted) setState(() => _isLoadingConversation = false);
} }