Commit Graph

13 Commits

Author SHA1 Message Date
bincxz 2784ecdf28 fix: sync inherited themes in editors 2026-04-10 21:30:25 +08:00
bincxz 75bbd1f300 fix: preserve theme inheritance and modal rollback 2026-04-10 21:21:51 +08:00
bincxz 4ee4ef7b60 fix: polish follow-app terminal theme UX 2026-04-10 21:03:14 +08:00
陈大猫 10ede85ae3 feat: Custom terminal themes with .itermcolors import (#245)
* feat: implement custom terminal themes with .itermcolors import (#228)\n\n- Add customThemeStore with CRUD operations and localStorage persistence\n- Create .itermcolors parser with RGB-to-hex conversion and auto theme type detection\n- Add CustomThemeEditor component with inline color pickers\n- Refactor ThemeCustomizeModal with Custom tab for create/import/edit/delete\n- Update all theme consumers (Terminal, TerminalLayer, LogView, ThemeSelectPanel,\n  SettingsTerminalTab, useSettingsState) to resolve custom themes\n- Add i18n keys for custom theme features (en + zh-CN)\n- Add isCustom flag to TerminalTheme model and STORAGE_KEY_CUSTOM_THEMES constant

* feat: add import .itermcolors button to Settings Terminal tab\n\nAllows importing .itermcolors files directly from Settings → Terminal\nwithout opening the theme modal first.

* fix: move delete button from editor to modal footer for clean layout\n\nThe delete button was rendering inside the CustomThemeEditor left panel,\ncausing misalignment with the full-width Cancel/Save footer. Now the\nfooter shows: [Delete] (left) | [Cancel] [Save] (right) when editing\nan existing custom theme.

* refactor: extract custom theme editor into standalone modal\n\nThe inline CustomThemeEditor was causing layout conflicts in the\nThemeCustomizeModal (editor + footer overlapping). Extracted into\na dedicated CustomThemeModal with:\n- Two-column layout: editor panel (left) + terminal preview (right)\n- Own footer: Delete (left) | Cancel + Save (right)\n- z-index 300 layering above the main theme modal\n- Proper scroll containment for the color editor

* fix: correct z-index stacking for custom theme modal\n\nRemoved inline style zIndex: 99999 from ThemeCustomizeModal that was\npushing it above CustomThemeModal. Now uses Tailwind z-[200] for the\nmain modal and z-[300] for the custom theme editor modal.

* feat: add new custom theme button to settings terminal tab\n\nReuses CustomThemeModal from the settings page. Creates a new theme\nbased on the currently selected theme, opens the editor modal, and\nautomatically selects the new theme on save.

* feat: add cross-window IPC sync for custom themes\n\nCustom themes created/imported/deleted in the Settings window are now\nimmediately synced to the main window (and vice versa) using the\nexisting netcatty:settings:changed IPC channel. Each mutation\nbroadcasts the change, and each window listens for incoming changes\nand reloads themes from localStorage.

* fix: show custom themes in ThemeSelectModal\n\nThemeSelectModal was only displaying built-in TERMINAL_THEMES.\nNow imports useCustomThemes hook and renders custom themes in a\nseparate section at the bottom of the theme list.

* feat: add edit/delete buttons for custom themes in settings\n\nWhen a custom theme is selected, Edit and Delete buttons appear next\nto the New/Import buttons. Edit opens the CustomThemeModal in edit\nmode, Delete removes the theme and falls back to the default theme.

* refactor: remove redundant header from CustomThemeEditor\n\nThe inner header with back arrow and title was duplicating the\nparent CustomThemeModal header. Removed the header block,\nArrowLeft import, and prefixed unused props with underscore.

* fix: add missing common.edit i18n key\n\nAdded 'Edit' / '编辑' translations for the common.edit key\nthat was showing as raw key text in the Settings page.

* fix: add error feedback for .itermcolors import in settings\n\nAdded step-by-step console logging for debugging import issues.\nShows user-visible alert on parse failure with localized message.\nAlso added terminal.customTheme.importError i18n keys.

* fix: handle extra keys in .itermcolors color dicts\n\nThe parseColorDict function assumed keys[i] aligned with reals[i],\nbut .itermcolors files with extra keys like 'Alpha Component' (real)\nand 'Color Space' (string) broke the index mapping.\n\nNow iterates through dict children properly, pairing each <key>\nwith its next sibling and skipping non-<real> values.

* fix: subscribe to custom theme store for reactive re-renders\n\nReplaced imperative customThemeStore.getThemeById() calls with reactive\nuseCustomThemes() hook in useMemo dependencies across 5 files:\n- useSettingsState.ts (currentTerminalTheme)\n- Terminal.tsx (effectiveTheme for host-override)\n- TerminalLayer.tsx (composeBarThemeColors)\n- LogView.tsx (currentTheme for log replay)\n- SettingsTerminalTab.tsx (currentTheme)\n\nThis ensures editing a custom theme in-place (same ID) triggers\nre-renders in all consuming components, instead of showing stale colors\nuntil the user switches theme IDs or reloads.

* fix: theme editor hex validation, import error feedback, and Escape propagation\n\n1. ColorInput: Use local state for text field so partial hex values\n   (#1, #abc) are held locally while typing. Only complete #rgb (auto-\n   normalized to #rrggbb) or #rrggbb values are committed to the theme.\n   On blur, partial values revert to the last valid color.\n\n2. ThemeCustomizeModal handleFileSelected: Added error feedback via\n   window.alert when .itermcolors parsing fails, reusing the existing\n   terminal.customTheme.importError i18n key. Also extended filename\n   regex to strip .xml extension.\n\n3. ThemeCustomizeModal Escape handler: Skip parent modal cancelation\n   when editingTheme is active, so pressing Escape only closes the\n   child CustomThemeModal without reverting the parent dialog.

* fix: backdrop click closes CustomThemeModal + remove nested buttons in ThemeItem\n\n1. CustomThemeModal: Attach onClick={onCancel} directly to the backdrop\n   div instead of checking e.target === e.currentTarget on the container.\n   The modal content div now stops event propagation to prevent\n   accidental dismissal when clicking inside the dialog.\n\n2. ThemeItem: Replace outer <button> with <div role=\"button\"> and inner\n   edit <button> with <div role=\"button\"> to eliminate invalid nested\n   interactive elements. Added keyboard handlers (Enter/Space) for\n   accessibility parity.

* fix: restore Escape key in CustomThemeModal + stabilize store snapshots\n\n1. CustomThemeModal: Add Escape key handler (capture phase) so pressing\n   Escape dismisses the child editor. Fixes regression where parent\n   ThemeCustomizeModal skips Escape when editingTheme is active but\n   the child had no handler of its own.\n\n2. customThemeStore: Cache the merged allThemes array (built-in +\n   custom) and only rebuild it when the store is mutated. The previous\n   getAllThemes() created a new array every call, violating the\n   useSyncExternalStore contract that getSnapshot must return a stable\n   reference between mutations.

* fix: accept <integer> plist nodes and guard NaN in itermcolors parser\n\nparseColorDict now accepts both <real> (float 0.0-1.0) and <integer>\n(0-255) plist value types for RGB components. Integer values are\nnormalized by dividing by 255. Also added isNaN guard on parseFloat\nresults to prevent malformed '#NaNNaNNaN' color strings from being\npersisted as custom themes.

* fix: use customThemeStore.getThemeById in HostDetailsPanel\n\nHostDetailsPanel used TERMINAL_THEMES.find() for both SSH and Telnet\ntheme previews, which only searched built-in themes. When a custom\ntheme was selected for a host, the preview fell back to Flexoki Dark\ndefaults. Now uses customThemeStore.getThemeById() which searches\nboth built-in and custom themes.

* chore: remove fake user counts from ThemeSelectPanel\n\nRemoved Math.random() generated fake user counts for Kanagawa and\nHacker themes, 'new' badges for Flexoki themes, and the Users icon.\nOnly meaningful labels remain: 'Default' for netcatty-dark and\n'Light mode' for netcatty-light.
2026-03-03 19:27:37 +08:00
LAPTOP-O016UC3M\Qi Chen c3c23d042f refactor: replace useFontState hook with global fontStore singleton
- Create fontStore.ts with useSyncExternalStore pattern (matches project style)
- Eliminate props drilling (availableFonts through 5+ layers)
- Improve font detection with KNOWN_MONOSPACE_FONTS (50+ fonts)
- Add eager initialization at app startup
- Remove unused useFontState.ts
- Components now use useAvailableFonts()/useFontById() directly
2026-01-08 18:05:15 +08:00
LAPTOP-O016UC3M\Qi Chen 3263676996 fix: Address PR review comments for local font support
- Improve font filtering logic with word boundary matching to avoid false positives
- Rename snake_case variable to camelCase (mono_fonts -> monoFonts)
- Translate Chinese comments to English
- Add TypeScript type definitions for Font Access API
- Check API availability before calling queryLocalFonts
- Apply CJK fallback fonts to local fonts
- Add 'local-' prefix for local font IDs to avoid collisions
- Handle permission denied gracefully
- Use TERMINAL_FONTS as default for availableFonts
- Add safer fallbacks for empty availableFonts in all components
- Export withCjkFallback function for reuse
2026-01-08 17:53:46 +08:00
qi-xmu 6a76287bf7 Add local mono fonts support 2026-01-08 15:38:20 +08:00
LAPTOP-O016UC3M\Qi Chen d8347582b4 Adds full UI internationalization and language switching
Implements comprehensive i18n support, replacing hardcoded UI strings with translation keys and introducing an i18n provider across the app. Adds persistent UI language selection, cross-window sync, and system menu localization. Updates settings and state to handle locale, propagates language changes to Electron, and adjusts components for runtime translation.

Enables a user-friendly, multi-language experience and prepares the app for further language expansion.
2025-12-17 12:06:28 +08:00
LAPTOP-O016UC3M\Qi Chen 9463387ea0 Formats code for consistency in terminal components
Unifies spacing and indentation in terminal-related components to enhance code readability and maintainability. No functional or behavioral changes introduced.
2025-12-12 22:06:11 +08:00
LAPTOP-O016UC3M\Qi Chen 43154e7992 Enhances terminal customization and accessibility options
Expands terminal settings with advanced customization such as emulation type, font weights, line padding, keyword highlighting, link modifiers, and middle-click behavior.
Adds support for clickable URLs, cross-window settings sync, and context-aware right-click actions.
Improves accessibility with minimum contrast ratio controls and allows keyword-based output highlighting.
Refines theme/font selection UI for performance and clarity.
2025-12-12 22:06:03 +08:00
bincxz be2073d94f Enables real-time terminal theme and font preview
Provides immediate feedback when customizing terminal appearance by applying theme, font, and font size changes in real time within the customization modal. Adds cancellation logic to revert unsaved changes, prevents duplicate IPC handler registration, and makes minor UI refinements for improved user experience.
2025-12-12 01:54:04 +08:00
bincxz b897c746dd Improves code readability with consistent formatting
Applies consistent spacing to import statements and component props
across several files to enhance maintainability and readability.
No logic or functional changes introduced.
2025-12-12 01:18:24 +08:00
bincxz 2f8f5a3d51 Adds per-host and global terminal font size support
Enables customizing terminal font size both globally and for individual hosts,
with persistent storage and UI controls in settings and terminal toolbars.

Improves user experience and accessibility by allowing finer display adjustments.
2025-12-12 01:17:53 +08:00