#76185 removed both defaults; only the bare shift+n chord hijacks normal
typing (uppercase N / IME input outside an input field). Cmd/Ctrl+N is a
deliberate two-key chord that matches every browser and chat app, so it
stays. Follow-up narrowing of the salvaged fix.
- Add disableF12Title/disableF12Desc to i18n/types.ts contract
- Use focused BrowserWindow from menu click callback
- Persist and restore disable-f12 from main process (cold-launch)
- Replace built-in menu role 'toggleDevTools' (which had F12 accelerator)
with explicit menu item using Ctrl+Shift+I / Cmd+Opt+I only
- Add f12Blocked flag in main process, controllable via IPC
- Add 'Disable F12 DevTools' toggle in Settings → Advanced
- F12 still opens DevTools by default; toggle blocks it
- Ctrl+Shift+I (or Cmd+Opt+I on Mac) always works regardless
Adds a rebindable 'session.archive' keybind action (shipped unbound, like
session.togglePin) plus an ⌥+⇧-click gesture on sidebar session rows,
extracted into a pure, unit-tested click resolver so modifier precedence
(⌥⇧ archive vs ⇧ pin vs ⌘/⌃⇧ new window) stays correct.
Salvaged from #59759. Closes#59308.
9c75e4863f added the global ⌘⇧G snap-to-cursor shortcut and wired its
dispose() into closeHudWindow() and before-quit. It missed the HUD's
own 'closed' listener (spawnHudWindow's win.on('closed', ...)), which
fires when the window is closed from its own side — e.g. ⌘W — without
going through closeHudWindow() first.
After a ⌘W close, the shortcut stays registered with no HUD left to
apply it to: harmless (applyHudSnapToPointer guards on a destroyed/null
hudWindow) but it keeps CommandOrControl+Shift+G claimed until the HUD
is reopened (register() releases first) or the app quits.
dispose() is idempotent (guards on its own `active` chord), so calling
it unconditionally in the 'closed' handler is safe even on paths where
closeHudWindow() already released it.
The session.new default keybindings included 'mod+n' and 'shift+n',
which fired when users typed uppercase N (Shift+N) or accidentally
pressed Ctrl+N while using an IME to type Chinese — silently creating
new sessions mid-conversation.
Remove both combos so New Session is only reachable via the sidebar
button. Ctrl+Shift+N (session.newWindow) is unaffected.
- use-keybinds: bail out of the global keydown dispatcher while an IME
composition is active. Windows Chinese IMEs use Ctrl+, as their
punctuation toggle, which also matched nav.settings and navigated away
mid-word — destroying the unsent composer draft (#41079).
- use-composer-draft.test: regression-pin the unmount-stash/remount-restore
contract so route navigation (Settings) can never again drop an unsent
draft with the React tree.
- use-composer-actions.test: the bounded-preview pipeline keys attachments
to the durable path and resolves thumbnails asynchronously; the dropped-
screenshot test now asserts the durable-path contract instead of the
retired full-res previewUrl field.
Addresses review feedback on #68744: downscaling inside
attachmentPreviewDataUrl made previewUrl the 2048px PNG, but current main
(d8cb73b4ab) feeds that field to ImageLightbox and useImageDownload, so
large attachments would open and download at reduced resolution.
- attachmentPreviewDataUrl returns the full-resolution data URL again
- ComposerAttachment gains thumbnailUrl?: string (store/composer.ts)
- attachImagePath stores previewUrl (full-res) + thumbnailUrl (downscaled)
- Attachment pill renders thumbnailUrl ?? previewUrl; lightbox/download
keep the full-res previewUrl
- optimisticAttachmentRef prefers thumbnailUrl for the in-flight bubble
display ref (same main-thread decode freeze at send time)
- Attachment-level regression test in use-composer-actions.test.ts:
full-res previewUrl preserved while thumbnailUrl is a separate
downscaled value (4000x3000 -> 2048x1536)
- Add submitting state + IME composition guard to prevent double-submit
- submitEdit() sets latch, then clears after 200ms timeout
- handleKeyDown() guards on composing so IME Enter doesn't submit
- Shift+Enter inserts newline without submitting
- Test validates Enter calls onEdit, latch clears for second session
Fixes#70771
Signed-off-by: xrwang8 <xrwang8@gmail.com>
The inline edit composer caps height at max-h-48 but had no overflow
rule, so long prompts were clipped with no way to reach the tail.
Add overflow-y-auto to match the main composer editor.
The salvaged branch predates the electron test project's node:test -> vitest
migration (test:desktop:platforms is now `vitest run --project electron`).
Import `test` from vitest so the suites are collected; assertions stay on
node:assert/strict per the existing electron test convention.
Addresses both review findings on the remote-gateway download PR:
1. Unbounded buffering (finding #1). fetchBuffer / fetchBufferViaOauthSession
accumulated the entire response (then copied it again via Buffer.concat)
before saveGatewayFile even opened the save dialog, so a large gateway file
could exhaust the native process. Both auth paths now stream: once response
headers arrive the connect timeout is cleared, the filename is derived, the
save dialog is shown, and the body is piped to the chosen destination with
backpressure. A read/write error tears down the stream and unlinks the
partial file. The byte-moving, data-URL decoding, and filename/path helpers
are extracted into gateway-file-download.ts so they're unit-testable without
Electron.
2. No fallback for older gateways (finding #2). saveGatewayFile required the new
/api/fs/download route. Desktop and the remote gateway update independently,
so a gateway predating this PR 404s. Added a 404-only compatibility fallback
to the existing capped /api/fs/read-data-url route (bounded, so it only
serves smaller files — enough to keep older backends working).
Tests: gateway-file-download.test.ts covers streaming, backpressure,
error-cleanup (unlink on write/response error), data-URL decoding, filename
derivation (incl. traversal reduction), and 404 detection;
gateway-file-download-transport.test.ts asserts both transports stream (no
whole-body Buffer.concat) and that the 404 fallback is wired. Both registered
in the desktop platform test list. Server-side /api/fs/download tests
(streaming + sensitive-file reject) already pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read the durable display transcript when creating a branch instead of copying the compacted model projection. Hydrate the Desktop branch boundary from persisted history, avoid stale whole-chat counts, and seed the new tile from the backend snapshot. Add regression coverage for compacted histories, visible-message counts, selected prefixes, and hydration races.
(cherry picked from commit c3d2d759ae104395adde215b2e293ccf8e895684)
Residual hunk from PR #84832's picker-rebind commit; the functional
surfaces.tsx change landed on main via #86250.
(cherry picked from commit 990936d6f6e752ddb474787c1f7fdc3ad4f4dc60, docstring hunk only)
Collapsed tool zones (terminal/logs) kept a down chevron after minimize,
so the restore affordance looked like another collapse. Point the icon in
the action direction — down when expanded, up when collapsed — matching
master-detail collapsible detail headers. Same fix for floating panes.
(cherry picked from commit 3392aeb9dba0ed9e9cabfb96b6010e46fa453ca1)