Add pomodoro, microbreaks, breathing guide, screen dimming, presentation mode, goals, multi-monitor, and activity manager
This commit is contained in:
@@ -3,6 +3,16 @@ use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// A custom break activity defined by the user.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CustomActivity {
|
||||
pub id: String,
|
||||
pub category: String,
|
||||
pub text: String,
|
||||
pub is_favorite: bool,
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
/// A single time range (e.g., 09:00 to 17:00)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TimeRange {
|
||||
@@ -107,6 +117,54 @@ pub struct Config {
|
||||
pub mini_click_through: bool, // Mini mode is click-through until hovered
|
||||
pub mini_hover_threshold: f32, // Seconds to hover before enabling drag (1.0-10.0)
|
||||
|
||||
// F8: Auto-start on Windows login
|
||||
pub auto_start_on_login: bool,
|
||||
|
||||
// F6: Custom break activities
|
||||
pub custom_activities: Vec<CustomActivity>,
|
||||
pub disabled_builtin_activities: Vec<String>,
|
||||
pub favorite_builtin_activities: Vec<String>,
|
||||
pub favorite_weight: u32, // Multiplier for favorites in random pool (2-10)
|
||||
|
||||
// F4: Guided breathing animation
|
||||
pub breathing_guide_enabled: bool,
|
||||
pub breathing_pattern: String, // "box", "relaxing", "energizing", "calm", "deep"
|
||||
|
||||
// F10: Break streaks & gamification
|
||||
pub daily_goal_enabled: bool,
|
||||
pub daily_goal_breaks: u32, // 1-30
|
||||
pub milestone_celebrations: bool,
|
||||
pub streak_notifications: bool,
|
||||
|
||||
// F1: Microbreaks & 20-20-20
|
||||
pub microbreak_enabled: bool,
|
||||
pub microbreak_frequency: u32, // 5-60 min
|
||||
pub microbreak_duration: u32, // 10-60 sec
|
||||
pub microbreak_sound_enabled: bool,
|
||||
pub microbreak_show_activity: bool,
|
||||
pub microbreak_pause_during_break: bool,
|
||||
|
||||
// F3: Pomodoro Mode
|
||||
pub pomodoro_enabled: bool,
|
||||
pub pomodoro_short_breaks: u32, // 1-10 (short breaks before long)
|
||||
pub pomodoro_long_break_duration: u32, // 5-60 min
|
||||
pub pomodoro_long_break_title: String, // max 100 chars
|
||||
pub pomodoro_long_break_message: String, // max 500 chars
|
||||
pub pomodoro_reset_on_skip: bool,
|
||||
|
||||
// F5: Screen dimming pre-break nudge
|
||||
pub screen_dim_enabled: bool,
|
||||
pub screen_dim_seconds: u32, // 3-60 sec before break
|
||||
pub screen_dim_max_opacity: f32, // 0.1-0.7
|
||||
|
||||
// F2: Presentation mode / fullscreen detection
|
||||
pub presentation_mode_enabled: bool,
|
||||
pub presentation_mode_defer_microbreaks: bool,
|
||||
pub presentation_mode_notification: bool,
|
||||
|
||||
// F9: Multi-monitor break enforcement
|
||||
pub multi_monitor_break: bool,
|
||||
|
||||
// Window positions (persisted between launches)
|
||||
pub main_window_x: Option<i32>,
|
||||
pub main_window_y: Option<i32>,
|
||||
@@ -186,6 +244,54 @@ impl Default for Config {
|
||||
mini_click_through: true,
|
||||
mini_hover_threshold: 3.0,
|
||||
|
||||
// F8: Auto-start
|
||||
auto_start_on_login: false,
|
||||
|
||||
// F6: Custom activities
|
||||
custom_activities: Vec::new(),
|
||||
disabled_builtin_activities: Vec::new(),
|
||||
favorite_builtin_activities: Vec::new(),
|
||||
favorite_weight: 3,
|
||||
|
||||
// F4: Breathing guide
|
||||
breathing_guide_enabled: true,
|
||||
breathing_pattern: "box".to_string(),
|
||||
|
||||
// F10: Gamification
|
||||
daily_goal_enabled: true,
|
||||
daily_goal_breaks: 8,
|
||||
milestone_celebrations: true,
|
||||
streak_notifications: true,
|
||||
|
||||
// F1: Microbreaks
|
||||
microbreak_enabled: false,
|
||||
microbreak_frequency: 20,
|
||||
microbreak_duration: 20,
|
||||
microbreak_sound_enabled: true,
|
||||
microbreak_show_activity: true,
|
||||
microbreak_pause_during_break: true,
|
||||
|
||||
// F3: Pomodoro
|
||||
pomodoro_enabled: false,
|
||||
pomodoro_short_breaks: 3,
|
||||
pomodoro_long_break_duration: 15,
|
||||
pomodoro_long_break_title: "Long break".to_string(),
|
||||
pomodoro_long_break_message: "Great work! Take a longer rest.".to_string(),
|
||||
pomodoro_reset_on_skip: false,
|
||||
|
||||
// F5: Screen dimming
|
||||
screen_dim_enabled: false,
|
||||
screen_dim_seconds: 10,
|
||||
screen_dim_max_opacity: 0.3,
|
||||
|
||||
// F2: Presentation mode
|
||||
presentation_mode_enabled: true,
|
||||
presentation_mode_defer_microbreaks: true,
|
||||
presentation_mode_notification: true,
|
||||
|
||||
// F9: Multi-monitor
|
||||
multi_monitor_break: true,
|
||||
|
||||
// Window positions
|
||||
main_window_x: None,
|
||||
main_window_y: None,
|
||||
@@ -349,6 +455,44 @@ impl Config {
|
||||
// UI zoom: 50-200%
|
||||
self.ui_zoom = self.ui_zoom.clamp(50, 200);
|
||||
|
||||
// F6: Custom activities
|
||||
if self.custom_activities.len() > 100 {
|
||||
self.custom_activities.truncate(100);
|
||||
}
|
||||
for act in &mut self.custom_activities {
|
||||
if act.text.len() > 500 {
|
||||
act.text.truncate(500);
|
||||
}
|
||||
}
|
||||
self.favorite_weight = self.favorite_weight.clamp(2, 10);
|
||||
|
||||
// F4: Breathing pattern
|
||||
let valid_patterns = vec!["box", "relaxing", "energizing", "calm", "deep"];
|
||||
if !valid_patterns.contains(&self.breathing_pattern.as_str()) {
|
||||
self.breathing_pattern = "box".to_string();
|
||||
}
|
||||
|
||||
// F10: Daily goal
|
||||
self.daily_goal_breaks = self.daily_goal_breaks.clamp(1, 30);
|
||||
|
||||
// F1: Microbreaks
|
||||
self.microbreak_frequency = self.microbreak_frequency.clamp(5, 60);
|
||||
self.microbreak_duration = self.microbreak_duration.clamp(10, 60);
|
||||
|
||||
// F3: Pomodoro
|
||||
self.pomodoro_short_breaks = self.pomodoro_short_breaks.clamp(1, 10);
|
||||
self.pomodoro_long_break_duration = self.pomodoro_long_break_duration.clamp(5, 60);
|
||||
if self.pomodoro_long_break_title.len() > 100 {
|
||||
self.pomodoro_long_break_title.truncate(100);
|
||||
}
|
||||
if self.pomodoro_long_break_message.len() > 500 {
|
||||
self.pomodoro_long_break_message.truncate(500);
|
||||
}
|
||||
|
||||
// F5: Screen dimming
|
||||
self.screen_dim_seconds = self.screen_dim_seconds.clamp(3, 60);
|
||||
self.screen_dim_max_opacity = self.screen_dim_max_opacity.clamp(0.1, 0.7);
|
||||
|
||||
// Validate color hex strings
|
||||
if !Self::is_valid_hex_color(&self.accent_color) {
|
||||
self.accent_color = "#ff4d00".to_string();
|
||||
|
||||
Reference in New Issue
Block a user