Commit Graph
28 Commits
Author SHA1 Message Date
Bill c94e0fbac7 fix: settings nav active label readable (white, like inactive tabs)
antd's runtime-injected .ant-tabs-tab-active .ant-tabs-tab-btn rule
(colorPrimary blue) out-ranks a same-specificity stylesheet rule, so the
active label stayed blue on the accent-tinted row; add the .ant-tabs-tab
class to out-specify it.
2026-09-20 22:35:07 +08:00
Bill f128c3e8be chore: event-loop stall detectors for hang diagnosis
WER records AppHangTransient with no stack, so measure lag in both
processes and log it on recovery: [main] event loop stalled / [renderer]
main thread stalled. Tells a main-process block from a renderer freeze
the next time the app 'freezes then recovers'.
2026-09-20 22:25:23 +08:00
Bill 806fd93638 fix: sync language at render time without notifying subscribers
setLanguage() during App's render fired onLanguageChange, which made the
same component's useSyncExternalStore schedule an update mid-render
(React: cannot update a component while rendering a different component).
syncLanguage() updates the module silently; re-renders flow through the
settings store, which is the only path a renderer language change takes.
2026-09-20 20:45:44 +08:00
Bill 23fa566fa9 fix(renderer): terminal input tracking, workspace/session safety, panel correctness
- terminal: drop the diffRewriteRef echo assumption (Tab-accept corrupted
  history and cwd tracking), handle readline control keys in the line
  buffer, clamp degenerate PTY sizes, live copyOnSelect, bound highlight
  regex input, wide-char-safe link ranges
- workspace: boot-restore try/finally (a failure used to disable snapshot
  saving for the whole run), connect re-entrancy guard + real error
  messages, broadcast registry keyed by panel id (split panes), tab
  close-others/right live-array fix, pointer-captured bottom-panel drag,
  dockview constants hoisted, hydrate-gated restore
- panels: no chmod 000 on unknown mode, chown keeps current gid, 12-bit
  special-permission round trip, overwrite confirm, redraw monitor
  charts, gate polling on visibility, no secret carry-over between
  connections, settings sent as minimal patches, update-state pull
- language applies on the first render; accent fg recomputed on theme
  switch; window.api is properly typed again (env.d.ts import path)
2026-09-20 20:27:02 +08:00
Bill 4c6a29ef28 feat: multi-language interface (zh-CN/zh-TW/en/ja), multilingual offline changelog, settings robustness
i18n
- shared/i18n: dependency-free t() with flat per-namespace dictionaries
  (common/settings/workspace/terminal/ssh/panels/main), zh-CN fallback
- language picker in Settings -> System; antd ConfigProvider locale follows it
- main process tracks the language too: tray menu, close prompt, ssh/sftp/
  zmodem errors and the log TUI marker are translated; tray rebuilds on change

changelog
- CHANGELOG.md (zh-CN canonical) + .zh-TW/.en/.ja, bundled via ?raw and read
  per interface language with per-version fallback to zh-CN (no network)
- sync-changelog.cjs merges RELEASE_NOTES[.<lang>].md per release; release.cjs
  refuses to publish without a zh-CN entry for the version

settings robustness
- closeAction 'ask' survives the sanitizer (was silently coerced to 'tray',
  which made the 'ask every time' option dead)
- highlight rules are repaired instead of dropped: string priority, 0/1
  enabled, missing fg colour; unknown fields preserved
- load-time warnings are written to settings-warnings.log (deduped, capped)

terminal/UI
- configurable terminal toolbar: open working directory (default on), session
  log recording (off), open logs folder (off)
- global shortcut field records key combos (modifier or F-key required)
- input suggestions + command history default to off, with a one-time reset
  migration for existing installs
- settings dialog scrolling fixed (antd v6 renamed the tabs container), theme
  gallery nested scrollbar removed, joined segmented pickers with readable
  selected-state text

tests: settings-store.mjs (15 checks) added; commands-store.mjs updated for
the new off-by-default history setting
2026-09-20 14:22:29 +08:00
Bill 34094d607b feat: shortcut recorder, configurable terminal toolbar, offline changelog
- Global shortcut setting: press-to-record input (Esc cancels, Backspace
  clears); requires a modifier or F-key so plain typing can't be hijacked
- Terminal toolbar: three settings-gated buttons — session-log record
  (default off), open logs dir (default off), open working directory
  (default on, new; local sessions only, cwd tracked via cd/OSC 7)
- Input suggestions + command history now default off, with a one-time
  migration that resets persisted true values for existing installs
- Settings dialog: fix broken scrolling — antd v6 renamed the Tabs scroll
  container to .ant-tabs-body-holder; theme gallery drops its nested
  scroll (single outer scrollbar)
- Offline changelog: CHANGELOG.md at repo root bundled via ?raw; About tab
  reads it first, network sources stay as fallback; scripts/sync-changelog.cjs
  merges RELEASE_NOTES.md per release (release.cjs fails without an entry)
- commands.ts history prefs default aligned with new off-by-default
2026-09-20 11:25:59 +08:00
Bill b3744b4705 fix: luminance-aware chrome theming for light themes; serialized settings writes; buffered log flush
- Derive tab-bar/chrome palette by background luminance: light themes keep
  a near-background bar with black-tinted tab overlays instead of a muddy
  gray strip; dark themes unchanged
- Theme dockview tabs via the group-scoped --dv-*-tab-* vars its own rules
  consume (they outspecify our .dv-tab rules and leaked abyss navy onto
  light tabs); bump inactive-tab hover specificity to match
- Convert settings dialog + highlight editor hardcoded white text/border
  tints to color-mix over --chrome-fg so panes stay readable on light themes
- commands.ts: per-file log write buffer with a single drain loop per file
  (burst output coalesces into one appendFile per IO tick, chain no longer
  grows per logWrite); stop-tail rides the same buffer
- settingsStore: serialize all writers through mutateSettings() queue that
  re-reads latest state per mutation (tray close-action vs settings UI full
  saves no longer clobber each other)
- tests: burst ordering + stop-tail case for the log buffer
2026-09-17 09:11:05 +08:00
Bill 237265e6ba feat: clickable URLs, left-rail settings nav, proportional resizable dialog
URLs in terminal output (http/https/ftp with ports, www. hosts, bare
localhost:port dev-server forms) are detected via a link provider: hover
underlines and shows the pointer, Ctrl/Cmd+Click opens the system browser.
Wrapped URLs spanning buffer rows resolve as one link. The 网址链接 highlight
preset grows to cover ftp:// and www. forms.

The settings dialog moves to a left navigation rail with the content column
scrolling on its own, sizes itself at ~70% of the main window and follows
main-window resizes in real time (until the user drags the corner grip),
stays centred while resizing, and keeps a stable height.
2026-09-15 15:07:47 +08:00
Bill d3d029fe4f fix: wire plain Ctrl/Cmd+V to paste and split the check by line count
Plain Ctrl+V was never the terminal's: it went to the pty as a literal ^V
(0x16) — the command history even recorded 'cd \u0016' — so nothing pasted
and the confirm dialog never saw it. It is now handled on the terminal host
in the capture phase, with preventDefault, feeding the same path as
Ctrl+Shift+V.

The paste check is now shape-based rather than length-based: two or more
lines confirm (a stray newline executes an unreviewed command), a single
line pastes straight through unless it is unusually long.
2026-09-15 11:45:17 +08:00
Bill d7abbaad9c fix: paste through xterm so large multi-line blocks insert instead of executing
confirmPaste wrote the raw text to the pty, so a large paste bypassed
bracketed paste and PowerShell ran it line by line; it also skipped
onData, which is why history/cwd tracking needed a separate mirror. Now the
text goes through term.paste(): xterm adds the \x1b[200~ markers when the
shell enabled bracketed paste (one edit, no execution) and the normal
onData path restores tracking for free.

The risky-paste bar becomes a proper dialog (确认粘贴 / 本次会话不再提示 /
关闭后续粘贴检测), matching the behaviour users expect from other
terminals.
2026-09-15 00:27:19 +08:00
Bill cbf4c224fb fix: allocate terminal titles by lowest free number instead of a counter
Closing 终端 6/7 then opening a new one produced 终端 8 rather than
refilling the gap. nextTerminalTitle now scans live panel titles and takes
the smallest unused N, which also subsumes the restore-time counter
seeding (syncTitleSeq is gone) — duplicate retitling after a restore fills
the lowest free number too.
2026-09-14 22:24:36 +08:00
Bill 28d8af6982 fix: keep terminal titles unique across session restore
The 终端 N counter lives only in memory, so after a restore it restarted at
zero and the next new terminal duplicated a restored title. Broadcast keys
targets by session id so duplicate titles never broke the fan-out itself,
but the target list became indistinguishable. Seed the counter past the
restored maximum on session restore / template apply, and retitle
duplicates already baked into existing snapshots.
2026-09-14 20:56:02 +08:00
Bill f09bed06b5 remove: drop the quick-input panel
The toggle state was a global singleton while the bolt button renders in
every pane's tab bar, so all panes showed the same open/close state and
the single floating panel (window bottom-right, sends to the *active*
session) never corresponded to the pane whose button was clicked. A true
per-pane rework is a medium refactor for a feature that overlaps with the
inline completion and the sidebar commands panel — removing instead.
2026-09-14 20:47:21 +08:00
Bill 0b4a87f1e7 fix: feed pasted text into the line buffer so history and cwd memory see it
App-driven paste (context menu / Ctrl+Shift+V) writes straight to the pty,
bypassing xterm's onData, and xterm-native paste arrives wrapped in
bracketed-paste markers that the buffer guards dropped. Either way a pasted
'cd D:\path' was recorded as the bare 'cd' typed before it, so the pane's
directory memory silently stayed home. Track submitted lines from pasted
text and strip bracketed-paste markers in the line buffer.
2026-09-14 20:01:23 +08:00
Bill 9a330499de fix: track bare drive switches (d:) for cwd memory
PowerShell/cmd users hop drives with a bare 'd:' — no cd keyword — so the
typed-command tracker never saw it, the pane's cwd stayed at its creation
directory, and the session snapshot restored it to home. Treat a bare
drive-letter line as a cd to the drive root; the main-process existence
check drops it on platforms without drive letters.
2026-09-14 19:27:20 +08:00
Bill be7332db17 perf: route PTY stream through a single shared IPC listener
Every pane registered its own global onPtyData/onPtyExit listener, so each
output chunk woke N listeners and N-1 discarded it after an id compare.
With many terminals under heavy output that fan-out is pure overhead.
Now one IPC listener dispatches through a Map keyed by sessionId: one
lookup per chunk, only the owning pane runs.
2026-09-14 16:59:57 +08:00
Bill bbee1d642d polish: about-page logo now uses the app icon instead of an OT text mark 2026-09-14 15:06:19 +08:00
Bill 277d8bb117 feat(commands): whole-history dedupe + switchable, capped history
历史命令去重从「只跟最新一条比」改为「全历史去重」:重敲任意一条已有命令
时把原条目提到最前(刷新 lastUsedAt)而不是新插一条,历史里每个命令只出现一次。

新增两个设置(设置 → 终端):
- 记录命令历史:关闭后不再记录新命令;已有历史保留,不清空
- 历史条数上限:默认 100,可配 1..500;写入按上限截断,读取也按当前
  上限截断(调低立即生效)

顺修一个暴露的既有 bug:logWrite 用 async appendFile,两次快速追加会
乱序落盘(line two 先于 line one)。改为按文件串行化追加。

测试:tests/commands-store.mjs 全历史去重 / 提到最前 / 上限生效 /
开关关闭不记录 / 关闭保留已有 / 恢复记录 / 越界上限夹紧,全部通过。
2026-09-14 12:01:23 +08:00
Bill beeb32a76b fix(session): keep panel ids distinct from session ids so restore rebinds panes
面板 id 曾直接复用 pty 会话 id(`addPanel({ id: sessionId })`),而
`updateParameters` 只能换会话、不能改面板 id。于是恢复时面板 id 指向一个
已不存在的会话:分屏少一个、剩下的 pane 背后没有 pty,界面看起来是空白,
也无法输入。

- 新增 `panelId()`,面板 id 与会话 id 彻底分离,并用于所有建面板处
  (新建终端、SSH 连接、分屏复制)
- 新增 `breakIdCoincidence()`:旧快照仍带 `panelId === sessionId`,
  在 `fromJSON` 之前重写 grid/panels/views/activeView 中的 id,
  返回 old→new 映射
- `rebindSessionPanels` 用该映射回查快照,恢复每个 pane 自己的目录
  (否则新 id 查不到记录,cwd 会静默退回 home)

验证(重启恢复 E2E,legacy 快照 + 2 分屏):
  2/2 pane 挂载、2 个独立存活会话、输入可回环、
  cwd 分别回到 D:/AIGC/OpenTerminal 与 C:/Windows、回写快照无 id 冲突;
  restoreSession=false 时正确忽略快照只建 1 个终端。
2026-09-14 11:29:56 +08:00
Bill 8eacd34338 polish: frame the sidebar with top and bottom borders to match the right edge 2026-09-14 02:26:36 +08:00
Bill 6c100542c5 fix: batch of review findings — dead install button, history pollution, TUI completion interference, ssh split session kill, scrollback live apply, zmodem second transfer, sftp shell quoting, replay buffer leak, release guards 2026-09-14 02:20:40 +08:00
Bill f63ee379a4 fix: send the first pty size immediately, debounce only subsequent resizes 2026-09-14 01:17:04 +08:00
Bill acdf955918 fix: debounce pty resize and skip no-op resizes (kills duplicated TUI frames on maximize/restore) 2026-09-14 01:12:15 +08:00
Bill 7f2e4c1110 feat: terminal right-click context menu (copy/paste/find/select-all/clear) 2026-09-08 20:50:59 +08:00
Bill 2b3fefafd0 feat: close-to-tray default + system settings entry; bump 1.0.3 2026-09-08 17:00:09 +08:00
Bill 8cb193fa6a feat: theme-driven chrome, customizable tab accent, UI polish
- Sidebar/tab bars/dividers/settings dialog follow the terminal theme
- Tab accent color customizable in theme settings (color picker)
- Title bar shows the app icon; Material Dark is the default theme
- Slimmer rectangular tabs (28px), slate scrollbars, visible pane dividers
- Fix pure-black xterm viewport gaps after pane resize
2026-09-08 00:57:56 +08:00
Bill f25a1627f3 feat: about tab with update check/download (Gitea feed first, GitHub fallback)
- updater: dual-feed state machine, manual check/download/install IPC,
  changelog from Gitea releases API with GitHub fallback
- settings: new About tab (version, channel, auto-check toggle, progress)
- system.autoCheckUpdate setting gates the startup check
2026-09-07 17:18:15 +08:00
Bill a9acdbe500 Initial commit: OpenTerminal v0.1.0
Open-source terminal app (local + SSH): split panes, themes, SFTP,
server monitoring, broadcast input, ZMODEM, system tray, single instance.
Electron + React + TypeScript. MIT License.
2026-09-07 16:15:50 +08:00