SIGN IN SIGN UP

fix(macos): platform-aware keyboard shortcuts, native traffic lights & error resilience (#114)

* feat(keyboard): platform-aware modifier system (Phase 1)

- New src/renderer/lib/platform.ts: isMac, isWindows, getPlatformModifier, isPlatformModifier helpers
- normalizeKeyEvent: separate ctrlKey→'ctrl' and metaKey→'cmd' (was conflating both to 'ctrl')
- matchesShortcut: macOS cross-modifier aliasing (cmd+k matches ctrl+k config)
- formatKeyForDisplay: 'cmd' token renders as ⌘ on macOS, 'ctrl' as ⌃
- Backward compatible: existing 'ctrl+...' config entries work on all platforms
- Tests updated for new behavior

* fix(keyboard): hardcoded shortcuts now use platform modifier (Phase 2)

- Ctrl+S/Save, Ctrl+B/File explorer: use isPlatformModifier (⌘ on macOS, Ctrl on Windows)
- Ctrl+W/Close tab: macOS uses ⌘+W, Ctrl+W in terminal passes through to shell (backward-kill-word)
- Project switch (Ctrl/Cmd+1-9): already worked, unchanged
- Fixes: ⌘+S, ⌘+W, ⌘+B now work on macOS
- Fixes: Ctrl+W in terminal no longer intercepted on macOS
- Use ref for handleCloseTerminal to avoid declaration-order TS error

* fix(terminal): macOS copy/paste convention + Ctrl passthrough (Phase 3)

- Clipboard operations (copy/paste/select-all) use platform modifier:
  macOS: ⌘+C/V/A, Windows/Linux: Ctrl+C/V/A
- Ctrl+C without selection still sends SIGINT on all platforms
- On macOS terminal, Ctrl+key shortcuts pass through to shell:
  Ctrl+R → reverse-i-search (not intercepted by app command history)
  Ctrl+W → backward-kill-word (not intercepted by close tab)
- ⌘+key shortcuts still intercepted by app as expected

* feat(ui): add React ErrorBoundary at root and per-pane level (Phase 4a)

- New ErrorBoundary component with default fallback UI and retry button
- ErrorFallback in separate file (react-refresh compliance)
- Wraps entire app root in TauriApp to prevent blank screen on crash
- Wraps each PaneContent in PaneRenderer to isolate pane-level errors
- Catches WebGL terminal crashes, browser webview mount errors, etc.
- Logs error + component stack to console for debugging

* fix(macos): Alt/Option key no longer intercepted on macOS (Phase 4b)

- usePreventAltMenu now only activates on Windows
- On macOS, Alt/Option is needed for typing special characters (@, €, £, etc.)
- Fixes inability to type special chars in terminals and editors on macOS

* chore(logging): improve default log levels for debug/release (Phase 4d)

- Debug builds: default to 'debug' level
- Release builds: default to 'warn' level
- Both overridable via RUST_LOG env var
- File-based logging deferred to v0.4.1 (requires fern/log4rs crate)

* test: update clipboard test for platform-aware modifier

- Test now uses platform-appropriate modifier (Ctrl on non-mac, Cmd on mac)
- Fixes test failure in jsdom where isMac=false and metaKey is not the clipboard modifier

* feat(keyboard): make close tab, save file, and file explorer shortcuts customizable

- Add closeTab (Ctrl+W), saveFile (Ctrl+S), toggleFileExplorer (Ctrl+B)
  to DEFAULT_KEYBOARD_SHORTCUTS — now user-customizable via settings
- Replace hardcoded key checks in WorkspaceLayout with matchesShortcut()
- macOS Ctrl+W terminal passthrough still works (isMac check preserved)
- Update test mock to include new shortcut entries

* feat(macos): native traffic lights via Rust setup hook

- In Rust setup (#[cfg(target_os = "macos")]):
  set_decorations(true) + set_title_bar_style(Overlay) before window is shown
- TitleBar.tsx: hide custom minimize/maximize/close on macOS
- Add 70px left spacer for native traffic lights on macOS
- Windows/Linux: custom window controls unchanged
- Rust compile clean, all 920 tests pass

* fix: CodeRabbit review fixes + browser tab panic

CodeRabbit findings:
- lib.rs: log decoration/titlebar setup failures instead of swallowing
- lib.rs: remove redundant `use tauri::Manager` (already in scope)
- matchesShortcut: reject ctrl+... on macOS before exact-match check,
  preventing double-fire (shell passthrough + app shortcut) on macOS
- tests: add shell passthrough guard test, split platform branches

Browser tab panic:
- Replace `tokio::spawn` with `tauri::async_runtime::spawn` in
  ExitRequested handler — the run callback fires on threads without
  a Tokio reactor (e.g. macOS WKWebView delegate threads)
A
Anaz S. Aji committed
592ddeb06379007c7a72e478fe4af32e19ffe4d4
Parent: afcbb35
Committed by GitHub <noreply@github.com> on 5/7/2026, 5:02:58 AM