using System.Text.Json; using System.Text.Json.Serialization; namespace Clawdbot.Windows.Core; /// /// Application settings persisted to disk. /// Stored at %LOCALAPPDATA%\Clawdbot\settings.json /// public class AppSettings { private static readonly string SettingsDirectory = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Clawdbot"); private static readonly string SettingsPath = Path.Combine(SettingsDirectory, "settings.json"); private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; /// /// Gateway WebSocket URL (default: ws://127.0.0.1:18789/) /// [JsonPropertyName("gatewayUrl")] public string GatewayUrl { get; set; } = "ws://127.0.0.1:18789/"; /// /// Whether to start Clawdbot when Windows starts /// [JsonPropertyName("startOnLogin")] public bool StartOnLogin { get; set; } = false; /// /// Whether to minimize to tray instead of closing when X is clicked /// [JsonPropertyName("minimizeToTray")] public bool MinimizeToTray { get; set; } = true; /// /// Whether to play notification sounds /// [JsonPropertyName("playSounds")] public bool PlaySounds { get; set; } = true; /// /// Whether to show balloon notifications for connection status changes /// [JsonPropertyName("showConnectionNotifications")] public bool ShowConnectionNotifications { get; set; } = true; /// /// Auto-reconnect interval in seconds (0 = disabled) /// [JsonPropertyName("reconnectIntervalSeconds")] public int ReconnectIntervalSeconds { get; set; } = 5; /// /// Exec approval timeout in seconds (0 = use server default) /// [JsonPropertyName("execApprovalTimeoutSeconds")] public int ExecApprovalTimeoutSeconds { get; set; } = 0; /// /// Last window position (X) /// [JsonPropertyName("windowX")] public double? WindowX { get; set; } /// /// Last window position (Y) /// [JsonPropertyName("windowY")] public double? WindowY { get; set; } /// /// Last window width /// [JsonPropertyName("windowWidth")] public double? WindowWidth { get; set; } /// /// Last window height /// [JsonPropertyName("windowHeight")] public double? WindowHeight { get; set; } /// /// Loads settings from disk, or returns default settings if file doesn't exist. /// public static AppSettings Load() { try { if (File.Exists(SettingsPath)) { var json = File.ReadAllText(SettingsPath); var settings = JsonSerializer.Deserialize(json, JsonOptions); if (settings != null) { AppLogger.Info($"Loaded settings from {SettingsPath}"); return settings; } } } catch (Exception ex) { AppLogger.Warn($"Failed to load settings: {ex.Message}"); } AppLogger.Info("Using default settings"); return new AppSettings(); } /// /// Saves settings to disk. /// public void Save() { try { // Ensure directory exists Directory.CreateDirectory(SettingsDirectory); var json = JsonSerializer.Serialize(this, JsonOptions); File.WriteAllText(SettingsPath, json); AppLogger.Info($"Saved settings to {SettingsPath}"); } catch (Exception ex) { AppLogger.Error($"Failed to save settings: {ex.Message}"); } } /// /// Resets settings to defaults and saves. /// public void Reset() { GatewayUrl = "ws://127.0.0.1:18789/"; StartOnLogin = false; MinimizeToTray = true; PlaySounds = true; ShowConnectionNotifications = true; ReconnectIntervalSeconds = 5; ExecApprovalTimeoutSeconds = 0; WindowX = null; WindowY = null; WindowWidth = null; WindowHeight = null; Save(); AppLogger.Info("Settings reset to defaults"); } /// /// Gets the path to the settings file. /// public static string GetSettingsFilePath() => SettingsPath; }