Skip to content

support sepia and black global themes with chat outline refactor#472

Merged
chiimagnus merged 6 commits into
mainfrom
crh1
Jun 25, 2026
Merged

support sepia and black global themes with chat outline refactor#472
chiimagnus merged 6 commits into
mainfrom
crh1

Conversation

@chiimagnus

Copy link
Copy Markdown
Member

Background

  1. 全局主题模式仅支持 system / light / dark:sepia 和 black 仅作为 reader-local 主题存在于 data-reader-themedata-theme-mode 全局模式写入后缺少对应 CSS 规则,导致 sepia/black 主题下 color-scheme--reader-highlight 等变量未生效。

  2. Chat Outline 自建面板与 Reader 共用 ReaderRailPanel 逻辑,但样式不一致:Chat 的 outline 使用自定义按钮样式(ENTRY_LIST_BUTTON_BASE_CLASS 硬编码 border、padding),Reader 的 outline 已迁移到 buttonMenuItemClassName() token。Chat 面板还使用了中文固定文本 "目录" 和 "用户消息",与国际化行为不一致。

  3. Outline 活跃项高亮依赖 window.innerHeightuseArticleOutlineMinimap 始终通过 globalThis.window 读取视口高度,当文章在自定义 scroll 容器中渲染时(如 ConversationDetailPane 的 reader viewport),活跃项跟踪会出现偏移。

  4. 评论面板频繁调用 React 更新函数(syncReactUpdate)导致警告:焦点切换、评论列表更新等场景多次同步触发 React 更新,JSDOM 测试中产生 Warning: flushSync was called from inside a lifecycle method 等告警。

Changes

Global theme mode: add sepia and black

  • APP_THEME_MODES['system', 'light', 'dark'] 扩展为 5 项,含 sepiablack
  • tokens.css 新增 [data-theme-mode='sepia'] / [data-theme-mode='black'] 规则,设置 color-scheme: light / dark,并定义 --reader-highlight
  • useAppThemeModecolorScheme 映射逻辑更新:sepialight 对应 light,其余映射到 dark
  • ThemePanel 新增 sepia 和 black 选项。

Chat Outline → shared ReaderRailPanel

  • ChatOutlinePanel 新增 import { ReaderRailPanel }buttonMenuItemClassName
  • 移除自定义 ENTRY_LIST_BUTTON_BASE_CLASSENTRY_MINIMAP_BUTTON_CLASS,统一使用 token 类名。
  • 触发按钮改用 TRIGGER_CLASS + TRIGGER_BARS_CLASS,样式与 Reader 侧栏对齐。
  • 列表项使用 buttonMenuItemClassName() + webclipper-btn--tone-muted,替代硬编码 border/background。
  • 移除面板内显示的 "目录" 标题和 "用户消息" 标签(document.body.textContent 不再包含中文)。
  • ReaderRailPanel 新增 menuPopoverPanelClassName(170) 替换硬编码样式,padding 从 tw-gap-3 收窄为 tw-gap-1 以匹配 chat 条目密度。

Outline scroll root support

  • useArticleOutlineMinimap 新增可选参数 scrollRoot?: Element
  • readViewportRect 接受 scrollRoot:当 scrollRoot 存在时使用 scrollRoot.getBoundingClientRect(),否则 fallback 到 window.innerHeight
  • syncActiveIndex 依赖 scrollRoot 变化重新计算。
  • ArticleReaderView 透传 outlineScrollRootreaderOutlinePortalTarget
  • ConversationDetailPane 新增 readerOutlinePortalTarget 状态,在 article header 中渲染 portal 目标,article outline rail 通过 createPortal 挂载到目标节点。
  • readerOutlinePortalTarget 存在时,reader 主体不再 inline 渲染 outline rail,避免重复。

Comment panel React update batching

  • 新增 asyncReactUpdate 函数,使用 queueMicrotask 将 React 更新推迟到微任务。
  • MountOptions 新增 deferReactUpdates 字段。
  • mountThreadedCommentsPanel 根据 deferReactUpdates 选择 syncReactUpdateasyncReactUpdate
  • ArticleCommentsSectioncommentChatWith 挂载时传入 deferReactUpdates: true

localStorage access safety

  • readBrowserLocalStorageValue / writeBrowserLocalStorageValueAppShell 中抽取为专用函数,统一访问 globalThis.window?.localStorage
  • locate.tsThreadedCommentsPanel.tsxinpage-comments-panel-shadow.tsisLocateDebugEnabled 改为先取 anyGlobal.window?.localStorage.getItem
  • useSettingsSection 中的 readStoredSettingsSection / writeStoredSettingsSection 同步改为 globalThis.window?.localStorage

Reader toolbar sticky removal

  • ReaderToolbar 移除 tw-sticky tw-top-5 类,toolbar 不再 sticky 定位。

Test improvements

  • 新增 tests/unit/chat-outline-panel.test.ts(113 行):验证无 entries 时不渲染、rail 面板正确、hover 展开 panel、active 项样式、点击选中。
  • 修复 inpage-comments-sidebar-toggle.test.ts:将 api.open() 等调用包裹在 act() 中,避免 React scheduler 警告。
  • 修复 app-shell-comments-sidebar.test.ts:将 selectionchange + pointerup 事件包裹在 act(async) 中。
  • reader-header-toolbar.test.ts:验证 black 主题写入。
  • 补充 attachEvent / detachEvent polyfill 到 JSDOM setup。

Tests

  • 执行 npm run compile && npm run test && npm run build 确认全量通过。
  • tests/unit/chat-outline-panel.test.ts
    • 传入空 entries,期望 [data-reader-rail-wrap="chat-outline"] 不存在
    • 传入 entries 且 activeIndex=2,期望选中项文本为 2. 给我一个行动清单
    • 触发 mouseover,期望 panel 展开且 data-reader-rail-panel="chat-outline" 存在
    • hover 未选中项,期望面板更新选中状态
  • tests/smoke/inpage-comments-sidebar-toggle.test.ts
    • 调用 api.open({ focusComposer: true }),期望 api.isOpen() === true
    • 重复 api.open(),期望 panel 保持打开(不关闭)
    • 触发 selectionchange + pointerup,期望 onComposerSelectionRequest 被调用
  • tests/smoke/reader-mode-regression.test.ts
    • 渲染 Reader 模式下评论 sidebar,期望无 console 警告
  • tests/unit/reader-header-toolbar.test.ts
    • 点击 black 主题按钮,期望 updateThemeMode 收到 'black'

@chiimagnus chiimagnus merged commit 40002c7 into main Jun 25, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant