iOS: episodes kept on the phone play with no connection (#425)
A WKWebView runs no service worker, so the page's Keep button (#412) was not shown in the app and everything played from the server. Now the page asks the app to keep the file (keep, unkeep, clearKept), and the app answers with what it holds (kept, keepFailed) whether or not anything plays. The app fetches with a background URLSession, so a download goes on with the app closed, into Application Support (not backed up; the files can be fetched again), and Playback plays from the file when there is one. The DeadAir copy is kept under its own path, as the browser keeps it. Places and finishes reached offline wait in an outbox, newest per address, and go when the network is back. Checked in the simulator against a local server: kept /media/42 and /media/42/deadair, then with the server refusing /media, a fresh launch played each from the phone and asked the server for nothing. The page itself still needs a connection to open (#435). Deploy the app (build 6) before the page: a new page in an old app shows a Keep button nothing answers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,37 @@ audio.src = '/media/99';
|
||||
ok(!last('load'), 'a video was handed to the host');
|
||||
ok(audio.calls.includes('src:/media/99'), 'a video did not play on the element');
|
||||
|
||||
// Kept on the phone (#425): no service worker in a WebView, so the button is the app's to answer.
|
||||
const enc42 = { id: 42, deadair: 0, mime: 'audio/mpeg' };
|
||||
ok(String(vm.runInContext('keepBtn(X)', Object.assign(ctx, { X: enc42 }))).includes('data-a="offline"'),
|
||||
'no Keep button in the app, which has no service worker to keep a file');
|
||||
since();
|
||||
await vm.runInContext('toggleKept(X, "Episode One")', ctx);
|
||||
ok(last('keep')?.url === '/media/42', 'Keep did not ask the app for the file');
|
||||
ok(vm.runInContext('keeping.has("/media/42")', ctx), 'the button did not show it was on its way');
|
||||
|
||||
// The app's answer, which comes whether or not anything is playing.
|
||||
audio.removeAttribute('src');
|
||||
ctx.window.ipxNative.on({ t: 'kept', urls: ['/media/42'], keeping: [] });
|
||||
ok(vm.runInContext('isKept(X)', ctx), "the app's list did not reach the page");
|
||||
ok(!vm.runInContext('keeping.has("/media/42")', ctx), 'still shown as on its way once kept');
|
||||
ok(vm.runInContext('mediaSrc(X)', ctx) === '/media/42?offline', 'a kept file is not asked for as kept');
|
||||
|
||||
since();
|
||||
await vm.runInContext('toggleKept(X, "Episode One")', ctx);
|
||||
ok(last('unkeep')?.url === '/media/42', 'pressing it again did not ask the app to let it go');
|
||||
ctx.window.ipxNative.on({ t: 'kept', urls: [], keeping: [] });
|
||||
ok(!vm.runInContext('isKept(X)', ctx), 'still kept after the app let it go');
|
||||
|
||||
// One that could not be kept stops showing as on its way.
|
||||
await vm.runInContext('toggleKept(X, "Episode One")', ctx);
|
||||
ctx.window.ipxNative.on({ t: 'keepFailed', url: '/media/42', message: 'The server said 404.' });
|
||||
ok(!vm.runInContext('keeping.has("/media/42")', ctx), 'a failed keep still shows as on its way');
|
||||
|
||||
since();
|
||||
await vm.runInContext('clearOffline()', ctx);
|
||||
ok(last('clearKept'), 'signing out left the phone holding what was kept');
|
||||
|
||||
if (failed) { console.error(`\n${failed} failed`); process.exit(1); }
|
||||
console.log('OK: native-bridge: the host takes playback and the page follows it');
|
||||
console.log('OK: native-bridge: the host takes playback and keeping, and the page follows it');
|
||||
process.exit(0);
|
||||
|
||||
Reference in New Issue
Block a user