-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.xaml.cs
More file actions
294 lines (261 loc) · 12.4 KB
/
App.xaml.cs
File metadata and controls
294 lines (261 loc) · 12.4 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Grex.Services;
namespace Grex
{
public partial class App : Application
{
private static readonly string LogFile = Path.Combine(Path.GetTempPath(), "Grex.log");
public App()
{
try
{
Log("App constructor: Starting");
// WinUI 3 apps don't need InitializeComponent for App class
Log("App constructor: Initialization completed");
// Subscribe to unhandled exceptions
this.UnhandledException += App_UnhandledException;
Log("App constructor: UnhandledException handler registered");
}
catch (Exception ex)
{
Log($"App constructor ERROR: {ex}");
throw;
}
}
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
try
{
Log("OnLaunched: Starting");
// Initialize Windows notification infrastructure (if supported)
NotificationService.Instance.Initialize();
Log("OnLaunched: NotificationService initialized");
// Initialize localization service (lazy initialization - resources loaded on-demand)
// Access the instance to ensure it's created, but don't fail if resources aren't available
try
{
Log("OnLaunched: Attempting to access LocalizationService.Instance");
var localizationService = Services.LocalizationService.Instance;
Log("OnLaunched: LocalizationService instance created successfully");
// Load saved UI language from settings (Bug 2 fix)
var savedUILanguage = SettingsService.GetUILanguage();
if (!string.IsNullOrEmpty(savedUILanguage))
{
Log($"OnLaunched: Loading saved UI language: {savedUILanguage}");
localizationService.SetCulture(savedUILanguage);
}
localizationService.Initialize();
Log("OnLaunched: LocalizationService initialized");
}
catch (Exception ex)
{
Log($"OnLaunched: LocalizationService initialization failed (non-fatal): {ex.Message}");
Log($"OnLaunched: LocalizationService exception type: {ex.GetType().Name}");
Log($"OnLaunched: LocalizationService stack trace: {ex.StackTrace}");
if (ex.InnerException != null)
{
Log($"OnLaunched: LocalizationService inner exception: {ex.InnerException.Message}");
Log($"OnLaunched: LocalizationService inner stack trace: {ex.InnerException.StackTrace}");
}
// Continue - localization will fall back to keys if resources aren't available
}
Log("OnLaunched: Creating MainWindow");
m_window = new MainWindow();
MainWindowInstance = m_window as MainWindow;
Log("OnLaunched: MainWindow created");
// Apply theme preference from settings after window is created
ApplyThemeFromSettings();
// Bug 1 fix: Refresh all views after window is created to apply saved UI language
if (MainWindowInstance != null)
{
MainWindowInstance.RefreshLocalization();
}
m_window.Activate();
Log("OnLaunched: Window activated");
// Window title localization is handled in MainWindow_Loaded event
// This ensures the window is fully initialized before attempting localization
// Check command line arguments
var arguments = Environment.GetCommandLineArgs();
if (arguments.Length > 1 && arguments[1] == "/settings")
{
if (MainWindowInstance != null)
{
// This needs to be handled by MainWindow to switch to the Settings tab
// We'll use a small delay to ensure the window is fully ready
m_window.DispatcherQueue.TryEnqueue(async () =>
{
await Task.Delay(100);
MainWindowInstance.NavigateToSettings();
});
}
}
// Check if running as administrator and show warning after window is activated
if (AdminHelper.IsRunAsAdmin())
{
Log("OnLaunched: Application is running as administrator");
// Show warning dialog after window is activated
_ = ShowAdminWarningDialogAsync();
}
}
catch (Exception ex)
{
Log($"OnLaunched ERROR: {ex}");
Log($"OnLaunched ERROR StackTrace: {ex.StackTrace}");
if (ex.InnerException != null)
{
Log($"OnLaunched ERROR InnerException: {ex.InnerException}");
Log($"OnLaunched ERROR InnerException StackTrace: {ex.InnerException.StackTrace}");
}
// Show notification before re-throwing
try
{
NotificationService.Instance.ShowError(
GetString("ApplicationStartupErrorTitle"),
GetString("ApplicationStartupErrorMessage", ex.Message));
}
catch
{
// If notification fails, at least we logged it
}
// Re-throw to see the error
throw;
}
}
private void ApplyThemeFromSettings()
{
try
{
var preference = Services.SettingsService.GetThemePreference();
// Apply theme through MainWindow instead of Application.RequestedTheme
// This avoids COMException when setting RequestedTheme before window is activated
if (MainWindowInstance != null)
{
MainWindowInstance.ApplyThemeAndBackdrop(preference);
Log($"ApplyThemeFromSettings: Applied theme via MainWindow (preference: {preference})");
}
else
{
// Fallback: try to set Application theme if window not available yet
// This should rarely happen, but handle it gracefully
ApplicationTheme theme;
switch (preference)
{
case Services.ThemePreference.Light:
theme = ApplicationTheme.Light;
break;
case Services.ThemePreference.Dark:
theme = ApplicationTheme.Dark;
break;
default: // System
// Get system theme from Windows settings
var uiSettings = new Windows.UI.ViewManagement.UISettings();
var systemTheme = uiSettings.GetColorValue(Windows.UI.ViewManagement.UIColorType.Background).ToString();
// If background is dark (low brightness), system is in dark mode
theme = systemTheme.StartsWith("#FF2") || systemTheme.StartsWith("#FF1") || systemTheme.StartsWith("#FF0")
? ApplicationTheme.Dark
: ApplicationTheme.Light;
break;
}
// Only set RequestedTheme if window is activated
if (m_window != null)
{
this.RequestedTheme = theme;
Log($"ApplyThemeFromSettings: Applied theme {theme} via Application.RequestedTheme (preference: {preference})");
}
}
}
catch (Exception ex)
{
Log($"ApplyThemeFromSettings ERROR: {ex}");
// Continue with default theme
}
}
private async Task ShowAdminWarningDialogAsync()
{
try
{
// Wait a bit for window to be fully activated and rendered
await Task.Delay(300);
if (m_window == null || MainWindowInstance == null)
{
Log("ShowAdminWarningDialogAsync: Window not available, cannot show dialog");
return;
}
var textBlock = new Microsoft.UI.Xaml.Controls.TextBlock
{
Text = GetString("AdminWarningMessage"),
TextWrapping = Microsoft.UI.Xaml.TextWrapping.Wrap,
MaxWidth = 520
};
var dialog = new ContentDialog
{
Title = GetString("AdminWarningTitle"),
Content = textBlock,
PrimaryButtonText = GetString("AdminWarningIgnoreButton"),
SecondaryButtonText = GetString("AdminWarningrexitButton"),
XamlRoot = m_window.Content.XamlRoot,
DefaultButton = ContentDialogButton.Primary
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Secondary)
{
Log("ShowAdminWarningDialogAsync: User chose to exit");
m_window?.Close();
Exit();
}
else
{
Log("ShowAdminWarningDialogAsync: User chose to continue as administrator");
}
}
catch (Exception ex)
{
Log($"ShowAdminWarningDialogAsync ERROR: {ex}");
}
}
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
Log($"App_UnhandledException: {e.Exception}");
Log($"App_UnhandledException StackTrace: {e.Exception.StackTrace}");
if (e.Exception.InnerException != null)
{
Log($"App_UnhandledException InnerException: {e.Exception.InnerException}");
}
// Show notification to user
try
{
NotificationService.Instance.ShowError(
GetString("UnhandledErrorTitle"),
GetString("UnhandledErrorMessage", e.Exception.Message));
}
catch
{
// If notification fails, at least we logged it
}
e.Handled = false; // Let it crash so we can see the error
}
private Window? m_window;
public static MainWindow? MainWindowInstance { get; private set; }
private static void Log(string message)
{
try
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
File.AppendAllText(LogFile, $"[{timestamp}] {message}\n");
}
catch
{
// Ignore logging errors
}
}
private static string GetString(string key) =>
Services.LocalizationService.Instance.GetLocalizedString(key);
private static string GetString(string key, params object[] args) =>
Services.LocalizationService.Instance.GetLocalizedString(key, args);
}
}