Commit graph

6 commits

Author SHA1 Message Date
5be1b3fbaf Hörbücher: Podcasts als Hörbuch markieren und in „Bücher“ hören
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m52s
Test / e2e (push) Successful in 1m59s
Ein Abo lässt sich als Hörbuch (oder Hörspiel) markieren (PodcastFeed.kind).
Es verlässt dann die Podcast-Welt: keine „Neu“-Folgen, keine Warteschlangen-
Automatik, nicht in „Folgen“. In der Bibliothek steht es neben den E-Books
(static/js/audiobooks.js, eine Datei für Web, Desktop und Android):
„Weiterhören“, ein Fortschritt pro Buch, die Kapitel in Reihenfolge,
Lesezeichen mit Notiz, Schlummer bis Kapitelende.

Server: /podcasts/audiobooks/ (+<id>/), /podcasts/bookmarks/…, Migration 0019.
Player (podcasts-web.js): podcastPlayBook spielt die Kapitel nacheinander
außerhalb der Warteschlange; ⏭ markiert nicht als gehört. Vertrag:
docs/audiobooks.md. native-podcast.js aus diora-android 7b1d500.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 13:05:00 +02:00
3e843aea9f Abo umziehen: Feed-Adresse ändern, alles behalten
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Has been cancelled
POST /podcasts/feeds/<id>/move/ gibt einem Abo eine neue Adresse und
behält Einstellungen, Folgen, Stellen, Gespielt- und Favoriten-Markierungen
und die Warteschlange. Bei einer YouTube-Adresse werden Folgen, deren Datei
nach ihrem Video benannt ist (podsync-artige Server), zu diesem Video, damit
der Kanal-Feed sie wiederfindet statt sie doppelt anzulegen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:11:44 +02:00
cde90bed8e YouTube-Kanäle als Podcasts abonnieren
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m34s
Test / e2e (push) Successful in 1m52s
Eine YouTube-Adresse (Kanal, Playlist, Video, Feed) lässt sich wie ein
Podcast abonnieren und in der Suche einfügen. Der Server liest dafür nur
die Kanalseite (einmal) und danach den RSS-Feed des Kanals; Ton oder Video
holt er nie: Die Adresse einer Folge ist die Videoseite (watch?v=…), und
jede App sucht sich den reinen Audio-Stream selbst (docs/youtube.md).
Shorts bleiben draußen, Stille-Analyse und ID3-Kapitel gibt es für solche
Folgen nicht.

Der Player im Browser verweist auf die Apps; die Desktop-App fragt ihren
Hauptprozess (yt-dlp) nach dem Stream. Eine Dauer, die der Feed nicht hat,
meldet der Player mit dem Fortschritt (progress/save: duration_seconds).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:33:26 +02:00
ffcb6fba4f Refactoring Schritt 1: Browser-Tests für den Reader, in der CI; Plan in docs/refactoring.md
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Has been cancelled
- e2e/reader.spec.js: ein Test-EPUB (e2e/make_epub.py) hochladen, öffnen ohne
  zu senden, lesen und Lesestand nach Neuladen, Fußnote, Markierung und
  Notizleiste, Hell/Dunkel samt Reader, alle Tabs ohne Seitenfehler.
- e2e/env.js: E2E_PORT und E2E_PYTHON; nie einen laufenden Server
  wiederverwenden (dahinter läge eine echte Datenbank).
- CI: eigener Job e2e (Playwright + Chromium); blockiert den Docker-Build nicht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:25:06 +02:00
884a18e8ef Hell und Dunkel (docs/theme.md), Vorlese-Schnittstelle für die Playerleiste; sw v102
Some checks failed
Build and push Docker image / build (push) Successful in 19s
Test / test (push) Has been cancelled
- Farbvariablen für beide Schemata in app.css (--bg --fg --muted --card --panel
  --hover --raised --border --border-strong --accent --on-accent --scrim
  --shadow), Hell als html[data-theme=light]. Umschalter im Kopf jeder Seite
  (base.html, vor dem ersten Zeichnen): Dunkel / Hell / Automatisch, ☾☀◐ in der
  Navigation; __dioraTheme / __dioraSetTheme / Ereignis diora-theme.
- Reader: neues Standard-Theme "Wie die App" (Dunkel/Hell folgt der App).
- ◑ (Kontrast zum Hintergrundbild) nur noch mit Hintergrundbild.
- home.js auf die Variablen.
- window.__dioraTts (state/toggle/stop/next/prev) und Ereignis diora-tts für
  die Playerleiste; mit __dioraTtsDock keine eigene Vorlese-Leiste mehr.
- Reader-Hinweise über der Playerleiste, wenn sie im Reader steht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:02:33 +02:00
60dd4926cf Lesestand: die zuletzt gelesene Stelle gewinnt, nicht mehr die weiteste; sw v100
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m21s
docs/progress-sync.md ist der Vertrag für Server, Web, Android und Desktop.

- Server: read_at (Zeit, zu der dort gelesen wurde, Uhrfehler des Geräts per
  sent_at herausgerechnet, nie nach "jetzt"), Gerät, weiteste Stelle. Ältere
  Schreibvorgänge (offline nachgereicht, liegengelassener Tab) gewinnen nicht.
  Apps ohne read_at: nur strikt vorwärts. Antwort = Zustand nach dem Schreiben.
  /books/ mit X-Server-Now, /api/sync/ mit server_now.
- Web-Reader: Zeit einer Stelle ist der Moment, in dem man durch eigenes Tun
  hinkam (Scrollen, Blättern, Tasten, Vorlesen); unverändert Liegendes
  schickt nichts bzw. nur seine alte Zeit. Vor dem Wiederherstellen und
  während eines Blicks (Fußnote, "Weit gescrollt") wird nicht gespeichert.
  Eigene Stellen in einem Ausgang (localStorage) bis der Server sie hat.
  Angebote "Auf <Gerät> weitergelesen" und "Weiteste Stelle".
- Tests: books/tests.py (Reihenfolge, Uhrfehler, Zukunft, alte Apps, weiteste
  Stelle, Liste und Snapshot).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:31:36 +02:00