using System; using System.Collections.Generic; using System.Linq; using System.Threading; using CommunityToolkit.Diagnostics; using OwlCore; using OwlCore.WinUI.Controls; using StrixMusic.Sdk.CoreModels; using StrixMusic.Sdk.ViewModels; using StrixMusic.Sdk.ViewModels.Notifications; using StrixMusic.Sdk.WinUI.Services.Localization; using StrixMusic.Sdk.WinUI.Services.NotificationService; using StrixMusic.Services; using StrixMusic.Services.CoreManagement; using Windows.ApplicationModel.Resources; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace StrixMusic.Shared { /// /// A top-level frame that holds all other app content. /// public sealed partial class AppFrame : UserControl { private SuperShell? _superShell; /// /// The backing dependency property for . /// public static readonly DependencyProperty NotificationsProperty = DependencyProperty.Register(nameof(Notifications), typeof(NotificationsViewModel), typeof(AppFrame), new PropertyMetadata(null)); /// /// Creates a new instance of . /// public AppFrame() { InitializeComponent(); Guard.IsNotNull(SynchronizationContext.Current, nameof(SynchronizationContext.Current)); Threading.SetPrimarySynchronizationContext(SynchronizationContext.Current); var window = Window.Current; Threading.SetPrimaryThreadInvokeHandler(a => window.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => a()).AsTask()); NotificationService = new NotificationService(); Notifications = new NotificationsViewModel(NotificationService); LocalizationService = new() { Startup = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.Startup)), SuperShell = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.SuperShell)), Common = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.Common)), Time = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.Time)), Music = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.Music)), Quips = ResourceLoader.GetForCurrentView(nameof(LocalizationResourceLoader.Quips)), }; AttachEvents(); AttachEvents(NotificationService); } /// /// A ViewModel for notifications displayed to the user. /// public NotificationsViewModel Notifications { get => (NotificationsViewModel)GetValue(NotificationsProperty); set => SetValue(NotificationsProperty, value); } /// /// The content overlay used as a popup dialog for the entire app. /// public ContentOverlay? ContentOverlay { get; private set; } /// /// A service that facilitates raising notifications. /// public NotificationService NotificationService { get; } /// /// A service for getting localized strings from providers. /// public LocalizationResourceLoader LocalizationService { get; } /// /// Navigates top the primary app content to the given . /// /// public void Present(FrameworkElement element) { PART_ContentPresenter.Content = element; } private void AttachEvents() { Loaded += AppFrame_Loaded; Unloaded += AppFrame_Unloaded; } private void AppFrame_Loaded(object sender, RoutedEventArgs e) { Loaded -= AppFrame_Loaded; ContentOverlay = OverlayPresenter; } private void AttachEvents(NotificationService notificationService) { notificationService.NotificationMarginChanged += NotificationService_NotificationMarginChanged; notificationService.NotificationAlignmentChanged += NotificationService_NotificationAlignmentChanged; } private void DetachEvents(NotificationService notificationService) { notificationService.NotificationMarginChanged -= NotificationService_NotificationMarginChanged; notificationService.NotificationAlignmentChanged -= NotificationService_NotificationAlignmentChanged; } private void DetachEvents() { Unloaded -= AppFrame_Unloaded; if (!(NotificationService is null)) DetachEvents(NotificationService); } /// /// Displays the AbstractUI panel for the given core. /// public void DisplayAbstractUIPanel(ICore core, AppSettings appSettings, IReadOnlyList loadedCores, ICoreManagementService coreManagementService) { _ = Threading.OnPrimaryThread(() => { _superShell ??= new SuperShell(appSettings, coreManagementService); _superShell.LoadedCores = loadedCores.ToList(); _superShell.CurrentCoreConfig = new CoreViewModel(core); _superShell.SelectedTabIndex = 1; OverlayPresenter.Show(_superShell, LocalizationService.Common?.GetString("Settings") ?? string.Empty); }); } /// /// Opens the SuperShell. /// public void DisplaySuperShell(AppSettings appSettings, IReadOnlyList loadedCores, ICoreManagementService coreManagementService) { _ = Threading.OnPrimaryThread(() => { _superShell ??= new SuperShell(appSettings, coreManagementService); _superShell.LoadedCores = loadedCores.ToList(); OverlayPresenter.Show(_superShell, LocalizationService.Common?.GetString("Settings") ?? string.Empty); }); } private void NotificationService_NotificationMarginChanged(object? sender, Thickness e) { NotificationItems.Margin = e; } private void NotificationService_NotificationAlignmentChanged(object? sender, (HorizontalAlignment Horizontal, VerticalAlignment Vertical) e) { NotificationItems.HorizontalAlignment = e.Horizontal; NotificationItems.VerticalAlignment = e.Vertical; } private void AppFrame_Unloaded(object? sender, RoutedEventArgs e) => DetachEvents(); private void AppFrame_OnLoaded(object? sender, RoutedEventArgs e) => Present(new AppLoadingView()); } }