-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathApp.axaml.cs
More file actions
116 lines (100 loc) · 3.99 KB
/
Copy pathApp.axaml.cs
File metadata and controls
116 lines (100 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Metadata;
using GeneralUpdate.Tools.Configuration;
using GeneralUpdate.Tools.ViewModels;
using GeneralUpdate.Tools.Views;
// Register Lingua markup extensions under Avalonia's default XAML namespace
// so that {Translate} and {FormatTranslate} work without an extra xmlns import.
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Irihi.Lingua")]
namespace GeneralUpdate.Tools;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Load translations from embedded JSON files (must be after platform init)
Services.LocalizationService.Instance.LoadFromResources();
// Initialize Lingua — must be after LocalizationService is loaded
_ = Irihi.Lingua.AppLanguageManager.Instance;
// Initialize configuration (synchronous path for startup reliability)
var config = LoadConfigSafe();
// Apply saved theme
RequestedThemeVariant = config.Theme == "Dark"
? Avalonia.Styling.ThemeVariant.Dark
: Avalonia.Styling.ThemeVariant.Light;
// Apply saved locale
Services.LocalizationService.Instance.Locale = config.Language;
var mainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(config)
};
// Restore window state
mainWindow.Width = config.WindowWidth;
mainWindow.Height = config.WindowHeight;
if (config.WindowMaximized)
mainWindow.WindowState = WindowState.Maximized;
// Save window state on close (synchronous to guarantee completion before exit)
var configService = ConfigServiceSingleton.Instance;
mainWindow.Closing += (_, _) =>
{
if (mainWindow.WindowState == WindowState.Maximized)
{
config.WindowMaximized = true;
}
else
{
config.WindowMaximized = false;
config.WindowWidth = mainWindow.Width;
config.WindowHeight = mainWindow.Height;
}
// Synchronous save: config is tiny (<2KB), completes in <1ms.
// Must NOT be fire-and-forget — the process exits after Close and
// a Task.Run might not complete in time.
try { configService.Save(); }
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(
$"[GeneralUpdate.Tools] Config save on close failed: {ex.Message}");
}
};
desktop.MainWindow = mainWindow;
}
base.OnFrameworkInitializationCompleted();
}
/// <summary>
/// Load configuration synchronously with exception protection.
/// Uses blocking I/O on first load to avoid async-initialization races in Avalonia.
/// Save operations remain async (fire-and-forget from window close / property changes).
/// </summary>
private static AppConfig LoadConfigSafe()
{
try
{
var configService = ConfigServiceSingleton.Instance;
// Synchronous load for startup reliability
configService.Load();
return configService.Config;
}
catch
{
return new AppConfig();
}
}
}
/// <summary>
/// Singleton accessor for <see cref="ConfigService"/>.
/// Mirrors the pattern used by <see cref="Services.LocalizationService"/>.
/// </summary>
public static class ConfigServiceSingleton
{
public static ConfigService Instance { get; } = new();
}