Commit Graph

16 Commits

Author SHA1 Message Date
YoVinchen
3d69da5b66 feat: add model configuration support and fix Gemini deeplink bug (#251)
* feat(providers): add notes field for provider management

- Add notes field to Provider model (backend and frontend)
- Display notes with higher priority than URL in provider card
- Style notes as non-clickable text to differentiate from URLs
- Add notes input field in provider form
- Add i18n support (zh/en) for notes field

* chore: format code and clean up unused props

- Run cargo fmt on Rust backend code
- Format TypeScript imports and code style
- Remove unused appId prop from ProviderPresetSelector
- Clean up unused variables in tests
- Integrate notes field handling in provider dialogs

* feat(deeplink): implement ccswitch:// protocol for provider import

Add deep link support to enable one-click provider configuration import via ccswitch:// URLs.

Backend:
- Implement URL parsing and validation (src-tauri/src/deeplink.rs)
- Add Tauri commands for parse and import (src-tauri/src/commands/deeplink.rs)
- Register ccswitch:// protocol in macOS Info.plist
- Add comprehensive unit tests (src-tauri/tests/deeplink_import.rs)

Frontend:
- Create confirmation dialog with security review UI (src/components/DeepLinkImportDialog.tsx)
- Add API wrapper (src/lib/api/deeplink.ts)
- Integrate event listeners in App.tsx

Configuration:
- Update Tauri config for deep link handling
- Add i18n support for Chinese and English
- Include test page for deep link validation (deeplink-test.html)

Files: 15 changed, 1312 insertions(+)

* chore(deeplink): integrate deep link handling into app lifecycle

Wire up deep link infrastructure with app initialization and event handling.

Backend Integration:
- Register deep link module and commands in mod.rs
- Add URL handling in app setup (src-tauri/src/lib.rs:handle_deeplink_url)
- Handle deep links from single instance callback (Windows/Linux CLI)
- Handle deep links from macOS system events
- Add tauri-plugin-deep-link dependency (Cargo.toml)

Frontend Integration:
- Listen for deeplink-import/deeplink-error events in App.tsx
- Update DeepLinkImportDialog component imports

Configuration:
- Enable deep link plugin in tauri.conf.json
- Update Cargo.lock for new dependencies

Localization:
- Add Chinese translations for deep link UI (zh.json)
- Add English translations for deep link UI (en.json)

Files: 9 changed, 359 insertions(+), 18 deletions(-)

* refactor(deeplink): enhance Codex provider template generation

Align deep link import with UI preset generation logic by:
- Adding complete config.toml template matching frontend defaults
- Generating safe provider name from sanitized input
- Including model_provider, reasoning_effort, and wire_api settings
- Removing minimal template that only contained base_url
- Cleaning up deprecated test file deeplink-test.html

* style: fix clippy uninlined_format_args warnings

Apply clippy --fix to use inline format arguments in:
- src/mcp.rs (8 fixes)
- src/services/env_manager.rs (10 fixes)

* style: apply code formatting and cleanup

- Format TypeScript files with Prettier (App.tsx, EnvWarningBanner.tsx, formatters.ts)
- Organize Rust imports and module order alphabetically
- Add newline at end of JSON files (en.json, zh.json)
- Update Cargo.lock for dependency changes

* feat: add model name configuration support for Codex and fix Gemini model handling

- Add visual model name input field for Codex providers
  - Add model name extraction and update utilities in providerConfigUtils
  - Implement model name state management in useCodexConfigState hook
  - Add conditional model field rendering in CodexFormFields (non-official only)
  - Integrate model name sync with TOML config in ProviderForm

- Fix Gemini deeplink model injection bug
  - Correct environment variable name from GOOGLE_GEMINI_MODEL to GEMINI_MODEL
  - Add test cases for Gemini model injection (with/without model)
  - All tests passing (9/9)

- Fix Gemini model field binding in edit mode
  - Add geminiModel state to useGeminiConfigState hook
  - Extract model value during initialization and reset
  - Sync model field with geminiEnv state to prevent data loss on submit
  - Fix missing model value display when editing Gemini providers

Changes:
  - 6 files changed, 245 insertions(+), 13 deletions(-)
2025-11-19 09:03:18 +08:00
Jason
0778347f84 refactor(endpoints): implement deferred submission and fix clear-all bug
Implement Solution A (complete deferred submission) for custom endpoint
management, replacing the dual-mode system with unified local staging.

Changes:
- Remove immediate backend saves from EndpointSpeedTest
  * handleAddEndpoint: local state update only
  * handleRemoveEndpoint: local state update only
  * handleSelect: remove lastUsed timestamp update
- Add explicit clear detection in ProviderForm
  * Distinguish "user cleared endpoints" from "user didn't modify"
  * Pass empty object {} as clear signal vs null for no-change
- Fix mergeProviderMeta to handle three distinct cases:
  * null/undefined: don't modify endpoints (no meta sent)
  * empty object {}: explicitly clear endpoints (send empty meta)
  * with data: add/update endpoints (overwrite)

Fixed Critical Bug:
When users deleted all custom endpoints, changes were not saved because:
- draftCustomEndpoints=[] resulted in customEndpointsToSave=null
- mergeProviderMeta(meta, null) returned undefined
- Backend interpreted missing meta as "don't modify", preserving old values

Solution:
Detect when user had endpoints and cleared them (hadEndpoints && length===0),
then pass empty object to mergeProviderMeta as explicit clear signal.

Architecture Improvements:
- Transaction atomicity: all fields submitted together on form save
- UX consistency: add/edit modes behave identically
- Cancel button: true rollback with no immediate saves
- Code simplification: removed ~40 lines of immediate save error handling

Testing:
- TypeScript type check: passed
- Rust backend tests: 10/10 passed
- Build: successful
2025-11-04 15:30:54 +08:00
Jason
fa9f4997af style(provider): improve type annotation formatting in EditProviderDialog 2025-10-31 18:15:59 +08:00
Jason
ef85b015d3 feat(provider): load live settings when editing active provider
- Add live settings fetching when editing the current active provider
- Use useMemo to prioritize live settings over SSOT configuration
- Implement graceful fallback to SSOT if live settings fetch fails
- Prevent unnecessary API calls with condition checks (open state and current provider)
2025-10-30 17:52:25 +08:00
Jason
8e4a0a1bbb 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`.
2025-10-30 14:59:15 +08:00
Jason
d296471b3b chore: apply prettier formatting to component files 2025-10-24 13:02:35 +08:00
Jason
495e66e3b6 refactor: improve endpoint management type safety and error handling
- Unify EndpointCandidate type definition in types.ts
- Remove all 'as any' type assertions in useSpeedTestEndpoints
- Add cleanup function to prevent race conditions in async operations
- Fix stale error messages persisting after successful deletion
- Improve error handling for endpoint deletion (distinguish not-found vs network errors)
- Extract timeout magic numbers to ENDPOINT_TIMEOUT_SECS constant
- Clarify URL validation to explicitly allow only http/https
- Fix ambiguous payload.meta assignment logic in ProviderForm
- Add i18n for new error messages (removeFailed, updateLastUsedFailed)
2025-10-24 09:24:03 +08:00
Jason
57661817d3 refine: standardize provider dialog dimensions to match MCP panel
Adjusted Add and Edit provider dialogs to use consistent sizing with MCP panel:
- Increased max width from max-w-2xl to max-w-3xl
- Unified max height to max-h-[85vh] (was 90vh)
- Added min-h-[600px] for minimum height constraint

This ensures visual consistency across all major dialog panels in the app.
2025-10-19 12:02:22 +08:00
Jason
eb6948a562 i18n: complete internationalization for provider and usage query panels
- Add 45+ new translation keys for usage query and usage script features
- Fix duplicate provider object in translation files that caused missing translations
- Remove all hardcoded Chinese text and defaultValue fallbacks from components
- Add proper translations for:
  * Usage footer (query status, plan usage display)
  * Usage script modal (script editor, validation, test controls)
  * Provider forms (basic fields, endpoints, model selectors)
  * Provider dialogs (add/edit hints and titles)

Modified 16 files:
- 2 translation files (zh.json, en.json)
- 14 component files (removed defaultValue, added t() calls)

All UI text now properly supports Chinese/English switching.
2025-10-19 11:55:46 +08:00
Jason
9fc5555ecf feat: add icons to provider dialog action buttons
Add visual indicators to the Add and Save buttons in provider dialogs
for improved UX and consistency with other dialogs.

Changes:
- AddProviderDialog: Add Plus icon to "Add" button
- EditProviderDialog: Add Save icon to "Save" button

Both dialogs now have clear visual affordances for primary actions,
matching the icon usage pattern in other modal dialogs throughout
the application.
2025-10-18 23:31:14 +08:00
Jason
9d6ccb6d15 refactor: move provider form buttons to DialogFooter for consistency
Restructure AddProviderDialog and EditProviderDialog to follow the
standardized dialog layout pattern with buttons in DialogFooter.

Changes:
- Add DialogFooter to AddProviderDialog and EditProviderDialog
- Add `showButtons` prop to ProviderForm (default: true for backward compatibility)
- Add `id="provider-form"` to form element for external form submission
- Move Cancel and Submit buttons from ProviderForm to DialogFooter
- Use `form="provider-form"` attribute on DialogFooter buttons to trigger submission

Benefits:
- Consistent dialog footer appearance across all dialogs
- Proper spacing and alignment with other modal dialogs
- Better visual hierarchy with separated content and action areas
- Maintains backward compatibility for ProviderForm usage elsewhere

All provider dialogs now follow the unified pattern:
- DialogHeader: Title and description
- Content area: flex-1 overflow-y-auto px-6 py-4
- DialogFooter: Action buttons with standard styling
2025-10-18 23:28:33 +08:00
Jason
57552b3159 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
2025-10-18 16:52:02 +08:00
Jason
31f56f7c86 fix: add scrollbars to provider dialogs and simplify theme toggle
## Changes

### Add scrollbars to provider dialogs
- **AddProviderDialog.tsx**: Add max-h-[90vh], flex flex-col layout, and scrollable content wrapper
- **EditProviderDialog.tsx**: Add max-h-[90vh], flex flex-col layout, and scrollable content wrapper
- Both dialogs now follow the same scrolling pattern as other dialogs in the app
- Wrap ProviderForm in `<div className="flex-1 overflow-y-auto -mx-6 px-6">` for proper scrolling

### Simplify theme toggle
- **mode-toggle.tsx**: Change from dropdown menu to direct toggle button
- Remove DropdownMenu and related imports
- Click now directly toggles between light and dark mode
- Simpler UX: one click to switch themes instead of opening a menu
- Remove "system" theme option from quick toggle (still available in settings if needed)

## Benefits
- **Consistent scrolling**: All dialogs now have proper scroll behavior when content exceeds viewport height
- **Better UX**: Theme toggle is faster and more intuitive with direct click
- **Code simplification**: Removed unnecessary dropdown menu complexity from theme toggle

All TypeScript type checks and Prettier formatting checks pass.
2025-10-16 16:39:03 +08:00
Jason
5f2bede5c4 style: restore original color scheme to shadcn/ui components
Restore the vibrant color palette from the pre-refactoring version while
maintaining shadcn/ui component architecture and modern design patterns.

## Color Scheme Restoration

### Button Component
- **default variant**: Blue primary (`bg-blue-500`) - matches old `primary`
- **destructive variant**: Red (`bg-red-500`) - matches old `danger`
- **secondary variant**: Gray text (`text-gray-500`) - matches old `secondary`
- **ghost variant**: Transparent hover (`hover:bg-gray-100`) - matches old `ghost`
- **mcp variant**: Emerald green (`bg-emerald-500`) - matches old `mcp`
- Updated border-radius to `rounded-lg` for consistency

### CSS Variables
- Set `--primary` to blue (`hsl(217 91% 60%)` ≈ `bg-blue-500`)
- Added complete shadcn/ui theme variables for light/dark modes
- Maintained semantic color tokens for maintainability

### Component-Specific Colors
- **"Currently Using" badge**: Green (`bg-green-500/10 text-green-500`)
- **Delete button hover**: Red (`hover:text-red-500 hover:bg-red-100`)
- **MCP button**: Emerald green with minimum width (`min-w-[80px]`)
- **Links/URLs**: Blue (`text-blue-500`)

## Benefits

-  Restored original vibrant UI (blue, green, red accents)
-  Maintained shadcn/ui component system (accessibility, animations)
-  Easy global theming via CSS variables
-  Consistent design language across all components
-  Code formatted with Prettier (shadcn/ui standards)

## Files Changed

- `src/index.css`: Added shadcn/ui theme variables with blue primary
- `src/components/ui/button.tsx`: Restored all original button color variants
- `src/components/providers/ProviderCard.tsx`: Green badge for current provider
- `src/components/providers/ProviderActions.tsx`: Red hover for delete button
- `src/components/mcp/McpPanel.tsx`: Use `mcp` variant for consistency
- `src/App.tsx`: MCP button with emerald color and wider width

The UI now matches the original colorful design while leveraging modern
shadcn/ui components for better maintainability and user experience.
2025-10-16 15:32:26 +08:00
Jason
bb48f4f6af refactor: consolidate provider form components
This commit completes Stage 2.5-2.6 of the refactoring plan by:

- Consolidating 8 provider form files (1941+ lines) into a single
  unified ProviderForm component (353 lines), reducing code by ~82%
- Implementing modern form management with react-hook-form and zod
- Adding preset provider categorization with grouped select UI
- Supporting dual-mode operation for both Claude and Codex configs
- Removing redundant subcomponents:
  - ApiKeyInput.tsx (72 lines)
  - ClaudeConfigEditor.tsx (205 lines)
  - CodexConfigEditor.tsx (667 lines)
  - EndpointSpeedTest.tsx (636 lines)
  - KimiModelSelector.tsx (195 lines)
  - PresetSelector.tsx (119 lines)

Key improvements:
- Type-safe form values with ProviderFormValues extension
- Automatic template value application for presets
- Better internationalization coverage
- Cleaner separation of concerns
- Enhanced UX with categorized preset groups

Updates AddProviderDialog and EditProviderDialog to pass appType prop
and handle preset category metadata.
2025-10-16 13:02:38 +08:00
Jason
b88eb88608 feat: complete stage 2 core refactor 2025-10-16 10:49:56 +08:00