Commit graph

31 commits

Author SHA1 Message Date
marwin
7d99e58286 Bücher: Ordner (eine Ebene) + "Zuletzt gelesen"-Leiste (SW v36)
All checks were successful
Build and push Docker image / build (push) Successful in 22s
Test / test (push) Successful in 34s
Ordnername lebt im bereits verschlüsselten meta-Blob (wie Titel/Autor),
daher keine Schema-Änderung nötig — nur ein schlanker Endpoint zum
Aktualisieren von meta_ct/meta_iv ohne die Buchdaten neu hochzuladen.
Die Bücheransicht zeigt jetzt immer oben die letzten 7 gelesenen Titel
als Shortcut-Leiste, darunter Ordner-Kacheln (root) bzw. den Inhalt
eines geöffneten Ordners (kein Verschachteln).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011j4LcoeddwFt6Rw8Wyaknj
2026-08-17 10:58:53 +02:00
marwin
bb143a249b Reader: Toast-Optik repariert — Button-Font und doppelter Textschatten (SW v35)
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 15s
.reader-toast-btn hatte keine font-family gesetzt; Buttons erben das
anders als normaler Text nicht vom body, dadurch fiel "Zurückspringen"
auf die System-Schrift statt Courier New zurück.

.reader-toast/.reader-toast-action erbten außerdem den globalen
Halo-Textschatten (--outline), der eigentlich Text gegen wechselnde
Hintergründe absetzen soll. Die Toasts tauschen Vorder-/Hintergrund
aber bewusst (weiße Pille, schwarzer Text) und sitzen bereits auf
eigenem, blickdichtem Hintergrund — der geerbte Schatten hatte
dadurch exakt die Textfarbe und verdickte die Schrift nur unnötig,
statt einen Kontrast-Effekt zu erzielen. Jetzt wie die übrigen
Elemente mit eigenem farbigen Hintergrund (.btn-play etc.) explizit
mit text-shadow:none von diesem Effekt ausgenommen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 00:02:05 +02:00
marwin
5053d0036a Reader: j/k-Scrollen ohne Ramp-up, an feste Kadenz statt Display-Hz gekoppelt (SW v34)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 17s
Die requestAnimationFrame-Schleife aus dem letzten Fix lief mit der tatsächlichen
Bildwiederholrate des Displays statt einer festen Rate — auf Laptops mit
120/144/165Hz-Panels bedeutete das 2-3x mehr scrollBy-Aufrufe (und damit
Scroll-Listener-Durchläufe) pro Sekunde als beabsichtigt, was sich als Lag
statt als Beschleunigung äußerte. Zurück zu setInterval, aber mit fester
20ms-Kadenz unabhängig vom Display und dt-kompensierter, konstanter
Geschwindigkeit (~1200px/s, kein Ramp-up mehr).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 23:50:23 +02:00
marwin
e70bb881cc Reader: schnelleres j/k-Scrollen; Offline-Modus auf Desktop repariert (SW v33)
All checks were successful
Build and push Docker image / build (push) Successful in 50s
Test / test (push) Successful in 16s
j/k nutzte ein starres 8px/16ms-setInterval (~500px/s, unsauber getaktet
gegenüber dem Frame-Takt) — ersetzt durch eine requestAnimationFrame-Schleife
mit sanftem Ramp-up (700 -> 1800px/s über 300ms), das behebt sowohl die zu
niedrige Geschwindigkeit als auch das Ruckeln kurz nach Scrollbeginn.

Der Service Worker war unter /static/js/sw.js registriert, wodurch sein
Scope (mangels Service-Worker-Allowed-Header) automatisch auf /static/js/
beschränkt war statt die ganze App abzudecken — Navigationen zu z.B. /
liefen nie durch den fetch-Handler, weshalb offline nur die Browser-eigene
Fehlerseite statt der App-Shell erschien. Jetzt wird sw.js zusätzlich unter
der Root /sw.js ausgeliefert (diora/urls.py) und dort mit explizitem
scope:'/' registriert; alte Registrierungen mit dem falschen Scope werden
beim Laden automatisch entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 23:31:01 +02:00
marwin
d3c435dd59 Reader: Notizen auf Mobile schnell setzbar statt über Randspalte (SW v32)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 15s
Auf schmalen Screens saß der Marker-Modus-Button bisher nur in der 150px-
Randspalte — man musste sie erst öffnen (und damit den ohnehin knappen
Lesebereich verkleinern), um überhaupt markieren zu können. Jetzt zusätzlich
ein Marker-Button direkt im Haupt-Header (nur <=600px sichtbar, Desktop
bleibt bei der bisherigen Anordnung in der Notes-Leiste).

Im Marker-Modus legt ein einfacher Tap auf reinen Lesetext (ohne Auswahl)
jetzt direkt eine freie Notiz an der Wortposition an — man muss nicht mehr
den exakten Klick-Punkt in der Randspalte treffen. Das Bearbeiten der
Notiz läuft auf schmalen Viewports über ein neues Bottom-Sheet (volle
Breite) statt über das Inline-Textfeld in der 150px-Spalte, das auf dem
Handy-Keyboard unangenehm zu bedienen ist.

Notiz-Objekte werden jetzt erst bei tatsächlich eingegebenem Text angelegt
und gespeichert (vorher: sofort beim Setzen des Ankers) — verhindert, dass
ein abgebrochener/leerer Tap eine Ghost-Notiz in currentHighlights
hinterlässt. Gilt für alle Eingabewege (Bottom-Sheet UND die bestehende
Inline-Randspalten-Bearbeitung), per Playwright verifiziert inkl. Escape-
Cancel auf Desktop.

Priorität laut Nutzer: Notizen-Erfassung muss auf Mobile gut funktionieren;
dass bestehende Notizen dort weniger prominent sichtbar sind, ist explizit
in Ordnung — die vertiefte Auseinandersetzung mit Notizen bleibt eine
Desktop-Aufgabe.

Verifiziert per Playwright (390×844 mobil + 1280×900 Desktop-Regression):
Marker-Button-Sichtbarkeit, Bottom-Sheet-Flow (Erstellen/Abbrechen/Speichern,
kein Ghost-Eintrag), reale Text-Selektion + Highlight+Notiz weiterhin
funktionsfähig auf Mobile, Desktop-Workflow (Randspalte, Inline-Editor,
Escape-Cancel, Blur-Commit) unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 20:13:55 +02:00
marwin
76068f6ed8 Reader: Fußnoten-Popover erkennt jetzt mehr EPUB-Konventionen (SW v31)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 14s
Die Erkennung von Fußnoten-Links war auf class="footnote" + gleiche-Datei-
Anker (href startsWith '#') hartkodiert. Andere Editionen markieren Fußnoten
anders — z.B. die e-artnow-Ausgabe von Marx' "Das Kapital" (zeno.org-Konvertierung)
nutzt gar keine Klasse und verlinkt mit einem <sup> als Kind (statt Vorfahre)
des <a> auf eine ANDERE Kapiteldatei ("../Text/Karl0045.html#F537") — dadurch
griff weder die Klassen- noch die Hash-Prüfung, das Popover blieb tot.

_looksLikeFootnoteLink() erkennt jetzt zusätzlich epub:type="noteref" (EPUB3-
Standard), jede Klasse mit "note"/"footnote"/"fn" im Namen, und als Fallback
jeden Link mit Fragment-Anker, der irgendwo mit einem <sup> verschachtelt ist
(in beide Richtungen) — der in EPUBs praktisch universelle Marker für
Fußnotenziffern. Die Fragment-Extraktion nimmt jetzt alles nach dem letzten
'#' statt nur bei href.startsWith('#'), da das Buch als eine zusammenhängende
DOM gerendert wird und getElementById dateiübergreifend funktioniert.

Verifiziert per Playwright: Marx-Edition zeigt jetzt beim Hover 1326 erkannte
Fußnoten-Links mit korrektem Popover-Inhalt; Žižeks "Weniger als nichts"
(vorher funktionierend, class="footnote"-basiert) weiterhin unverändert
funktionsfähig — keine Regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 18:55:48 +02:00
marwin
42bc090a28 Reader: Marker-Farben mit color:inherit statt UA-Default-Schwarz (SW v30)
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 15s
mark-Elemente haben browserseitig einen UA-Default (color:black), der bislang
nicht überschrieben wurde — beim Markieren von Text im dunklen Standard-Theme
(weißer Fließtext) sprang die Markierung dadurch abrupt auf schwarzen Text.
Jetzt color:inherit, damit markierter Text immer die Farbe des umgebenden
Texts behält; die vier Hintergrundfarben sind dafür kräftiger/dunkler gewählt,
sodass sie in allen drei Themes (dunkel/weißer Text, Sepia, Hell) ausreichend
Kontrast zum inherited Text bieten (WCAG-Kontrastwerte 4.8:1–11.7:1, per
Playwright-Screenshot in allen drei Themes gegengeprüft).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 18:44:09 +02:00
marwin
b805d62b11 Books: Notizen-Sidebar auto-öffnen, Notizen-Download + Gelesen-Status in Übersicht (SW v29)
All checks were successful
Build and push Docker image / build (push) Successful in 17s
Test / test (push) Successful in 16s
- EBook.is_read (Migration) + neuer /books/<id>/read/-Endpoint zum Togglen
- book_list liefert is_read und has_highlights (Existenz einer Highlights-Zeile)
- Reader öffnet die Notizen-Sidebar automatisch, wenn das Buch bereits
  Markierungen/Notizen hat, statt sie hinter dem manuellen Toggle zu verstecken
- Buch-Übersicht: Download-Button für Notizen/Markierungen direkt aus der Liste
  (ohne den Reader zu öffnen), "Als gelesen markieren" mit Bestätigungsdialog,
  Filter "Gelesene Bücher anzeigen" (standardmäßig aus)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 18:10:33 +02:00
marwin
f9573d3d62 Reader: lange Notizen wurden im Rand zu früh ausgeblendet (SW v28)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
_repositionMarginMarkers() filterte Einträge anhand eines festen ±60px-
Fensters um den reinen Ankerpunkt, bevor die tatsächliche Kartenhöhe bekannt
war. Für Notizen mit mehr Text als eine "Standard"-Karte reichte das nicht:
die Karte hätte teilweise schon sichtbar sein müssen, obwohl ihr Anker noch
weiter außerhalb lag — sie blieb beim Scrollen also länger verschwunden als
erwartet.

Vorfilter jetzt großzügig (mind. 400px bzw. die Höhe des sichtbaren
Bereichs), danach ein zweiter Cull-Durchgang mit den tatsächlich gemessenen
Kartenhöhen nach dem Stapeln — dadurch werden nur Einträge entfernt, die
wirklich komplett außerhalb liegen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 14:09:02 +02:00
marwin
9648730be6 Reader: Prozentanzeige mit Nachkommastelle bei langen Büchern (SW v27)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Bei sehr langen Büchern (ab ca. 1 Mio. Zeichen, entspricht etwa 600-700
Druckseiten) bewegt sich die ganzzahlige Prozentanzeige beim Lesen kaum noch
— eine Nachkommastelle macht sie wieder aussagekräftig. Betrifft die
Fortschrittsanzeige im Reader-Header sowie die "≈X% im Buch"-Koordinate bei
Annotationen-Export und -Verzeichnis.

Formatierung über toLocaleString() (Komma bei de, Punkt bei en, etc.). Das
Fortschrittsfeld ist dafür von <input type="number"> auf type="text" mit
inputmode="decimal" umgestellt — number-Inputs erzwingen intern immer einen
Punkt, unabhängig von der Locale.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 13:51:05 +02:00
marwin
7bfce034ba Reader: Marker-Modus statt impliziter Auswahl, Notiz-Anker rein positional (SW v26)
All checks were successful
Build and push Docker image / build (push) Successful in 17s
Test / test (push) Successful in 16s
Vier vom Nutzer gemeldete Bugs behoben:

- Markierter Text war kaum lesbar: der globale weiße Text-Outline (fürs
  Hintergrundbild-Feature gedacht) kollidierte mit der Highlight-Farbe.
  Reader sitzt immer auf eigenem, opakem Hintergrund — Outline dort komplett
  deaktiviert.
- "Notiz zu Markierung hinzufügen" öffnete weiterhin die rechte Sidebar statt
  den Rand. Jeder Notiz-Eintragspunkt (Highlight+Notiz aus der Textauswahl,
  Edit-Note-Klick auf eine Markierung im Fließtext) läuft jetzt über
  _openMarginAndEditNote() — öffnet bei Bedarf den Rand und bearbeitet dort
  inline. openNoteEditor()/rechte Sidebar für Notizen komplett entfernt.
- Kernursache für "Notiz verschwindet, Markierung heftet sich an falsche
  Notiz": Anker basierten auf XPath mit Sibling-Index unter den Textknoten
  eines Blocks — jede weitere Markierung im selben Block (surroundContents
  spaltet Textknoten) verschob diese Indizes und korrumpierte lautlos ALLE
  anderen Anker im selben Block. Anker adressieren jetzt stattdessen
  Block-Index + Zeichen-Offset innerhalb des Blocks (wie das bestehende
  Lesefortschritt-Ankersystem) — Wrapping/Unwrapping durch andere
  Markierungen ändert weder Blockreihenfolge noch Zeichenanzahl, ist also
  erschütterungsfrei für andere Anker im selben Block.
- Löschen einer Markierung riss zuvor aus demselben Grund weiter unten
  liegende Notizen optisch mit raus (Daten blieben in der DB) — mit dem
  neuen Ankersystem behoben.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 13:28:19 +02:00
marwin
3f40a4078a Reader: Notiz-Eingabe direkt im Rand statt Sprung zur Sidebar (SW v25)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 14s
Notizen setzen/bearbeiten passiert jetzt inline an der Stelle im Notizen-Rand,
wo die Notiz auch angezeigt wird — kein Wechsel mehr zur rechten Sidebar.
Textfeld wird beim Öffnen automatisch fokussiert und ausgewählt. Enter
speichert, Escape verwirft die Änderung.

Stift-Button (Marker-Modus) zieht in die Titelzeile des Notizen-Rands um,
neben "Notes" — vorher musste man dafür ständig zur Hauptleiste zurück, die
im Immersive-Modus eingeklappt ist.

Nebenbei zwei Bugs beim Testen gefunden und behoben: ein Klick auf leere
Randfläche während ein Editor bereits offen war, legte durchs Blur-Event
gleichzeitig eine zweite, ungewollte Notiz an; und Escape im Notizfeld
bubbled zum globalen Escape-Handler durch, der dann den ganzen Reader
schloss (und damit die gerade bearbeiteten Highlights aus dem Speicher warf).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 11:23:16 +02:00
marwin
a2f4be8e1e Reader: Positions-Koordinate im Export + Verzeichnis für Markierungen/Notizen (SW v24)
Echte Buchseiten sind fürs Erste zurückgestellt (kein Konzept dafür bei
reflowable EPUB-Text) — stattdessen bekommt jeder Export-Eintrag jetzt eine
grobe Prozent-Koordinate ("≈37% im Buch"), zusätzlich zur Kapitelgruppierung.

Neu: ein Verzeichnis für Markierungen/Notizen im selben Sidebar-Stil wie die
Lesezeichen (Button in der Margin-Kopfzeile), das alle Einträge in
Lesereihenfolge mit Vorschau und Koordinate auflistet und per Klick an die
jeweilige Textstelle springt — anders als die Margin-Leiste, die nur zeigt,
was gerade sichtbar ist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 11:10:56 +02:00
marwin
bc180daab0 Reader: Marker-Modus statt impliziter Auswahl, Notiz-Anker rein positional (SW v23)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 14s
Drei Nachbesserungen am Annotationen-Feature nach Live-Test:

- Neuer Stift-Button (Marker-Modus) in der Kopfleiste: Textauswahl löst das
  Highlight-Popup nur noch aus, wenn der Modus aktiv ist — vorher war die
  Funktion unauffindbar (impliziter "einfach Text markieren"-Gestus ohne
  sichtbaren Einstiegspunkt) und hätte jede Textauswahl (auch zum Kopieren)
  gekapert.
- Freiform-Notizen bekommen keine Textdekoration mehr im Lesefluss — der
  Anker dient nur der Positionierung im Rand, nicht der optischen Markierung.
- Die Margin-Sidebar zeigt Notiztext jetzt direkt lesbar als kleine
  Post-it-Karte an der zugehörigen Stelle (mit Stapel-Logik gegen
  Überlappung), statt nur ein abstraktes Symbol zum Anklicken. Reine
  Highlights ohne Notiz bleiben ein kleiner Farbpunkt.
- Highlight-Popover/Tooltip klammern ihre Position jetzt hart an den
  Viewport, damit eine Auswahl nahe Seitenrand nicht unsichtbar außerhalb
  des sichtbaren Bereichs landet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 10:49:30 +02:00
marwin
090aec9c60 Reader: Annotationen — Marker, freie Notizen, Margin-Sidebar, Export (SW v22)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Textauswahl→Highlight-Popover war implementiert, aber nie verdrahtet (kein
mouseup/touchend-Listener) — als Voraussetzung mit behoben. Neu: freiformige
Notizen ohne Textmarkierung, verankert per Klick in einer neuen linken
Margin-Sidebar (Notiz am ersten Wort der Zeile auf Klickhöhe); Sidebar zeigt
Marker für alle Highlights/Notizen im sichtbaren Bereich und schiebt den
Lesetext nach rechts. Export sammelt alle Markierungen/Notizen eines Buchs in
Lesereihenfolge, nach Kapitel gruppiert, als Textdatei. EPUB-only — PDFs haben
noch keinen Text-Layer (siehe Issue #10).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 10:17:01 +02:00
marwin
17e205b6f0 Reader/UI: mehrere Fixes + Playwright-Setup (SW v21)
All checks were successful
Build and push Docker image / build (push) Successful in 55s
Test / test (push) Successful in 15s
- Books: Reader sprang beim Scroll+sofortigem Tap auf die alte Position
  zurück (Anker-Tracking lief nur alle 2s über den Save-Debounce, jetzt
  eigener 150ms-Tracker unabhängig davon)
- Books: +/- Buttons neben den Reader-Slidern (Font/Zeilenhöhe/Breite)
- Books: Sicherheitsnetz-Toast bei plötzlichen großen Scroll-Sprüngen
  (Fling, aus Versehen 'G' gedrückt) mit Zurückspringen-Option; bewusste
  Sprünge (TOC, Lesezeichen, Fortschritts-Eingabe, Suche) lösen ihn nicht aus
- Radio: Donation-Hinweis kam bei vielen Lieblingssendern gefühlt ständig —
  jetzt zusätzlich auf ~1-von-10 Plays gedrosselt
- UI: farbige Emoji-Icons (🔍📻💡 etc.) durch monochrome Unicode-Symbole
  ersetzt, die nicht mehr je nach OS/Browser-Font unterschiedlich aussehen;
  Lesezeichen-Icon war zudem fast identisch zum TOC-Icon
- UI: native alert()/confirm()/prompt() durch eigenes Modal-System ersetzt
- UI: Hash-basiertes URL-Routing für Tabs (#radio/saved, #podcasts/feeds, …)
  — Browser-Zurück/Vor und Deep-Links funktionieren jetzt
- Tests: Playwright e2e-Setup gegen isolierte Test-DB (DIORA_DB_NAME),
  Smoke- und Auth-Specs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 09:01:52 +02:00
marwin
daffd0002b Books: Fortschritt-Konflikt via Anker-Blockindex statt scroll_fraction (SW v15)
All checks were successful
Build and push Docker image / build (push) Successful in 1m1s
Test / test (push) Successful in 15s
Die max()-Semantik aus v14 verglich nur die grobe scroll_fraction. Da
scroll_fraction und position_anchor gemeinsam, aber entkoppelt gespeichert
werden, konnte ein einzelner Save mit transient zu hoher fraction (z.B.
instabiles Layout beim Laden) die Position dauerhaft einfrieren: jeder
spätere echte Fortschritt hatte eine kleinere fraction und wurde inklusive
Anker verworfen — der Leser landete immer wieder an derselben Stelle.

Fix: Vergleich läuft jetzt über den Blockindex im Anker (die Größe, die
auch die Sprungposition bestimmt), mit innerFraction als Tiebreaker.
scroll_fraction dient nur noch als Fallback für PDFs ohne Anker. Server
(_progress_is_further) und Client (_cmpProgress) nutzen identische Logik;
loadBookList-Push und lokaler Cache ebenfalls. Bestehende eingefrorene
Einträge entfrieren sich beim ersten Weiterlesen selbst.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 20:52:27 +02:00
marwin
29f6cc4413 Books: Fortschritt-Konflikt via max() lösen — weiter = gewinnt (SW v14)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Der am weitesten gelesene Wert hat immer Vorrang:
- Server: scroll_fraction = max(neu, aktuell) — ein afk-Fenster bei 10%
  kann nicht mehr 80% überschreiben
- Client loadBookList: wenn lokaler Fortschritt > Server, wird gepusht
  und für die Anzeige verwendet (deckt Offline-Lesen ab)
- Pending-Flag-Logik entfernt — nicht mehr nötig dank max-Semantik
- saveReaderProgress(force=true): neuer force-Parameter schreibt
  Position unabhängig vom gespeicherten Maximum; Button ⚑ im
  Reader-Header für den Ausnahmefall "zurück-zum-Anfang"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 15:41:35 +02:00
marwin
28756ffdc2 Books: Fortschritt-Sync robuster — Pending-Flag statt Timestamp (SW v13)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 18s
Timestamp-Vergleich in _saveBookMeta entfernt: client-seitige
ISO-Strings (new Date().toISOString) lagen fast immer leicht vor dem
Serverwert und haben dadurch regelmässig korrekten Online-Fortschritt
überschrieben.

Neu: explizites Pending-Flag (localStorage diora_pending_progress) —
gesetzt wenn saveReaderProgress offline scheitert, gelöscht nach
erfolgreicher Synchronisierung.

- _saveBookMeta nutzt das Flag statt Zeitstempel: Server-Daten
  überschreiben lokalen Fortschritt nur wenn kein Pending-Flag gesetzt
- _syncPendingProgress: pusht ausstehenden Fortschritt beim
  online-Event bevor loadBookList läuft
- saveReaderProgress setzt das Flag nur wenn !navigator.onLine

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 15:29:38 +02:00
marwin
b097eea600 Books: offline-Fortschritt wird nicht überschrieben (SW v12)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 16s
- _saveBookMeta vergleicht local vs. Server last_read — neuere lokale
  Daten (offline gelesen) überleben den nächsten Server-Abruf
- loadBookList pusht beim Online-Werden automatisch lokal neueren
  Fortschritt an den Server bevor die Liste gerendert wird
- saveBookmarks/saveHighlights markieren fehlgeschlagene Saves als
  pending sync (localStorage); beim nächsten online-Event werden alle
  pending Annotationen zuerst gepusht, dann erst die Buchliste geladen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 07:22:32 +02:00
marwin
5d69edc57e Layout: Tab-Leiste position:fixed + padding-top korrekt (SW v11)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 16s
Statt padding-top gegen die Navbar zu kämpfen ist #tabs jetzt
position:fixed direkt unterhalb der Navbar (top:var(--nav-h),
z-index:150). Damit ist die Leiste garantiert immer sichtbar,
unabhängig vom Scroll-Zustand oder Offline-Status.

main-content padding-top auf calc(var(--nav-h)+3rem) erhöht um
Platz für Navbar+Tabs zu schaffen. Offline-Banner vereinfacht zu
einer body-Klasse (kein fixed DOM-Element mehr).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 00:34:53 +02:00
marwin
d7a27b188d Layout + SW: Tab-Leiste sichtbar + kein veralteter Cache
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 15s
- main-content padding-top auf calc(var(--nav-h) + 0.75rem) erhöht
  damit die Tab-Leiste (Radio/Focus/Podcasts/Books) sicher unterhalb
  der fixed Navbar liegt — auf Desktop und Mobile
- SW v10: sendet SW_ACTIVATED an alle offenen Tabs wenn ein neuer SW
  übernimmt; app.js lädt daraufhin neu (außer wenn ein Buch geöffnet
  ist) — verhindert dass der Browser eine uralte HTTP-gecachte Version
  ausliefert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 00:19:00 +02:00
marwin
a96591c63f SW: cache navigation response offline (v9)
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 14s
Ohne diesen Fix schlägt das Öffnen der App im Flugzeug fehl, weil der
Service Worker die HTML-Seite (/) nicht cached — der Browser zeigt
dann eine Netzwerkfehler-Seite bevor JS überhaupt startet.

Strategie: Network-first für Navigationsanfragen, bei Netzwerkfehler
die zuletzt gecachte Version ausliefern. Nach dem ersten Online-Besuch
funktioniert die App vollständig offline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 23:58:07 +02:00
marwin
3d25519367 PWA: fix icon purpose entries + bump SW cache to v8
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 17s
Chrome 98+ hat Probleme mit kombinierten purpose-Werten ("any maskable")
auf einem einzelnen Icon-Eintrag. Separate Einträge für "any" und
"maskable" sind zuverlässiger und entsprechen der Spec-Empfehlung.
SW-Version auf v8 erhöht, um nach den JS-Änderungen einen sauberen
Cache-Neustart zu erzwingen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 23:49:32 +02:00
Marwin Schulz
b0ce463cca Debug books: show visible status at each load stage, bump SW to v7
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 15s
Each step in loadBookList now updates the visible UI so the exact
failure point is obvious without opening DevTools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:28:00 +01:00
Marwin Schulz
96a21f5482 Bump SW cache to v6 to force re-cache updated app.js/app.css
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 17s
Previous changes (renderBookList keyOk warning, openBook overlay fix)
were being served from the stale v5 cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 11:49:23 +01:00
marwin
824b77a033 Add gPodder sync API and bump SW cache to v5
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 17s
- Implement gPodder API v2 compatible endpoints at /api/2/:
  - Auth: login/logout via HTTP Basic Auth or session
  - Devices: list and register sync devices
  - Subscriptions: get/add/remove per device, delta sync with ?since=
  - Episode actions: upload play/position events, syncs to EpisodeProgress
- Server URL for AntennaPod: https://diora.creamfresh.xyz/api/2/
- Bump SW cache diora-v4 → v5 to force re-fetch of updated app.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 06:36:41 +01:00
marwin
500b3fa780 Fix SW: only cache static assets, not API/HTML responses
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Caching /books/ caused stale empty list after upload. Caching / caused
stale window.USER_ID after session changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:05:50 +01:00
marwin
b234f74115 Bump SW cache to v3 to invalidate stale cached app.js and HTML
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 15s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:42:40 +01:00
Marwin Schulz
2bd83f6315 Add podcast feature with feed management, Docker cron, and ebook reader assets
All checks were successful
Build and push Docker image / build (push) Successful in 12s
Test / test (push) Successful in 13s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:39:59 +01:00
marwin
8c3eec4ca1 Initial commit 2026-03-16 19:19:22 +01:00