Files
multica/packages/views/chat/floating-chat.tsx
Lambda 0e596acb1c feat(chat): Settings toggle for the floating chat window (MUL-4235)
Re-introduce the floating chat overlay on top of Chat V2 as an optional,
Settings-gated surface instead of deleting it outright.

- Settings → Preferences → Chat: a switch (floatingChatEnabled, persisted
  client preference, default ON) to show/hide the floating window.
- FloatingChat wrapper owns the two gates: the preference, and the /chat
  route (hidden on the tab so the same activeSessionId isn't shown twice).
- ChatFab + a compact ChatWindow that reuse the shared useChatController and
  conversation components, so activeSessionId stays in lockstep with the tab.
- Restore use-chat-context-items so the overlay's @ surfaces the current
  issue/project (the 'current context' affordance) — the tab stays manual.
- i18n (en/zh-Hans/ja/ko), store unit tests.

typecheck: core/views/web/desktop green. tests: chat store 9, settings 82,
chat 39 pass.

Co-authored-by: multica-agent <github@multica.ai>
2026-07-08 15:48:57 +08:00

38 lines
1.3 KiB
TypeScript

"use client";
import { useChatStore } from "@multica/core/chat";
import { useWorkspacePaths } from "@multica/core/paths";
import { useNavigation } from "../navigation";
import { ChatFab } from "./components/chat-fab";
import { ChatWindow } from "./components/chat-window";
/**
* Mount point for the floating chat overlay (FAB + window). Rendered once in
* each app shell's dashboard layout; owns the two gates that decide whether the
* overlay exists at all:
*
* 1. The Settings → Chat preference (`floatingChatEnabled`). When a user turns
* the floating window off, Chat lives only in its dedicated tab.
* 2. The Chat tab route itself. On `/:slug/chat` the full-page surface already
* owns the conversation, so a floating copy of the same `activeSessionId`
* would be pure duplication — hide it there.
*/
export function FloatingChat() {
const enabled = useChatStore((s) => s.floatingChatEnabled);
const { pathname } = useNavigation();
const wsPaths = useWorkspacePaths();
if (!enabled) return null;
// Suppress on the Chat tab — it renders the same conversation full-page.
if (pathname === wsPaths.chat() || pathname.startsWith(`${wsPaths.chat()}/`)) {
return null;
}
return (
<>
<ChatWindow />
<ChatFab />
</>
);
}