added multilang and settings
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using CursorLang.Models;
|
||||
|
||||
namespace CursorLang.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Хранит настройки в %APPDATA%\CursorLang\settings.json.
|
||||
/// </summary>
|
||||
public sealed class SettingsService : IDisposable
|
||||
{
|
||||
private static readonly JsonSerializerOptions SerializerOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
Converters = { new ColorJsonConverter(), new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
private readonly string _filePath;
|
||||
private readonly DispatcherTimer _saveTimer;
|
||||
private AppSettings? _settings;
|
||||
|
||||
public SettingsService()
|
||||
{
|
||||
string folder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"CursorLang");
|
||||
_filePath = Path.Combine(folder, "settings.json");
|
||||
|
||||
// Ползунки меняют значения непрерывно, поэтому запись на диск
|
||||
// откладывается до паузы в изменениях
|
||||
_saveTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(500) };
|
||||
_saveTimer.Tick += OnSaveTimerTick;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Читает настройки с диска либо отдаёт значения по умолчанию,
|
||||
/// и дальше сам сохраняет любые изменения.
|
||||
/// </summary>
|
||||
public AppSettings Load()
|
||||
{
|
||||
_settings = ReadFile() ?? CreateDefault();
|
||||
_settings.PropertyChanged += OnSettingsChanged;
|
||||
return _settings;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (_settings is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_filePath)!);
|
||||
File.WriteAllText(_filePath, JsonSerializer.Serialize(_settings, SerializerOptions));
|
||||
}
|
||||
catch (Exception e) when (e is IOException or UnauthorizedAccessException)
|
||||
{
|
||||
// Настройки — не тот случай, ради которого стоит ронять приложение
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_saveTimer.Stop();
|
||||
_saveTimer.Tick -= OnSaveTimerTick;
|
||||
|
||||
if (_settings is not null)
|
||||
{
|
||||
_settings.PropertyChanged -= OnSettingsChanged;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
private AppSettings? ReadFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(_filePath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<AppSettings>(File.ReadAllText(_filePath), SerializerOptions);
|
||||
}
|
||||
catch (Exception e) when (e is IOException or UnauthorizedAccessException or JsonException)
|
||||
{
|
||||
// Испорченный файл не должен мешать запуску: начнём с умолчаний
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Язык по умолчанию берём системный, если он поддерживается
|
||||
private static AppSettings CreateDefault()
|
||||
{
|
||||
string uiLanguage = System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
|
||||
return new AppSettings { Language = uiLanguage == "ru" ? "ru" : "en" };
|
||||
}
|
||||
|
||||
private void OnSettingsChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
_saveTimer.Stop();
|
||||
_saveTimer.Start();
|
||||
}
|
||||
|
||||
private void OnSaveTimerTick(object? sender, EventArgs e)
|
||||
{
|
||||
_saveTimer.Stop();
|
||||
Save();
|
||||
}
|
||||
|
||||
// Color не сериализуется штатно, а хранить его читаемым в файле удобно
|
||||
private sealed class ColorJsonConverter : JsonConverter<Color>
|
||||
{
|
||||
public override Color Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
string? value = reader.GetString();
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return Colors.Black;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return (Color)ColorConverter.ConvertFromString(value)!;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return Colors.Black;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Color value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user