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 는 false 와 640 을 모두 그대로 받으므로 옛 파일이 살아남는다.
///
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
}