🐛 Add well defined mounted check in messages notifier
This commit is contained in:
@@ -128,7 +128,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
uniqueMessages.add(message);
|
uniqueMessages.add(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = AsyncValue.data(uniqueMessages);
|
if (ref.mounted) state = AsyncValue.data(uniqueMessages);
|
||||||
} finally {
|
} finally {
|
||||||
_isUpdatingState = false;
|
_isUpdatingState = false;
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
take: _pageSize,
|
take: _pageSize,
|
||||||
);
|
);
|
||||||
state = AsyncValue.data(newMessages);
|
if (ref.mounted) state = AsyncValue.data(newMessages);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +408,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
talker.log('Finished message sync');
|
talker.log('Finished message sync');
|
||||||
// Always reset global syncing state, regardless of disposal
|
// 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;
|
_isSyncing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,7 +500,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
|
|
||||||
_hasMore = messages.length == _pageSize;
|
_hasMore = messages.length == _pageSize;
|
||||||
|
|
||||||
state = AsyncValue.data(messages);
|
if (ref.mounted) state = AsyncValue.data(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadMore() async {
|
Future<void> loadMore() async {
|
||||||
@@ -509,7 +511,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
Future.microtask(() => ref.read(chatSyncingProvider.notifier).set(true));
|
Future.microtask(() => ref.read(chatSyncingProvider.notifier).set(true));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = (ref.mounted ? state.value : null) ?? [];
|
||||||
final offset = currentMessages.length;
|
final offset = currentMessages.length;
|
||||||
|
|
||||||
final newMessages = await listMessages(offset: offset, take: _pageSize);
|
final newMessages = await listMessages(offset: offset, take: _pageSize);
|
||||||
@@ -518,9 +520,11 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_hasMore = false;
|
_hasMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
state = AsyncValue.data(
|
state = AsyncValue.data(
|
||||||
_sortMessages([...currentMessages, ...newMessages]),
|
_sortMessages([...currentMessages, ...newMessages]),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} catch (err, stackTrace) {
|
} catch (err, stackTrace) {
|
||||||
talker.log(
|
talker.log(
|
||||||
'Error loading more messages',
|
'Error loading more messages',
|
||||||
@@ -531,12 +535,14 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
} finally {
|
} finally {
|
||||||
// Always reset global syncing state, regardless of disposal
|
// 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<void> sendMessage(
|
Future<void> sendMessage(
|
||||||
WidgetRef ref,
|
WidgetRef outerRef,
|
||||||
String content,
|
String content,
|
||||||
List<UniversalFile> attachments, {
|
List<UniversalFile> attachments, {
|
||||||
SnPoll? poll,
|
SnPoll? poll,
|
||||||
@@ -569,14 +575,14 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_fileUploadProgress[localMessage.id] = {};
|
_fileUploadProgress[localMessage.id] = {};
|
||||||
await _database.saveMessageWithSender(localMessage);
|
await _database.saveMessageWithSender(localMessage);
|
||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = (ref.mounted ? state.value : null) ?? [];
|
||||||
state = AsyncValue.data([localMessage, ...currentMessages]);
|
state = AsyncValue.data([localMessage, ...currentMessages]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var cloudAttachments = List.empty(growable: true);
|
var cloudAttachments = List.empty(growable: true);
|
||||||
for (var idx = 0; idx < attachments.length; idx++) {
|
for (var idx = 0; idx < attachments.length; idx++) {
|
||||||
final cloudFile = await FileUploader.createCloudFile(
|
final cloudFile = await FileUploader.createCloudFile(
|
||||||
ref: ref,
|
ref: outerRef,
|
||||||
fileData: attachments[idx],
|
fileData: attachments[idx],
|
||||||
onProgress: (progress, _) {
|
onProgress: (progress, _) {
|
||||||
_fileUploadProgress[localMessage.id]?[idx] = progress ?? 0.0;
|
_fileUploadProgress[localMessage.id]?[idx] = progress ?? 0.0;
|
||||||
@@ -619,6 +625,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
await _database.deleteMessage(localMessage.id);
|
await _database.deleteMessage(localMessage.id);
|
||||||
await _database.saveMessageWithSender(updatedMessage);
|
await _database.saveMessageWithSender(updatedMessage);
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = state.value ?? [];
|
||||||
if (editingTo != null) {
|
if (editingTo != null) {
|
||||||
final newMessages = currentMessages
|
final newMessages = currentMessages
|
||||||
@@ -637,6 +644,8 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
}).toList();
|
}).toList();
|
||||||
state = AsyncValue.data(newMessages);
|
state = AsyncValue.data(newMessages);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
talker.log('Message with nonce $nonce sent successfully');
|
talker.log('Message with nonce $nonce sent successfully');
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
talker.log(
|
talker.log(
|
||||||
@@ -651,6 +660,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
localMessage.id,
|
localMessage.id,
|
||||||
MessageStatus.failed,
|
MessageStatus.failed,
|
||||||
);
|
);
|
||||||
|
if (ref.mounted) {
|
||||||
final newMessages = (state.value ?? []).map((m) {
|
final newMessages = (state.value ?? []).map((m) {
|
||||||
if (m.id == localMessage.id) {
|
if (m.id == localMessage.id) {
|
||||||
return m..status = MessageStatus.failed;
|
return m..status = MessageStatus.failed;
|
||||||
@@ -658,6 +668,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
return m;
|
return m;
|
||||||
}).toList();
|
}).toList();
|
||||||
state = AsyncValue.data(newMessages);
|
state = AsyncValue.data(newMessages);
|
||||||
|
}
|
||||||
showErrorAlert(e);
|
showErrorAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -698,6 +709,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
await _database.deleteMessage(pendingMessageId);
|
await _database.deleteMessage(pendingMessageId);
|
||||||
await _database.saveMessageWithSender(updatedMessage);
|
await _database.saveMessageWithSender(updatedMessage);
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
final newMessages = (state.value ?? []).map((m) {
|
final newMessages = (state.value ?? []).map((m) {
|
||||||
if (m.id == pendingMessageId) {
|
if (m.id == pendingMessageId) {
|
||||||
return updatedMessage;
|
return updatedMessage;
|
||||||
@@ -705,6 +717,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
return m;
|
return m;
|
||||||
}).toList();
|
}).toList();
|
||||||
state = AsyncValue.data(newMessages);
|
state = AsyncValue.data(newMessages);
|
||||||
|
}
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
talker.log(
|
talker.log(
|
||||||
'Failed to retry message $pendingMessageId',
|
'Failed to retry message $pendingMessageId',
|
||||||
@@ -718,6 +731,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
pendingMessageId,
|
pendingMessageId,
|
||||||
MessageStatus.failed,
|
MessageStatus.failed,
|
||||||
);
|
);
|
||||||
|
if (ref.mounted) {
|
||||||
final newMessages = (state.value ?? []).map((m) {
|
final newMessages = (state.value ?? []).map((m) {
|
||||||
if (m.id == pendingMessageId) {
|
if (m.id == pendingMessageId) {
|
||||||
return m..status = MessageStatus.failed;
|
return m..status = MessageStatus.failed;
|
||||||
@@ -725,6 +739,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
return m;
|
return m;
|
||||||
}).toList();
|
}).toList();
|
||||||
state = AsyncValue.data(_sortMessages(newMessages));
|
state = AsyncValue.data(_sortMessages(newMessages));
|
||||||
|
}
|
||||||
showErrorAlert(e);
|
showErrorAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,13 +771,14 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
if (!isSilentMessage) {
|
if (!isSilentMessage) {
|
||||||
await _database.saveMessageWithSender(localMessage);
|
await _database.saveMessageWithSender(localMessage);
|
||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = (ref.mounted ? state.value : null) ?? [];
|
||||||
final existingIndex = currentMessages.indexWhere(
|
final existingIndex = currentMessages.indexWhere(
|
||||||
(m) =>
|
(m) =>
|
||||||
m.id == localMessage.id ||
|
m.id == localMessage.id ||
|
||||||
(localMessage.nonce != null && m.nonce == localMessage.nonce),
|
(localMessage.nonce != null && m.nonce == localMessage.nonce),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
if (existingIndex >= 0) {
|
if (existingIndex >= 0) {
|
||||||
final newList = [...currentMessages];
|
final newList = [...currentMessages];
|
||||||
newList[existingIndex] = localMessage;
|
newList[existingIndex] = localMessage;
|
||||||
@@ -773,6 +789,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (remoteMessage.type) {
|
switch (remoteMessage.type) {
|
||||||
case "messages.delete":
|
case "messages.delete":
|
||||||
@@ -837,15 +854,17 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
|
|
||||||
await _database.updateMessage(_database.messageToCompanion(updatedMessage));
|
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);
|
final index = currentMessages.indexWhere((m) => m.id == updatedMessage.id);
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
final newList = [...currentMessages];
|
final newList = [...currentMessages];
|
||||||
newList[index] = updatedMessage;
|
newList[index] = updatedMessage;
|
||||||
state = AsyncValue.data(_sortMessages(newList));
|
state = AsyncValue.data(_sortMessages(newList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> receiveMessageDeletion(String messageId) async {
|
Future<void> receiveMessageDeletion(String messageId) async {
|
||||||
// Block message deletions during jumps to prevent list resets
|
// Block message deletions during jumps to prevent list resets
|
||||||
@@ -857,7 +876,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
talker.log('Received message deletion $messageId');
|
talker.log('Received message deletion $messageId');
|
||||||
_pendingMessages.remove(messageId);
|
_pendingMessages.remove(messageId);
|
||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = (ref.mounted ? state.value : null) ?? [];
|
||||||
final messageIndex = currentMessages.indexWhere((m) => m.id == messageId);
|
final messageIndex = currentMessages.indexWhere((m) => m.id == messageId);
|
||||||
|
|
||||||
LocalChatMessage? messageToUpdate;
|
LocalChatMessage? messageToUpdate;
|
||||||
@@ -883,12 +902,14 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
|
|
||||||
await _database.saveMessageWithSender(deletedMessage);
|
await _database.saveMessageWithSender(deletedMessage);
|
||||||
|
|
||||||
|
if (ref.mounted) {
|
||||||
if (messageIndex != -1) {
|
if (messageIndex != -1) {
|
||||||
final newList = [...currentMessages];
|
final newList = [...currentMessages];
|
||||||
newList[messageIndex] = deletedMessage;
|
newList[messageIndex] = deletedMessage;
|
||||||
state = AsyncValue.data(newList);
|
state = AsyncValue.data(newList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> deleteMessage(String messageId) async {
|
Future<void> deleteMessage(String messageId) async {
|
||||||
talker.log('Deleting message $messageId');
|
talker.log('Deleting message $messageId');
|
||||||
@@ -907,7 +928,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_pendingMessages.remove(messageId);
|
_pendingMessages.remove(messageId);
|
||||||
await _database.deleteMessage(messageId);
|
await _database.deleteMessage(messageId);
|
||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = (ref.mounted ? state.value : null) ?? [];
|
||||||
final newMessages = currentMessages
|
final newMessages = currentMessages
|
||||||
.where((m) => m.id != messageId)
|
.where((m) => m.id != messageId)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -1063,7 +1084,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if message is already in current state to avoid duplicate loading
|
// 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(
|
final existingIndex = currentMessages.indexWhere(
|
||||||
(m) => m.id == messageId,
|
(m) => m.id == messageId,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user