"use client"; import Link from "next/link"; import type { RefObject } from "react"; import { BookMarked, ClipboardCheck, FileText, Maximize2, MessagesSquare, Minimize2, Square, } from "lucide-react"; import { ThinkingIndicator } from "@/components/ThinkingIndicator"; import { Button } from "@/components/ui/Button"; import type { useAutosave } from "@/lib/autosave/useAutosave"; import { friendlyError } from "@/lib/errors/messages"; import { buttonClass } from "@/lib/ui/variants"; import { CONTEXT_DRAWER_ENABLED } from "./ContextDrawer"; import { AI_CONVERSATION_ENABLED } from "./AiConversationDrawer"; // 写章失败提示:友好文案(不暴露 raw code)+ 可选「去设置」动作(F4)。 function StreamErrorNote({ streamError, }: { streamError: { code: string; message: string }; }) { const friendly = friendlyError(streamError.code, streamError.message); return (

{friendly.text} {friendly.actionHref ? ( <> {" "} {friendly.actionLabel} ) : null}

); } // 专注写作开关(P3-4):图标按钮,进入=隐藏左侧图标导航 + 目录 TOC 加宽正文,退出还原。 // aria-pressed 表状态、aria-label 表动作,键盘可达(复用共享 Button 焦点环)。 function FocusToggle({ focus, onToggle, }: { focus: boolean; onToggle: () => void; }) { return ( ); } // 底栏(P1-1 瘦身 + P3-6 分区):按「信息 | 操作 | 状态」三区排布。 // 信息=字数/生成中;操作=速查/对话记录/审稿/专注(+流式时的「停」);状态=保存态(右侧)。 interface ToolbarProps { projectId: string; chapterNo: number; wordCount: number; savedLabel: string | null; saveStatus: ReturnType["status"]; streaming: boolean; streamError: { code: string; message: string } | null; // 流式里程碑播报句(完成/停止/失败);仅在 role=status 区出现,不逐 token 刷新。 liveMessage: string; // 流式时的「停」:底栏 sticky,滚到长正文下方也够得着(中央条会滚出视野)。 onStop: () => void; // 专注写作开关(P3-4)。 focus: boolean; onToggleFocus: () => void; // 打开上下文速查抽屉(WFW-6)。 onOpenContext: () => void; contextTriggerRef: RefObject; // 打开对话记录抽屉(AC-3)。 onOpenConversation: () => void; conversationTriggerRef: RefObject; } export function Toolbar({ projectId, chapterNo, wordCount, savedLabel, saveStatus, streaming, streamError, liveMessage, onStop, focus, onToggleFocus, onOpenContext, contextTriggerRef, onOpenConversation, conversationTriggerRef, }: ToolbarProps) { return (
{streamError ? : null}
{/* 信息区:字数 / 生成中(含流式时的「停」)。 */}
{streaming ? ( ) : null} {streaming ? ( // ThinkingIndicator 自带 role=status,开始时播报一次「生成中」; // 易变字数 aria-hidden,仅供视觉,不逐 token 打扰屏读。 ) : ( 字数 {wordCount} )} {/* 终结句播报区:完成/停止/失败时写入,屏读只播报里程碑。 */} {liveMessage}
{/* 操作区:速查 / 对话记录 / 审稿 / 专注;与信息区以细分隔线拉开。 */}
{CONTEXT_DRAWER_ENABLED ? ( ) : null} {AI_CONVERSATION_ENABLED ? ( ) : null} {/* 唯一强调的「审稿」= 写→审→验收的前进 CTA(导航去重后仅此一处强调,左栏另有入口)。 */}
{/* 状态区:保存态,右侧对齐。 */}
); }