diff --git a/Shared/ViewModels/LibrarySearchViewModel.swift b/Shared/ViewModels/LibrarySearchViewModel.swift index 0aeb6098..24523a7a 100644 --- a/Shared/ViewModels/LibrarySearchViewModel.swift +++ b/Shared/ViewModels/LibrarySearchViewModel.swift @@ -11,6 +11,7 @@ import Combine import CombineExt import Foundation import JellyfinAPI +import SwiftUI final class LibrarySearchViewModel: ViewModel { @@ -42,8 +43,7 @@ final class LibrarySearchViewModel: ViewModel { } func setupPublishersForSupportedItemType() { - - let supportedItemTypeListPublishers = Publishers.CombineLatest3($movieItems, $showItems, $episodeItems) + Publishers.CombineLatest3($movieItems, $showItems, $episodeItems) .debounce(for: 0.25, scheduler: DispatchQueue.main) .map { arg -> [ItemType] in var typeList = [ItemType]() @@ -58,21 +58,29 @@ final class LibrarySearchViewModel: ViewModel { } return typeList } - - supportedItemTypeListPublishers - .assign(to: \.supportedItemTypeList, on: self) + .receive(on: DispatchQueue.main) + .sink(receiveValue: { [weak self] typeList in + withAnimation { + self?.supportedItemTypeList = typeList + } + }) .store(in: &cancellables) - supportedItemTypeListPublishers - .withLatestFrom(supportedItemTypeListPublishers, $selectedItemType) - .compactMap { typeList, selectedItemType in - if typeList.contains(selectedItemType) { + $supportedItemTypeList + .receive(on: DispatchQueue.main) + .withLatestFrom($selectedItemType) + .compactMap { selectedItemType in + if self.supportedItemTypeList.contains(selectedItemType) { return selectedItemType } else { - return typeList.first + return self.supportedItemTypeList.first } } - .assign(to: \.selectedItemType, on: self) + .sink(receiveValue: { [weak self] itemType in + withAnimation { + self?.selectedItemType = itemType + } + }) .store(in: &cancellables) } @@ -87,6 +95,7 @@ final class LibrarySearchViewModel: ViewModel { enableTotalRecordCount: false, enableImages: false) .trackActivity(loading) + .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in @@ -99,8 +108,10 @@ final class LibrarySearchViewModel: ViewModel { ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query, sortOrder: [.ascending], parentId: parentID, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], - includeItemTypes: [ItemType.movie.rawValue], sortBy: ["SortName"], enableUserData: true, enableImages: true) + includeItemTypes: [ItemType.movie.rawValue], sortBy: ["SortName"], enableUserData: true, + enableImages: true) .trackActivity(loading) + .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in @@ -110,8 +121,10 @@ final class LibrarySearchViewModel: ViewModel { ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query, sortOrder: [.ascending], parentId: parentID, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], - includeItemTypes: [ItemType.series.rawValue], sortBy: ["SortName"], enableUserData: true, enableImages: true) + includeItemTypes: [ItemType.series.rawValue], sortBy: ["SortName"], enableUserData: true, + enableImages: true) .trackActivity(loading) + .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in @@ -121,8 +134,10 @@ final class LibrarySearchViewModel: ViewModel { ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, limit: 50, recursive: true, searchTerm: query, sortOrder: [.ascending], parentId: parentID, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], - includeItemTypes: [ItemType.episode.rawValue], sortBy: ["SortName"], enableUserData: true, enableImages: true) + includeItemTypes: [ItemType.episode.rawValue], sortBy: ["SortName"], enableUserData: true, + enableImages: true) .trackActivity(loading) + .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in diff --git a/Shared/ViewModels/LibraryViewModel.swift b/Shared/ViewModels/LibraryViewModel.swift index ae134564..377230fb 100644 --- a/Shared/ViewModels/LibraryViewModel.swift +++ b/Shared/ViewModels/LibraryViewModel.swift @@ -48,14 +48,13 @@ final class LibraryViewModel: ViewModel { } } - init( - parentID: String? = nil, - person: BaseItemPerson? = nil, - genre: NameGuidPair? = nil, - studio: NameGuidPair? = nil, - filters: LibraryFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], sortBy: [.name]), - columns: Int = 7 - ) { + init(parentID: String? = nil, + person: BaseItemPerson? = nil, + genre: NameGuidPair? = nil, + studio: NameGuidPair? = nil, + filters: LibraryFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], sortBy: [.name]), + columns: Int = 7) + { self.parentID = parentID self.person = person self.genre = genre @@ -67,7 +66,6 @@ final class LibraryViewModel: ViewModel { $filters .sink(receiveValue: requestItems(with:)) .store(in: &cancellables) - } func requestItems(with filters: LibraryFilters) { @@ -80,10 +78,13 @@ final class LibraryViewModel: ViewModel { genreIDs = filters.withGenres.compactMap(\.id) } let sortBy = filters.sortBy.map(\.rawValue) - let shouldBeRecursive: Bool = filters.filters.contains(.isFavorite) || personIDs != [] || studioIDs != [] || genreIDs != [] - ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * 100, limit: 100, recursive: shouldBeRecursive, + + ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * 100, limit: 100, + recursive: true, searchTerm: nil, sortOrder: filters.sortOrder, parentId: parentID, - fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], includeItemTypes: filters.filters.contains(.isFavorite) ? ["Movie", "Series", "Season", "Episode"] : ["Movie", "Series"], + fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], + includeItemTypes: filters.filters + .contains(.isFavorite) ? ["Movie", "Series", "Season", "Episode"] : ["Movie", "Series"], filters: filters.filters, sortBy: sortBy, tags: filters.tags, enableUserData: true, personIds: personIDs, studioIds: studioIDs, genreIds: genreIDs, enableImages: true) .trackActivity(loading) @@ -112,10 +113,13 @@ final class LibraryViewModel: ViewModel { genreIDs = filters.withGenres.compactMap(\.id) } let sortBy = filters.sortBy.map(\.rawValue) - let shouldBeRecursive: Bool = filters.filters.contains(.isFavorite) || personIDs != [] || studioIDs != [] || genreIDs != [] - ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * 100, limit: 100, recursive: shouldBeRecursive, + + ItemsAPI.getItemsByUserId(userId: SessionManager.main.currentLogin.user.id, startIndex: currentPage * 100, limit: 100, + recursive: true, searchTerm: nil, sortOrder: filters.sortOrder, parentId: parentID, - fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], includeItemTypes: filters.filters.contains(.isFavorite) ? ["Movie", "Series", "Season", "Episode"] : ["Movie", "Series"], + fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], + includeItemTypes: filters.filters + .contains(.isFavorite) ? ["Movie", "Series", "Season", "Episode"] : ["Movie", "Series"], filters: filters.filters, sortBy: sortBy, tags: filters.tags, enableUserData: true, personIds: personIDs, studioIds: studioIDs, genreIds: genreIDs, enableImages: true) .sink(receiveCompletion: { [weak self] completion in @@ -148,10 +152,10 @@ final class LibraryViewModel: ViewModel { } private func calculateRows(for itemList: [BaseItemDto]) -> [LibraryRow] { - guard itemList.count > 0 else { return [] } + guard !itemList.isEmpty else { return [] } let rowCount = itemList.count / columns var calculatedRows = [LibraryRow]() - for i in (0...rowCount) { + for i in 0 ... rowCount { let firstItemIndex = i * columns var lastItemIndex = firstItemIndex + columns if lastItemIndex > itemList.count { @@ -159,22 +163,18 @@ final class LibraryViewModel: ViewModel { } var rowCells = [LibraryRowCell]() - for item in itemList[firstItemIndex..