using AvParser.Core.Collecting; using AvParser.Infrastructure.Storage; using AvParser.UI.Navigation; using Microsoft.Extensions.DependencyInjection; using ReactiveUI; using ReactiveUI.Primitives; namespace AvParser.UI.ViewModels; /// Landing page: what is registered, where data lives, and shortcuts into the app. public sealed class DashboardViewModel : PageViewModel { private readonly IServiceProvider _services; /// Creates the dashboard. /// Registered media sources, shown as cards. /// Where the app writes settings and logs. /// /// Used to resolve at click time rather than at construction /// time. Injecting it directly would be a cycle: the navigation service is built from every /// page, so a page cannot also depend on it up front. /// public DashboardViewModel(IMediaSourceCatalog catalog, IAppPaths paths, IServiceProvider services) { ArgumentNullException.ThrowIfNull(catalog); ArgumentNullException.ThrowIfNull(paths); _services = services ?? throw new ArgumentNullException(nameof(services)); Sources = [.. catalog.Sources.Select(source => new MediaSourceViewModel(source))]; DataDirectory = paths.DataDirectory; MediaDirectory = paths.MediaDirectory; GoToCollectCommand = ReactiveCommand.Create(() => Navigate()); GoToSettingsCommand = ReactiveCommand.Create(() => Navigate()); } /// public override string TitleKey => "Page.Dashboard"; /// public override string IconKey => "IconHome"; /// Registered media sources, shown as cards. public IReadOnlyList Sources { get; } /// Where settings and logs are written. public string DataDirectory { get; } /// Where collected media is written. public string MediaDirectory { get; } /// Jumps to the Collect page. public ReactiveCommand GoToCollectCommand { get; } /// Jumps to the Settings page. public ReactiveCommand GoToSettingsCommand { get; } private void Navigate() where TPage : PageViewModel => _services.GetRequiredService().NavigateTo(); }