From b966b429c67e7460b299014004333ea86b82f4ad Mon Sep 17 00:00:00 2001 From: David Federman Date: Sun, 25 Jan 2026 18:18:49 -0800 Subject: [PATCH] Make CardFactory injectable --- src/JellyBox/AppServices.cs | 4 +++- src/JellyBox/Models/CardFactory.cs | 23 +++++++++++++------ src/JellyBox/ViewModels/HomeViewModel.cs | 12 ++++------ .../ViewModels/ItemDetailsViewModel.cs | 9 +++++--- src/JellyBox/ViewModels/MoviesViewModel.cs | 12 ++++------ src/JellyBox/ViewModels/ShowsViewModel.cs | 12 ++++------ 6 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/JellyBox/AppServices.cs b/src/JellyBox/AppServices.cs index ccf532d..7d796c7 100644 --- a/src/JellyBox/AppServices.cs +++ b/src/JellyBox/AppServices.cs @@ -1,4 +1,5 @@ using System.Net.Http.Headers; +using JellyBox.Models; using JellyBox.Services; using JellyBox.ViewModels; using Jellyfin.Sdk; @@ -59,9 +60,10 @@ private AppServices() serviceCollection.AddScoped(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // View Models serviceCollection.AddTransient(); diff --git a/src/JellyBox/Models/CardFactory.cs b/src/JellyBox/Models/CardFactory.cs index 742ef78..9680b3d 100644 --- a/src/JellyBox/Models/CardFactory.cs +++ b/src/JellyBox/Models/CardFactory.cs @@ -4,14 +4,23 @@ namespace JellyBox.Models; -internal static class CardFactory +#pragma warning disable CA1812 // Avoid uninstantiated internal classes. Used via dependency injection. +internal sealed class CardFactory +#pragma warning restore CA1812 // Avoid uninstantiated internal classes { - public static Card CreateFromItem( + private readonly JellyfinImageResolver _imageResolver; + private readonly NavigationManager _navigationManager; + + public CardFactory(JellyfinImageResolver imageResolver, NavigationManager navigationManager) + { + _imageResolver = imageResolver; + _navigationManager = navigationManager; + } + + public Card CreateFromItem( BaseItemDto item, CardShape shape, - ImageType? preferredImageType, - JellyfinImageResolver imageResolver, - NavigationManager navigationManager) + ImageType? preferredImageType) { double aspectRatio = GetAspectRatio(shape); ImageType imageType; @@ -48,7 +57,7 @@ public static Card CreateFromItem( } int imageHeight = (int)Math.Round(imageWidth / aspectRatio); - JellyfinImage image = imageResolver.ResolveImage(item, imageType, imageWidth, imageHeight); + JellyfinImage image = _imageResolver.ResolveImage(item, imageType, imageWidth, imageHeight); return new Card { @@ -56,7 +65,7 @@ public static Card CreateFromItem( ImageWidth = imageWidth, ImageHeight = imageHeight, Image = image, - NavigateCommand = new RelayCommand(() => navigationManager.NavigateToItem(item)), + NavigateCommand = new RelayCommand(() => _navigationManager.NavigateToItem(item)), }; } diff --git a/src/JellyBox/ViewModels/HomeViewModel.cs b/src/JellyBox/ViewModels/HomeViewModel.cs index 7aa8bfd..02e2080 100644 --- a/src/JellyBox/ViewModels/HomeViewModel.cs +++ b/src/JellyBox/ViewModels/HomeViewModel.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using JellyBox.Models; -using JellyBox.Services; using Jellyfin.Sdk; using Jellyfin.Sdk.Generated.Models; @@ -12,19 +11,16 @@ internal sealed partial class HomeViewModel : ObservableObject #pragma warning restore CA1812 // Avoid uninstantiated internal classes { private readonly JellyfinApiClient _jellyfinApiClient; - private readonly JellyfinImageResolver _imageResolver; - private readonly NavigationManager _navigationManager; + private readonly CardFactory _cardFactory; public ObservableCollection
Sections { get; } = new(); public HomeViewModel( JellyfinApiClient jellyfinApiClient, - JellyfinImageResolver imageResolver, - NavigationManager navigationManager) + CardFactory cardFactory) { _jellyfinApiClient = jellyfinApiClient; - _imageResolver = imageResolver; - _navigationManager = navigationManager; + _cardFactory = cardFactory; } public async void Initialize() @@ -103,7 +99,7 @@ public async void Initialize() continue; } - cards.Add(CardFactory.CreateFromItem(item, cardShape, preferredImageType, _imageResolver, _navigationManager)); + cards.Add(_cardFactory.CreateFromItem(item, cardShape, preferredImageType)); } return new Section diff --git a/src/JellyBox/ViewModels/ItemDetailsViewModel.cs b/src/JellyBox/ViewModels/ItemDetailsViewModel.cs index dc550ee..d08e09a 100644 --- a/src/JellyBox/ViewModels/ItemDetailsViewModel.cs +++ b/src/JellyBox/ViewModels/ItemDetailsViewModel.cs @@ -31,6 +31,7 @@ internal sealed partial class ItemDetailsViewModel : ObservableObject private readonly JellyfinApiClient _jellyfinApiClient; private readonly JellyfinImageResolver _imageResolver; private readonly NavigationManager _navigationManager; + private readonly CardFactory _cardFactory; [ObservableProperty] public partial BaseItemDto? Item { get; set; } @@ -101,11 +102,13 @@ internal sealed partial class ItemDetailsViewModel : ObservableObject public ItemDetailsViewModel( JellyfinApiClient jellyfinApiClient, JellyfinImageResolver imageResolver, - NavigationManager navigationManager) + NavigationManager navigationManager, + CardFactory cardFactory) { _jellyfinApiClient = jellyfinApiClient; _imageResolver = imageResolver; _navigationManager = navigationManager; + _cardFactory = cardFactory; } internal async void HandleParameters(ItemDetails.Parameters parameters) @@ -468,7 +471,7 @@ private void UpdateUserData() continue; } - cards.Add(CardFactory.CreateFromItem(item, CardShape.Backdrop, ImageType.Thumb, _imageResolver, _navigationManager)); + cards.Add(_cardFactory.CreateFromItem(item, CardShape.Backdrop, ImageType.Thumb)); } return new Section @@ -560,7 +563,7 @@ private void UpdateUserData() continue; } - cards.Add(CardFactory.CreateFromItem(item, cardShape, ImageType.Thumb, _imageResolver, _navigationManager)); + cards.Add(_cardFactory.CreateFromItem(item, cardShape, ImageType.Thumb)); } // TODO: Support list view for Type == MusicAlbum | Season diff --git a/src/JellyBox/ViewModels/MoviesViewModel.cs b/src/JellyBox/ViewModels/MoviesViewModel.cs index b72cfb5..f28c7b2 100644 --- a/src/JellyBox/ViewModels/MoviesViewModel.cs +++ b/src/JellyBox/ViewModels/MoviesViewModel.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using JellyBox.Models; -using JellyBox.Services; using JellyBox.Views; using Jellyfin.Sdk; using Jellyfin.Sdk.Generated.Models; @@ -13,8 +12,7 @@ internal sealed partial class MoviesViewModel : ObservableObject #pragma warning restore CA1812 // Avoid uninstantiated internal classes { private readonly JellyfinApiClient _jellyfinApiClient; - private readonly JellyfinImageResolver _imageResolver; - private readonly NavigationManager _navigationManager; + private readonly CardFactory _cardFactory; private Guid? _collectionItemId; @@ -22,12 +20,10 @@ internal sealed partial class MoviesViewModel : ObservableObject public MoviesViewModel( JellyfinApiClient jellyfinApiClient, - JellyfinImageResolver imageResolver, - NavigationManager navigationManager) + CardFactory cardFactory) { _jellyfinApiClient = jellyfinApiClient; - _imageResolver = imageResolver; - _navigationManager = navigationManager; + _cardFactory = cardFactory; } public void HandleParameters(Movies.Parameters parameters) @@ -65,7 +61,7 @@ private async Task InitializeMoviesAsync() continue; } - Movies.Add(CardFactory.CreateFromItem(item, CardShape.Portrait, preferredImageType: null, _imageResolver, _navigationManager)); + Movies.Add(_cardFactory.CreateFromItem(item, CardShape.Portrait, preferredImageType: null)); } } } diff --git a/src/JellyBox/ViewModels/ShowsViewModel.cs b/src/JellyBox/ViewModels/ShowsViewModel.cs index 951d631..cc20805 100644 --- a/src/JellyBox/ViewModels/ShowsViewModel.cs +++ b/src/JellyBox/ViewModels/ShowsViewModel.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using JellyBox.Models; -using JellyBox.Services; using JellyBox.Views; using Jellyfin.Sdk; using Jellyfin.Sdk.Generated.Models; @@ -13,8 +12,7 @@ internal sealed partial class ShowsViewModel : ObservableObject #pragma warning restore CA1812 // Avoid uninstantiated internal classes { private readonly JellyfinApiClient _jellyfinApiClient; - private readonly JellyfinImageResolver _imageResolver; - private readonly NavigationManager _navigationManager; + private readonly CardFactory _cardFactory; private Guid? _collectionItemId; @@ -22,12 +20,10 @@ internal sealed partial class ShowsViewModel : ObservableObject public ShowsViewModel( JellyfinApiClient jellyfinApiClient, - JellyfinImageResolver imageResolver, - NavigationManager navigationManager) + CardFactory cardFactory) { _jellyfinApiClient = jellyfinApiClient; - _imageResolver = imageResolver; - _navigationManager = navigationManager; + _cardFactory = cardFactory; } public void HandleParameters(Shows.Parameters parameters) @@ -66,7 +62,7 @@ private async Task InitializeShowsAsync() continue; } - Shows.Add(CardFactory.CreateFromItem(item, CardShape.Portrait, preferredImageType: null, _imageResolver, _navigationManager)); + Shows.Add(_cardFactory.CreateFromItem(item, CardShape.Portrait, preferredImageType: null)); } } }