Podcasts im Browser: Mit Projekt verknüpfen (Folgen, Player mit Zeitmarke), Merken in der Folgenansicht (diora-android 4f514cd); sw v142
Some checks failed
Test / test (push) Waiting to run
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Has been cancelled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrwnslz 2026-10-19 20:19:22 +02:00
parent e5a170838b
commit de50debad9
2 changed files with 34 additions and 4 deletions

View file

@ -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',

View file

@ -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');