Commit Graph

33 Commits

  • feat(settings): add Gemini configuration directory support (#255)
    * style: apply code formatting across backend and frontend
    
    Apply cargo fmt and prettier formatting to improve code readability.
    No functional changes.
    
    Changes:
    - Rust: multi-line assertion formatting (gemini_config, env_checker)
    - Rust: simplify chained method calls (provider)
    - TypeScript: add trailing commas to function parameters (codexProviderPresets)
    
    * feat(settings): add Gemini configuration directory support
    
    Add custom configuration directory support for Gemini:
    - Add geminiConfigDir field to Settings type
    - Extend DirectorySettings component with Gemini input
    - Update useDirectorySettings hook for Gemini directory management
    - Add i18n translations for Gemini directory settings
  • refactor(mcp): complete v3.7.0 cleanup - remove legacy code and warnings
    This commit finalizes the v3.7.0 unified MCP architecture migration by
    removing all deprecated code paths and eliminating compiler warnings.
    
    Frontend Changes (~950 lines removed):
    - Remove deprecated components: McpPanel, McpListItem, McpToggle
    - Remove deprecated hook: useMcpActions
    - Remove unused API methods: importFrom*, syncEnabledTo*, syncAllServers
    - Simplify McpFormModal by removing dual-mode logic (unified/legacy)
    - Remove syncOtherSide checkbox and conflict detection
    - Clean up unused imports and state variables
    - Delete associated test files
    
    Backend Changes (~400 lines cleaned):
    - Remove unused Tauri commands: import_mcp_from_*, sync_enabled_mcp_to_*
    - Delete unused Gemini MCP functions: get_mcp_status, upsert/delete_mcp_server
    - Add #[allow(deprecated)] to compatibility layer commands
    - Add #[allow(dead_code)] to legacy helper functions for future migration
    - Simplify boolean expression in mcp.rs per Clippy suggestion
    
    API Deprecation:
    - Mark legacy APIs with @deprecated JSDoc (getConfig, upsertServerInConfig, etc.)
    - Preserve backward compatibility for v3.x, planned removal in v4.0
    
    Verification:
    -  Zero TypeScript errors (pnpm typecheck)
    -  Zero Clippy warnings (cargo clippy)
    -  All code formatted (prettier + cargo fmt)
    -  Builds successfully
    
    Total cleanup: ~1,350 lines of code removed/marked
    Breaking changes: None (all legacy APIs still functional)
  • refactor(frontend): remove redundant 'Sync All' button from MCP panel
    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.
  • feat(frontend): implement unified MCP panel for v3.7.0
    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+i18n): add prompt management and improve prompt editor i18n (#193)
    * 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.
  • fix(error-handling): isolate tray menu update failures from main operations
    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.
  • fix(ui): sync tray menu order after drag-and-drop sorting (#179)
    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)
  • refactor(usage): consolidate query logic to eliminate DRY violations
    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
  • feat(usage): add auto-refresh interval for usage queries
    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
  • refactor(hooks): introduce unified post-change sync utility
    - 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.
  • feat(i18n): add internationalization support for tray menu
    - 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
  • refactor(types): rename AppType to AppId for semantic clarity
    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`.
  • feat: sync current providers to live files after config import
    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.
  • refine: center toast notifications and silence plugin sync feedback
    - 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
  • fix: unify dialog layout and fix content padding issues
    - Fix negative margin overflow in all dialog content areas
    - Standardize dialog structure with flex-col layout
    - Add consistent py-4 spacing to all content areas
    - Ensure proper spacing between header, content, and footer
    
    Affected components:
    - AddProviderDialog, EditProviderDialog
    - McpFormModal, McpPanel
    - UsageScriptModal
    - SettingsDialog
    
    All dialogs now follow unified layout pattern:
    - DialogContent: flex flex-col max-h-[90vh]
    - Content area: flex-1 overflow-y-auto px-6 py-4
    - No negative margins that cause content overflow
  • refactor: remove config file location display feature
    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.
  • fix: prevent language switch state reset caused by dependency cycle
    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.
  • refactor: improve code quality and consistency
    Changes:
    1. Remove unused variable in useSettings.ts (readPersistedLanguage)
    2. Replace manual state management with React Query in UsageFooter
       - Create useUsageQuery hook with 5-minute cache
       - Simplify component from 227 lines to 81 lines (-64%)
       - Improve consistency with project's React Query pattern
       - Enable automatic refetch and error handling
  • refactor: extract MCP business logic to useMcpActions hook
    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
  • refactor: split useSettings hook into specialized hooks
    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
  • refactor: extract business logic to useProviderActions hook
    Major improvements:
    - Create `src/hooks/useProviderActions.ts` (147 lines)
      - Consolidate provider operations (add, update, delete, switch)
      - Extract Claude plugin sync logic
      - Extract usage script save logic
    
    - Simplify `App.tsx` (347 → 226 lines, -35%)
      - Remove 8 callback functions
      - Remove Claude plugin sync logic
      - Remove usage script save logic
      - Cleaner and more maintainable
    
    - Replace `onNotify` prop with `toast` in:
      - `UsageScriptModal.tsx`
      - `McpPanel.tsx`
      - `McpFormModal.tsx`
      - `McpWizardModal.tsx`
      - Unified notification system using sonner
    
    Benefits:
    - Reduced coupling and improved maintainability
    - Business logic isolated in hooks, easier to test
    - Consistent notification system across the app
  • refactor: cleanup and minor improvements
    - Remove unused useDarkMode hook (now using shadcn theme-provider)
    - Clean up MCP components (remove redundant code)
    - Add restart API to settings
    - Minor type improvements
  • feat: complete stage 4 cleanup and code formatting
    This commit completes stage 4 of the refactoring plan, focusing on cleanup
    and optimization of the modernized codebase.
    
    ## Key Changes
    
    ### Code Cleanup
    - Remove legacy `src/lib/styles.ts` (no longer needed)
    - Remove old modal components (`ImportProgressModal.tsx`, `ProviderList.tsx`)
    - Streamline `src/lib/tauri-api.ts` from 712 lines to 17 lines (-97.6%)
      - Remove global `window.api` pollution
      - Keep only event listeners (`tauriEvents.onProviderSwitched`)
      - All API calls now use modular `@/lib/api/*` layer
    
    ### Type System
    - Clean up `src/vite-env.d.ts` (remove 156 lines of outdated types)
    - Remove obsolete global type declarations
    - All TypeScript checks pass with zero errors
    
    ### Code Formatting
    - Format all source files with Prettier (82 files)
    - Fix formatting issues in 15 files:
      - App.tsx and core components
      - MCP management components
      - Settings module components
      - Provider management components
      - UI components
    
    ### Documentation Updates
    - Update `REFACTORING_CHECKLIST.md` with stage 4 progress
    - Mark completed tasks in `REFACTORING_MASTER_PLAN.md`
    
    ## Impact
    
    **Code Reduction:**
    - Total: -1,753 lines, +384 lines (net -1,369 lines)
    - tauri-api.ts: 712 → 17 lines (-97.6%)
    - Removed styles.ts: -82 lines
    - Removed vite-env.d.ts declarations: -156 lines
    
    **Quality Improvements:**
    -  Zero TypeScript errors
    -  Zero TODO/FIXME comments
    -  100% Prettier compliant
    -  Zero `window.api` references
    -  Fully modular API layer
    
    ## Testing
    - [x] TypeScript compilation passes
    - [x] Code formatting validated
    - [x] No linting errors
    
    Stage 4 completion: 100%
    Ready for stage 5 (testing and bug fixes)
  • - feat(vscode-sync): restore auto-sync logic and enable by default
    - 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(utils): extract Codex base_url parsing into shared helpers
    - 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
  • feat(ui): implement dark mode with system preference support
    - 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