Der Podcast-Tab der Web-App zeigt jetzt dieselbe Oberfläche wie die Android-App: native-podcast.js aus diora-android, unverändert kopiert nach static/podcasts/ (tools/sync_podcast_ui.py, mit Quell-Commit im Kopf), dazu die Podcast-Teile von native.css. static/js/podcasts-web.js spielt im Browser die Rolle der App (window.DioraPodcastHost statt DioraNative): - Zustand aus /podcasts/state/, in localStorage für einen schnellen Start; Änderungen sofort lokal und der Reihe nach an den Server (Outbox, übersteht Neuladen und Offline), wie Podcasts.kt, inkl. „immer sortiert halten“ - eigener Player (nicht das Radio-Audio-Element), Warteschlange = Playlist, wie RadioService.EpisodeTracker: Stelle fortsetzen, Intro/Outro, Fortschritt alle 10 s und bei Pause, „gehört“ kurz vor Schluss (auch bei „nächste“), automatisch weiter, nach Pause etwas zurück (0,8/3/10/20 s), Tempo und Lautstärke (bis 1) pro Podcast, Sleep-Timer nur während des Abspielens mit Ausblenden - Sperrbildschirm und Medientasten über navigator.mediaSession - Abspiel-Einstellungen dieses Geräts in localStorage (wie PlaybackPrefs) - keine Downloads (die Oberfläche blendet sie aus) - Radio und Podcast nie gleichzeitig: eine Folge stoppt das Radio, ein Sender legt die Folge weg - Bottom-Sheet und Mini-Player-Dock über der Radio-Leiste; auf breiten Bildschirmen eine mittige Spalte (760 px) In der App und der Desktop-App (window.DioraNative vorhanden) tut podcasts-web.js nichts. Entfernt: der alte Podcast-Tab (Markup, ~1000 Zeilen in app.js, CSS), die Podcast-Leiste im Player, INITIAL_PODCAST_FEEDS und das Herunterladen von Folgen in den Browser-Cache (der Service Worker räumt diora-podcast-v1 ab). Service-Worker-Cache auf v52, neue Dateien im App-Shell. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
3.2 KiB
Python
78 lines
3.2 KiB
Python
"""Copy the phone app's podcast page into the web app.
|
|
|
|
The browser shows the same podcast UI as the Android app: diora-android's
|
|
web-native/static/native-podcast.js, unchanged, on top of a browser host
|
|
(static/js/podcasts-web.js). This copies that file and the podcast parts of
|
|
native.css (the bottom sheet and everything from the podcast section on) to
|
|
static/podcasts/, with the source commit in a header comment.
|
|
|
|
Usage: python tools/sync_podcast_ui.py [path/to/diora-android]
|
|
(default: ../diora-android next to this checkout)
|
|
|
|
Afterwards bump CACHE in static/js/sw.js so browsers fetch the new files.
|
|
"""
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
DEST = ROOT / 'static' / 'podcasts'
|
|
|
|
# Sections of native.css the podcast page needs: (start marker, end marker or None = to the end).
|
|
CSS_SECTIONS = [
|
|
('/* ---- bottom sheet', '/* ---- reader'),
|
|
('/* ---- podcasts (phones only', None),
|
|
]
|
|
|
|
|
|
def source_line(android, rel):
|
|
"""'diora-android <commit> <date>' of the file, plus a note if it has uncommitted changes."""
|
|
def git(*args):
|
|
return subprocess.run(['git', '-C', str(android), *args], capture_output=True, text=True).stdout.strip()
|
|
line = 'diora-android ' + (git('log', '-1', '--format=%h %cs', '--', rel) or 'unknown commit')
|
|
if git('status', '--short', '--', rel):
|
|
line += ' + uncommitted changes'
|
|
return line
|
|
|
|
|
|
def cut(text, start, end):
|
|
i = text.find(start)
|
|
if i < 0:
|
|
sys.exit(f'sync_podcast_ui: {start!r} not found in native.css')
|
|
j = text.find(end, i) if end else len(text)
|
|
if j < 0:
|
|
sys.exit(f'sync_podcast_ui: {end!r} not found after {start!r} in native.css')
|
|
return text[i:j].rstrip() + '\n'
|
|
|
|
|
|
def main():
|
|
android = Path(sys.argv[1]) if len(sys.argv) > 1 else ROOT.parent / 'diora-android'
|
|
static = android / 'web-native' / 'static'
|
|
if not (static / 'native-podcast.js').exists():
|
|
sys.exit(f'sync_podcast_ui: no diora-android checkout at {android}')
|
|
DEST.mkdir(parents=True, exist_ok=True)
|
|
|
|
js_src = source_line(android, 'web-native/static/native-podcast.js')
|
|
js = (static / 'native-podcast.js').read_text(encoding='utf-8')
|
|
(DEST / 'native-podcast.js').write_text(
|
|
f'// Copied from {js_src}: web-native/static/native-podcast.js\n'
|
|
'// by tools/sync_podcast_ui.py. Do not edit here: change it in diora-android\n'
|
|
'// and copy again. The browser host is static/js/podcasts-web.js.\n\n' + js,
|
|
encoding='utf-8', newline='\n')
|
|
|
|
css_src = source_line(android, 'web-native/static/native.css')
|
|
css = (static / 'native.css').read_text(encoding='utf-8')
|
|
parts = [cut(css, start, end) for start, end in CSS_SECTIONS]
|
|
(DEST / 'podcast-ui.css').write_text(
|
|
f'/* Copied from {css_src}: the podcast parts of web-native/static/native.css\n'
|
|
' (bottom sheet, podcasts) by tools/sync_podcast_ui.py. Do not edit here.\n'
|
|
' The web\'s own additions are in podcasts-web.css. */\n\n' + '\n'.join(parts),
|
|
encoding='utf-8', newline='\n')
|
|
|
|
print(f'native-podcast.js: {js_src}')
|
|
print(f'podcast-ui.css: {css_src}')
|
|
print('Now bump CACHE in static/js/sw.js.')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|