diff --git a/appleApp/AppleCore/FluxaAppleCatalogLoader.swift b/appleApp/AppleCore/FluxaAppleCatalogLoader.swift new file mode 100644 index 0000000..2e5edb2 --- /dev/null +++ b/appleApp/AppleCore/FluxaAppleCatalogLoader.swift @@ -0,0 +1,88 @@ +import Foundation + +struct FluxaAppleCatalogRequest: Sendable { + let id: String + let title: String + let url: URL + let contentType: String + let addonTransportUrl: String? + let catalogType: String? +} + +final class FluxaAppleCatalogLoader { + private let session: URLSession + private let decoder = JSONDecoder() + private let encoder = JSONEncoder() + + init(session: URLSession = .shared) { + self.session = session + } + + func loadSnapshot(requests: [FluxaAppleCatalogRequest]) async throws -> String { + var rows = [FluxaAppleCatalogRow]() + for request in requests { + let (data, response) = try await session.data(from: request.url) + guard let httpResponse = response as? HTTPURLResponse, + (200..<300).contains(httpResponse.statusCode) else { + throw URLError(.badServerResponse) + } + let catalog = try decoder.decode(FluxaAppleStremioCatalogResponse.self, from: data) + rows.append( + FluxaAppleCatalogRow( + id: request.id, + title: request.title, + canLoadMore: false, + items: catalog.metas.map { + FluxaAppleCatalogItem( + id: $0.id, + type: $0.type ?? request.contentType, + title: $0.name, + subtitle: $0.releaseInfo ?? "", + artworkUrl: $0.poster, + logoUrl: $0.logo, + addonTransportUrl: request.addonTransportUrl, + catalogType: request.catalogType + ) + } + ) + ) + } + return String(decoding: try encoder.encode(FluxaAppleCatalogSnapshot(rows: rows)), as: UTF8.self) + } +} + +private struct FluxaAppleStremioCatalogResponse: Decodable { + let metas: [FluxaAppleStremioMeta] +} + +private struct FluxaAppleStremioMeta: Decodable { + let id: String + let type: String? + let name: String + let poster: String? + let logo: String? + let releaseInfo: String? +} + +private struct FluxaAppleCatalogSnapshot: Encodable { + let rows: [FluxaAppleCatalogRow] + let isLoading = false +} + +private struct FluxaAppleCatalogRow: Encodable { + let id: String + let title: String + let canLoadMore: Bool + let items: [FluxaAppleCatalogItem] +} + +private struct FluxaAppleCatalogItem: Encodable { + let id: String + let type: String + let title: String + let subtitle: String + let artworkUrl: String? + let logoUrl: String? + let addonTransportUrl: String? + let catalogType: String? +} diff --git a/appleApp/iOS/FluxaAppleCatalogBootstrap.swift b/appleApp/iOS/FluxaAppleCatalogBootstrap.swift new file mode 100644 index 0000000..d5e2edb --- /dev/null +++ b/appleApp/iOS/FluxaAppleCatalogBootstrap.swift @@ -0,0 +1,16 @@ +import FluxaShared +import Foundation + +@MainActor +final class FluxaAppleCatalogBootstrap { + private let loader: FluxaAppleCatalogLoader + + init(loader: FluxaAppleCatalogLoader = FluxaAppleCatalogLoader()) { + self.loader = loader + } + + func refresh(requests: [FluxaAppleCatalogRequest]) async throws { + let snapshot = try await loader.loadSnapshot(requests: requests) + FluxaApple.shared.updateCatalogHomeJson(homeJson: snapshot) + } +}