feat: enhanced sockets, tuned retries and polling fallback
This commit is contained in:
@@ -55,10 +55,27 @@ class ChatMessagesNotifier extends StateNotifier<List<ChatMessage>> {
|
||||
// locally streamed assistant content with an outdated server copy.
|
||||
if (previous?.updatedAt != next?.updatedAt) {
|
||||
final serverMessages = next?.messages ?? const [];
|
||||
// Only replace local messages if the server has strictly more messages
|
||||
// (i.e., includes new content we don't have yet).
|
||||
// Primary rule: adopt server messages when there are strictly more of them.
|
||||
if (serverMessages.length > state.length) {
|
||||
state = serverMessages;
|
||||
return;
|
||||
}
|
||||
|
||||
// Secondary rule: if counts are equal but the last assistant message grew,
|
||||
// adopt the server copy to recover from missed socket events.
|
||||
if (serverMessages.isNotEmpty && state.isNotEmpty) {
|
||||
final serverLast = serverMessages.last;
|
||||
final localLast = state.last;
|
||||
final serverText = serverLast.content.trim();
|
||||
final localText = localLast.content.trim();
|
||||
final sameLastId = serverLast.id == localLast.id;
|
||||
final isAssistant = serverLast.role == 'assistant';
|
||||
final serverHasMore = serverText.isNotEmpty && serverText.length > localText.length;
|
||||
final localEmptyButServerHas = localText.isEmpty && serverText.isNotEmpty;
|
||||
if (sameLastId && isAssistant && (serverHasMore || localEmptyButServerHas)) {
|
||||
state = serverMessages;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -1408,16 +1408,21 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
||||
try {
|
||||
final full = await api.getConversation(active.id);
|
||||
ref
|
||||
.read(activeConversationProvider.notifier)
|
||||
.state =
|
||||
full;
|
||||
.read(activeConversationProvider.notifier)
|
||||
.state = full;
|
||||
} catch (e) {
|
||||
debugPrint(
|
||||
'DEBUG: Failed to refresh conversation: $e',
|
||||
);
|
||||
// Could show a snackbar here if needed
|
||||
debugPrint('DEBUG: Failed to refresh conversation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Also refresh the conversations list to reconcile missed events
|
||||
// and keep timestamps/order in sync with the server.
|
||||
try {
|
||||
ref.invalidate(conversationsProvider);
|
||||
// Best-effort await to stabilize UI; ignore errors.
|
||||
await ref.read(conversationsProvider.future);
|
||||
} catch (_) {}
|
||||
|
||||
// Add small delay for better UX feedback
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user