Sound was dead in the app because status 0 is not a failure; and back is a swipe to the RIGHT
Oliver on the first shell build: *"I don't hear any of the games sounds.. daniel the umpire is synthesized which is horrible and no music is playing on start"* — two independent causes. - **Opaque fetch.** Capacitor serves the bundle through a custom WKURLSchemeHandler, and `fetch` reports those responses as `status: 0, ok: false` with the whole body present and decoding perfectly. All three loads in `audio.js` guarded with `if (!r.ok) throw`, so inside the app every recorded sound failed at the door: the umpire fell through to the synthesized `say()`, no bed started, no sample played. The synthesized sfx kept working, which made it read as a mixing bug rather than a loader one. Fixed once, in the shared `bytes()` helper every audio fetch now routes through — a status of 0 is the ABSENCE of an HTTP status, so trust it only when there is one and a real 404 still falls back. Any future `!r.ok` on a bundle-relative fetch is this same bug. - **The ring switch.** WKWebView's WebAudio runs in the SoloAmbient session, which the hardware silent switch mutes outright — a silent game on a phone that lives on silent, with nothing on screen to explain it. AppDelegate now sets AVAudioSession `.playback`, the games category. Confirmed in the shell: the bed reaches PLAYING, the context is `running` with no gesture at all (autoplay really is allowed in WKWebView, as LATER predicted), and `say()` never fires. On the web, a genuinely missing file still falls back — checked both. And the swipe flips: **right goes back**, the way iOS's own pop gesture goes (*"that's the iOS way"*). Left now does nothing. Noted in PROJECT.md that on a platform gesture the platform's convention beats the literal wording of the brief, and that is worth saying up front. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d71a26831a
commit
76ea1d0d79
6 files changed
+67
-20
No files matched your search
+34
-9
@@ -2582,15 +2582,40 @@ inside a `<script type="module">` is a hard 404 the moment the same file is serv
|
||||
purpose — iOS already routes these through the system's own vibration setting.
|
||||
**Untested on hardware.** The simulator has no Taptic Engine, so every weight and gap below is a
|
||||
guess on paper and needs its own phone round before any of it is assumed good.
|
||||
- **SWIPE LEFT GOES BACK** in the menus. Every screen but the splash wears exactly one chevron, and
|
||||
that button already knows where back is for its own screen — so the gesture finds the visible
|
||||
`.chev` and clicks it rather than keeping a second map of the wizard that would drift the first
|
||||
time a stage is added. Threshold 60 px, horizontal-dominant so the stats and board screens still
|
||||
scroll. The `touchend` listener is deliberately **not passive**: a swipe that starts and ends
|
||||
inside one of the big poster cards also produces that card's click, and `preventDefault` is what
|
||||
stops the screen answering forward in the same frame the chevron walked it back.
|
||||
**iOS convention is the opposite** (the system pop gesture drags rightward from the left edge).
|
||||
Built to the brief as asked; flipping it is the sign on one comparison in `main.js`.
|
||||
- **SWIPE RIGHT GOES BACK** in the menus — the direction iOS's own pop gesture goes. (Built leftward
|
||||
first, to the letter of the brief; Oliver flipped it the same hour: *"that's the iOS way"*. The
|
||||
lesson is cheap and worth keeping: on a platform gesture, the platform's convention beats the
|
||||
literal wording of the request — say so up front rather than shipping it and flagging it after.)
|
||||
Every screen but the splash wears exactly one chevron, and that button already knows where back is
|
||||
for its own screen — so the gesture finds the visible `.chev` and clicks it rather than keeping a
|
||||
second map of the wizard that would drift the first time a stage is added. Threshold 60 px,
|
||||
horizontal-dominant so the stats and board screens still scroll. The `touchend` listener is
|
||||
deliberately **not passive**: a swipe that starts and ends inside one of the big poster cards also
|
||||
produces that card's click, and `preventDefault` is what stops the screen answering forward in the
|
||||
same frame the chevron walked it back.
|
||||
- **SOUND, and it was broken twice over on the first shell build.** Oliver, minutes after it ran:
|
||||
*"I don't hear any of the games sounds.. daniel the umpire is synthesized which is horrible and no
|
||||
music is playing on start"*. Two independent causes, both now fixed, both worth knowing before the
|
||||
next plugin:
|
||||
1. **`fetch` responses from the app bundle are OPAQUE.** Capacitor serves `capacitor://localhost`
|
||||
through a custom `WKURLSchemeHandler`, and `fetch` reports those as `status: 0, ok: false` —
|
||||
with the full body present and decoding perfectly. `audio.js` guarded all three of its loads
|
||||
with a plain `if (!r.ok) throw`, so inside the app EVERY recorded sound failed at the door: the
|
||||
umpire fell through to the synthesized `say()`, no bed ever started, no sample ever played.
|
||||
The synthesized sfx kept working, which made it read as a mixing bug rather than a loader one.
|
||||
Fixed once, in the shared `bytes()` helper every audio fetch now routes through: **a status of
|
||||
0 is the absence of an HTTP status, not a failure** — trust the status only when there is one,
|
||||
so a real 404 still falls back. **Any future `!r.ok` guard on a bundle-relative fetch is this
|
||||
same bug.** (`stats.js` is fine: its board calls go to the live host over real HTTPS.)
|
||||
2. **The ring switch muted everything on device.** WKWebView's WebAudio runs in the SoloAmbient
|
||||
session, which the hardware silent switch kills outright — a completely silent game on a phone
|
||||
that lives on silent, with nothing on screen to explain it. `AppDelegate` now sets
|
||||
`AVAudioSession .playback`, the games-and-media category. That is a shell-only fix; the web
|
||||
build has no say in it, and it is a good part of why the shell is worth having for sound.
|
||||
|
||||
Confirmed in the shell after both fixes: the bed reaches `PLAYING`, the context is `running`
|
||||
**with no gesture at all** (autoplay really is allowed in WKWebView, as LATER predicted), and the
|
||||
`say()` fallback never fires. On the web, a genuinely missing file still falls back — checked.
|
||||
- **The app has no server behind it.** Inside the shell the page is served from the bundle
|
||||
(`capacitor://localhost`), so `fetch('api/scores')` and the netplay socket would have resolved
|
||||
against the app's own files. `config.NATIVE`/`config.API` and one branch in `net.js` point the
|
||||
|
||||
Reference in new issue
Block a user