ReviewOS

also looking at this

craft-native/craft

fix(native): interaction, audio, document and checkpoint gaps stranded after #401

#415
Merged glennmichael123 wants to merge codex/issues-388-400-344 into main
19 files +987 -50
docs/guides/native-stx.mdmodified+34-0
Changes to docs/guides/native-stx.md
@@ -1391,6 +1391,40 @@ unchanged. `craft.files.download` resolves a non-2xx response as
13911391`{ ok: false, status, body }`; transport failures still reject with the native
13921392network error codes.
13931393
1394Both maintained native hosts implement `craft.files.pickFile`. Android maps the
1395shared MIME, UTI, and common extension filters to `ACTION_OPEN_DOCUMENT`, copies
1396each selected document into the same app-owned directory, and enforces the
1397shared 512 MiB default/per-file limit before publishing a descriptor. A
1398dismissed picker resolves with an empty array; a canceled or oversized copy
1399never leaves a partial file behind. The same cancellation cleanup applies while
1400Android is decoding a picked image or copying a video, so a request canceled
1401after the picker closes cannot publish or leak an app-owned file. Use this for
1402GPX, TCX, FIT, PDF, or other documents that are not photos or videos. On iOS,
1403failed photo JPEG creation or finalization also removes its staging directory,
1404so a rejected image import does not accumulate orphaned temporary files.
1405
1406`craft.audio` playback is screen-owned on both hosts. Android requests audio
1407focus before preparing a player, reports a denied request as `AUDIO_FOCUS_DENIED`,
1408pauses on a transient interruption and resumes on focus gain, ducks during a
1409duckable interruption, and releases focus when the last sound ends or the
1410screen closes. iOS observes `AVAudioSession` interruptions and resumes sounds
1411only when the system grants the `shouldResume` option. A permanent Android
1412focus loss releases every player and sends each sound's error event; replacement,
1413decode failure, cancellation, interruption, and teardown also release their
1414player resources.
1415Control calls resolve `false` when their sound id is not owned by the screen,
1416matching the browser host instead of reporting a false success.
1417
1418Checkpoint names use the same bounded filename contract on both native hosts:
1419letters, digits, `.`, `_`, and `-`, up to 128 characters, without a leading
1420dot. Non-JSON values and invalid names are rejected before a write is posted;
1421the previous confirmed checkpoint remains available after a failed or
1422interrupted replacement. If a screen closes while a checkpoint is still being
1423written, its promise rejects instead of hanging; the host's later worker
1424completion cannot publish a second result for that request. iOS also reports a
1425failed result when its writer completes after the screen runtime is disposed or
1426has already been deallocated.
1427
13941428The `media` capability (iOS) keeps video and audio on the phone for offline,
13951429in Application Support rather than the temporary directory, left out of
13961430iCloud backups. `craft.media.keep(url, { headers })` downloads the file once