192 lines
5.1 KiB
Swift
192 lines
5.1 KiB
Swift
//
|
|
// Swiftfin is subject to the terms of the Mozilla Public
|
|
// License, v2.0. If a copy of the MPL was not distributed with this
|
|
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
//
|
|
// Copyright (c) 2023 Jellyfin & Jellyfin Contributors
|
|
//
|
|
|
|
import Combine
|
|
import CoreStore
|
|
import Factory
|
|
import Foundation
|
|
import JellyfinAPI
|
|
import UIKit
|
|
|
|
final class HomeViewModel: ViewModel {
|
|
|
|
@Published
|
|
var errorMessage: String?
|
|
@Published
|
|
var hasNextUp: Bool = false
|
|
@Published
|
|
var hasRecentlyAdded: Bool = false
|
|
@Published
|
|
var libraries: [BaseItemDto] = []
|
|
@Published
|
|
var resumeItems: [BaseItemDto] = []
|
|
|
|
override init() {
|
|
super.init()
|
|
|
|
refresh()
|
|
}
|
|
|
|
@objc
|
|
func refresh() {
|
|
|
|
hasNextUp = false
|
|
hasRecentlyAdded = false
|
|
libraries = []
|
|
resumeItems = []
|
|
|
|
Task {
|
|
logger.debug("Refreshing home screen")
|
|
|
|
await MainActor.run {
|
|
isLoading = true
|
|
}
|
|
|
|
refreshHasRecentlyAddedItems()
|
|
refreshResumeItems()
|
|
refreshHasNextUp()
|
|
|
|
do {
|
|
try await refreshLibrariesLatest()
|
|
} catch {
|
|
await MainActor.run {
|
|
isLoading = false
|
|
errorMessage = error.localizedDescription
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
await MainActor.run {
|
|
isLoading = false
|
|
errorMessage = nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Libraries Latest Items
|
|
|
|
private func refreshLibrariesLatest() async throws {
|
|
let userViewsPath = Paths.getUserViews(userID: userSession.user.id)
|
|
let response = try await userSession.client.send(userViewsPath)
|
|
|
|
guard let allLibraries = response.value.items else {
|
|
await MainActor.run {
|
|
libraries = []
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
let excludedLibraryIDs = await getExcludedLibraries()
|
|
|
|
let newLibraries = allLibraries
|
|
.filter { $0.collectionType == "movies" || $0.collectionType == "tvshows" }
|
|
.filter { library in
|
|
!excludedLibraryIDs.contains(where: { $0 == library.id ?? "" })
|
|
}
|
|
|
|
await MainActor.run {
|
|
libraries = newLibraries
|
|
}
|
|
}
|
|
|
|
private func getExcludedLibraries() async -> [String] {
|
|
let currentUserPath = Paths.getCurrentUser
|
|
let response = try? await userSession.client.send(currentUserPath)
|
|
|
|
return response?.value.configuration?.latestItemsExcludes ?? []
|
|
}
|
|
|
|
// MARK: Recently Added Items
|
|
|
|
private func refreshHasRecentlyAddedItems() {
|
|
Task {
|
|
let parameters = Paths.GetLatestMediaParameters(
|
|
includeItemTypes: [.movie, .series],
|
|
limit: 1
|
|
)
|
|
let request = Paths.getLatestMedia(userID: userSession.user.id, parameters: parameters)
|
|
let response = try await userSession.client.send(request)
|
|
|
|
await MainActor.run {
|
|
hasRecentlyAdded = !response.value.isEmpty
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: Resume Items
|
|
|
|
private func refreshResumeItems() {
|
|
Task {
|
|
let resumeParameters = Paths.GetResumeItemsParameters(
|
|
limit: 20,
|
|
fields: ItemFields.minimumCases,
|
|
enableUserData: true,
|
|
includeItemTypes: [.movie, .episode]
|
|
)
|
|
|
|
let request = Paths.getResumeItems(userID: userSession.user.id, parameters: resumeParameters)
|
|
let response = try await userSession.client.send(request)
|
|
|
|
guard let items = response.value.items else { return }
|
|
|
|
await MainActor.run {
|
|
resumeItems = items
|
|
}
|
|
}
|
|
}
|
|
|
|
func markItemUnplayed(_ item: BaseItemDto) {
|
|
guard resumeItems.contains(where: { $0.id == item.id! }) else { return }
|
|
|
|
Task {
|
|
let request = Paths.markUnplayedItem(
|
|
userID: userSession.user.id,
|
|
itemID: item.id!
|
|
)
|
|
let _ = try await userSession.client.send(request)
|
|
|
|
refreshResumeItems()
|
|
refreshHasNextUp()
|
|
}
|
|
}
|
|
|
|
func markItemPlayed(_ item: BaseItemDto) {
|
|
guard resumeItems.contains(where: { $0.id == item.id! }) else { return }
|
|
|
|
Task {
|
|
let request = Paths.markPlayedItem(
|
|
userID: userSession.user.id,
|
|
itemID: item.id!
|
|
)
|
|
let _ = try await userSession.client.send(request)
|
|
|
|
refreshResumeItems()
|
|
refreshHasNextUp()
|
|
}
|
|
}
|
|
|
|
// MARK: Next Up Items
|
|
|
|
private func refreshHasNextUp() {
|
|
Task {
|
|
let parameters = Paths.GetNextUpParameters(
|
|
userID: userSession.user.id,
|
|
limit: 1
|
|
)
|
|
let request = Paths.getNextUp(parameters: parameters)
|
|
let response = try await userSession.client.send(request)
|
|
|
|
await MainActor.run {
|
|
hasNextUp = !(response.value.items?.isEmpty ?? true)
|
|
}
|
|
}
|
|
}
|
|
}
|