using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml; using Microsoft.Windows.Globalization; using Nito.AsyncEx; using Serilog; using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Core; using Windows.Foundation.Metadata; using Windows.Storage; using Wino.Core.Domain; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Translations; using Wino.Core.Services; using Wino.Messaging.Client.Shell; using Wino.Services; using WinUIEx; namespace Wino.Mail.WinUI; public abstract class WinoApplication : Application, IRecipient { public new static WinoApplication Current => (WinoApplication)Application.Current; public const string WinoLaunchLogPrefix = "[Wino Launch] "; public IServiceProvider Services { get; } protected IWinoLogger LogInitializer { get; } protected IApplicationConfiguration AppConfiguration { get; } public INewThemeService NewThemeService { get; } public IUnderlyingThemeService UnderlyingThemeService { get; } public IThumbnailService ThumbnailService { get; } protected IDatabaseService DatabaseService { get; } protected ITranslationService TranslationService { get; } public static WindowEx? MainWindow { get; set; } protected WinoApplication() { ConfigurePrelaunch(); Services = ConfigureServices(); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; UnhandledException += OnAppUnhandledException; LogInitializer = Services.GetRequiredService(); AppConfiguration = Services.GetRequiredService(); NewThemeService = Services.GetRequiredService(); DatabaseService = Services.GetRequiredService(); TranslationService = Services.GetRequiredService(); UnderlyingThemeService = Services.GetRequiredService(); ThumbnailService = Services.GetRequiredService(); // Make sure the paths are setup on app start. AppConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path; AppConfiguration.PublisherSharedFolderPath = ApplicationData.Current.GetPublisherCacheFolder(ApplicationConfiguration.SharedFolderName).Path; AppConfiguration.ApplicationTempFolderPath = ApplicationData.Current.TemporaryFolder.Path; ConfigureLogging(); } private void CurrentDomain_UnhandledException(object? sender, System.UnhandledExceptionEventArgs e) => Log.Fatal(e.ExceptionObject as Exception, "AppDomain Unhandled Exception"); private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e) => Log.Error(e.Exception, "Unobserved Task Exception"); private void OnAppUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { Log.Fatal(e.Exception, "Unhandled Exception"); e.Handled = true; } public IEnumerable GetActivationServices() { yield return DatabaseService; yield return TranslationService; yield return Services.GetRequiredService(); } public Task InitializeServicesAsync() => GetActivationServices().Select(a => a.InitializeAsync()).WhenAll(); public bool IsInteractiveLaunchArgs(object args) => args is IActivatedEventArgs; public void LogActivation(string log) => Log.Information($"{WinoLaunchLogPrefix}{log}"); protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { base.OnLaunched(args); LogActivation("OnLaunched."); } private void ConfigurePrelaunch() { if (ApiInformation.IsMethodPresent("Windows.ApplicationModel.Core.CoreApplication", "EnablePrelaunch")) CoreApplication.EnablePrelaunch(true); } public abstract IServiceProvider ConfigureServices(); public void ConfigureLogging() { string logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ClientLogFile); LogInitializer.SetupLogger(logFilePath); } public virtual void OnLanguageChanged(AppLanguageModel languageModel) { var newCulture = new CultureInfo(languageModel.Code); ApplicationLanguages.PrimaryLanguageOverride = languageModel.Code; CultureInfo.DefaultThreadCurrentCulture = newCulture; CultureInfo.DefaultThreadCurrentUICulture = newCulture; } public void Receive(LanguageChanged message) => OnLanguageChanged(TranslationService.CurrentLanguageModel); }