cherry-studio/docs/en/references/data/preference-overview.md
fullex 819c209821 docs(data): update README and remove outdated API design guidelines
- Revised the README files for shared data and main data layers to improve clarity and structure.
- Consolidated documentation on shared data types and API types, removing the now-deleted `api-design-guidelines.md`.
- Streamlined directory structure descriptions and updated links to relevant documentation.
- Enhanced quick reference sections for better usability and understanding of the data architecture.
2025-12-29 17:15:06 +08:00

6.7 KiB

Preference System Overview

The Preference system provides centralized management for user configuration and application settings with cross-window synchronization.

Purpose

PreferenceService handles data that:

  • Is a user-modifiable setting that affects app behavior
  • Has a fixed key structure with stable value types
  • Needs to persist permanently until explicitly changed
  • Should sync automatically across all application windows

Key Characteristics

Fixed Key Structure

  • Predefined keys in the schema (users modify values, not keys)
  • Supports 158 configuration items
  • Nested key paths supported (e.g., app.theme.mode)

Atomic Values

  • Each preference item represents one logical setting
  • Values are typically: boolean, string, number, or simple array/object
  • Changes are independent (updating one doesn't affect others)

Cross-Window Synchronization

  • Changes automatically broadcast to all windows
  • Consistent state across main window, mini window, etc.
  • Conflict resolution handled by Main process

Update Strategies

Optimistic Updates (Default)

// UI updates immediately, then syncs to database
await preferenceService.set('app.theme.mode', 'dark')
  • Best for: frequent, non-critical settings
  • Behavior: Local state updates first, then persists
  • Rollback: Automatic revert if persistence fails

Pessimistic Updates

// Waits for database confirmation before updating UI
await preferenceService.set('api.key', 'secret', { optimistic: false })
  • Best for: critical settings (API keys, security options)
  • Behavior: Persists first, then updates local state
  • No rollback needed: UI only updates on success

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│ Renderer Process                                             │
│ ┌─────────────────────────────────────────────────┐         │
│ │ usePreference Hook                               │         │
│ │ - Subscribe to preference changes               │         │
│ │ - Optimistic/pessimistic update support         │         │
│ └──────────────────────┬──────────────────────────┘         │
│                        ▼                                     │
│ ┌─────────────────────────────────────────────────┐         │
│ │ PreferenceService (Renderer)                    │         │
│ │ - Local cache for fast reads                    │         │
│ │ - IPC proxy to Main process                     │         │
│ │ - Subscription management                       │         │
│ └──────────────────────┬──────────────────────────┘         │
└─────────────────────────┼────────────────────────────────────┘
                          │ IPC
┌─────────────────────────┼────────────────────────────────────┐
│ Main Process            ▼                                    │
│ ┌─────────────────────────────────────────────────┐         │
│ │ PreferenceService (Main)                        │         │
│ │ - Full memory cache of all preferences          │         │
│ │ - SQLite persistence via Drizzle ORM            │         │
│ │ - Cross-window broadcast                        │         │
│ └──────────────────────┬──────────────────────────┘         │
│                        ▼                                     │
│ ┌─────────────────────────────────────────────────┐         │
│ │ SQLite Database (preference table)              │         │
│ │ - scope + key structure                         │         │
│ │ - JSON value storage                            │         │
│ └─────────────────────────────────────────────────┘         │
└──────────────────────────────────────────────────────────────┘

Main vs Renderer Responsibilities

Main Process PreferenceService

  • Source of truth for all preferences
  • Full memory cache for fast access
  • SQLite persistence via preference table
  • Broadcasts changes to all renderer windows
  • Handles batch operations and transactions

Renderer Process PreferenceService

  • Local cache for read performance
  • Proxies write operations to Main
  • Manages React hook subscriptions
  • Handles optimistic update rollbacks
  • Listens for cross-window updates

Database Schema

Preferences are stored in the preference table:

// Simplified schema
{
  scope: string    // e.g., 'default', 'user'
  key: string      // e.g., 'app.theme.mode'
  value: json      // The preference value
  createdAt: number
  updatedAt: number
}

Preference Categories

Application Settings

  • Theme mode, language, font sizes
  • Window behavior, startup options

Feature Toggles

  • Show/hide UI elements
  • Enable/disable features

User Customization

  • Keyboard shortcuts
  • Default values for operations

Provider Configuration

  • AI provider settings
  • API endpoints and tokens

Usage Summary

For detailed code examples and API usage, see Preference Usage Guide.

Operation Hook Service Method
Read single usePreference(key) preferenceService.get(key)
Write single setPreference(value) preferenceService.set(key, value)
Read multiple usePreferences([...keys]) preferenceService.getMultiple([...keys])
Write multiple - preferenceService.setMultiple({...})