web/src/native.ts (#45) has handed playback to a host since September, and there was no host in this repo: the earlier app, rays/ipodderx-app, grew native lists beside the page and is left behind. This one is the page and a player: a WKWebView of ipx-web, AVPlayer behind the bridge with the audio session to play on locked, now playing and the remote commands (15 back, 30 forward, scrubbing), and positions and read written from the player's own clock, with DeadAir's copy named so the server reads the position on its clock. Built with XcodeGen on a Mac; nothing here compiles the Swift. Its icon is web/logo.svg at 1024. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RqkrVDqdiQEMWAkNGQ2tYA
32 lines
1.1 KiB
Swift
32 lines
1.1 KiB
Swift
import Foundation
|
|
import WebKit
|
|
|
|
/// The web view signs in; the player rides on what that left behind.
|
|
///
|
|
/// ipx knows who is asking by cookie: `ipx_session` from its own form, `CF_Authorization` from
|
|
/// Cloudflare Access in front of the tunnel. That is why the player needs no API of its own. But
|
|
/// AVPlayer and URLSession read `HTTPCookieStorage.shared`, and WKWebView keeps a store of its
|
|
/// own, so this copies one into the other whenever the web view's changes.
|
|
final class CookieBridge: NSObject, WKHTTPCookieStoreObserver {
|
|
private let store: WKHTTPCookieStore
|
|
|
|
init(store: WKHTTPCookieStore) {
|
|
self.store = store
|
|
super.init()
|
|
store.add(self)
|
|
sync()
|
|
}
|
|
|
|
func cookiesDidChange(in cookieStore: WKHTTPCookieStore) { sync() }
|
|
|
|
/// All of them, replaced: a cookie the web view dropped (signing out) has to go here too, or
|
|
/// the player would go on playing as someone who signed out.
|
|
private func sync() {
|
|
store.getAllCookies { all in
|
|
let shared = HTTPCookieStorage.shared
|
|
shared.cookies?.forEach(shared.deleteCookie)
|
|
all.forEach(shared.setCookie)
|
|
}
|
|
}
|
|
}
|