From fee149c1fbc63f52aa66148018e569e30cca6161 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Sun, 22 Mar 2026 20:04:15 +0100
Subject: [PATCH] fix: voice transcript display, audio file persistence, debug logging

---
 lib/models/message.dart      |    7 +++++--
 lib/screens/chat_screen.dart |   18 +++++++++++++++++-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/lib/models/message.dart b/lib/models/message.dart
index 48dc9c0..8a034ec 100644
--- a/lib/models/message.dart
+++ b/lib/models/message.dart
@@ -114,18 +114,21 @@
     };
   }
 
-  /// Lightweight JSON for persistence (strips temp audio paths, keeps images).
+  /// Lightweight JSON for persistence (strips base64 audio, keeps file paths and images).
   Map<String, dynamic> toJsonLight() {
+    // Keep audioUri if it's a file path (starts with '/') — these are saved audio files.
+    // Strip base64 audio data (large, temp) — those won't survive restart.
+    final keepAudio = audioUri != null && audioUri!.startsWith('/');
     return {
       'id': id,
       'role': role.name,
       'type': type.name,
       'content': content,
+      if (keepAudio) 'audioUri': audioUri,
       'timestamp': timestamp,
       if (status != null) 'status': status!.name,
       if (duration != null) 'duration': duration,
       // Keep imageBase64 — images are typically 50-200 KB and must survive restart.
-      // audioUri is intentionally omitted: it is a temp file path that won't survive restart.
       if (imageBase64 != null) 'imageBase64': imageBase64,
     };
   }
diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart
index 0c302f5..3137ff4 100644
--- a/lib/screens/chat_screen.dart
+++ b/lib/screens/chat_screen.dart
@@ -34,6 +34,15 @@
   ConsumerState<ChatScreen> createState() => _ChatScreenState();
 }
 
+Future<void> _chatLog(String msg) async {
+  try {
+    final dir = await getApplicationDocumentsDirectory();
+    final file = File('${dir.path}/mqtt_debug.log');
+    final ts = DateTime.now().toIso8601String().substring(11, 19);
+    await file.writeAsString('[$ts] $msg\n', mode: FileMode.append);
+  } catch (_) {}
+}
+
 class _ChatScreenState extends ConsumerState<ChatScreen>
     with WidgetsBindingObserver {
   MqttService? _ws;
@@ -307,7 +316,7 @@
   Future<void> _handleIncomingVoice(Map<String, dynamic> msg) async {
     final sessionId = msg['sessionId'] as String?;
     final audioData = msg['audioBase64'] as String? ?? msg['audio'] as String? ?? msg['data'] as String?;
-    final content = msg['content'] as String? ?? msg['text'] as String? ?? '';
+    final content = msg['content'] as String? ?? msg['transcript'] as String? ?? msg['text'] as String? ?? '';
     final duration = msg['duration'] as int?;
 
     final message = Message(
@@ -346,8 +355,11 @@
     );
 
     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) {
+      _chatLog('voice: cross-session, storing for $sessionId');
       await _storeForSession(sessionId, storedMessage);
+      _chatLog('voice: stored, incrementing unread');
       _incrementUnread(sessionId);
       final sessions = ref.read(sessionsProvider);
       final session = sessions.firstWhere(
@@ -414,8 +426,12 @@
   /// Store a message for a non-active session so it persists when the user switches to it.
   Future<void> _storeForSession(String sessionId, Message message) async {
     final existing = await MessageStore.loadAll(sessionId);
+    _chatLog('storeForSession: $sessionId existing=${existing.length} adding type=${message.type.name} content="${message.content.substring(0, message.content.length.clamp(0, 30))}" audioUri=${message.audioUri != null ? "set(${message.audioUri!.length})" : "null"}');
     MessageStore.save(sessionId, [...existing, message]);
     await MessageStore.flush();
+    // Verify
+    final verify = await MessageStore.loadAll(sessionId);
+    _chatLog('storeForSession: verified ${verify.length} messages after save');
   }
 
   void _incrementUnread(String sessionId) {

--
Gitblit v1.3.1