fluxa/appleApp/AppleCore/FluxaAppleCatalogLoader.swift
KhooLy a0db322fed fix: move Apple catalog/detail/discover/search snapshot DTOs from shared to core
Xcode's embedAndSignAppleFrameworkForXcode task for :shared: is
intermittently disabled by the Kotlin Gradle Plugin's own IDE/index-build
detection (onlyIf 'Task is enabled' is false), silently skipping the
framework embed and leaving these types unavailable to Swift. core's
framework already embeds reliably for iOS (matching tvOS), so these plain
DTOs move there instead; the Compose-dependent DataSource wrappers stay in
shared, which already re-exports core.
2026-07-28 19:04:13 +03:00

106 lines
3.9 KiB
Swift

import Foundation
import FluxaCore
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
init(session: URLSession = .shared) {
self.session = session
}
func loadRows(requests: [FluxaAppleCatalogRequest]) async throws -> [AppleCatalogRowSnapshot] {
var rows = [AppleCatalogRowSnapshot]()
var lastError: Error?
for request in requests {
do {
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)
}
guard let catalogItems = FluxaCoreStremio.parseCatalogItems(
body: String(decoding: data, as: UTF8.self),
fallbackType: request.contentType
) else {
throw URLError(.cannotParseResponse)
}
rows.append(
AppleCatalogRowSnapshot(
id: request.id,
title: request.title,
items: catalogItems.map {
AppleCatalogItemSnapshot(
id: $0.id,
type: $0.type,
title: $0.title,
subtitle: $0.subtitle,
artworkUrl: $0.artworkUrl,
logoUrl: $0.logoUrl,
addonTransportUrl: request.addonTransportUrl,
catalogType: request.catalogType,
progress: nil,
topTenRank: nil
)
},
canLoadMore: false
)
)
} catch {
lastError = error
}
}
if rows.isEmpty, let lastError {
throw lastError
}
return rows
}
func loadSearchItems(requests: [FluxaAppleSearchRequest]) async throws -> [AppleCatalogItemSnapshot] {
var items = [AppleCatalogItemSnapshot]()
var lastError: Error?
for request in requests {
do {
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)
}
guard let catalogItems = FluxaCoreStremio.parseCatalogItems(
body: String(decoding: data, as: UTF8.self),
fallbackType: request.contentType
) else {
throw URLError(.cannotParseResponse)
}
items.append(contentsOf: catalogItems.map {
AppleCatalogItemSnapshot(
id: $0.id,
type: $0.type,
title: $0.title,
subtitle: $0.subtitle,
artworkUrl: $0.artworkUrl,
logoUrl: $0.logoUrl,
addonTransportUrl: request.addonTransportUrl,
catalogType: request.catalogType,
progress: nil,
topTenRank: nil
)
})
} catch {
lastError = error
}
}
if items.isEmpty, let lastError {
throw lastError
}
return items
}
}