mirror of
https://github.com/FluxaMedia/fluxa.git
synced 2026-08-09 08:27:32 +00:00
72 lines
2.7 KiB
Swift
72 lines
2.7 KiB
Swift
import FluxaShared
|
|
import Foundation
|
|
|
|
@MainActor
|
|
final class FluxaAppleSearchStartup {
|
|
private let coordinator: FluxaAppleHeadlessCoordinator
|
|
private let encoder = JSONEncoder()
|
|
|
|
init(coordinator: FluxaAppleHeadlessCoordinator) {
|
|
self.coordinator = coordinator
|
|
}
|
|
|
|
func search(query: String) async {
|
|
let normalizedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !normalizedQuery.isEmpty else {
|
|
FluxaApple.shared.updateSearch(snapshot: AppleSearchSnapshot(query: "", results: [], isLoading: false))
|
|
return
|
|
}
|
|
do {
|
|
let action = FluxaAppleSearchAction(
|
|
type: "searchRequested",
|
|
query: normalizedQuery,
|
|
language: "en",
|
|
profile: FluxaAppleSearchProfile(id: "apple-default")
|
|
)
|
|
let actionJson = String(decoding: try encoder.encode(action), as: UTF8.self)
|
|
let result = try await coordinator.dispatch(actionJson: actionJson)
|
|
updateSharedSearch(result: result, query: normalizedQuery)
|
|
} catch {
|
|
FluxaApple.shared.updateSearch(snapshot: AppleSearchSnapshot(query: normalizedQuery, results: [], isLoading: false))
|
|
}
|
|
}
|
|
|
|
private func updateSharedSearch(result: FluxaAppleHeadlessResult, query: String) {
|
|
let results: [AppleCatalogItemSnapshot]
|
|
if case .object(let search)? = result.state["search"],
|
|
case .array(let values)? = search["results"] {
|
|
results = values.compactMap(sharedItem)
|
|
} else {
|
|
results = []
|
|
}
|
|
FluxaApple.shared.updateSearch(snapshot: AppleSearchSnapshot(query: query, results: results, isLoading: false))
|
|
}
|
|
|
|
private func sharedItem(_ value: FluxaAppleJsonValue) -> AppleCatalogItemSnapshot? {
|
|
guard case .object(let item) = value,
|
|
let id = text(item["id"]),
|
|
let type = text(item["type"]),
|
|
let title = text(item["name"]) else {
|
|
return nil
|
|
}
|
|
return AppleCatalogItemSnapshot(id: id, type: type, title: title, subtitle: text(item["releaseInfo"]) ?? "", artworkUrl: text(item["poster"]), logoUrl: text(item["logo"]), addonTransportUrl: text(item["addonTransportUrl"]), catalogType: text(item["catalogType"]), progress: nil, topTenRank: nil)
|
|
}
|
|
|
|
private func text(_ value: FluxaAppleJsonValue?) -> String? {
|
|
guard case .string(let text)? = value else {
|
|
return nil
|
|
}
|
|
return text
|
|
}
|
|
}
|
|
|
|
private struct FluxaAppleSearchAction: Encodable {
|
|
let type: String
|
|
let query: String
|
|
let language: String
|
|
let profile: FluxaAppleSearchProfile
|
|
}
|
|
|
|
private struct FluxaAppleSearchProfile: Encodable {
|
|
let id: String
|
|
}
|