/* * Copyright (c) 2026 James Maes (KofTwentyTwo) * SPDX-License-Identifier: MIT */ using System.Windows; using System.Windows.Controls; using KofTwentyTwo.AppKit.Updates; using KofTwentyTwo.AppKit.Wpf; namespace AppKit.Sample.Wpf; /// The sample's main window: each control exercises one AppKit service. public partial class MainWindow : Window { private readonly SampleSettings _settings = SampleApp.SettingsStore.Load(); private readonly UpdateCoordinator _updates; /// Brands the window, wires the update coordinator, restores the saved settings, shows the splash, and schedules the quiet startup update check. public MainWindow() { InitializeComponent(); Title = SampleApp.Info.DisplayName; this.SetAppIcon(SampleApp.Info); _updates = new UpdateCoordinator( new VelopackUpdateService(SampleApp.Info.RepositoryUrl!), new MessageBoxPrompter(() => this), SampleApp.Info.DisplayName, Program.Log); GreetingText.Text = _settings.Greeting; SplashToggle.IsChecked = _settings.ShowSplashScreen; CheckTheme(); SplashOverlay.ShowOver(RootGrid, SampleApp.Info, _settings); Closed += (_, _) => LogWindow.CloseCurrent(); if(_settings.CheckForUpdatesOnStartup) { Loaded += async (_, _) => { await Task.Delay(_settings.ShowSplashScreen ? _settings.SplashMilliseconds + 500 : 1000); await _updates.CheckQuietlyAsync(); }; } } /// File, Exit. private void Exit_Click(object sender, RoutedEventArgs e) => Close(); /// View, theme: applies the chosen Fluent theme to the application and saves it. private void Theme_Click(object sender, RoutedEventArgs e) { _settings.Theme = (string)((FrameworkElement)sender).Tag; WpfShell.ApplyTheme(Application.Current, _settings.ThemeKind); CheckTheme(); Save(); } /// View, Show splash at startup: saves the preference. private void Splash_Click(object sender, RoutedEventArgs e) { _settings.ShowSplashScreen = SplashToggle.IsChecked; Save(); } /// Help, Check for updates: runs the interactive update flow. private async void CheckForUpdates_Click(object sender, RoutedEventArgs e) => await _updates.CheckInteractivelyAsync(); /// Help, Activity log: opens the live log window, or brings the open one forward. private void ActivityLog_Click(object sender, RoutedEventArgs e) => LogWindow.ShowSingle(Program.Log, SampleApp.Info); /// Help, About: shows the About window. private void About_Click(object sender, RoutedEventArgs e) => AboutWindow.Show(SampleApp.Info, this); /// Writes an INFO entry, to show logging. private void LogInfo_Click(object sender, RoutedEventArgs e) { Program.Log.Info("The user pressed 'Write a log entry'."); StatusText.Text = "Wrote an INFO entry."; } /// Logs a handled exception with its stack trace, to show error logging. private void LogError_Click(object sender, RoutedEventArgs e) { try { throw new InvalidOperationException("A deliberately handled sample failure."); } catch(InvalidOperationException ex) { Program.Log.Error("Sample operation failed.", ex); StatusText.Text = "Wrote an ERROR entry with its stack trace."; } } /// Throws on purpose, to show that the crash net logs the exception and the app keeps running. private void Throw_Click(object sender, RoutedEventArgs e) { StatusText.Text = "Threw; the crash net logged it and the app kept running."; throw new InvalidOperationException("Deliberately unhandled sample exception."); } /// Checks the View menu item that matches the saved theme and clears the others. private void CheckTheme() { foreach(MenuItem item in new[] { ThemeSystem, ThemeLight, ThemeDark }) { item.IsChecked = string.Equals((string)item.Tag, _settings.Theme, StringComparison.Ordinal); } } /// Saves the settings and reports a failed save in the status line. private void Save() { if(!SampleApp.SettingsStore.Save(_settings)) { StatusText.Text = "Could not save settings."; } } }