diff --git a/desktop/src/apps/MessagesApp.tsx b/desktop/src/apps/MessagesApp.tsx index 3fc3b3c..31ed4f6 100644 --- a/desktop/src/apps/MessagesApp.tsx +++ b/desktop/src/apps/MessagesApp.tsx @@ -33,6 +33,8 @@ import { useVisualViewport } from "@/hooks/use-visual-viewport"; import { useDropTarget } from "@/shell/dnd/use-drop-target"; import { resolveAgentEmoji } from "@/lib/agent-emoji"; import { ChannelSettingsPanel } from "./chat/ChannelSettingsPanel"; +import { HelpPanel } from "./chat/HelpPanel"; +import { AllThreadsList } from "./chat/AllThreadsList"; import { AgentContextMenu } from "./chat/AgentContextMenu"; import { SlashMenu, type SlashCommandsBySlug } from "./chat/SlashMenu"; import { TypingFooter, type AgentTyping } from "./chat/TypingFooter"; @@ -90,6 +92,7 @@ interface Channel { archived_agent_id?: string; archived_agent_slug?: string; muted?: string[]; + ephemeral_ttl_seconds?: number | null; }; } @@ -169,6 +172,13 @@ type WsStatus = "connecting" | "connected" | "disconnected"; /* Helpers */ /* ------------------------------------------------------------------ */ +function formatTTL(seconds: number): string { + if (seconds < 3600) return `${Math.round(seconds / 60)}m`; + if (seconds < 86400) return `${Math.round(seconds / 3600)}h`; + if (seconds < 604800 * 4) return `${Math.round(seconds / 86400)}d`; + return `${Math.round(seconds / 604800)}w`; +} + function relativeTime(iso: string): string { const diff = Date.now() - new Date(iso).getTime(); const mins = Math.floor(diff / 60000); @@ -250,6 +260,8 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; const [newChannel, setNewChannel] = useState({ name: "", type: "topic" as "topic" | "group", description: "" }); const [prefillBanner, setPrefillBanner] = useState<{ promptName: string; agentName?: string } | null>(null); const [showSettings, setShowSettings] = useState(false); + const [showHelp, setShowHelp] = useState(false); + const [showAllThreads, setShowAllThreads] = useState(false); const [contextMenu, setContextMenu] = useState<{ slug: string; x: number; y: number } | null>(null); const [agentInfoPopover, setAgentInfoPopover] = useState< { slug: string; framework: string; model: string; status: string; x: number; y: number } | null @@ -643,15 +655,22 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; const showSlash = input.startsWith("/"); const slashQuery = showSlash ? input.slice(1).split(/\s/, 1)[0] || "" : ""; - /* ---- mutex: settings vs thread panel ---- */ + /* ---- mutex: settings vs thread panel vs all-threads ---- */ const handleOpenSettings = () => { closeThread(); + setShowAllThreads(false); setShowSettings(true); }; const handleOpenThreadFor = (channelId: string, parentId: string) => { setShowSettings(false); + setShowAllThreads(false); openThreadFor(channelId, parentId); }; + const handleOpenAllThreads = () => { + setShowSettings(false); + closeThread(); + setShowAllThreads(true); + }; /* ---- send message ---- */ const sendMessage = async () => { @@ -1285,13 +1304,20 @@ export function MessagesApp({ windowId: _windowId, title }: { windowId: string; className="ml-1 opacity-60 hover:opacity-100" >ⓘ )} - + ⏳ {formatTTL(currentChannel.settings.ephemeral_ttl_seconds)} + + )} + + >?