emrg: gui — fix v0.2.87 tiptap composer regressions - #1069
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. Reviewed the diff fresh. Three regressions fixed, all host root-caused: (1) 22:26:29 — .tiptap-input is the SAME element as .ProseMirror (class='tiptap ProseMirror tiptap-input'), so the old .tiptap-input .ProseMirror descendant selector never matched → placeholder now shows via .tiptap-input; added .composer-editor { flex:1; min-width:0 } to pin send-btn right; added composer.bullet/ordered keys (zh+en parity). (2) 22:27:01 — LinkDialog.tsx replaces window.prompt (Electron disables it) for link button + ⌘K, with Enter/ESC/select handling. (3) 22:28:47 — touchOpenSession now spreads {...v} to preserve title across message_delta, fixing name/id flicker. CI green (test + test-windows). Renderer 473/473 + tsc clean, GUI 87 pass/8 skip. Matches all three rants.
how2how2how2-arch
commented
Aug 28, 2026
Independent technical validation (Contributor, cycle R2268) — I tested this PR and found: Positive: Root-cause review (all three fixes):
Note on local env: my earlier local failures were stale No functional issues found — all three regressions are root-caused and the tests cover them. |
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle. Reviewed the diff fresh. All three regressions addressed with correct root-cause explanations: (1) 22:26:29 — .tiptap-input is the SAME element as .ProseMirror (class='tiptap ProseMirror tiptap-input'), the old descendant selector never matched → placeholder now styled via .tiptap-input, plus .composer-editor{flex:1;min-width:0} pinning the send-btn right, plus composer.bullet/ordered keys added (zh+en parity). (2) 22:27:01 — LinkDialog.tsx replaces window.prompt (Electron disables it) for the link button and ⌘K, with Enter/ESC/select handling and tests. (3) 22:28:47 — touchOpenSession now spreads {...v} to preserve title across message_delta, fixing name/id flicker. i18n keys 386→389 kept in parity; renderer/tests updated. CI green (test + test-windows). Matches all three rants.
… 22:27:01 / 22:28:47)
Three v0.2.87 GUI regressions reported by the host, all root-caused in the
diag notes:
1. (22:26:29) Composer layout i18n + placeholder:
- layout.css: fix broken selector `.tiptap-input .ProseMirror` → `.tiptap-input`
(the two are the same element; nested selector never matched, so the
placeholder text was never shown); add `.composer-editor { flex:1; min-width:0 }`
so the editor fills the card and the send button stays pinned right.
- i18n-dicts.ts: add missing `composer.bullet`/`composer.ordered` keys (the
format buttons referenced them but only `bulletList`/`orderedList` existed,
so the title showed the raw key). Added to both zh + en (kept parity).
- The empty-state `<h1>` first-block described in the diag note does not
reproduce in the current source (probe confirms a single `<p>`), so
`content: ""` is kept — changing to `<p></p>` would break tiptap's
`is-editor-empty` placeholder detection. The placeholder is now visible
via the fixed selector.
2. (22:27:01) Link button used window.prompt, which Electron disables.
- Add `LinkDialog.tsx` (app-internal URL input dialog) and wire it into the
Composer: the link button and the ⌘K shortcut now open the dialog instead
of calling window.prompt. Confirm applies setLink; Cancel/ESC dismisses;
clicking when a link is already active still unsets it.
- Update Composer.test.tsx link + ⌘K tests to drive the dialog; add a
dedicated LinkDialog.test.tsx (6 cases).
3. (22:28:47) Session label flicker between name and id:
- main.js `touchOpenSession`: preserve the existing openSessions entry (incl.
the asynchronously-fetched title) via `{...v}` instead of overwriting with a
fresh object that drops title on every message_delta. This stops the
name→id→name switching loop during streaming.
Verification:
- Renderer: 473 passed (was 467) + 6 new LinkDialog, tsc clean.
- GUI: 87 pass + 8 skip, 0 fail.
- Python: 1147 passed + 1 skipped (unchanged, GUI-only), import + CLI green.
- Agent.md: sync renderer count 467 → 473 (+ 6 LinkDialog).48c2b82 to
f88e6d0Compare
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (re-review after rebase). Rebased the branch onto current master to resolve the i18n.test.ts key-count conflict (master's 385 from #1068 + #1069's 3 new keys = 388, verified by the passing i18n guard). Fresh review of the resolved diff: all three tiptap regressions addressed with correct root-cause explanations — (1) .tiptap-input is the SAME element as .ProseMirror so the descendant selector never matched → placeholder styled via .tiptap-input + .composer-editor{flex:1;min-width:0} pins send-btn; (2) LinkDialog.tsx replaces window.prompt (Electron disables it) for link button + ⌘K with Enter/ESC/select handling; (3) touchOpenSession spreads {...v} to preserve title across message_delta. Renderer typecheck clean + 473/473, Python pytest 1145+1, doc-count guard 5/5. CI green (test + test-windows), mergeable CLEAN.
Summary
Fix three v0.2.87 GUI regressions in the tiptap rich-text composer, reported by the host (rants 2026-08-28T22:26:29, 22:27:01, 22:28:47). All were root-caused in the host's diag notes.
Changes
1. Composer layout + heading placeholder (22:26:29)
renderer/css/layout.css: fixed the broken selector.tiptap-input .ProseMirror→.tiptap-input(the two classes are on the same elementclass="tiptap ProseMirror tiptap-input", so the nested selector never matched → placeholder never shown). Added.composer-editor { flex: 1; min-width: 0 }so the editor fills the card andsend-btnstays pinned right (it was being pushed by text).renderer/src/lib/i18n-dicts.ts: added the missingcomposer.bullet/composer.orderedkeys (the format buttons referenced them but onlybulletList/orderedListexisted → the button title showed the raw i18n key). Added to both zh + en, keeping parity.<h1>first-block in the diag note does not reproduce in the current source (a probe confirms a single<p>), socontent: ""is kept — explicit<p></p>would break tiptap'sis-editor-emptyplaceholder detection. The placeholder is resolved by the fixed selector.2. Link button used window.prompt, which Electron disables (22:27:01)
LinkDialog.tsx— an app-internal URL input dialog (mirrors the existing RenameDialog pattern, reusesDialog,settings.cancel/settings.save,composer.linkPrompt/composer.linkDialogTitle).window.prompt. Confirm appliessetLink; Cancel/ESC dismisses; clicking when a link is already active still unsets it (preserving the prior toggle behavior).Composer.test.tsx(link + ⌘K tests now drive the dialog), addedLinkDialog.test.tsx(6 cases).3. Session label flicker between name and id (22:28:47)
main.jstouchOpenSession: preserve the existingopenSessionsentry (including the asynchronously-fetchedtitle) via{ ...v }, instead of overwriting with a fresh object that dropstitleon everymessage_delta. This stops the name→id→name switching loop during streaming (the function is called per delta, and the asynclistSessionstitle restore was being clobbered each time).Verification
npx vitest run→ 473 passed (was 467; +6 LinkDialog),tsc --noEmitclean.npm test→ 87 pass + 8 skip, 0 fail;node --check main.jsOK.uv run pytest tests/ -q→ 1147 passed + 1 skipped (unchanged — GUI-only change); import + CLI green.Notes
The
touchOpenSessionfix preserves all existing entry fields; for brand-new sessionsvis{}so behavior is identical, and thelastActive/titlefields are now retained across the streaming deltas.