Files
core-cooldown/src/lib/stores/config.ts

234 lines
6.3 KiB
TypeScript

import { writable, get } from "svelte/store";
import { invoke } from "@tauri-apps/api/core";
export interface TimeRange {
start: string; // Format: "HH:MM"
end: string; // Format: "HH:MM"
}
export interface DaySchedule {
enabled: boolean;
ranges: TimeRange[];
}
export interface CustomActivity {
id: string;
category: string;
text: string;
is_favorite: boolean;
enabled: boolean;
}
export interface Config {
break_duration: number;
break_frequency: number;
auto_start: boolean;
break_title: string;
break_message: string;
fullscreen_mode: boolean;
strict_mode: boolean;
allow_end_early: boolean;
immediately_start_breaks: boolean;
working_hours_enabled: boolean;
working_hours_schedule: DaySchedule[];
dark_mode: boolean;
color_scheme: string;
backdrop_opacity: number;
notification_enabled: boolean;
notification_before_break: number;
snooze_duration: number;
snooze_limit: number;
skip_cooldown: number;
sound_enabled: boolean;
sound_volume: number;
sound_preset: string;
idle_detection_enabled: boolean;
idle_timeout: number;
smart_breaks_enabled: boolean;
smart_break_threshold: number;
smart_break_count_stats: boolean;
show_break_activities: boolean;
ui_zoom: number;
accent_color: string;
break_color: string;
countdown_font: string;
background_blobs_enabled: boolean;
mini_click_through: boolean;
mini_hover_threshold: number;
// F8: Auto-start on login
auto_start_on_login: boolean;
// F6: Custom activities
custom_activities: CustomActivity[];
disabled_builtin_activities: string[];
favorite_builtin_activities: string[];
favorite_weight: number;
// F4: Breathing guide
breathing_guide_enabled: boolean;
breathing_pattern: string;
// F10: Gamification
daily_goal_enabled: boolean;
daily_goal_breaks: number;
milestone_celebrations: boolean;
streak_notifications: boolean;
// F1: Microbreaks
microbreak_enabled: boolean;
microbreak_frequency: number;
microbreak_duration: number;
microbreak_sound_enabled: boolean;
microbreak_show_activity: boolean;
microbreak_pause_during_break: boolean;
// F3: Pomodoro
pomodoro_enabled: boolean;
pomodoro_short_breaks: number;
pomodoro_long_break_duration: number;
pomodoro_long_break_title: string;
pomodoro_long_break_message: string;
pomodoro_reset_on_skip: boolean;
// F5: Screen dimming
screen_dim_enabled: boolean;
screen_dim_seconds: number;
screen_dim_max_opacity: number;
// F2: Presentation mode
presentation_mode_enabled: boolean;
presentation_mode_defer_microbreaks: boolean;
presentation_mode_notification: boolean;
// F9: Multi-monitor
multi_monitor_break: boolean;
}
const defaultConfig: Config = {
break_duration: 5,
break_frequency: 25,
auto_start: true,
break_title: "Rest your eyes",
break_message: "Look away from the screen. Stretch and relax.",
fullscreen_mode: true,
strict_mode: false,
allow_end_early: true,
immediately_start_breaks: false,
working_hours_enabled: false,
working_hours_schedule: [
{ enabled: true, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: true, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: true, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: true, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: true, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: false, ranges: [{ start: "09:00", end: "18:00" }] },
{ enabled: false, ranges: [{ start: "09:00", end: "18:00" }] },
],
dark_mode: true,
color_scheme: "Ocean",
backdrop_opacity: 0.92,
notification_enabled: true,
notification_before_break: 30,
snooze_duration: 5,
snooze_limit: 3,
skip_cooldown: 60,
sound_enabled: true,
sound_volume: 70,
sound_preset: "bell",
idle_detection_enabled: true,
idle_timeout: 120,
smart_breaks_enabled: true,
smart_break_threshold: 300,
smart_break_count_stats: false,
show_break_activities: true,
ui_zoom: 100,
accent_color: "#ff4d00",
break_color: "#7c6aef",
countdown_font: "",
background_blobs_enabled: true,
mini_click_through: true,
mini_hover_threshold: 3.0,
// F8
auto_start_on_login: false,
// F6
custom_activities: [],
disabled_builtin_activities: [],
favorite_builtin_activities: [],
favorite_weight: 3,
// F4
breathing_guide_enabled: true,
breathing_pattern: "box",
// F10
daily_goal_enabled: true,
daily_goal_breaks: 8,
milestone_celebrations: true,
streak_notifications: true,
// F1
microbreak_enabled: false,
microbreak_frequency: 20,
microbreak_duration: 20,
microbreak_sound_enabled: true,
microbreak_show_activity: true,
microbreak_pause_during_break: true,
// F3
pomodoro_enabled: false,
pomodoro_short_breaks: 3,
pomodoro_long_break_duration: 15,
pomodoro_long_break_title: "Long break",
pomodoro_long_break_message: "Great work! Take a longer rest.",
pomodoro_reset_on_skip: false,
// F5
screen_dim_enabled: false,
screen_dim_seconds: 10,
screen_dim_max_opacity: 0.3,
// F2
presentation_mode_enabled: true,
presentation_mode_defer_microbreaks: true,
presentation_mode_notification: true,
// F9
multi_monitor_break: true,
};
export const config = writable<Config>(defaultConfig);
export async function loadConfig() {
try {
const cfg = await invoke<Config>("get_config");
config.set(cfg);
} catch (e) {
console.error("Failed to load config:", e);
}
}
export async function saveConfig(): Promise<boolean> {
try {
const cfg = get(config);
await invoke("save_config", { config: cfg });
return true;
} catch (e) {
console.error("Failed to save config:", e);
return false;
}
}
export async function notifyConfigChanged() {
try {
const cfg = get(config);
await invoke("update_pending_config", { config: cfg });
} catch (e) {
console.error("Failed to update pending config:", e);
}
}
export async function resetConfig() {
try {
const cfg = await invoke<Config>("reset_config");
config.set(cfg);
} catch (e) {
console.error("Failed to reset config:", e);
}
}
// Debounced auto-save: updates backend immediately, persists to disk after 400ms idle
let saveTimer: ReturnType<typeof setTimeout> | null = null;
export function autoSave() {
notifyConfigChanged();
if (saveTimer) clearTimeout(saveTimer);
saveTimer = setTimeout(() => {
saveConfig();
}, 400);
}