Skip to content

WIP: assorted frontend fixes and chat UI polish#673

Draft
qqqqqf-q wants to merge 24 commits into
memohai:mainfrom
qqqqqf-q:feat/ui-refactor
Draft

WIP: assorted frontend fixes and chat UI polish#673
qqqqqf-q wants to merge 24 commits into
memohai:mainfrom
qqqqqf-q:feat/ui-refactor

Conversation

@qqqqqf-q

Copy link
Copy Markdown
Collaborator

概况

还在整理中的一批前端改动,比较散,没有单一主题。主要是聊天区、侧栏、设置页和一些顺手修的技术债,顺手把后端/UI turn 也补了一刀。

大概动了什么

聊天 / Composer

  • 多 session tab、后台 tab 保活
  • composer 窄屏适配、多行、跳转按钮、hover/字重等细节
  • ACP session 发送按钮空态不再消失
  • settings 改完 bot/agent 后 composer 菜单会刷新(web 路由 + desktop 跨窗口)

侧栏 / 布局

  • Files 组头与 Chat/Schedule 对齐
  • Schedule 创建按钮改成 Plus
  • dockview schedule panel 背景微调

设置 / Providers

  • provider 详情从 inject 改成 v-model
  • avatar 首字母逻辑抽成共用函数
  • 若干 settings 页 PageShell / desktop shell 相关

后端顺手

  • talk-while-acting 的多条 assistant 消息合并成一个 turn
  • display workspace 默认终端优先 xfce4-terminal

其他

  • UI contract guard / memoh-web skill 文档
  • 一些 a11y label、删除确认等小修

还没做 / 不在这个 PR

  • README 文案在单独 worktree docs/readme-revamp
  • Desktop zoom-to-action 方案在本地 tmp/,未提交

Test plan

  • 聊天 composer:普通 session / ACP session 发送按钮表现
  • settings 改 bot 名或 agent 后回到 chat,composer 列表是否更新
  • desktop 双窗口:settings 改配置后 chat 窗口 agent 菜单
  • 侧栏 Files / Schedule 组头视觉
  • providers 列表进详情再返回
  • 带 tool call 穿插文本的历史消息是否仍在一个 ActionBar 里

qqqqqf-q added 24 commits June 17, 2026 17:40
…ages

- Add DesktopRuntimeMode ("local" | "remote") via DesktopRuntimeModeKey.
  Local desktop (Memoh Local) auto-logs with [admin] and hides sign-out.
  Remote desktop and browser keep full account features including sign-out.
- Update desktop entrypoints to provide the runtime mode.
- Migrate appearance, profile, usage from ad-hoc <section><h1> to shared PageShell.
- Provider list: stop hiding unconfigured registry templates so they appear in UI (include in this UI batch as requested).
- Message column and composer now use matching responsive padding (px-4 / sm:px-6 / lg:px-10).
- Split multiline trigger into textMultiline (newlines/wrap) + narrowMultiline (pane too small for pill row).
- Measure model label + ACP project label + send button natural width via refs + scrollWidth.
- Force multiline layout when remaining space for textarea drops below threshold; add min-w-0 and truncation on labels.
- Add :aria-label="$t(common.delete)" or copy on icon-only buttons.
- Use DropdownMenuItem variant="destructive" for schedule delete action.
- Reflow the composer to multiline when the pane is too narrow to seat the
  input + model capsule + send on one pill row, measured from intrinsic widths
  so the verdict can't oscillate across the layout switch
- Keep the placeholder on a single line in the pill row (no two-line wrap)
- Truncate the model name with a dynamic max-width (the Button's shrink-0
  otherwise lets a long name overflow instead of ellipsing)
- Align the composer to the message column edge-for-edge: drop the outer gutter
  the message list bypasses via its absolute inset-0 scroll layer
- Mask the composer band up to the box's widest point so messages don't bleed
  past it, with no fade and the seam hidden behind the box
- Raise the dockview pane minimum width so a split pane can't shrink to a sliver
Sessions can now live in their own tabs instead of a single chat panel
that always mirrors the active session. The store reads/writes per
session id (messages, loading, overrides, startup failure, optimistic
send/approval/ask_user), so pinned tabs stream independently and can be
dragged into a split for side-by-side.

Sidebar: plain click switches the primary tab in place (instant); Cmd/
Ctrl+click, middle-click, or the row menu open a session as its own
pinned tab. The active-row highlight follows the focused tab's session
rather than the primary tab's, so it stays correct with multiple tabs.
A pinned chat tab for a non-active session previously only streamed for
turns the user started in it; server-initiated streams and inbound
messages were dropped until a full reload. The panel host now registers
its bound session as "observed" (ref-counted, so overlapping tabs are
fine), and the store applies background streams and schedules a debounced
refresh for observed sessions. Stray streams for sessions with no open
tab are still ignored so they can't create phantom turns.
…k, CJK weight

- Restyle the jump-to-latest button as a solid bordered chip (bg-card +
  border-border, ghost interaction, no shadow), a step larger and lifted off
  the box
- Trim the composer to ~52px (py-2 + 36px controls, radius = half height) so it
  reads less chubby without shrinking the controls
- Make the composer "+" a hair larger and fully foreground (drop the /85 alpha)
- Lighten the model picker hover to the standard control overlay (--ui-hover);
  the wide pill was using the strong icon-ghost overlay and read too heavy
- Nudge the light-mode user-bubble ink toward black (lower L/C) for density
  without a per-surface weight exception
- Lift the chat CJK reading weights (+10 across body/strong/headings); Latin
  unchanged
Capture the cross-layer model a future agent needs so it stops
re-introducing the same class of front-end debt: ownership/locality +
the four override planes (packages/ui/AGENTS.md); the composition
boundary (five exits + the className red line), the debt taxonomy,
seam-first debugging, and a self-re-review protocol (memoh-web skill);
plus an AI default-aesthetic trap table and error/terminology copy +
container-query guidance.
The px rules already scanned apps/web with a baseline ratchet, but interaction
chrome / raw color / invented shadow were enforced only in packages/ui — app
pages were a known gap. Add an app-scope injection family (hover:/active: fills,
raw colors, shadow-* utilities) that scans apps/web with its own baseline
(ui-app-baseline.json): 237 existing injections across 90 files are
grandfathered, new injection HARD-fails. ui-allow-style is the per-line escape.
Assistant replies that interleave plain text with tool calls should stay in
a single turn instead of splitting on every text-only message.
Use xfce4-terminal when available and polish the xterm fallback styling;
install xfce4-terminal in the desktop workspace image.
…itials

Drop provide/inject for the active provider, remove the duplicate add card,
and reuse avatarInitials() across list and detail views.
Re-pull bots when returning to chat on web and when the settings window
invalidates bot queries on desktop, so the composer agent menu stays current.
ACP chats have no SessionInfoRing in the trailing slot, so the send button
should stay mounted in its disabled state instead of disappearing.
Match files pane group header typography with chat/schedule, use Plus for
schedule create, and drop redundant panel background in dockview schedule.
…ge boundaries

Invisible user rows from browser/computer screenshot feedback must not flush
the pending assistant turn, and UI-format pagination extends each page head
back to a real turn boundary so action bars are never split across pages.
Local desktop sessions can open the OS directory dialog to bind a working
folder, with recent choices cached in localStorage for the composer menu.
Browser and computer observe/action steps stay in one process segment with
browsing-aware collapsed labels, assistant body images keep natural aspect
ratio, and the display canvas uses the page background token.
…lder picker

Reload history when cross-tab storage sync switches the active session or
cache is empty, cross-fade send and stop on one brand button, and let local
ACP sessions choose a project folder from the composer before the first turn.
…sconnects

Keep the GStreamer encoder warm briefly when the last WebRTC viewer disconnects so reconnecting does not pay a cold-start penalty.
Use a fixed display panel id, focus existing panels instead of spawning display:2+, and add buffering status copy for the video stream warm-up.
Opt-in query param forces the macOS desktop shell layout in the browser so marketing captures can run against the real build without affecting normal web visitors.
Expose pnpm preview and mise run desktop:preview for reproducing prod-only rendering issues without a full package build.
…loads

Add optimizeDeps.include for lazily loaded editor dependencies so opening bot settings tabs does not trigger esbuild re-crawls and full page reloads during dev.
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