using System.Text.Json;
namespace OpenNest.Data;
///
/// The desktop apps' per-user settings file, %APPDATA%\OpenNest\user-settings.json: one JSON
/// object of setting names to their text values. The WinForms app writes it through
/// AppDataSettingsProvider (values in System.Configuration's invariant text form, e.g.
/// "1936, 1048" for a size); the Avalonia app reads and writes the same names, so both apps
/// share one file on Windows.
///
public static class UserSettingsFile
{
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
/// %APPDATA%\OpenNest\user-settings.json (~/.config/OpenNest on Linux).
public static string DefaultPath => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"OpenNest", "user-settings.json");
///
/// The stored values. A missing, unreadable or corrupt file reads as empty, and an entry
/// whose value is not text is skipped; reading never changes the file.
///
public static Dictionary Read(string path)
{
var values = new Dictionary();
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
return values;
try
{
using var document = JsonDocument.Parse(File.ReadAllText(path));
if (document.RootElement.ValueKind != JsonValueKind.Object)
return values;
foreach (var property in document.RootElement.EnumerateObject())
{
if (property.Value.ValueKind == JsonValueKind.String)
values[property.Name] = property.Value.GetString()!;
}
}
catch (Exception ex) when (SettingsFile.IsUnreadableFile(ex))
{
values.Clear();
}
return values;
}
///
/// Replaces the file with through a temporary file. Settings are a
/// convenience: a failed write returns false and leaves the previous file in place.
///
public static bool Write(string path, IReadOnlyDictionary values)
{
try
{
SettingsFile.Write(path, JsonSerializer.Serialize(values, JsonOptions));
return true;
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
return false;
}
}
///
/// Re-reads the file, applies and writes it back, so entries this
/// build does not know (from a newer copy, or the other desktop app) are kept.
///
public static bool Update(string path, Action> change)
{
ArgumentNullException.ThrowIfNull(change);
var values = Read(path);
change(values);
return Write(path, values);
}
}