jellyflood/Shared/ViewModels/XtreamViewModel/XtreamViewModel.swift

107 lines
2.5 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) 2025 Jellyfin & Jellyfin Contributors
//
import Defaults
import Factory
import Foundation
import JellyfinAPI
import OrderedCollections
final class XtreamViewModel: ViewModel, Stateful {
@Injected(\.sessionManager)
private var sessionManager
var xtreamSession: XtreamSession? {
sessionManager.xtreamSession
}
// MARK: Action
enum Action: Equatable {
case error(JellyfinAPIError)
case refresh
}
// MARK: State
enum State: Hashable {
case content
case error(JellyfinAPIError)
case initial
case refreshing
}
@Published
var xtreamChannels: OrderedSet<BaseItemDto> = []
@Published
var backgroundStates: Set<BackgroundState> = []
@Published
var state: State = .initial
func respond(to action: Action) -> State {
switch action {
case let .error(error):
return .error(error)
case .refresh:
cancellables.removeAll()
Task {
do {
try await refresh()
await MainActor.run {
self.state = .content
}
} catch {
await MainActor.run {
self.state = .error(.init(error.localizedDescription))
}
}
}
.store(in: &cancellables)
return .refreshing
}
}
private func refresh() async throws {
guard let session = xtreamSession else {
throw XtreamAPIError.invalidResponse
}
await MainActor.run {
xtreamChannels.removeAll()
}
let categories = try await session.client.getLiveCategories()
// Convert Xtream categories to BaseItemDto for now
// TODO: Create proper Xtream data models
let items = categories.map { category -> BaseItemDto in
var item = BaseItemDto()
item.id = category.categoryId
item.name = category.categoryName
item.type = .channel
return item
}
await MainActor.run {
xtreamChannels.elements = items
}
}
func randomItemImageSources(for channel: BaseItemDto) async throws -> [ImageSource] {
// TODO: Implement Xtream-specific image fetching
[]
}
}