From 6cbbea9b96db551e5c0ac26f0ace3d4c3d82a276 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Mon, 06 Apr 2026 15:02:33 +0200
Subject: [PATCH] fix: single pailot/out topic, per-session file locks, merge protection, resume reconnect
---
lib/screens/chat_screen.dart | 33 +++++++++++++++++++--------------
1 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart
index e889469..f331ab9 100644
--- a/lib/screens/chat_screen.dart
+++ b/lib/screens/chat_screen.dart
@@ -216,12 +216,15 @@
_ws!.onOpen = () {
_sessionReady = false; // Gate messages until sessions arrive
_pendingMessages.clear();
- final activeId = ref.read(activeSessionIdProvider);
- _sendCommand('sync', activeId != null ? {'activeSessionId': activeId} : null);
- // catch_up is sent after sessions arrive (in _handleSessions)
-
- // Re-register APNs token after reconnect so daemon always has a fresh token
- _push?.onMqttConnected();
+ // Delay sync slightly to let broker acknowledge our subscriptions first.
+ // Without this, the catch_up response arrives before pailot/control/out
+ // subscription is active, and the message is lost.
+ Future.delayed(const Duration(milliseconds: 500), () {
+ if (!mounted) return;
+ final activeId = ref.read(activeSessionIdProvider);
+ _sendCommand('sync', activeId != null ? {'activeSessionId': activeId} : null);
+ _push?.onMqttConnected();
+ });
};
_ws!.onResume = () {
// App came back from background. The in-memory state already has
@@ -534,8 +537,10 @@
status: MessageStatus.sent,
);
- final activeId = ref.read(activeSessionIdProvider);
- if (sessionId != null && sessionId != activeId) {
+ // Use currentSessionId from notifier (what's actually loaded in the provider)
+ // not activeSessionIdProvider (can be stale after background resume)
+ final currentId = ref.read(messagesProvider.notifier).currentSessionId;
+ if (sessionId != null && sessionId != currentId) {
// Store message for the other session so it's there when user switches
TraceService.instance.addTrace(
'message stored for session',
@@ -608,9 +613,9 @@
duration: duration,
);
- final activeId = ref.read(activeSessionIdProvider);
- _chatLog('voice: sessionId=$sessionId activeId=$activeId audioPath=$savedAudioPath content="${content.substring(0, content.length.clamp(0, 30))}"');
- if (sessionId != null && sessionId != activeId) {
+ final currentId = ref.read(messagesProvider.notifier).currentSessionId;
+ _chatLog('voice: sessionId=$sessionId currentId=$currentId audioPath=$savedAudioPath content="${content.substring(0, content.length.clamp(0, 30))}"');
+ if (sessionId != null && sessionId != currentId) {
_chatLog('voice: cross-session, storing for $sessionId');
await _storeForSession(sessionId, storedMessage);
_chatLog('voice: stored, incrementing unread');
@@ -679,9 +684,9 @@
status: MessageStatus.sent,
);
- // Cross-session routing: store for target session if not active
- final activeId = ref.read(activeSessionIdProvider);
- if (sessionId != null && sessionId != activeId) {
+ // Cross-session routing: store for target session if not currently loaded
+ final currentId = ref.read(messagesProvider.notifier).currentSessionId;
+ if (sessionId != null && sessionId != currentId) {
_storeForSession(sessionId, message);
_incrementUnread(sessionId);
return;
--
Gitblit v1.3.1