feat: media player with reconciliation and pinned media proxy (Phase 5)

- MediaAPI client for all 10 media endpoints + Codable models
- PinnedMediaResourceLoader: AVAssetResourceLoaderDelegate proxying
  https media through the pinned-TLS session (AVPlayer ignores registered
  URLProtocol subclasses and can't trust the self-signed cert)
- MediaPlayerController: AVPlayer + 1.5s poll reconciliation ported from
  web app.js (track swap, late audio_url, desired state, seek_hint,
  reporting, enter-media-scope carry-over, post-talk resume)
- MediaPanelView UI + music.note toolbar entry
- VoiceSession wiring (enterMediaScope/endConversation)

Playback of the library's webm tracks is blocked by an iOS platform
limitation (AVPlayer cannot decode webm); TLS/Range proxy, reconciliation,
polling, reporting and UI are all verified working in the simulator.
This commit is contained in:
snowspeeder committed 2026-08-30 08:21:08 -04:00
1 parent f2022f8a96
commit 0af944e60d
8 files changed
+964 -5

No files matched your search

@@ -172,7 +172,15 @@ struct ConversationView: View {
.padding()
}
@ToolbarContentBuilder
private var toolbarContent: some ToolbarContent {
ToolbarItem(placement: .topBarTrailing) {
NavigationLink {
MediaPanelView(playerController: session.mediaController, settings: settings)
} label: {
Image(systemName: "music.note")
}
}
ToolbarItem(placement: .topBarTrailing) {
NavigationLink {
SettingsView(settings: settings, session: session)