Commit Graph
11 Commits
Author SHA1 Message Date
Bill 35583b2c15 feat(lock): main-window lock screen; harden env gating, sandbox and ssh teardown
Lock screen (main-window overlay, no second window):
- scrypt password verifier in <userData>/lock.json (per-write salt,
  timingSafeEqual); salt/hash/password never leave the main process
- lock now / idle auto-lock / lock at startup, growing failure cooldown,
  lock flags persisted so a quit-and-relaunch cannot bypass the lock
- locked shell and body portals go inert while sessions keep running;
  menu accelerators (reload, DevTools, zoom) are swallowed while locked
- settings gains a Lock tab; all copy in zh-CN/zh-TW/en/ja

Security and stability:
- packaged builds ignore ELECTRON_RENDERER_URL / OT_UPDATE_URL (devEnv)
- renderer preload runs with sandbox: true
- unreadable known_hosts store fails closed instead of being overwritten
- connect-time secrets gated by the bookmark's auth method (connectPromptFor)
- ssh stream teardown is idempotent: PTY_EXIT broadcasts exactly once
- sysinfo polling is refcounted for split panes (forceStopPolling on close)
- session-log index entries are path-contained; settings store writes
  atomically with EPERM/EBUSY retry
- sync-changelog tolerates CRLF checkouts (was a silent no-op)
- retry ssh2 host-key generation (flaky malformed key, ~1/500)

Tests: lock-store + lock-controller suites; transport-death PTY_EXIT e2e;
GitHub Actions CI (typecheck + 10 offline tests + build)
2026-09-24 22:16:43 +08:00
Bill e08e1cfec4 feat(highlight): preset overhaul, categories, stats, theme colours, per-host profiles
Rules & engine:
- 22 presets (was 11): split status into okstate/warnstate/badstate, add delop,
  createop, danger, secret, level, exitcode, percent, http; status words are
  case-insensitive and cover the ✓ ✔ ✅ ✗ ✘ ✖ ❌ ⚠ symbol set
- value bands: the first number in a match picks the colour
  (percent: <20% red / 20-50% yellow / 50-80% light green / >=80% green)
- optional per-rule `caseInsensitive`, `category`, `bands`; load-time
  `refreshBuiltinRules` upgrades untouched built-in patterns in place

Settings page:
- three-way master switch `highlightMode` (all / basic / off); `basic` runs only
  the five safety+status rules and `off` empties the rule set rather than
  bypassing HighlightStream (which would drop the held tail)
- category column + grouping (`highlightGroupByCategory`), per-rule hit/duration
  stats (`highlightStats`, opt-in sink, snapshot once a second), theme-following
  colours (`highlightThemeColors`, hue-bucket mapping onto the ANSI palette),
  import/export JSON envelope, live preview through the real engine
- named rule subsets bound per host (`highlightPerHost` + `highlightProfiles`
  + `SshConnection.highlightProfileId`); empty ruleIds = every rule

Tests: new tests/hl-rules.mjs (word boundaries, case flag, negative words,
bands, import/export, preview, basic mode, categories, stats, theme colours,
profiles) + profile round-trip in tests/settings-store.mjs
2026-09-23 11:14:31 +08:00
Bill 481f54ed59 feat: custom terminal background image + theme editor hardening
- settings: backgroundImage/backgroundImageOpacity (10..100, default 60)
- main: otimg:// protocol serves only the configured background file
  (path-allowlisted, 403 otherwise); dev http origin cannot load file:
- TerminalView: allowTransparency + transparent theme background while an
  image is set; .term-bg-image layer behind the xterm surface
- terminal.css: .has-bg-image keeps .xterm-viewport transparent — the old
  chrome-bg pin covered the image layer (root cause of image not showing)
- ThemeSettingsTab: image picker + opacity slider
- ThemeEditor: duplicate-name hint now covers builtin names too; seed
  colors normalized to #rrggbb
- settingsStore: sanitize theme colors, reject non-hex values
2026-09-20 23:24:43 +08:00
Bill e04f4f0ac1 fix(main): SFTP data integrity, session lifecycle, security hardening
- upload: per-chunk buffer (ssh2 re-reads the overflow tail after the ACK;
  a reused buffer silently corrupted every file >= ~254KB)
- close the cached SFTP channel on eviction, attach an 'error' handler,
  close the download handle, time out execQuiet, fail partial deletes
- per-session StringDecoder for the ssh data plane (CJK mojibake), real
  exit codes, safe replay truncation, zmodem abort/counter/timer fixes
- sysinfo: idempotent poll end, error routing, per-poll watchdog, proc(5)
  CPU total; expand cd ~/$HOME/%USERPROFILE% paths; log sanitizer fixes
- security: will-navigate guard, central IPC sender check, scheme
  allowlist for openExternal, single-instance else branch, layout id and
  log-name whitelists, custom theme sanitizing, atomic JSON writes with
  EPERM retry in store.writeJson
- updater: per-attempt feed choice, quitAndInstall relaunch, dev guard,
  update-state getter
2026-09-20 20:26:34 +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 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 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 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