Files
AlayaCore/AlayaCore/Services/SettingsService.cs
2026-04-04 20:51:53 +01:00

132 lines
4.1 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AlayaCore.Abstractions.Interfaces.Services;
using AlayaCore.Models.Configuration;
using Newtonsoft.Json;
namespace AlayaCore.Services
{
public sealed class SettingsService : ISettingsService
{
private const string LauncherSettingsFileName = "Launcher.json";
public LauncherOptions LauncherOptions { get; }
public SettingsService(LauncherOptions launcherOptions)
{
LauncherOptions = launcherOptions ?? throw new ArgumentNullException(nameof(launcherOptions));
}
public async Task SetForceReinstallAsync(bool value, CancellationToken cancellationToken = default)
{
LauncherOptions.ForceReinstall = value;
await SaveLauncherOptionsAsync(cancellationToken).ConfigureAwait(false);
}
public async Task SaveLauncherOptionsAsync(CancellationToken cancellationToken = default)
{
await SaveAsync(
LauncherSettingsFileName,
LauncherOptions,
cancellationToken).ConfigureAwait(false);
}
public async Task LoadLauncherOptionsAsync(CancellationToken cancellationToken = default)
{
LauncherOptions? loadedOptions = await LoadAsync<LauncherOptions>(
LauncherSettingsFileName,
cancellationToken).ConfigureAwait(false);
if (loadedOptions == null)
{
return;
}
LauncherOptions.ForceReinstall = loadedOptions.ForceReinstall;
}
private async Task SaveAsync<T>(
string fileName,
T value,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentException("File name cannot be null, empty, or whitespace.", nameof(fileName));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
cancellationToken.ThrowIfCancellationRequested();
string fullPath = GetFullPath(fileName);
string? directoryPath = Path.GetDirectoryName(fullPath);
if (string.IsNullOrWhiteSpace(directoryPath))
{
throw new InvalidOperationException("Could not resolve the settings directory path.");
}
Directory.CreateDirectory(directoryPath);
string temporaryPath = fullPath + ".tmp";
string json = JsonConvert.SerializeObject(value, Formatting.Indented);
await File.WriteAllTextAsync(temporaryPath, json, cancellationToken).ConfigureAwait(false);
if (File.Exists(fullPath))
{
File.Delete(fullPath);
}
File.Move(temporaryPath, fullPath);
}
private async Task<T?> LoadAsync<T>(
string fileName,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentException("File name cannot be null, empty, or whitespace.", nameof(fileName));
}
cancellationToken.ThrowIfCancellationRequested();
string fullPath = GetFullPath(fileName);
if (!File.Exists(fullPath))
{
return default;
}
string json = await File.ReadAllTextAsync(fullPath, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(json))
{
return default;
}
try
{
return JsonConvert.DeserializeObject<T>(json);
}
catch (JsonException ex)
{
throw new InvalidDataException(
$"Failed to deserialize settings file '{fullPath}' to {typeof(T).Name}.",
ex);
}
}
private static string GetFullPath(string fileName)
{
return Path.Combine(AppContext.BaseDirectory, "Config", fileName);
}
}
}