diff --git a/static/js/sw.js b/static/js/sw.js index 641b099..753418d 100644 --- a/static/js/sw.js +++ b/static/js/sw.js @@ -2,7 +2,7 @@ * diora service worker — caches the app shell for offline use. */ -const CACHE = 'diora-v52'; +const CACHE = 'diora-v53'; const SHELL = [ '/static/css/app.css', '/static/js/app.js', diff --git a/static/podcasts/native-podcast.js b/static/podcasts/native-podcast.js index add74ee..d9ceb97 100644 --- a/static/podcasts/native-podcast.js +++ b/static/podcasts/native-podcast.js @@ -1,4 +1,4 @@ -// Copied from diora-android 3600b15 2026-10-02: web-native/static/native-podcast.js +// Copied from diora-android f94c501 2026-10-02: web-native/static/native-podcast.js // by tools/sync_podcast_ui.py. Do not edit here: change it in diora-android // and copy again. The browser host is static/js/podcasts-web.js. @@ -262,7 +262,13 @@ playedItem(), headsetItem(), ]), - DL && group('↓', 'Downloads', 'automatisch, Limit, aufräumen', () => dlSettingsItems()), + DL && group('↓', 'Downloads', 'automatisch, Limit, aufräumen', () => [ + // Account-wide (server): new subscriptions start with auto-download on or off. + 'auto_download_default' in s && {icon: s.auto_download_default ? '☑' : '☐', label: 'Neue Abos laden von selbst', + hint: s.auto_download_default ? 'an: neue Folgen neuer Abos werden geladen' : 'aus: pro Podcast einschaltbar', + action: () => N.podcastSettings(JSON.stringify({auto_download_default: !s.auto_download_default}))}, + ...dlSettingsItems(), + ]), group('⇅', 'Abos umziehen', 'OPML exportieren und importieren', () => [ {icon: '⇩', label: 'Abos exportieren (OPML)', hint: 'zum Umziehen in eine andere App', action: exportOpml}, {icon: '⇧', label: 'Abos importieren (OPML)', action: importOpml}, @@ -757,6 +763,15 @@ const v = typeof customPrompt === 'function' ? await customPrompt(title, now || '') : null; if (v != null) save({[key]: v.trim()}); }; + // AntennaPod's per-podcast auto-download: new episodes land on the phone by themselves. + if ('auto_download' in live && N.podcastDownloads) { + row.append(chip('Auto-Download', live.auto_download ? 'an' : 'aus', !!live.auto_download, () => + openSheet(`Neue Folgen von „${plain(live.title)}“ herunterladen?`, [ + {icon: live.auto_download ? '●' : '○', label: 'Ja, von selbst', hint: 'im WLAN, innerhalb des Download-Limits', + action: () => save({auto_download: true})}, + {icon: !live.auto_download ? '●' : '○', label: 'Nein', hint: 'nur die Warteschlange wird geladen', action: () => save({auto_download: false})}, + ]))); + } row.append(chip('Filter', words || 'aus', !!words, () => openSheet('Welche neuen Folgen zählen?', [ {icon: '+', label: 'Nur mit diesen Wörtern im Titel', hint: live.include_words || 'alle', action: () => ask('include_words', 'Nur Folgen, deren Titel eines dieser Wörter enthält (mit Komma getrennt):', live.include_words)}, @@ -1728,8 +1743,8 @@ // The limit and the clean-up the AntennaPod way (Downloads.kt, DownloadPlan.toClean). const DL_LIMITS = [5, 10, 25, 50, 100, 500, 0]; const DL_CLEANUPS = [ - {value: 'queue', label: 'Wenn nicht mehr in der Warteschlange', - hint: 'automatische Downloads, sobald ihre Folge dort fehlt; beim Limit auch gehörte'}, + {value: 'queue', label: 'Wenn Platz gebraucht wird', + hint: 'beim Limit gehen Folgen, die nicht in der Warteschlange stehen: gehörte zuerst'}, {value: 'never', label: 'Nie', hint: 'beim Limit lädt die App nichts mehr von selbst'}, ]; const dlLimitLabel = n => (n ? n + ' Folgen' : 'Unbegrenzt'); @@ -1816,6 +1831,9 @@ action: () => openSheet('Höchstens so viele Folgen auf dem Telefon', DL_LIMITS.map(n => ({ icon: s.limit === n ? '●' : '○', label: dlLimitLabel(n), active: s.limit === n, hint: n === 25 ? 'Standard' : null, action: () => dlSet({limit: n})})))}, + 'enqueue' in s && {icon: s.enqueue ? '☑' : '☐', label: 'Heruntergeladene Folgen einreihen', + hint: s.enqueue ? 'an: was geladen wird, kommt in die Warteschlange' : 'aus', + action: () => dlSet({enqueue: !s.enqueue})}, s.cleanup && {icon: '♻', label: 'Aufräumen', hint: (DL_CLEANUPS.find(c => c.value === s.cleanup) || DL_CLEANUPS[0]).label, action: () => openSheet('Downloads aufräumen', DL_CLEANUPS.map(c => ({ icon: s.cleanup === c.value ? '●' : '○', label: c.label, hint: c.hint, active: s.cleanup === c.value,