mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-04 06:51:35 -05:00
Roslyn Bridge flagged these as copy-paste clusters; each pair now shares one implementation so a fix lands everywhere at once: - Shape.OffsetInward/OffsetOutward differed only in the target winding. - BestFitFinder kept its own copy of SpatialQuery's arc-extreme points. - SplitDrawingForm rebuilt DrawingSplitter's clip-region grid for preview. - GeometryOptimizer's collinear/coradial finders (one misspelled GetCoradialArs) become one generic FindRelated. - Five settings files repeated the write-with-retry loop, and two also repeated the unit parser and unreadable-file filter (SettingsFile). - ClampsForm and SupportGridForm repeated their row/box builders. - Vertical/HorizontalRemnantComparer share a RemnantComparer base. Behavior is unchanged except that Engine/NestStorage settings loads now also tolerate NotSupported/Security exceptions, matching the other settings files' never-throw contract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
2.5 KiB
C#
70 lines
2.5 KiB
C#
using System.Text.Json;
|
|
|
|
namespace OpenNest.Data;
|
|
|
|
/// <summary>Where the desktop app persists nests: local .nest files or the shared nest server.</summary>
|
|
public enum NestStorageMode
|
|
{
|
|
File,
|
|
Database,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Storage-mode toggle and nest-server address, stored at %APPDATA%\OpenNest\storage.json.
|
|
/// Loading never throws; a missing or corrupt file means File mode so existing installs
|
|
/// keep the original behavior until the operator opts in.
|
|
/// </summary>
|
|
public sealed class NestStorageSettings
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
WriteIndented = true,
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
PropertyNameCaseInsensitive = true,
|
|
};
|
|
|
|
public NestStorageMode Mode { get; set; } = NestStorageMode.File;
|
|
|
|
/// <summary>Base URL of the nest server, e.g. http://barge.lan:8090. No trailing slash required.</summary>
|
|
public string ServerUrl { get; set; } = "";
|
|
|
|
/// <summary>True when Database mode is active and a server URL is configured.</summary>
|
|
public bool IsDatabaseMode =>
|
|
Mode == NestStorageMode.Database && !string.IsNullOrWhiteSpace(ServerUrl);
|
|
|
|
/// <summary>Validate and normalize a nest server base URL without changing storage mode.</summary>
|
|
public static bool TryNormalizeServerUrl(string? url, out string normalized)
|
|
{
|
|
normalized = NormalizeUrl(url);
|
|
if (Uri.TryCreate(normalized, UriKind.Absolute, out var uri)
|
|
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
|
|
return true;
|
|
|
|
normalized = "";
|
|
return false;
|
|
}
|
|
|
|
/// <summary>%APPDATA%\OpenNest\storage.json.</summary>
|
|
public static string DefaultPath => Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
"OpenNest", "storage.json");
|
|
|
|
public static NestStorageSettings Load(string path)
|
|
{
|
|
var settings = SettingsFile.Read<NestStorageSettings>(path, JsonOptions) ?? new();
|
|
settings.ServerUrl = NormalizeUrl(settings.ServerUrl);
|
|
return settings;
|
|
}
|
|
|
|
/// <summary>Writes camelCase JSON, creating the parent directory and retrying IO collisions.</summary>
|
|
public void Save(string path)
|
|
{
|
|
var json = JsonSerializer.Serialize(
|
|
new NestStorageSettings { Mode = Mode, ServerUrl = NormalizeUrl(ServerUrl) },
|
|
JsonOptions);
|
|
SettingsFile.Write(path, json);
|
|
}
|
|
|
|
private static string NormalizeUrl(string? url) => (url ?? "").Trim().TrimEnd('/');
|
|
}
|