Commit graph

290 commits

Author SHA1 Message Date
1cb6584395 Buch-Metadaten: Änderung auf veraltetem Stand wird abgelehnt (409 mit dem aktuellen), das Web baut sie darauf neu auf
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
Eine App mit alter Bücherliste (Desktop während des langsamen Syncs) hat beim Öffnen fünf
MEW-Bände mit ihrem alten Stand überschrieben – Titel, Autor, Ordner weg. base_iv sagt dem
Server, von welchem Stand eine Änderung ausgeht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:03:49 +02:00
58b337d224 docs/podcasts.md: im Strom nach gehörten Folgen sortieren, Gehörte vor Ungehörten
Some checks failed
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 9m20s
Test / e2e (push) Failing after 1m21s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:49:37 +02:00
2a3b4b760b docs/podcasts.md: Plan für Strom, Merkliste, Wiedergabeliste und Abo-Stufen
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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:46:00 +02:00
f539158a19 Podcasts: „auf einmal“ heißt innerhalb einer Stunde – stündliche Nachrichten bleiben häufig
Some checks failed
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m23s
Test / e2e (push) Failing after 1m21s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:30:38 +02:00
2cb5dc4c04 Podcasts: alle Folgen an einem Tag (Archiv, Kurs) zählen als selten, nicht als täglich
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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:29:39 +02:00
ba3c6ff905 Podcasts: Folgen einer Kategorie (?folder=), wie oft ein Podcast erscheint (interval_days) für „Nach Zeitraum, seltene zuerst“
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Has been cancelled
- GET /podcasts/episodes/?folder=<name> ('' = ohne Ordner)
- /podcasts/state/: interval_days je Feed (mittlerer Abstand der neuesten 10 Folgen,
  eine Abfrage per Window, eine Stunde gemerkt)
- Podcast-Oberfläche aus diora-android bd98557 (Zeiträume, Ordner-Chips in „Folgen“)
- docs/library.md, sw v134

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:23:06 +02:00
86a6bb52d7 Buchdateien in eine eigene Tabelle (EBookFile): Änderungen an Titel, Ordner, gelesen schreiben nicht mehr megabyteweise die Datei mit
Some checks failed
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m25s
Test / e2e (push) Failing after 1m23s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:11:19 +02:00
e3d597a3c0 Nachrichten: Lesehilfen ohne Sprachmodell (feeds/textproc.py, docs/news-text.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
- Floskeln je Quelle (Spendenboxen u. ä.) verschwinden aus dem Artikel
- Überblick einer Meldung aus mehreren Quellen: Zusammenfassung (LexRank + MMR),
  was nur ein Bericht sagt, Wortwahl je Quelle, dieselbe Meldung in der anderen Sprache
  (GET /feeds/stories/<id>/overview/)
- Themen-Chips über den Nachrichten (topics auf der ersten Seite, ?ids= filtert)
- before= mit unkodiertem '+' gibt keinen 500 mehr
- sw v133

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:07:51 +02:00
c8e05bdb0a Bücherliste liest nie mehr an den Dateien vorbei: Datum, gelesen, Cover aus abdeckenden Indizes (37 s → schnell; die Desktop-App gab nach 10 s auf)
Some checks failed
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m15s
Test / e2e (push) Failing after 1m19s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:37:11 +02:00
b09a4625a4 SQLite im WAL-Modus, Transaktionen IMMEDIATE: Leser warten nicht mehr auf lange Schreibvorgänge (Feed-Abruf, große Uploads) – kein „database is locked“ mehr bei GET /books/
Some checks failed
Build and push Docker image / build (push) Successful in 16s
Test / e2e (push) Failing after 1m23s
Test / test (push) Successful in 9m15s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:04:37 +02:00
46e47df6d0 PDFs: nur Seiten nahe der Ansicht zeichnen (ferne wieder freigeben), sofort öffnen; Öffnen lässt sich abbrechen (Knopf, Schließen, anderes Buch)
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
Ein MEW-Band mit 1000 Seiten bereitete vorher jede Seite vor und zeichnete alle, bevor er sich
zeigte – Minuten und Gigabytes. e2e/pdf.spec.js mit einem 400-Seiten-PDF (e2e/make_pdf.py, pypdf).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:57:03 +02:00
7f9d6fc22a Bibliothek: Ausgaben – PDF und EPUB (oder zwei Übersetzungen) als ein Werk, in der Liste einmal mit ihren Formaten
Some checks failed
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m16s
Test / e2e (push) Failing after 2m42s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:27:14 +02:00
2327eb06d5 feeds: unfertige Änderungen aus f2583cb wieder heraus (versehentlich mit committet, liegen weiter im Arbeitsbaum)
All checks were successful
Build and push Docker image / build (push) Successful in 17s
Test / test (push) Successful in 9m28s
Test / e2e (push) Successful in 2m6s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:06:38 +02:00
f2583cbefd Generierte Cover: „blaue Bände“ für Werke von Marx und Engels, mit Buchrücken und Bandnummer
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>
2026-10-19 14:06:19 +02:00
e43facb620 docs/theme.md: Desktop-App lässt bei „Automatisch“ das System entscheiden (0.1.31)
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m8s
Test / e2e (push) Successful in 2m7s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:16:36 +02:00
a399374216 YouTube-Kanäle: zufällige 404 abfangen; „Automatisch“ in der Android-App
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m7s
Test / e2e (push) Successful in 2m10s
- YouTube antwortet auf Kanal-Feeds derzeit bei etwa zwei von drei Abrufen
  grundlos mit 404 (Kanäle zeigten „lädt nicht: HTTP 404“): ein YouTube-Feed
  wird bis zu 12-mal im Abstand von 0,25 s gefragt. Tests dazu.
- Erscheinungsbild „Automatisch“: in der Android-App folgt die WebView nicht
  dem System, sondern dem (dunklen) App-Theme – die Seite fragt dort
  DioraNative.systemScheme() und hört __dioraSystemScheme bei einem Wechsel.
sw.js: diora-v129.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 08:16:09 +02:00
3c7be76a93 Zeitschriften: Artikel richtig erkennen (GegenStandpunkt, PDF-Hefte)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m0s
Test / e2e (push) Successful in 2m0s
- EPUB: ein Artikel ist eine Datei; die Einträge danach in dieselbe Datei
  sind seine Abschnitte, gleich auf welcher Ebene (beim GegenStandpunkt
  stehen Zwischenüberschriften teils ganz oben). Unterzeile = die Schlagzeile
  unter dem Titel, nicht nummerierte Abschnitte.
- PDF: die meisten Hefte haben keine Lesezeichen – die Artikel kommen jetzt
  aus dem gedruckten Inhaltsverzeichnis (Jacobin, NLR, LuXemburg,
  manuskripte): Seitenzahl vorn oder hinten, Autor in eigener Spalte oder
  darunter („Von …“), Titel in Versalien über mehrere Zeilen, Rubriken; die
  gedruckten Seitenzahlen werden über die Titel auf die PDF-Seiten abgebildet.
- Index-Version 2: schon gebaute Indizes werden neu gebaut.
sw.js: diora-v128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:48:44 +02:00
ea7d62789f Zeitschriften: das Heft und seine Artikel
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m1s
Test / e2e (push) Successful in 2m1s
Das Heft bleibt das Dokument, der Artikel die Einheit, in der man sich
bewegt (docs/library.md):
- Artikel-Index auf dem Gerät aus dem Inhaltsverzeichnis des EPUB bzw. den
  Lesezeichen des PDF (Rubriken, Anreißer, Lesezeit), verschlüsselt im Meta.
- Stand pro Artikel (gelesen / übersprungen, wo man war), verschlüsselt im
  Meta, offline gepuffert.
- Bibliothek: Segmentbalken pro Heft, „7 von 23 gelesen“; ein Tipp öffnet den
  Heft-Inhalt mit Rubriken, Stand je Artikel, „Im Heft weiterlesen“, „Heft
  abschließen“.
- Reader: Kopfzeile „Artikel 8 von 23“, am Ende jedes Artikels eine Zäsur
  (gelesen, Weiter im Heft, Zum Inhalt, überspringen); bei PDF eine Leiste
  beim Weiterblättern. Durchgelesene Artikel zählen als gelesen, Sprünge nicht.
sw.js: diora-v127.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:14:28 +02:00
fa9dc073cb Hörbücher herunterladen (Android-App)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m8s
Test / e2e (push) Successful in 2m2s
In der Ansicht eines Hörbuchs „↓ Herunterladen“: alle Kapitel, die noch
fehlen, ab dem nächsten (mit Fortschritt „Lädt … 12/56“, danach „Auf dem
Gerät“); je Kapitel ein Download-Zeichen (laden, Fortschritt, erneut
versuchen, löschen) und im ⋮-Menü „Vom Gerät löschen“. Nur wo der Host
Downloads kann (DioraNative.podcastDownload); sw.js: diora-v126.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:16:39 +02:00
c52da00405 Bibliothek: größerer „Zuletzt gelesen“-Bereich
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 9m3s
Test / e2e (push) Successful in 2m9s
Das zuletzt gelesene Buch groß (Cover, Titel, Fortschritt, Seite, „vor 2
Stunden“, Knopf „Weiterlesen“), darunter die davor gelesenen in einer
Reihe mit Cover und Fortschritt. Breite Bildschirme größer, E-Ink in
Schwarz-Weiß; Fortschrittsbalken auf E-Ink hell mit schwarzem Anteil.
sw.js: diora-v125.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:08:03 +02:00
f1158e32a7 Generierte Cover: Ordner wählen das Motiv, neue Motive für Klassiker, Horror, Religion, Kinderbücher und Informatik
All checks were successful
Build and push Docker image / build (push) Successful in 18s
Test / test (push) Successful in 9m3s
Test / e2e (push) Successful in 2m29s
Kurze Stichwörter treffen nur noch am Wortanfang bzw. als ganzes Wort ("gen" nicht in
"Leiden", "war" nicht in "Gegenwart"), Ordnernamen werden nicht mehr nach Wörtern
durchsucht, sondern über FOLDER_THEMES einem Motiv zugeordnet. Mehr Varianten für
Philosophie, Psychoanalyse und Krimi; Großbuchstaben und lange Autorennamen laufen
nicht mehr über den Rand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:44:45 +02:00
caeb67e886 Mehrere Bücher: Fehlschläge werden erneut versucht (Server-Neustart, kurzer Abbruch), Knopf „erneut versuchen“; Bücher bis 100 MB
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m9s
Test / e2e (push) Successful in 2m31s
Ein Import aus der Cloud lief während eines Updates des Servers; alle Bücher
danach scheiterten in Sekunden. Jetzt bis zu drei weitere Versuche je Buch
(3, 8, 20 s), am Ende ein Knopf für die übrigen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:52:31 +02:00
f3b0080790 Serien für Bücher: erkannt, als Stapel, selbst zuweisen und verwalten
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 18s
Test / test (push) Has been cancelled
- Beim Hochladen liest diora die Serie aus dem E-Book (calibre:series und
  series_index, EPUB 3 belongs-to-collection mit group-position); vorhandene
  Bücher werden am Titel erkannt („Der Zauberberg. Erster Band“, „…: Teil 3“).
- In der Bibliothek ist eine Serie ab zwei Bänden ein Stapel („2 Bände · bei
  Band 1“), darin die Bände in Reihenfolge; beim Suchen und Filtern einzeln.
- ⋮ → „Serie …“: vorhandene oder neue Serie, Band-Nummer, oder „Keine Serie“.
  In der Serie: umbenennen, Reihenfolge, auflösen. Alles im verschlüsselten
  Meta (series, seriesIndex; '' = bewusst keine).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:47:18 +02:00
6d7fb4a849 Neue Navigations-Icons (Stil B), mehrere Bücher auf einmal, generiertes Cover pro Buch wählbar
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 9m6s
Test / e2e (push) Successful in 2m45s
- Icons: eigene SVGs, kräftig und geometrisch (2,4 px, eckige Enden), in
  nav.js für alle Leisten (DioraNav.icon, sections()/groups() .svg); der
  aktive Bereich gefüllt.
- Hochladen: mehrere Dateien auf einmal (Auswahl oder auf die Bibliothek
  ziehen) und aus der Cloud per Häkchen („Alle auswählen“, „n importieren“);
  nacheinander mit Fortschritt, ein schon vorhandenes Buch (Titel und Autor)
  wird übersprungen.
- Pro Buch: „Generiertes Cover verwenden“ statt des eigenen (im verschlüsselten
  Meta, cover: 'generated').

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:21:10 +02:00
4e4fac227c Podcast-UI aus diora-android 449118c (Ordner-Chips, ein Kopf je Bereich); E-Ink: Art-Abzeichen in Abos & Quellen lesbar
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 9m5s
Test / e2e (push) Successful in 2m50s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:06:41 +02:00
d870ed6f9d Blogs: Ordner verwalten und zuweisen wie überall; leere Bibliothek zeigt den Kopf mit +
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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:56:19 +02:00
8f5be379fe Bibliothek neu: Ordner als Filter-Chips überall, Cover-Raster, Cover verschlüsselt und generiert (noch nicht veröffentlicht)
- Ordner wie Tags (docs/library.md): folders.js zeichnet die Chip-Reihe, das
  Blatt „In Ordner …“ (Häkchen, Neuer Ordner) und „Ordner verwalten“
  (umbenennen = zusammenlegen, löschen, Reihenfolge). E-Books: `folders` im
  verschlüsselten Meta, Reihenfolge in verschlüsselten Bibliotheks-Einstellungen
  (/books/prefs/). Podcasts/Hörbücher: PodcastFeed.folders (Migration 0021,
  übernimmt `folder`), /podcasts/folders/ (+rename, +delete). Blogs: Reihenfolge
  (/feeds/folders/order/).
- Bibliothek (53-library.js): Kopf mit Suche, Sortierung, Raster/Liste und +;
  Chips Angefangen · Ungelesen · Gelesen · Ordner; eine „Weiterlesen“-Karte;
  Mehrfachauswahl (lange drücken). E-Ink und diora Reader beginnen als Liste.
- Cover Ende-zu-Ende verschlüsselt (covers.js, /books/<id>/cover/): aus dem
  E-Book (EPUB-Coverbild, PDF Seite 1), 300 px, mit dem Nutzerschlüssel
  verschlüsselt, einmal hochgeladen; sparsam im Leerlauf, nie beim Lesen, nie
  auf E-Ink.
- Bücher ohne Cover bekommen eins (gencover.js): Stichwörter aus Titel, Autor,
  Regal und Ordnern wählen ein Gestaltungskonzept (Konstruktivismus, Geometrie,
  Psyche, Wellen, Karte, Kosmos, Ornament, Botanik, Berge, Zellen, Raster,
  Schatten, Typo, sonst Bauhaus); ein Hash aus Titel und Autor Palette, Aufbau
  und Details – einzigartig, überall gleich, nichts gespeichert.
- Hörbücher: Ordner-Chips statt Kacheln, „In Ordner …“ mit mehreren Ordnern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:44:23 +02:00
d7930fcdb9 Bibliothek ordnen (Navigation Phase 3): Hörbuch-Reihen und -Ordner, Zeitschriften je Heft
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 8m58s
Test / e2e (push) Successful in 1m57s
- Hörbücher: Reihen werden aus den Titeln erkannt („Das Kapital – Erster
  Band“, „…: Teil 3“, „… – Folge 12“, „Der Zauberberg. Erster Band“) und als
  Stapel gezeigt, darin die Bände in Reihenfolge. Ordner je Hörbuch
  (PodcastFeed.folder, Migration 0020), im Buch über ⋮ → Ordner zuweisen.
- Zeitschriften: ein Heft wird als Zeitschrift markiert (⋮ → Als Zeitschrift
  führen, im verschlüsselten Meta); unmarkiert entscheidet weiter der Ordner
  „Zeitschriften“. Die Hefte stehen nach Zeitschrift gruppiert, neueste zuerst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:45:14 +02:00
143950df94 Abos & Quellen: alle Abos an einem Ort (Navigation Phase 2)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m58s
Test / e2e (push) Successful in 1m58s
Ein neuer Abschnitt (docs/sources.md, static/js/sources.js) für Podcasts,
YouTube-Kanäle, Hörbücher, Nachrichten und Blogs:
- ein Feld zum Hinzufügen: Adresse (Feed, Seite, YouTube) oder Name eines
  Podcasts; die Art ist wählbar (Podcast, Hörbuch, Nachrichten, Blog);
  /feeds/discover/ erkennt dafür Podcasts (Folgen mit Ton oder Video);
- eine Liste aller Abos mit Filtern (auch „Probleme“) und Suche;
- je Abo: Inhalt öffnen, Einstellungen (die vorhandenen Editoren), Art ändern,
  abbestellen; OPML-Import und -Export.
In der Seitenleiste unten, auf dem Telefon im App-Menü; ⚙ in den Feeds führt
hierher. Abschnitte, die beim Laden schon gezeigt werden, füllen sich jetzt
auch (nav.js zeigt sie nach dem Laden aller Skripte noch einmal).
Podcast-UI aus diora-android 50c6f9c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:23:12 +02:00
a48dca07ea Navigation: diora Reader zeigt die Lesen-Abschnitte in seiner Leiste; Podcast-UI aus diora-android 26f5019
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m59s
Test / e2e (push) Successful in 2m0s
Auf dem tolino stehen Bücher, Zeitschriften, Nachrichten, Blogs direkt in der
Leiste unten (html.nav-flat, keine Abschnittszeile: auf E-Ink nicht wischen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:53:38 +02:00
b21f59f4eb Home: Hörbücher als eigener Block, ihre Kapitel nicht unter Podcasts
Ein laufendes Kapitel steht mit „Kapitel i/n · <Buch>“ unter Hörbücher, sonst
das zuletzt gehörte Buch mit ▶ Weiterhören (audiobooks.js __dioraAudiobookGo).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:42:20 +02:00
838457f6f9 Navigation: Lesen und Hören (Phase 1, noch nicht veröffentlicht)
Die Bereiche nach dem, was man tut (docs/navigation.md): Home; Lesen mit
Bücher, Zeitschriften, Nachrichten, Blogs; Hören mit Hörbücher, Podcasts,
Radio, Ambient. static/js/nav.js ist die eine Definition für alle Plattformen
(DioraNav: Abschnitte, Gruppen, go, Hash, zuletzt gewählter Abschnitt je
Gruppe). Die Webseite zeichnet ihre Leiste daraus: breit alle Abschnitte unter
ihrer Gruppe, schmal Home · Lesen · Hören mit einer Abschnittszeile oben.

- Hörbücher haben ein eigenes Panel (#tab-audiobooks), nicht mehr über den E-Books.
- Zeitschriften: die Bücher im Ordner „Zeitschriften“ (oder „Magazine“).
- Nachrichten/Blogs wählt die Navigation; der eigene Umschalter verschwindet dann.
- Ein Link auf einen Abschnitt (#news …) schlägt die Startseite.

Die Apps zeichnen ihre Leiste (native-radio.js, diora-android) bald ebenfalls
daraus; bis dahin bleibt das hier unveröffentlicht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:31:58 +02:00
12b651b772 Hörbücher: Kapitel einzeln als (nicht) gehört, Reihenfolge nach Korrekturen
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 8m58s
Test / e2e (push) Successful in 1m54s
- Jedes Kapitel hat ✓/○ zum Umschalten. Ein bis zum Ende gehörtes, das wieder
  als nicht gehört gilt, beginnt von vorn (mark-played setzt die Stelle zurück).
- Feeds, die Titel, Datum oder Nummer schon bekannter Folgen korrigieren, werden
  übernommen: davon hängt die Kapitelreihenfolge ab (Das Kapital, Erster Band,
  hatte Daten aus einer älteren Fassung des Feeds). Ein Aktualisieren von Hand
  und das Markieren als Hörbuch lesen den Feed dafür ganz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:08:44 +02:00
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
a3673a6042 YouTube: Kanal eines Videos auch über externalChannelId finden
All checks were successful
Test / e2e (push) Successful in 1m53s
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m35s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:15:42 +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
1d6ddabb7b Podcast-Player: abgelaufene Download-Links überstehen
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m24s
Test / e2e (push) Successful in 1m48s
SoundCloud leitet die Feed-Adresse auf einen signierten Link um, der nach
zwei Minuten abläuft. Das Audio-Element fragt für jeden weiteren Teil der
Datei diesen Link an, wird abgewiesen (MEDIA_ERR_NETWORK) und blieb danach
kaputt, bis die App neu startete. Jetzt wird die Folge bei einem Fehler an
derselben Stelle neu geladen (bis zu dreimal pro Minute), und nach dem
Aufgeben beim nächsten Abspielen frisch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:28:37 +02:00
de1940b4e5 Stille überspringen: Regeln des Pausen-Kürzers, sanftere Übergänge
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m20s
Test / e2e (push) Successful in 1m53s
Der Server findet die Pausen jetzt nach den Regeln der App (PauseCutter):
10-ms-Fenster, Rauschboden als gleitendes Perzentil, ein Fünftel jeder Pause
bleibt (60–250 ms), halb davor, halb danach. Ältere Ergebnisse werden neu
berechnet (v: 2).

Der Player läuft durch diese Teile höchstens 4× schnell statt 8×: Chromium
schaltet darüber stumm, und weil currentTime in 10–20-ms-Schritten läuft,
landete der Wechsel zurück bei 8× bis zu 200 ms in der Sprache. Pro Pause
wird das Tempo gewählt, das am meisten spart und trotzdem rechtzeitig endet.
Das Tempo des Podcasts setzt die Rate während einer Pause nicht mehr zurück.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:18:16 +02:00
cac8027fb3 Stille überspringen (Browser/Desktop): Pausen schnell durchspielen statt springen; sw v109
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 8m15s
Test / e2e (push) Successful in 1m53s
Ein Sprung im gestreamten Podcast wartet aufs Netz (hörbares Haken). Jetzt
läuft eine Pause mit 4-facher Geschwindigkeit (höchstens 8x), je 0,12 s
bleiben an beiden Enden; nur Pausen über 3 s werden noch übersprungen.
Geprüft alle 40 ms statt mit timeupdate (alle 250 ms). Browser-Tab im
Hintergrund (gedrosselte Timer): weiter mit Sprüngen, sonst liefe Sprache
sekundenlang vierfach. Gemessen in der Desktop-App: Pausen 52,85–53,34 und
57,03–57,58 s schnell durchlaufen, kein Sprung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:01:57 +02:00
1c74e60224 Vorbereitete Bücher: Schlüssel enthält die Fußnoten-Erkennung der App-Schicht; sw v108
All checks were successful
Test / test (push) Successful in 8m18s
Build and push Docker image / build (push) Successful in 14s
Test / e2e (push) Successful in 2m0s
Änderungen an native-ui.js (diora-android) erneuern jetzt auch die im
IndexedDB gespeicherte Aufbereitung (window.__dioraPrepareSig).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:54:12 +02:00
a7d4d92f9e Reader: offene Notizleiste schiebt den Text nicht mehr aus der Mitte; sw v107
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m19s
Test / e2e (push) Successful in 1m52s
Die Leiste nimmt ihre Breite links weg; dieselbe Breite kommt rechts als
Abstand dazu, soweit Platz ist (die Spalte wird dafür nie schmaler). Beides
gleitet gleichzeitig, der Text bleibt stehen. Neu berechnet beim Öffnen und
Schließen der Leiste, bei Fenstergröße und Zeilenlänge/Schrift.

e2e: Test dafür (breit: Spalte bleibt, schmal: weicht aus, bleibt gleich
breit, liegt nicht unter der Leiste); Service Worker in den Tests aus (sein
Neuladen störte mitten im Test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:43:03 +02:00
656520fe8e Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
Some checks failed
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 8m23s
Test / e2e (push) Failing after 1m54s
32 klassische Skripte in der alten Reihenfolge (01-core … 99-init), ohne
Änderung am Code darin: geschnitten nur zwischen Anweisungen, je Datei
'use strict' wie vorher für die ganze Datei. Geprüft (acorn): kein Code, der
beim Laden läuft, braucht einen Namen aus einer späteren Datei. Globale
Funktionen und let/const bleiben global, die App-Schichten (native.js,
native-eink.js, …) umhüllen sie wie bisher. Template und sw.js-SHELL listen
die Dateien; diora-android build_web nimmt static/js rekursiv.

Getestet: 14 Browser-Tests (e2e), Desktop-App (Buch, Lesestand, Leiste im
Reader, Hell/Dunkel).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:30:43 +02:00
a16fcac388 Browser: beim Vorlesen bleibt die Playerleiste auch im Vollbild-Reader; sw v105
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:26:40 +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
fd8f20ba3a Notizleiste: ruckelfrei in langen Büchern; sw v104
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m19s
Mit offener Notizleiste kostete jeder Scroll-Schritt in Das Kapital (26.000
Blöcke, 8 Markierungen) 90–110 ms, jetzt rund 3 ms:
- resolveAnchorRange nimmt die zwischengespeicherte Blockliste (_epubBlocks)
  statt für jede Markierung alle Blöcke neu zu suchen.
- Die Position jeder Markierung im Buch wird gemerkt, bis sich das Layout
  ändert.
- Die Karten liegen auf einer Ebene in Buchkoordinaten; beim Scrollen wird
  nur diese verschoben. Gebaut und vermessen wird nur, wenn sich Markierungen
  oder Layout ändern, und dann alle Karten in einem Durchgang.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:15:58 +02:00
b8a68c63db Podcast-Oberfläche aus diora-android 6a02899 (Vorlesen in der Leiste, Zurück auf dem Podcast-Tab, Farbvariablen); sw v103
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 8m19s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:05:23 +02:00
33ca682709 Feeds und Podcast-Seite im Browser auf die Farbvariablen (docs/theme.md)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:05:16 +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
080cdbde5a Podcast-Oberfläche aus diora-android 5821dfa (__dioraPlayerNow für den Bildschirmschoner); sw v101
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m21s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:05:13 +02:00