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;
}