refactor: optimize chat drawer state management by using a detached provider container for improved performance and loading state handling
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user