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:
@@ -58,15 +58,26 @@ function syncKeepButtons(){
|
||||
for(const e of S.entries)
|
||||
if(e.enclosures.some(isKept)!==!!$(`#eps .ep[data-key="${CSS.escape(entryKey(e))}"] .kept`)) swapRow(e);
|
||||
}
|
||||
/// The button for a file on the server that plays; none without a worker to play it offline.
|
||||
/// The button for a file on the server that plays; none without a worker, or an app, to play it
|
||||
/// offline.
|
||||
function keepBtn(x: Enclosure){
|
||||
if(!worker) return '';
|
||||
if(!worker&&!ipxHost) return '';
|
||||
const k=isKept(x), label=k?'Kept on this device to play offline. Remove it':'Keep on this device to play offline';
|
||||
return `<button class="btn ico" data-a="offline" data-enc="${x.id}" data-url="${keepUrl(x)}" aria-pressed="${k}" aria-busy="${keeping.has(keepUrl(x))}" title="${label}" aria-label="${label}">${k?ICON.kept:ICON.keep}</button>`;
|
||||
}
|
||||
async function toggleKept(x: Enclosure, name: string){
|
||||
const url=keepUrl(x);
|
||||
if(keeping.has(url)) return;
|
||||
// In the iOS app the phone keeps the file and its player plays it (#425): a WebView runs no
|
||||
// service worker, and the app's player could not read the page's cache if it did. The app
|
||||
// answers with what it holds, hostKept below.
|
||||
if(ipxHost){
|
||||
if(kept.has(url)){ ipxHost({t:'unkeep',url}); toast('Removed from this device: '+name); return; }
|
||||
keeping.add(url); syncKeepButtons();
|
||||
toast('Keeping on this device: '+name);
|
||||
ipxHost({t:'keep',url});
|
||||
return;
|
||||
}
|
||||
const c=await caches.open(KEPT);
|
||||
if(kept.has(url)){
|
||||
await c.delete(url); kept.delete(url); syncKeepButtons();
|
||||
@@ -91,8 +102,26 @@ async function toggleKept(x: Enclosure, name: string){
|
||||
}finally{ keeping.delete(url); syncKeepButtons(); }
|
||||
}
|
||||
|
||||
/// What the app holds and is fetching (#425), told when the page starts and after each change,
|
||||
/// or that one could not be kept. Only a file asked for here says it was kept: the list at start
|
||||
/// is no news.
|
||||
function hostKept(m: {t: string, urls?: string[], keeping?: string[], url?: string, message?: string}){
|
||||
if(m.t==='keepFailed'){
|
||||
keeping.delete(m.url||'');
|
||||
toast(m.message||'Unable to keep it on this device. Try again.',true);
|
||||
syncKeepButtons();
|
||||
return;
|
||||
}
|
||||
const asked=new Set(keeping);
|
||||
kept.clear(); for(const u of m.urls||[]) kept.add(u);
|
||||
keeping.clear(); for(const u of m.keeping||[]) keeping.add(u);
|
||||
for(const u of asked) if(kept.has(u)) toast('Kept on this device, to play offline');
|
||||
syncKeepButtons();
|
||||
}
|
||||
|
||||
/// Everything kept for offline, gone: at sign-out, and when another account signs in here.
|
||||
async function clearOffline(){
|
||||
ipxHost?.({t:'clearKept'});
|
||||
try{ for(const k of await caches.keys()) if(k.startsWith('ipx-')) await caches.delete(k); }catch{}
|
||||
kept.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user