# 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, quick assistant, etc.
- Conflict resolution handled by Main process

## Update Strategies

### Optimistic Updates (Default)

```typescript
// 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

```typescript
// 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

### Statistics (Debug)

Main process provides `getStats(details?)` for debugging subscription status:

- Returns total keys, main process subscriptions, and window subscriptions
- Pass `details=true` for per-key breakdown
- **Warning**: Resource-intensive, recommended for development only

```typescript
import { application } from '@application'

const preferenceService = application.get('PreferenceService')
const stats = preferenceService.getStats(true);
```

## Database Schema

Preferences are stored in the `preference` table:

```typescript
// 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](./preference-usage.md).

| 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({...})`     |

## Related Documentation

- [Preference Schema Guide](./preference-schema-guide.md) - Adding new preference keys
- [Preference Usage Guide](./preference-usage.md) - Hooks and service API
