From de50debad93d0486091bf5a2384789fe2f35bdb8 Mon Sep 17 00:00:00 2001 From: mrwnslz Date: Mon, 19 Oct 2026 20:19:22 +0200 Subject: [PATCH] =?UTF-8?q?Podcasts=20im=20Browser:=20Mit=20Projekt=20verk?= =?UTF-8?q?n=C3=BCpfen=20(Folgen,=20Player=20mit=20Zeitmarke),=20Merken=20?= =?UTF-8?q?in=20der=20Folgenansicht=20(diora-android=204f514cd);=20sw=20v1?= =?UTF-8?q?42?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- static/js/sw.js | 2 +- static/podcasts/native-podcast.js | 36 ++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/static/js/sw.js b/static/js/sw.js index 68002c7..1320bf1 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-v141'; +const CACHE = 'diora-v142'; const SHELL = [ '/static/css/app.css', '/static/js/app/01-core.js', diff --git a/static/podcasts/native-podcast.js b/static/podcasts/native-podcast.js index c3c9b9e..b995f72 100644 --- a/static/podcasts/native-podcast.js +++ b/static/podcasts/native-podcast.js @@ -1,4 +1,4 @@ -// Copied from diora-android 1c1ec4e 2026-10-19: web-native/static/native-podcast.js +// Copied from diora-android 4f514cd 2026-10-19: 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. @@ -451,6 +451,26 @@ toast('In der ' + QNAME() + (label ? ': ' + label.label.toLowerCase() : '')); } + // An episode into a research project (diora-web docs/projects.md); from the player with + // the place it's at (a time mark „ab 12:34“). + function linkProject(e, position) { + if (!window.DioraProjects) return; + const r = e.raw || queue().find(q => q.episode__id === e.id) || later().find(q => q.episode__id === e.id) || {}; + const d = storedDetails(e.id) || {}; + DioraProjects.link('episode', e.id, { + title: plain(e.title || r.title || r.episode__title || d.title || ''), + podcast: plain(e.feed || r.feed__title || r.episode__feed__title || ''), + author: plain(d.author || r.author || ''), + date: e.date || r.pub_date || r.episode__pub_date || d.pub_date || null, + url: d.link || r.link || r.audio_url || r.episode__audio_url || '', + feed: e.feedId || r.feed__id || r.episode__feed__id || null, + position: Math.max(0, Math.round(position || 0)), + }); + } + + const projectItem = e => window.DioraProjects && {icon: '◇', label: 'Mit Projekt verknüpfen …', + hint: (DioraProjects.of('episode', e.id) || []).map(p => p.name).join(', ') || null, action: () => linkProject(e, 0)}; + function openAudiobook(feedId) { if (!feedId || typeof window.__dioraAudiobookOpen !== 'function') return false; closeNotes(); @@ -564,6 +584,7 @@ v2() && N.podcastLaterAdd && !inLater(e) && {icon: '+', label: 'Auf die Merkliste', hint: 'für später', action: () => toggleLater(e)}, {icon: '✕', svg: 'listx', label: 'Aus der ' + QNAME() + ' nehmen', hint: dlDone(e.id) && !v2() ? 'Datei bleibt' : null, action: () => N.podcastDequeue(e.id)}, + projectItem(e), discardItem(e, opts), selectItem(e, opts), ]); @@ -607,6 +628,7 @@ !e.played && {icon: '✓', label: 'Als gehört markieren', hint: kept || queued ? 'verlässt die Listen' : null, action: () => markPlayed(e)}, e.played && {icon: '↺', label: 'Als ungehört markieren', action: () => N.podcastMarkPlayed(e.id, false)}, ...dlMenuItems(e), + projectItem(e), discardItem(e, opts), selectItem(e, opts), ]); @@ -4434,8 +4456,13 @@ b.addEventListener('click', ev => { ev.stopPropagation(); run(); setTimeout(episodeScreenParts, 150); }); actions.append(b); }; - if (inQueue(e.id)) act('listx', '', 'Aus Warteschlange', () => { N.podcastDequeue(e.id); e.raw.in_queue = false; }); + if (v2() && N.podcastLaterAdd) { + if (inLater(e)) act('listx', '', 'Aus der Merkliste', () => toggleLater(e)); + else act(null, '+', 'Merken', () => toggleLater(e)); + if (inQueue(e.id)) act('listx', '', 'Aus der Liste', () => { N.podcastDequeue(e.id); e.raw.in_queue = false; }); + } else if (inQueue(e.id)) act('listx', '', 'Aus Warteschlange', () => { N.podcastDequeue(e.id); e.raw.in_queue = false; }); else act(null, '+', 'Einreihen', () => { enqueue(e); e.raw.in_queue = true; }); + if (window.DioraProjects) act(null, '◇', 'Projekt', () => linkProject(e, 0)); if (DL && (e.raw.audio_url || e.raw.episode__audio_url)) { const d = downloads[e.id]; if (!d || d.state === 'failed') act(null, '↓', 'Laden', () => dlStart(e)); @@ -4613,7 +4640,10 @@ button('⏭', keepSkipped() ? 'Nächste Folge (diese bleibt in der Warteschlange)' : 'Folge abschließen, nächste spielen', finishAndNext, 'nui-pod-next'), N.playerTransfer && button('⇄', 'Wiedergabe auf …', deviceMenu, 'nui-pod-devices'), - button('≡', 'Warteschlange', showQueue), + window.DioraProjects && button('◇', 'Mit Projekt verknüpfen – ab dieser Stelle', () => linkProject({ + id: player.episodeId, title: player.title, feed: player.feed, feedId: player.feedId, + }, (player.pos || 0) / 1000), 'nui-pod-project'), + button('≡', QNAME(), showQueue), ].filter(Boolean)); panel.append(extra); const notes = el('div', 'nui-pod-notesbox');