Matthias Nott
2026-03-08 4c266155785aad5050ebff7211e3d5f9e15c3238
contexts/ChatContext.tsx
....@@ -167,7 +167,8 @@
167167 // Per-session typing indicator (sessionId → boolean)
168168 const typingMapRef = useRef<Record<string, boolean>>({});
169169 const [isTyping, setIsTyping] = useState(false);
170
- // Toast for other-session incoming messages
170
+ // Toast queue for other-session incoming messages (show one at a time)
171
+ const toastQueueRef = useRef<{ sessionId: string; sessionName: string; preview: string }[]>([]);
171172 const [incomingToast, setIncomingToast] = useState<{ sessionId: string; sessionName: string; preview: string } | null>(null);
172173 // PAI projects list
173174 const [projects, setProjects] = useState<PaiProject[]>([]);
....@@ -265,13 +266,19 @@
265266 ...u,
266267 [sessionId]: (u[sessionId] ?? 0) + 1,
267268 }));
268
- // Show toast for other-session messages (assistant only, skip system noise)
269
+ // Queue toast for other-session messages (assistant only, skip system noise)
269270 if (msg.role === "assistant") {
270271 setSessions((prev) => {
271272 const session = prev.find((s) => s.id === sessionId);
272273 const name = session?.name ?? sessionId.slice(0, 8);
273274 const preview = msg.type === "voice" ? "🎤 Voice note" : msg.type === "image" ? "📷 Image" : (msg.content ?? "").slice(0, 60);
274
- setIncomingToast({ sessionId, sessionName: name, preview });
275
+ const toast = { sessionId, sessionName: name, preview };
276
+ // If no toast is showing, show immediately; otherwise queue
277
+ setIncomingToast((current) => {
278
+ if (current === null) return toast;
279
+ toastQueueRef.current.push(toast);
280
+ return current;
281
+ });
275282 return prev;
276283 });
277284 }
....@@ -444,7 +451,7 @@
444451 status: "sending",
445452 };
446453 addMessageToActive(msg);
447
- const sent = wsSend(text);
454
+ const sent = wsSend(text, activeSessionIdRef.current ?? undefined);
448455 updateMessageStatus(id, sent ? "sent" : "error");
449456 },
450457 [wsSend, addMessageToActive, updateMessageStatus]
....@@ -466,7 +473,7 @@
466473 addMessageToActive(msg);
467474 try {
468475 const base64 = await encodeAudioToBase64(audioUri);
469
- const sent = wsVoice(base64, "", id);
476
+ const sent = wsVoice(base64, "", id, activeSessionIdRef.current ?? undefined);
470477 updateMessageStatus(id, sent ? "sent" : "error");
471478 } catch (err) {
472479 console.error("Failed to encode audio:", err);
....@@ -489,7 +496,7 @@
489496 status: "sending",
490497 };
491498 addMessageToActive(msg);
492
- const sent = wsImageSend(imageBase64, caption, mimeType);
499
+ const sent = wsImageSend(imageBase64, caption, mimeType, activeSessionIdRef.current ?? undefined);
493500 updateMessageStatus(id, sent ? "sent" : "error");
494501 },
495502 [wsImageSend, addMessageToActive, updateMessageStatus]
....@@ -560,7 +567,9 @@
560567 }, [sendCommand]);
561568
562569 const dismissToast = useCallback(() => {
563
- setIncomingToast(null);
570
+ // Show next queued toast, or clear
571
+ const next = toastQueueRef.current.shift();
572
+ setIncomingToast(next ?? null);
564573 }, []);
565574
566575 const loadMoreMessages = useCallback(() => {