using System.Collections.ObjectModel; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using OwlCore.Provisos; using OwlCore.Services; using StrixMusic.Sdk.WinUI.Services.ShellManagement; using StrixMusic.Services; namespace StrixMusic.Shared.ViewModels { /// /// View model used to select shells. /// public class ShellSelectorViewModel : ObservableObject, IAsyncInit { private readonly AppSettings _settings; private ShellInfoViewModel? _preferredShell; private ShellInfoViewModel? _fallbackShell; /// /// Initializes a new instance of the class. /// public ShellSelectorViewModel(AppSettings settings) { _settings = settings; AllShells = new ObservableCollection(); FullyResponsiveShells = new ObservableCollection(); SaveSelectedShellAsyncCommand = new AsyncRelayCommand(SaveSelectedShell); } /// public async Task InitAsync(CancellationToken cancellationToken = default) { Logger.LogInformation($"Entered {nameof(InitAsync)}"); // Gets the list of loaded shells. foreach (var shell in ShellRegistry.MetadataRegistry) { var viewModel = new ShellInfoViewModel(shell); Logger.LogInformation($"Adding {viewModel.Metadata.Id} to available shells"); AllShells.Add(viewModel); if (viewModel.IsFullyResponsive) { Logger.LogInformation($"Adding {viewModel.Metadata.Id} to fully responsive shells"); FullyResponsiveShells.Add(viewModel); } await viewModel.InitAsync(); } foreach (var shell in AllShells) { // Mark the current shell selected or Default (if unset) if (shell.Metadata.Id == _settings.PreferredShell) { Logger.LogInformation($"Setting preferred shell: {shell.Metadata.Id}"); PreferredShell = shell; } if (shell.Metadata.Id == _settings.FallbackShell) { Logger.LogInformation($"Setting fallback shell: {shell.Metadata.Id}"); FallbackShell = shell; } } Logger.LogInformation($"Exited {nameof(InitAsync)}"); } /// /// All shells that the user can pick from. /// public ObservableCollection AllShells { get; } /// /// All shells that are fully responsive. One of these should be used as a fallback when the primary shell isn't fully responsive. /// public ObservableCollection FullyResponsiveShells { get; } /// /// The user's preferred shell. /// public ShellInfoViewModel? PreferredShell { get => _preferredShell; set { SetProperty(ref _preferredShell, value, nameof(PreferredShell)); UpdateFallbackShell(); } } private void UpdateFallbackShell() { if (PreferredShell is null) return; if (PreferredShell.IsFullyResponsive) { FallbackShell = null; } else { // Setting the correct fallback shell back for non-responsive shells. foreach (var shell in AllShells) { if (shell.Metadata.Id == _settings.FallbackShell) { Logger.LogInformation($"Setting fallback shell: {shell.Metadata.Id}"); FallbackShell = shell; } } } } /// public ShellInfoViewModel? FallbackShell { get => _fallbackShell; set => SetProperty(ref _fallbackShell, value, nameof(FallbackShell)); } /// /// When fired, the is saved and applied. /// public IAsyncRelayCommand SaveSelectedShellAsyncCommand { get; } /// public bool IsInitialized { get; private set; } private async Task SaveSelectedShell() { if (PreferredShell != null) _settings.PreferredShell = PreferredShell.Metadata.Id; if (FallbackShell != null) _settings.FallbackShell = FallbackShell.Metadata.Id; await _settings.SaveAsync(); } } }