| .. | .. |
|---|
| 34 | 34 | ConsumerState<ChatScreen> createState() => _ChatScreenState(); |
|---|
| 35 | 35 | } |
|---|
| 36 | 36 | |
|---|
| 37 | +Future<void> _chatLog(String msg) async { |
|---|
| 38 | + try { |
|---|
| 39 | + final dir = await getApplicationDocumentsDirectory(); |
|---|
| 40 | + final file = File('${dir.path}/mqtt_debug.log'); |
|---|
| 41 | + final ts = DateTime.now().toIso8601String().substring(11, 19); |
|---|
| 42 | + await file.writeAsString('[$ts] $msg\n', mode: FileMode.append); |
|---|
| 43 | + } catch (_) {} |
|---|
| 44 | +} |
|---|
| 45 | + |
|---|
| 37 | 46 | class _ChatScreenState extends ConsumerState<ChatScreen> |
|---|
| 38 | 47 | with WidgetsBindingObserver { |
|---|
| 39 | 48 | MqttService? _ws; |
|---|
| .. | .. |
|---|
| 307 | 316 | Future<void> _handleIncomingVoice(Map<String, dynamic> msg) async { |
|---|
| 308 | 317 | final sessionId = msg['sessionId'] as String?; |
|---|
| 309 | 318 | final audioData = msg['audioBase64'] as String? ?? msg['audio'] as String? ?? msg['data'] as String?; |
|---|
| 310 | | - final content = msg['content'] as String? ?? msg['text'] as String? ?? ''; |
|---|
| 319 | + final content = msg['content'] as String? ?? msg['transcript'] as String? ?? msg['text'] as String? ?? ''; |
|---|
| 311 | 320 | final duration = msg['duration'] as int?; |
|---|
| 312 | 321 | |
|---|
| 313 | 322 | final message = Message( |
|---|
| .. | .. |
|---|
| 346 | 355 | ); |
|---|
| 347 | 356 | |
|---|
| 348 | 357 | final activeId = ref.read(activeSessionIdProvider); |
|---|
| 358 | + _chatLog('voice: sessionId=$sessionId activeId=$activeId audioPath=$savedAudioPath content="${content.substring(0, content.length.clamp(0, 30))}"'); |
|---|
| 349 | 359 | if (sessionId != null && sessionId != activeId) { |
|---|
| 360 | + _chatLog('voice: cross-session, storing for $sessionId'); |
|---|
| 350 | 361 | await _storeForSession(sessionId, storedMessage); |
|---|
| 362 | + _chatLog('voice: stored, incrementing unread'); |
|---|
| 351 | 363 | _incrementUnread(sessionId); |
|---|
| 352 | 364 | final sessions = ref.read(sessionsProvider); |
|---|
| 353 | 365 | final session = sessions.firstWhere( |
|---|
| .. | .. |
|---|
| 414 | 426 | /// Store a message for a non-active session so it persists when the user switches to it. |
|---|
| 415 | 427 | Future<void> _storeForSession(String sessionId, Message message) async { |
|---|
| 416 | 428 | final existing = await MessageStore.loadAll(sessionId); |
|---|
| 429 | + _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"}'); |
|---|
| 417 | 430 | MessageStore.save(sessionId, [...existing, message]); |
|---|
| 418 | 431 | await MessageStore.flush(); |
|---|
| 432 | + // Verify |
|---|
| 433 | + final verify = await MessageStore.loadAll(sessionId); |
|---|
| 434 | + _chatLog('storeForSession: verified ${verify.length} messages after save'); |
|---|
| 419 | 435 | } |
|---|
| 420 | 436 | |
|---|
| 421 | 437 | void _incrementUnread(String sessionId) { |
|---|