Zap Studio

Settings

Persistent settings system with type-safe APIs and a pre-built Settings page.

Local.ts includes a complete settings system with persistent storage, type-safe APIs, and a pre-built Settings page.

Understanding the Settings System

Settings in Local.ts flow through a layered architecture:

  1. Models (database/models/settings.rs) — Data structures and type definitions
  2. Services (services/settings.rs) — Database operations (get/update settings)
  3. Commands (commands/settings.rs) — Tauri handlers that call services
  4. Frontend — Zustand store and React hooks

When you update a setting, it flows from the frontend through commands and services to the database, then syncs back to the UI.

Available Settings

CategorySettingDescriptionDefault
AppearanceThemeLight, dark, or systemsystem
Sidebar ExpandedKeep sidebar opentrue
BehaviorShow in System TrayDisplay tray icontrue
Launch at LoginAuto-start with systemfalse
NotificationsEnable NotificationsAllow native notificationstrue
DeveloperEnable LoggingRecord application logstrue
Log LevelMinimum severity to loginfo

Reading Settings

Use the useSettings hook to access settings in your components:

import { useSettings } from "@/stores/settings";

function MyComponent() {
  const settings = useSettings((state) => state.settings);

  if (!settings) return null;

  return (
    <div>
      <p>Current theme: {settings.theme}</p>
      <p>Logging enabled: {settings.enableLogging ? "Yes" : "No"}</p>
    </div>
  );
}

Updating Settings

Call updateSettings with a partial settings object. Only the fields you provide will be updated:

import { useSettings } from "@/stores/settings";

function ThemeToggle() {
  const updateSettings = useSettings((state) => state.updateSettings);

  const switchToDark = async () => {
    await updateSettings({ theme: "dark" });
  };

  return <button type="button" onClick={switchToDark}>Dark Mode</button>;
}

You can update multiple settings at once:

await updateSettings({
  theme: "light",
  enableLogging: true,
  logLevel: "debug",
});

Accessing Settings Outside React

For non-React code, access the store directly:

import { useSettings } from "@/stores/settings";

// Get current settings
const settings = useSettings.getState().settings;

// Update settings
await useSettings.getState().updateSettings({ theme: "dark" });

TypeScript Types

Settings have full TypeScript support. Import the types for use in your code:

import type { Settings, SettingsUpdate, Theme, LogLevel } from "@/lib/tauri/settings/types";

// Theme: "light" | "dark" | "system"
// LogLevel: "error" | "warn" | "info" | "debug" | "trace"

function processSettings(settings: Settings) {
  console.log(settings.theme);
}

The Settings interface:

interface Settings {
  theme: Theme;
  sidebarExpanded: boolean;
  showInTray: boolean;
  launchAtLogin: boolean;
  enableLogging: boolean;
  logLevel: LogLevel;
  enableNotifications: boolean;
}

Adding New Settings

To add a new setting, you need to update both the backend and frontend.

1. Create a Database Migration

Generate a new migration:

cd src-tauri
diesel migration generate add_my_setting

Write the SQL in up.sql:

ALTER TABLE settings ADD COLUMN my_setting INTEGER NOT NULL DEFAULT 0;

And the rollback in down.sql:

ALTER TABLE settings DROP COLUMN my_setting;

Run the migration:

diesel migration run

2. Update the Rust Models

In src-tauri/src/database/models/settings.rs, add the field to each struct:

// In SettingsRow
pub struct SettingsRow {
    // ... existing fields
    pub my_setting: i32,
}

// In Settings
pub struct Settings {
    // ... existing fields
    pub my_setting: bool,
}

// In SettingsUpdate
pub struct SettingsUpdate {
    // ... existing fields
    pub my_setting: Option<bool>,
}

// In SettingsChangeset
pub struct SettingsChangeset {
    // ... existing fields
    pub my_setting: Option<i32>,
}

Update the from_row and From<SettingsUpdate> implementations to handle the new field.

3. Update TypeScript Types

In src/lib/tauri/settings/types.ts:

export interface Settings {
  // ... existing fields
  mySetting: boolean;
}

4. Add UI Controls

Add a toggle or input in src/routes/settings.tsx for users to modify the setting.

Edit on GitHub

Last updated on

On this page