using System.IO; using System.Text.Json; namespace SheetMe.Designer.Services; /// /// 사용자별 화면 취향 보존 — %LocalAppData%\SheetMe\prefs.json. /// /// 업무 데이터가 아니라 "이 사람이 이 화면을 어떻게 보길 원하는가"만 담는다. 매 실행마다 사용자가 /// 같은 조작을 반복하게 만들지 않는 것이 목적이라, 읽기·쓰기 실패는 전부 삼키고 기본값으로 간다 /// (설정 파일 때문에 앱이 막히면 안 된다). 와 같은 폴더 규약. /// public static class UserPrefs { #region Member Fields private static readonly string SettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SheetMe", "prefs.json"); /// /// 값 형식이 인 이유: 전에는 Dictionary<string, bool> 였고 /// 그래서 숫자를 담을 수 없었다(창 크기·패널 폭을 저장하지 못한 원인이다). /// 여기서 형식을 string 이나 double 로 바꾸면 이미 깔린 prefs.json 이 /// 역직렬화에서 터져 기존 취향이 통째로 초기화된다. /// JsonElement 는 false640 을 모두 그대로 받으므로 옛 파일이 살아남는다. /// private static Dictionary values = new(StringComparer.Ordinal); private static bool loaded; #endregion #region Methods /// 불리언 취향 읽기 — 미저장이면 기본값 public static bool GetBool(string key, bool fallback) { EnsureLoaded(); return values.TryGetValue(key, out var value) && value.ValueKind is JsonValueKind.True or JsonValueKind.False ? value.GetBoolean() : fallback; } /// 불리언 취향 저장 public static void SetBool(string key, bool value) { EnsureLoaded(); if (GetBool(key, !value) == value && values.ContainsKey(key)) { return; } values[key] = JsonSerializer.SerializeToElement(value); Save(); } /// 숫자 취향 읽기 — 미저장이거나 형식이 다르면 기본값 public static double GetDouble(string key, double fallback) { EnsureLoaded(); return values.TryGetValue(key, out var value) && value.ValueKind == JsonValueKind.Number && value.TryGetDouble(out var number) && double.IsFinite(number) ? number : fallback; } /// /// 숫자 취향 여러 개를 한 번에 저장 — 창을 닫을 때 6개를 각각 저장하면 파일을 6번 쓴다. /// public static void SetDoubles(params (string Key, double Value)[] entries) { EnsureLoaded(); var changed = false; foreach (var (key, value) in entries) { if (!double.IsFinite(value) || Math.Abs(GetDouble(key, double.NaN) - value) < 0.5) { continue; } values[key] = JsonSerializer.SerializeToElement(Math.Round(value, 1)); changed = true; } if (changed) { Save(); } } private static void EnsureLoaded() { if (loaded) { return; } loaded = true; try { if (File.Exists(SettingsPath)) { values = JsonSerializer.Deserialize>(File.ReadAllText(SettingsPath)) ?? new Dictionary(StringComparer.Ordinal); } } catch { // 손상된 설정은 무시하고 기본값으로 — 다음 저장 때 덮인다 } } private static void Save() { try { Directory.CreateDirectory(Path.GetDirectoryName(SettingsPath)!); File.WriteAllText(SettingsPath, JsonSerializer.Serialize(values)); } catch { // 쓰기 실패(권한·잠금)로 업무를 막지 않는다 — 이번 실행에만 반영된다 } } #endregion }