diff --git a/lib/pods/chat/messages_notifier.dart b/lib/pods/chat/messages_notifier.dart index e76de22e..0c5765b5 100644 --- a/lib/pods/chat/messages_notifier.dart +++ b/lib/pods/chat/messages_notifier.dart @@ -128,7 +128,7 @@ class MessagesNotifier extends _$MessagesNotifier { uniqueMessages.add(message); } } - state = AsyncValue.data(uniqueMessages); + if (ref.mounted) state = AsyncValue.data(uniqueMessages); } finally { _isUpdatingState = false; } @@ -350,7 +350,7 @@ class MessagesNotifier extends _$MessagesNotifier { offset: 0, take: _pageSize, ); - state = AsyncValue.data(newMessages); + if (ref.mounted) state = AsyncValue.data(newMessages); return; } @@ -408,7 +408,9 @@ class MessagesNotifier extends _$MessagesNotifier { } finally { talker.log('Finished message sync'); // Always reset global syncing state, regardless of disposal - Future.microtask(() => ref.read(chatSyncingProvider.notifier).set(false)); + Future.microtask(() { + if (ref.mounted) ref.read(chatSyncingProvider.notifier).set(false); + }); _isSyncing = false; } } @@ -498,7 +500,7 @@ class MessagesNotifier extends _$MessagesNotifier { _hasMore = messages.length == _pageSize; - state = AsyncValue.data(messages); + if (ref.mounted) state = AsyncValue.data(messages); } Future loadMore() async { @@ -509,7 +511,7 @@ class MessagesNotifier extends _$MessagesNotifier { Future.microtask(() => ref.read(chatSyncingProvider.notifier).set(true)); } try { - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final offset = currentMessages.length; final newMessages = await listMessages(offset: offset, take: _pageSize); @@ -518,9 +520,11 @@ class MessagesNotifier extends _$MessagesNotifier { _hasMore = false; } - state = AsyncValue.data( - _sortMessages([...currentMessages, ...newMessages]), - ); + if (ref.mounted) { + state = AsyncValue.data( + _sortMessages([...currentMessages, ...newMessages]), + ); + } } catch (err, stackTrace) { talker.log( 'Error loading more messages', @@ -531,12 +535,14 @@ class MessagesNotifier extends _$MessagesNotifier { showErrorAlert(err); } finally { // Always reset global syncing state, regardless of disposal - Future.microtask(() => ref.read(chatSyncingProvider.notifier).set(false)); + Future.microtask(() { + if (ref.mounted) ref.read(chatSyncingProvider.notifier).set(false); + }); } } Future sendMessage( - WidgetRef ref, + WidgetRef outerRef, String content, List attachments, { SnPoll? poll, @@ -569,14 +575,14 @@ class MessagesNotifier extends _$MessagesNotifier { _fileUploadProgress[localMessage.id] = {}; await _database.saveMessageWithSender(localMessage); - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; state = AsyncValue.data([localMessage, ...currentMessages]); try { var cloudAttachments = List.empty(growable: true); for (var idx = 0; idx < attachments.length; idx++) { final cloudFile = await FileUploader.createCloudFile( - ref: ref, + ref: outerRef, fileData: attachments[idx], onProgress: (progress, _) { _fileUploadProgress[localMessage.id]?[idx] = progress ?? 0.0; @@ -619,24 +625,27 @@ class MessagesNotifier extends _$MessagesNotifier { await _database.deleteMessage(localMessage.id); await _database.saveMessageWithSender(updatedMessage); - final currentMessages = state.value ?? []; - if (editingTo != null) { - final newMessages = currentMessages - .where((m) => m.id != localMessage.id) // remove pending message - .map( - (m) => m.id == editingTo.id ? updatedMessage : m, - ) // update original message - .toList(); - state = AsyncValue.data(newMessages); - } else { - final newMessages = currentMessages.map((m) { - if (m.id == localMessage.id) { - return updatedMessage; - } - return m; - }).toList(); - state = AsyncValue.data(newMessages); + if (ref.mounted) { + final currentMessages = state.value ?? []; + if (editingTo != null) { + final newMessages = currentMessages + .where((m) => m.id != localMessage.id) // remove pending message + .map( + (m) => m.id == editingTo.id ? updatedMessage : m, + ) // update original message + .toList(); + state = AsyncValue.data(newMessages); + } else { + final newMessages = currentMessages.map((m) { + if (m.id == localMessage.id) { + return updatedMessage; + } + return m; + }).toList(); + state = AsyncValue.data(newMessages); + } } + talker.log('Message with nonce $nonce sent successfully'); } catch (e, stackTrace) { talker.log( @@ -651,13 +660,15 @@ class MessagesNotifier extends _$MessagesNotifier { localMessage.id, MessageStatus.failed, ); - final newMessages = (state.value ?? []).map((m) { - if (m.id == localMessage.id) { - return m..status = MessageStatus.failed; - } - return m; - }).toList(); - state = AsyncValue.data(newMessages); + if (ref.mounted) { + final newMessages = (state.value ?? []).map((m) { + if (m.id == localMessage.id) { + return m..status = MessageStatus.failed; + } + return m; + }).toList(); + state = AsyncValue.data(newMessages); + } showErrorAlert(e); } } @@ -698,13 +709,15 @@ class MessagesNotifier extends _$MessagesNotifier { await _database.deleteMessage(pendingMessageId); await _database.saveMessageWithSender(updatedMessage); - final newMessages = (state.value ?? []).map((m) { - if (m.id == pendingMessageId) { - return updatedMessage; - } - return m; - }).toList(); - state = AsyncValue.data(newMessages); + if (ref.mounted) { + final newMessages = (state.value ?? []).map((m) { + if (m.id == pendingMessageId) { + return updatedMessage; + } + return m; + }).toList(); + state = AsyncValue.data(newMessages); + } } catch (e, stackTrace) { talker.log( 'Failed to retry message $pendingMessageId', @@ -718,13 +731,15 @@ class MessagesNotifier extends _$MessagesNotifier { pendingMessageId, MessageStatus.failed, ); - final newMessages = (state.value ?? []).map((m) { - if (m.id == pendingMessageId) { - return m..status = MessageStatus.failed; - } - return m; - }).toList(); - state = AsyncValue.data(_sortMessages(newMessages)); + if (ref.mounted) { + final newMessages = (state.value ?? []).map((m) { + if (m.id == pendingMessageId) { + return m..status = MessageStatus.failed; + } + return m; + }).toList(); + state = AsyncValue.data(_sortMessages(newMessages)); + } showErrorAlert(e); } } @@ -756,21 +771,23 @@ class MessagesNotifier extends _$MessagesNotifier { if (!isSilentMessage) { await _database.saveMessageWithSender(localMessage); - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final existingIndex = currentMessages.indexWhere( (m) => m.id == localMessage.id || (localMessage.nonce != null && m.nonce == localMessage.nonce), ); - if (existingIndex >= 0) { - final newList = [...currentMessages]; - newList[existingIndex] = localMessage; - state = AsyncValue.data(_sortMessages(newList)); - } else { - state = AsyncValue.data( - _sortMessages([localMessage, ...currentMessages]), - ); + if (ref.mounted) { + if (existingIndex >= 0) { + final newList = [...currentMessages]; + newList[existingIndex] = localMessage; + state = AsyncValue.data(_sortMessages(newList)); + } else { + state = AsyncValue.data( + _sortMessages([localMessage, ...currentMessages]), + ); + } } } @@ -837,13 +854,15 @@ class MessagesNotifier extends _$MessagesNotifier { await _database.updateMessage(_database.messageToCompanion(updatedMessage)); - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final index = currentMessages.indexWhere((m) => m.id == updatedMessage.id); - if (index >= 0) { - final newList = [...currentMessages]; - newList[index] = updatedMessage; - state = AsyncValue.data(_sortMessages(newList)); + if (ref.mounted) { + if (index >= 0) { + final newList = [...currentMessages]; + newList[index] = updatedMessage; + state = AsyncValue.data(_sortMessages(newList)); + } } } @@ -857,7 +876,7 @@ class MessagesNotifier extends _$MessagesNotifier { talker.log('Received message deletion $messageId'); _pendingMessages.remove(messageId); - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final messageIndex = currentMessages.indexWhere((m) => m.id == messageId); LocalChatMessage? messageToUpdate; @@ -883,10 +902,12 @@ class MessagesNotifier extends _$MessagesNotifier { await _database.saveMessageWithSender(deletedMessage); - if (messageIndex != -1) { - final newList = [...currentMessages]; - newList[messageIndex] = deletedMessage; - state = AsyncValue.data(newList); + if (ref.mounted) { + if (messageIndex != -1) { + final newList = [...currentMessages]; + newList[messageIndex] = deletedMessage; + state = AsyncValue.data(newList); + } } } @@ -907,7 +928,7 @@ class MessagesNotifier extends _$MessagesNotifier { _pendingMessages.remove(messageId); await _database.deleteMessage(messageId); - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final newMessages = currentMessages .where((m) => m.id != messageId) .toList(); @@ -1063,7 +1084,7 @@ class MessagesNotifier extends _$MessagesNotifier { } // Check if message is already in current state to avoid duplicate loading - final currentMessages = state.value ?? []; + final currentMessages = (ref.mounted ? state.value : null) ?? []; final existingIndex = currentMessages.indexWhere( (m) => m.id == messageId, );