From 4c266155785aad5050ebff7211e3d5f9e15c3238 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Sun, 08 Mar 2026 07:37:45 +0100
Subject: [PATCH] feat: explicit session addressing + toast queue + solid toast styling
---
contexts/ChatContext.tsx | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/contexts/ChatContext.tsx b/contexts/ChatContext.tsx
index b109bb7..144f375 100644
--- a/contexts/ChatContext.tsx
+++ b/contexts/ChatContext.tsx
@@ -167,7 +167,8 @@
// Per-session typing indicator (sessionId → boolean)
const typingMapRef = useRef<Record<string, boolean>>({});
const [isTyping, setIsTyping] = useState(false);
- // Toast for other-session incoming messages
+ // Toast queue for other-session incoming messages (show one at a time)
+ const toastQueueRef = useRef<{ sessionId: string; sessionName: string; preview: string }[]>([]);
const [incomingToast, setIncomingToast] = useState<{ sessionId: string; sessionName: string; preview: string } | null>(null);
// PAI projects list
const [projects, setProjects] = useState<PaiProject[]>([]);
@@ -265,13 +266,19 @@
...u,
[sessionId]: (u[sessionId] ?? 0) + 1,
}));
- // Show toast for other-session messages (assistant only, skip system noise)
+ // Queue toast for other-session messages (assistant only, skip system noise)
if (msg.role === "assistant") {
setSessions((prev) => {
const session = prev.find((s) => s.id === sessionId);
const name = session?.name ?? sessionId.slice(0, 8);
const preview = msg.type === "voice" ? "🎤 Voice note" : msg.type === "image" ? "📷 Image" : (msg.content ?? "").slice(0, 60);
- setIncomingToast({ sessionId, sessionName: name, preview });
+ const toast = { sessionId, sessionName: name, preview };
+ // If no toast is showing, show immediately; otherwise queue
+ setIncomingToast((current) => {
+ if (current === null) return toast;
+ toastQueueRef.current.push(toast);
+ return current;
+ });
return prev;
});
}
@@ -444,7 +451,7 @@
status: "sending",
};
addMessageToActive(msg);
- const sent = wsSend(text);
+ const sent = wsSend(text, activeSessionIdRef.current ?? undefined);
updateMessageStatus(id, sent ? "sent" : "error");
},
[wsSend, addMessageToActive, updateMessageStatus]
@@ -466,7 +473,7 @@
addMessageToActive(msg);
try {
const base64 = await encodeAudioToBase64(audioUri);
- const sent = wsVoice(base64, "", id);
+ const sent = wsVoice(base64, "", id, activeSessionIdRef.current ?? undefined);
updateMessageStatus(id, sent ? "sent" : "error");
} catch (err) {
console.error("Failed to encode audio:", err);
@@ -489,7 +496,7 @@
status: "sending",
};
addMessageToActive(msg);
- const sent = wsImageSend(imageBase64, caption, mimeType);
+ const sent = wsImageSend(imageBase64, caption, mimeType, activeSessionIdRef.current ?? undefined);
updateMessageStatus(id, sent ? "sent" : "error");
},
[wsImageSend, addMessageToActive, updateMessageStatus]
@@ -560,7 +567,9 @@
}, [sendCommand]);
const dismissToast = useCallback(() => {
- setIncomingToast(null);
+ // Show next queued toast, or clear
+ const next = toastQueueRef.current.shift();
+ setIncomingToast(next ?? null);
}, []);
const loadMoreMessages = useCallback(() => {
--
Gitblit v1.3.1