This reverts commit ba336fc416.
Reason: Found issues that need to be addressed before reintroducing
the auto-launch feature. Will reimplement with fixes.
Implement auto-launch functionality with proper state synchronization
and error handling across Windows, macOS, and Linux platforms.
Key changes:
- Add auto_launch module using auto-launch crate 0.5
- Define typed errors (AutoLaunchPathError, AutoLaunchEnableError, etc.)
- Sync system state with settings.json on app startup
- Only call system API when auto-launch state actually changes
- Add UI toggle in Window Settings panel
- Add i18n support for auto-launch settings (en/zh)
Implementation details:
- Settings file (settings.json) is the single source of truth
- On startup, system state is synced to match settings.json
- Error handling uses Rust type system with proper error propagation
- Frontend optimized to avoid unnecessary system API calls
Platform support:
- Windows: HKEY_CURRENT_USER registry modification
- macOS: AppleScript-based launch item (configurable to Launch Agent)
- Linux: XDG autostart desktop file
All MCP operations already auto-sync to live configs:
- upsert_server() → sync_server_to_apps()
- toggle_app() → sync_server_to_app() or remove_server_from_app()
- delete_server() → remove_server_from_all_apps()
The manual 'Sync All' button was redundant and could confuse users
into thinking they need to manually sync after each change.
Changes:
- Remove 'Sync All' button from UnifiedMcpPanel header
- Remove useSyncAllMcpServers hook
- Remove handleSyncAll function and syncAllMutation state
- Remove RefreshCw icon import
- Remove sync-related i18n translations (en/zh)
Note: Backend sync_all_mcp_servers command remains for potential
future use (e.g., recovery tool), but is no longer exposed in UI.
Complete Phase 3 (P0) frontend implementation for unified MCP management:
**New Files:**
- src/hooks/useMcp.ts: React Query hooks for unified MCP operations
- src/components/mcp/UnifiedMcpPanel.tsx: Unified MCP management panel
- src/components/ui/checkbox.tsx: Checkbox component from shadcn/ui
**Features:**
- Unified panel with three-column layout: server info + app checkboxes + actions
- Multi-app control: Claude/Codex/Gemini checkboxes for each server
- Real-time stats: Show enabled server counts per app
- Full CRUD operations: Add, edit, delete, sync all servers
**Integration:**
- Replace old app-specific McpPanel with UnifiedMcpPanel in App.tsx
- Update McpFormModal to support unified mode with apps field
- Add i18n support: mcp.unifiedPanel namespace (zh/en)
**Type Safety:**
- Ensure McpServer.apps field always initialized
- Fix all test files to include apps field
- TypeScript type check passes ✅
**Architecture:**
- Single source of truth: mcp.servers manages all MCP configs
- Per-server app control: apps.claude/codex/gemini boolean flags
- Backward compatible: McpFormModal supports both unified and legacy modes
Next: P1 tasks (import dialogs, sub-components, tests)
* feat(prompts): add prompt management across Tauri service and React UI
- backend: add commands/prompt.rs, services/prompt.rs, register in commands/mod.rs and lib.rs, refine app_config.rs
- frontend: add PromptPanel, PromptFormModal, PromptListItem, MarkdownEditor, usePromptActions, integrate in App.tsx
- api: add src/lib/api/prompts.ts
- i18n: update src/i18n/locales/{en,zh}.json
- build: update package.json and pnpm-lock.yaml
* feat(i18n): improve i18n for prompts and Markdown editor
- update src/i18n/locales/{en,zh}.json keys and strings
- apply i18n in PromptFormModal, PromptPanel, and MarkdownEditor
- align prompt text with src-tauri/src/services/prompt.rs
* feat(prompts): add enable/disable toggle and simplify panel UI
- Add PromptToggle component and integrate in prompt list items
- Implement toggleEnabled with optimistic update; enable via API, disable via upsert with enabled=false;
reload after success
- Simplify PromptPanel: remove file import and current-file preview to keep CRUD flow focused
- Tweak header controls style (use mcp variant) and minor copy: rename “Prompt Management” to “Prompts”
- i18n: add disableSuccess/disableFailed messages
- Backend (Tauri): prevent duplicate backups when importing original prompt content
* style: unify code formatting with trailing commas
* feat(prompts): add Gemini filename support to PromptFormModal
Update filename mapping to use Record<AppId, string> pattern, supporting
GEMINI.md alongside CLAUDE.md and AGENTS.md.
* fix(prompts): sync enabled prompt to file when updating
When updating a prompt that is currently enabled, automatically sync
the updated content to the corresponding live file (CLAUDE.md/AGENTS.md/GEMINI.md).
This ensures the active prompt file always reflects the latest content
when editing enabled prompts.
Previously, if updateTrayMenu() failed after a successful main operation
(like sorting, adding, or updating providers), the entire operation would
appear to fail with a misleading error message, even though the core
functionality had already succeeded.
This resulted in false negative feedback where:
- Backend data was successfully updated
- Frontend UI was successfully refreshed
- Tray menu failed to update
- User saw "operation failed" message (incorrect)
Changes:
- Wrap updateTrayMenu() calls in nested try-catch blocks
- Log tray menu failures separately with descriptive messages
- Ensure main operation success is reported accurately
- Prevent tray menu failures from triggering main operation error handlers
Files modified:
- src/hooks/useDragSort.ts (drag-and-drop sorting)
- src/lib/query/mutations.ts (add/delete/switch mutations)
- src/hooks/useProviderActions.ts (update provider)
This fixes the bug introduced in PR #179 and prevents similar issues
across all provider operations.
The drag-and-drop sorting feature introduced in PR #126 (9eb991d) was
updating the provider sort order in the backend and frontend, but failed
to update the tray menu to reflect the new order.
Changes:
- Add updateTrayMenu() call after successful sort order update
- Ensures tray menu items are immediately reordered to match the UI
This fixes the issue where dragging providers in the main window would
not update their order in the system tray menu.
Fixes: 9eb991d (feat(ui): add drag-and-drop sorting for provider list)
Breaking Changes:
- Removed useAutoUsageQuery hook (119 lines)
- Unified all usage queries into single useUsageQuery hook
Technical Improvements:
- Eliminated duplicate state management (React Query + manual useState)
- Fixed single source of truth principle violation
- Replaced manual setInterval with React Query's built-in refetchInterval
- Reduced UsageFooter complexity by 28% (54 → 39 lines)
New Features:
- useUsageQuery now accepts autoQueryInterval option
- Automatic query interval control (0 = disabled, min 1 minute)
- Built-in lastQueriedAt timestamp from dataUpdatedAt
- Auto-query only enabled for currently active provider
Architecture Benefits:
- Single data source: manual and auto queries share same cache
- No more state inconsistency between manual/auto query results
- Leverages React Query's caching, deduplication, and background updates
- Cleaner separation of concerns
Code Changes:
- src/lib/query/queries.ts: Enhanced useUsageQuery with auto-query support
- src/components/UsageFooter.tsx: Simplified to use single query hook
- src/hooks/useAutoUsageQuery.ts: Deleted (redundant)
- All type checks passed
New Features:
- Users can configure auto-query interval in "Configure Usage Query" dialog
- Interval in minutes (0 = disabled, recommend 5-60 minutes)
- Auto-query only enabled for currently active provider
- Display last query timestamp in relative time format (e.g., "5 min ago")
- Execute first query immediately when enabled, then repeat at intervals
Technical Implementation:
- Backend: Add auto_query_interval field to UsageScript struct
- Frontend: Create useAutoUsageQuery Hook to manage timers and query state
- UI: Add auto-query interval input field in UsageScriptModal
- Integration: Display auto-query results and timestamp in UsageFooter
- i18n: Add Chinese and English translations
UX Improvements:
- Minimum interval protection (1 minute) to prevent API abuse
- Auto-cleanup timers on component unmount
- Silent failure handling for auto-queries, non-intrusive to users
- Prioritize auto-query results, fallback to manual query results
- Timestamp display positioned next to refresh button for better clarity
- Add postChangeSync.ts utility with Result pattern for graceful error handling
- Replace try-catch with syncCurrentProvidersLiveSafe in useImportExport
- Add directory-change-triggered sync in useSettings to maintain SSOT
- Introduce partial-success status to distinguish import success from sync failures
- Add test coverage for sync behavior in different scenarios
This refactoring ensures config.json changes are reliably synced to live
files while providing better user feedback for edge cases.
- Implement TrayTexts struct to manage multilingual tray menu text
- Auto-refresh tray menu when language settings change
- Add missing notification message translations
- Format code for consistency
Rename `AppType` to `AppId` across the entire frontend codebase to better
reflect its purpose as an application identifier rather than a type category.
This aligns frontend naming with backend command parameter conventions.
Changes:
- Rename type `AppType` to `AppId` in src/lib/api/types.ts
- Remove `AppType` export from src/lib/api/index.ts
- Update all component props from `appType` to `appId` (43 files)
- Update all variable names from `appType` to `appId`
- Synchronize documentation (CHANGELOG, refactoring plans)
- Update test files and MSW mocks
BREAKING CHANGE: `AppType` type is no longer exported. Use `AppId` instead.
All component props have been renamed from `appType` to `appId`.
Core Improvements:
- Add sync_current_providers_live command to synchronize in-memory provider
settings to corresponding live files (~/.claude/settings.json or ~/.codex/auth.json)
- Introduce partial-success state to distinguish between 'import succeeded
but sync failed' scenario, providing clear user feedback
- Remove unused skip_live_backfill parameter from switch_provider command
- Separate responsibilities: backend handles import/backup, frontend handles
sync/error presentation
Technical Details:
- Codex: sync auth.json + config.toml with MCP configuration
- Claude: sync settings.json
- Bidirectional sync: read back after write to update in-memory settings_config
- Full i18n support (English and Chinese)
- Graceful handling when no current provider is active
Affected Files:
- Backend: import_export.rs, commands.rs, lib.rs
- Frontend: useImportExport.ts, ImportExportSection.tsx, settings.ts
- i18n: en.json, zh.json
This ensures SSOT (Single Source of Truth) consistency between config.json
and live configuration files after import operations.
- Change toast position from top-right to top-center for better visibility
- Remove success notifications for plugin sync operations to reduce noise
- Keep error notifications to alert users of actual issues
Remove the config file location display from settings dialog to simplify
the user interface. Users who need to access the config file can still do
so through the advanced settings section.
Changes:
- Removed ConfigPathDisplay component and its usage
- Removed configPath and openConfigFolder from useSettings hook
- Removed configPath and openConfigFolder from useSettingsMetadata hook
- Removed related i18n keys: configFileLocation, openFolder
- Updated settings dialog to remove the config path display section
This simplifies the settings UI while maintaining access to config
directory management through the advanced settings tab.
Fixed an issue where clicking the language switcher would cause a brief flash
and fail to persist the language change. The root cause was a dependency cycle
in useSettingsForm where readPersistedLanguage depended on i18n.language,
causing the initialization effect to re-run and reset state whenever the
language changed.
Changed the dependency from [i18n.language] to [i18n] since the i18n object
itself is stable and doesn't change when the language changes, while the
function can still access the current language value via closure.
Before optimization:
- McpPanel.tsx: 298 lines (component + business logic)
After optimization:
- McpPanel.tsx: 234 lines (-21%, UI focused)
- useMcpActions.ts: 137 lines (business logic)
Benefits:
✅ Separation of concerns: UI vs business logic
✅ Reusability: MCP operations can be used in other components
✅ Testability: business logic can be tested independently
✅ Consistency: follows same pattern as useProviderActions
✅ Optimistic updates: toggle enabled status with rollback on error
✅ Unified error handling: all MCP errors use toast notifications
Technical details:
- Extract reload, toggleEnabled, saveServer, deleteServer
- Implement optimistic UI updates for toggle
- Centralize error handling and toast messages
- Remove duplicate error handling code from component
Before optimization:
- useSettings.ts: 516 lines (single monolithic hook)
After optimization:
- useSettingsForm.ts: 158 lines (form state management)
- useDirectorySettings.ts: 297 lines (directory management)
- useSettingsMetadata.ts: 95 lines (metadata management)
- useSettings.ts: 215 lines (composition layer)
- Total: 765 lines (+249 lines, but with clear separation of concerns)
Benefits:
✅ Single Responsibility Principle: each hook focuses on one domain
✅ Testability: independent hooks are easier to unit test
✅ Reusability: specialized hooks can be reused in other components
✅ Maintainability: reduced cognitive load per file
✅ Zero breaking changes: SettingsDialog auto-adapted to new interface
Technical details:
- useSettingsForm: pure form state + language sync
- useDirectorySettings: directory selection/reset + default value computation
- useSettingsMetadata: config path + portable mode + restart flag
- useSettings: composition layer + save logic + reset logic
- Remove unused useDarkMode hook (now using shadcn theme-provider)
- Clean up MCP components (remove redundant code)
- Add restart API to settings
- Minor type improvements
- refactor(settings): remove the VS Code auto-sync toggle from Settings UI
- feat(provider-list): enable auto-sync after "Apply to VS Code"; disable after "Remove"
- chore(prettier): run Prettier on changed files
- verify: typecheck and renderer build pass
- Files
- added: src/hooks/useVSCodeAutoSync.ts
- modified: src/App.tsx
- modified: src/components/ProviderList.tsx
- modified: src/components/SettingsModal.tsx
- Notes
- Auto-sync now defaults to enabled for new users (stored in localStorage; existing saved state is respected).
- No settings toggle is shown; manual Apply/Remove in the list still works as before.
- refactor(ProviderList): use shared base_url helpers
- refactor(App): reuse shared base_url helpers for VS Code sync
- fix(auto-sync): global shared VS Code auto-apply state (localStorage + event broadcast)
- feat(tray): auto-apply to VS Code on Codex provider-switched when enabled
- behavior: manual Apply enables auto-sync; manual Remove disables; official providers clear managed keys only
- chore(typecheck): pass pnpm typecheck
- Add useDarkMode hook for managing theme state and persistence
- Integrate dark mode toggle button in app header
- Update all components with dark variant styles using Tailwind v4
- Create centralized style utilities for consistent theming
- Support system color scheme preference as fallback
- Store user preference in localStorage for persistence