mirror of
https://github.com/FluxaMedia/fluxa.git
synced 2026-08-10 09:05:45 +00:00
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.
106 lines
3.9 KiB
Swift
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
|
|
}
|
|
}
|