Files
openclaw/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMediaPlaybackLoader.swift
Peter Steinberger 0021e51f22 feat(apple): media renditions, Now Playing, video upload (#116051)
* feat(apple): complete media playback and uploads

* fix(apple): preserve movie picker metadata

* fix(apple): harden rendition and picker routing

* style(apple): fix macOS media formatting
2026-07-29 15:50:18 -04:00

48 lines
1.4 KiB
Swift

import Foundation
struct ChatMediaPlaybackRetryPolicy: Sendable {
/// Eleven waits total 120 seconds. The initial request plus these retries
/// gives transcoding time to finish without leaving a card pending forever.
static let bounded = ChatMediaPlaybackRetryPolicy(delays: [
.seconds(1),
.seconds(2),
.seconds(4),
.seconds(8),
.seconds(15),
.seconds(15),
.seconds(15),
.seconds(15),
.seconds(15),
.seconds(15),
.seconds(15),
])
let delays: [Duration]
}
enum ChatMediaPlaybackLoader {
typealias Load = @MainActor @Sendable () async throws -> OpenClawChatLoadedMedia?
typealias Sleep = @MainActor @Sendable (Duration) async throws -> Void
@MainActor
static func load(
policy: ChatMediaPlaybackRetryPolicy = .bounded,
request: Load,
onPreparing: @MainActor @Sendable () -> Void,
sleep: Sleep = { try await Task.sleep(for: $0) }) async throws -> OpenClawChatLoadedMedia?
{
var loaded = try await request()
guard case .preparing = loaded else { return loaded }
onPreparing()
for delay in policy.delays {
try Task.checkCancellation()
try await sleep(delay)
loaded = try await request()
guard case .preparing = loaded else { return loaded }
onPreparing()
}
return nil
}
}