iOS: CarPlay (#420)

A CarPlay scene beside the phone's: In Progress, Unread and Shows as
CPListTemplates from ipx's API, read with the player's credentials, and
a pick played through the same Playback, so it resumes from the saved
place, saves as it goes and marks read at 90%. Now Playing is the
system's template over Playback's now-playing info.

When the car starts a different episode the page is sent
{t:"replaced"} and closes its player bar. Left open, the bar would have
gone on as the old episode while the host's clock belonged to the new
one, saving that time and marking the wrong item read.

The badge's fetch moves into API.get, which CarPlay shares. Build 13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ray Slakinski
2026-11-09 08:10:29 -05:00
parent 711b0395f1
commit 2bb7ed2109
12 changed files with 354 additions and 18 deletions

View File

@@ -19,7 +19,8 @@ from `project.yml`, so `.xcodeproj` is not in git: edit the yml. Nothing on Towe
A free personal team works, but a build on it expires after seven days and is reinstalled from
Xcode. A paid account ($99 a year) makes that a year and adds TestFlight. Playing with the screen
locked is a plist key (`UIBackgroundModes: audio`), not an entitlement, so it works on either.
CarPlay's own dashboard app does not: Apple grants `com.apple.developer.carplay-audio` on request.
CarPlay does not: Apple grants `com.apple.developer.carplay-audio` on request (granted for team
8743L8D729 on 2026-11-09), and the App ID needs it ticked under Additional Capabilities.
## Which server
@@ -133,6 +134,7 @@ App to page, as `window.ipxNative.on(...)`:
| `{t:"push", token, sandbox}` | at `ready` and when Apple gives a new one: the phone's push token, for the page to register with ipx (`POST /api/push/devices`) (#433) |
| `{t:"sleep", left}` | at `ready`, while the timer runs: seconds left, for a page that reloaded |
| `{t:"slept"}` | the timer ran out and playback paused |
| `{t:"replaced"}` | the car chose another episode; the page's player bar closes without saving |
The app writes the position (every ten seconds and on pause) and marks an item read at 90%, from
its own clock, so both happen while the page is frozen. Video stays in the page.
@@ -141,5 +143,7 @@ its own clock, so both happen while the page is frozen. Video stays in the page.
* Without the player token the cookie is the only credential: when Cloudflare Access's expires
mid-drive, playback stops with "Sign in again", and opening the app signs in.
* CarPlay's dashboard app needs Apple's entitlement first; then it is a second scene over the same
`Playback`.
* CarPlay (`CarScreen.swift`) reads ipx with the player's credentials and nothing else: launched
by the car with the phone's app never opened since a restart, it has only cookies saved to disk,
and without the player token a lapsed Access cookie shows "iPX can't reach your server". Its
lists need a connection; a kept episode plays without one once it is picked.