using System.Text.Json; namespace Lumi.Companion.Overlay; public sealed class OverlaySettingsStore(string path) { private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) { WriteIndented = true }; public LumiOverlaySettings Current { get; private set; } = new(); public async Task LoadAsync(CancellationToken cancellationToken = default) { if (!File.Exists(path)) { Current.Normalize(); return; } try { await using var stream = File.OpenRead(path); Current = await JsonSerializer.DeserializeAsync(stream, JsonOptions, cancellationToken).ConfigureAwait(false) ?? new(); } catch (JsonException) { var backup = path + $".invalid-{DateTimeOffset.UtcNow:yyyyMMddHHmmss}"; File.Copy(path, backup, true); Current = new(); } Current.Normalize(); } public async Task SaveAsync(LumiOverlaySettings value, CancellationToken cancellationToken = default) { value.Normalize(); Directory.CreateDirectory(Path.GetDirectoryName(path)!); var temporary = path + ".tmp"; await using (var stream = new FileStream(temporary, FileMode.Create, FileAccess.Write, FileShare.None)) { await JsonSerializer.SerializeAsync(stream, value, JsonOptions, cancellationToken).ConfigureAwait(false); await stream.FlushAsync(cancellationToken).ConfigureAwait(false); } File.Move(temporary, path, true); Current = value; } }