Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Reader Settings
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
// Typography defaults. Phones keep the long-standing ones; a wide screen
|
|
|
|
|
|
// (desktop browser, diora desktop) starts bigger and wider.
|
|
|
|
|
|
const _READER_TYPE_DEFAULTS_NARROW = { fontSize: 16, lineHeight: 1.8, maxWidth: 65, fontWeight: null };
|
|
|
|
|
|
const _READER_TYPE_DEFAULTS_WIDE = { fontSize: 20, lineHeight: 1.6, maxWidth: 90, fontWeight: 375 };
|
|
|
|
|
|
const _READER_WIDTH_MAX = 140; // ch, the width slider's upper end ("Full" stays separate)
|
|
|
|
|
|
|
|
|
|
|
|
function _readerTypeDefaults() {
|
|
|
|
|
|
return window.matchMedia('(min-width: 900px)').matches
|
|
|
|
|
|
? _READER_TYPE_DEFAULTS_WIDE : _READER_TYPE_DEFAULTS_NARROW;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Nachrichten und Blogs im Buch-Reader, Doppelklick für Vollbild, Hörbücher wie die Bücher-Bibliothek
65-article.js (DioraArticle): Artikel öffnen im selben Reader wie Bücher – Schrift, Farben,
Seiten/Doppelseite mit Fußnoten am Seitenfuß, Suche, Vorlesen, Vollbild. Lesezeichen,
Markierungen und Notizspalte bleiben Büchern vorbehalten. Merken, Projekt und Original
stehen in der Kopfzeile (Apps: im Lesemenü). feeds.js gibt sein eigenes Overlay auf;
Fortschritt wie bisher (bis zum unteren Bildschirmrand gelesen, ab 90 % gelesen).
Einstellungen der Artikel gelten für alle Artikel zusammen.
62-reader.js: Doppelklick (Maus) auf den Text schaltet Vollbild an/aus, die Leisten gehen mit.
audiobooks.js: die Hörbücher sind gebaut wie die Bücher – Kopf mit Suche, Sortierung und +,
Chips Angefangen/Ungehört/Gehört und Ordner, „Weiterhören“ wie „Weiterlesen“, Kacheln aus
denselben Bausteinen (53-library.js gibt seine Styles auch an #audiobook-shelf), Cover quadratisch.
63-pages.js: bei nur einem Kapitel zeigt die Fußzeile nur die Seiten.
sw CACHE v158
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 20:15:00 +01:00
|
|
|
|
// Where the settings shown are kept: the book's id, or 'article' (all articles, 65-article.js).
|
|
|
|
|
|
let _readerSettingsKey = null;
|
|
|
|
|
|
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
function loadReaderSettings(bookId) {
|
Nachrichten und Blogs im Buch-Reader, Doppelklick für Vollbild, Hörbücher wie die Bücher-Bibliothek
65-article.js (DioraArticle): Artikel öffnen im selben Reader wie Bücher – Schrift, Farben,
Seiten/Doppelseite mit Fußnoten am Seitenfuß, Suche, Vorlesen, Vollbild. Lesezeichen,
Markierungen und Notizspalte bleiben Büchern vorbehalten. Merken, Projekt und Original
stehen in der Kopfzeile (Apps: im Lesemenü). feeds.js gibt sein eigenes Overlay auf;
Fortschritt wie bisher (bis zum unteren Bildschirmrand gelesen, ab 90 % gelesen).
Einstellungen der Artikel gelten für alle Artikel zusammen.
62-reader.js: Doppelklick (Maus) auf den Text schaltet Vollbild an/aus, die Leisten gehen mit.
audiobooks.js: die Hörbücher sind gebaut wie die Bücher – Kopf mit Suche, Sortierung und +,
Chips Angefangen/Ungehört/Gehört und Ordner, „Weiterhören“ wie „Weiterlesen“, Kacheln aus
denselben Bausteinen (53-library.js gibt seine Styles auch an #audiobook-shelf), Cover quadratisch.
63-pages.js: bei nur einem Kapitel zeigt die Fußzeile nur die Seiten.
sw CACHE v158
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 20:15:00 +01:00
|
|
|
|
_readerSettingsKey = bookId;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
// Reset to defaults, then apply per-book overrides
|
|
|
|
|
|
Object.assign(readerSettings, { theme: 'app', fontFamily: 'serif', noBold: false,
|
PDF: öffnet an der gespeicherten Seite, Leserfarben, Seitenzahlen wie im Buch (sw CACHE v166)
Der Lesestand wird gleich beim Öffnen erfragt (parallel zur Datei), ein PDF zeichnet zuerst
die Seite, an der es weitergeht, statt Seite 1; Titel, Inhaltsverzeichnis und Seitenzahlen
kommen nebenher und halten das Öffnen nicht mehr auf. Eine Zeichnung, die schon läuft, wird
abgewartet statt neu begonnen.
„Leserfarben“ (neben Originalfarben und Invertieren): die Seite in den Farben des Lesers
(Dunkel, Sepia) per SVG-Filter, Bilder darüber wie gedruckt (ihre Lage aus den
Zeichenbefehlen); ein Bild, das die halbe Seite füllt, ist ein Scan und wird mit umgefärbt.
pdf.js' eigene pageColors färben die Bilder mit um. Ein anderes Design ändert nur die Farben
des Filters.
Seitenzahlen des Buchs (PageLabels: „iv“, „A-3“) im Kopf mit der Seite der Datei daneben,
eingeben lässt sich beides; Lesezeichen und der Zurück-Knopf nennen sie. Das Test-PDF hat
dafür Seitenzahlen und ein farbiges Bild bekommen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:42:26 +01:00
|
|
|
|
pdfZoom: 100, pdfInverted: false, pdfPageColors: false, pdfPaginated: false, pdfSpread: false },
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
_readerTypeDefaults());
|
|
|
|
|
|
try {
|
|
|
|
|
|
const saved = JSON.parse(localStorage.getItem(`diora_reader_settings_${bookId}`) || '{}');
|
|
|
|
|
|
// Settings saved before v2 hold every value, changed or not. A value equal
|
|
|
|
|
|
// to the old default was never chosen, so it gives way to today's default.
|
|
|
|
|
|
if (!saved.v) {
|
|
|
|
|
|
for (const [key, old] of Object.entries(_READER_TYPE_DEFAULTS_NARROW)) {
|
|
|
|
|
|
if (saved[key] === old) delete saved[key];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Before v3 the reader's theme was always stored, "dark" by default: that now means "Wie die App".
|
|
|
|
|
|
if ((saved.v || 0) < 3 && saved.theme === 'dark') delete saved.theme;
|
|
|
|
|
|
delete saved.v;
|
|
|
|
|
|
Object.assign(readerSettings, saved);
|
|
|
|
|
|
if (saved.pdfPaginated === undefined) {
|
|
|
|
|
|
readerSettings.pdfPaginated = window.innerWidth < 768;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function saveReaderSettings() {
|
Nachrichten und Blogs im Buch-Reader, Doppelklick für Vollbild, Hörbücher wie die Bücher-Bibliothek
65-article.js (DioraArticle): Artikel öffnen im selben Reader wie Bücher – Schrift, Farben,
Seiten/Doppelseite mit Fußnoten am Seitenfuß, Suche, Vorlesen, Vollbild. Lesezeichen,
Markierungen und Notizspalte bleiben Büchern vorbehalten. Merken, Projekt und Original
stehen in der Kopfzeile (Apps: im Lesemenü). feeds.js gibt sein eigenes Overlay auf;
Fortschritt wie bisher (bis zum unteren Bildschirmrand gelesen, ab 90 % gelesen).
Einstellungen der Artikel gelten für alle Artikel zusammen.
62-reader.js: Doppelklick (Maus) auf den Text schaltet Vollbild an/aus, die Leisten gehen mit.
audiobooks.js: die Hörbücher sind gebaut wie die Bücher – Kopf mit Suche, Sortierung und +,
Chips Angefangen/Ungehört/Gehört und Ordner, „Weiterhören“ wie „Weiterlesen“, Kacheln aus
denselben Bausteinen (53-library.js gibt seine Styles auch an #audiobook-shelf), Cover quadratisch.
63-pages.js: bei nur einem Kapitel zeigt die Fußzeile nur die Seiten.
sw CACHE v158
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 20:15:00 +01:00
|
|
|
|
const key = currentBookId || _readerSettingsKey;
|
|
|
|
|
|
if (key) {
|
|
|
|
|
|
localStorage.setItem(`diora_reader_settings_${key}`, JSON.stringify({ ...readerSettings, v: 3 }));
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function applyReaderSettings(isPdf) {
|
|
|
|
|
|
const overlay = $('reader-overlay');
|
|
|
|
|
|
const contentEl = $('reader-content');
|
|
|
|
|
|
if (!overlay || !contentEl) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPdf) {
|
|
|
|
|
|
contentEl.style.fontSize = readerSettings.fontSize + 'px';
|
|
|
|
|
|
contentEl.style.lineHeight = readerSettings.lineHeight;
|
|
|
|
|
|
contentEl.style.setProperty('--reader-max-width', readerSettings.maxWidth + 'ch');
|
|
|
|
|
|
const fontMap = {
|
|
|
|
|
|
serif: "'Source Serif 4', Georgia, 'Times New Roman', serif",
|
|
|
|
|
|
sans: 'system-ui, -apple-system, sans-serif',
|
|
|
|
|
|
humanist: 'Verdana, Geneva, sans-serif',
|
|
|
|
|
|
mono: "'Courier New', monospace",
|
|
|
|
|
|
};
|
|
|
|
|
|
contentEl.style.fontFamily = fontMap[readerSettings.fontFamily] || fontMap.serif;
|
|
|
|
|
|
contentEl.classList.toggle('reader-no-bold', !!readerSettings.noBold);
|
|
|
|
|
|
// Weight: null keeps the stylesheet's. --reader-weight lets old WebViews
|
|
|
|
|
|
// without variable-font support (which drop weights like 425) pick a
|
|
|
|
|
|
// static cut instead.
|
|
|
|
|
|
contentEl.style.fontWeight = '';
|
|
|
|
|
|
if (readerSettings.fontWeight) {
|
|
|
|
|
|
contentEl.style.fontWeight = String(readerSettings.fontWeight);
|
|
|
|
|
|
contentEl.style.setProperty('--reader-weight', String(readerSettings.fontWeight));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
contentEl.style.removeProperty('--reader-weight');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_currentPositionAnchor && currentBookId) {
|
|
|
|
|
|
_suppressScrollJumpDetect();
|
|
|
|
|
|
requestAnimationFrame(() => restoreFromAnchor($('reader-content'), _currentPositionAnchor));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Theme
|
|
|
|
|
|
overlay.classList.remove('reader-theme-sepia', 'reader-theme-bright');
|
|
|
|
|
|
const readerTheme = readerSettings.theme === 'app'
|
|
|
|
|
|
? (document.documentElement.getAttribute('data-theme') === 'light' ? 'bright' : 'dark')
|
|
|
|
|
|
: readerSettings.theme;
|
|
|
|
|
|
if (readerTheme === 'sepia') overlay.classList.add('reader-theme-sepia');
|
|
|
|
|
|
else if (readerTheme === 'bright') overlay.classList.add('reader-theme-bright');
|
|
|
|
|
|
|
|
|
|
|
|
// PDF invert
|
|
|
|
|
|
if (isPdf && readerSettings.pdfInverted) overlay.classList.add('pdf-inverted');
|
|
|
|
|
|
else overlay.classList.remove('pdf-inverted');
|
PDF: öffnet an der gespeicherten Seite, Leserfarben, Seitenzahlen wie im Buch (sw CACHE v166)
Der Lesestand wird gleich beim Öffnen erfragt (parallel zur Datei), ein PDF zeichnet zuerst
die Seite, an der es weitergeht, statt Seite 1; Titel, Inhaltsverzeichnis und Seitenzahlen
kommen nebenher und halten das Öffnen nicht mehr auf. Eine Zeichnung, die schon läuft, wird
abgewartet statt neu begonnen.
„Leserfarben“ (neben Originalfarben und Invertieren): die Seite in den Farben des Lesers
(Dunkel, Sepia) per SVG-Filter, Bilder darüber wie gedruckt (ihre Lage aus den
Zeichenbefehlen); ein Bild, das die halbe Seite füllt, ist ein Scan und wird mit umgefärbt.
pdf.js' eigene pageColors färben die Bilder mit um. Ein anderes Design ändert nur die Farben
des Filters.
Seitenzahlen des Buchs (PageLabels: „iv“, „A-3“) im Kopf mit der Seite der Datei daneben,
eingeben lässt sich beides; Lesezeichen und der Zurück-Knopf nennen sie. Das Test-PDF hat
dafür Seitenzahlen und ein farbiges Bild bekommen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:42:26 +01:00
|
|
|
|
// Leserfarben: another theme changes the filter's colours; switching it on or off draws
|
|
|
|
|
|
// the pages anew (with or without their pictures laid over them).
|
|
|
|
|
|
if (isPdf && currentPdfDoc) {
|
|
|
|
|
|
_pdfColorFilter();
|
|
|
|
|
|
if (_pdfView && _pdfView.colorsKey !== _pdfColorsKey()) reRenderPdf();
|
|
|
|
|
|
}
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
|
|
|
|
|
|
// Annotations (marker mode + margin panel) are EPUB-only for now — PDFs have no text layer yet
|
|
|
|
|
|
const marginBtn = $('reader-margin-btn');
|
|
|
|
|
|
if (marginBtn) marginBtn.style.display = isPdf ? 'none' : '';
|
|
|
|
|
|
if (isPdf && readerAnnotationsMarginOpen) toggleAnnotationsMargin();
|
|
|
|
|
|
document.querySelectorAll('.marker-mode-btn').forEach(b => { b.style.display = isPdf ? 'none' : ''; });
|
|
|
|
|
|
if (isPdf && markerModeActive) toggleMarkerMode();
|
2026-10-14 19:43:03 +02:00
|
|
|
|
// Line length or font changed: the column's place next to an open margin too.
|
|
|
|
|
|
if (readerAnnotationsMarginOpen) _centerReaderColumn();
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Font weight slider: the variable Source Serif 4 takes any weight, the
|
|
|
|
|
|
// system fonts only their fixed cuts (multiples of 100).
|
|
|
|
|
|
function _readerWeightStep() {
|
|
|
|
|
|
return readerSettings.fontFamily === 'serif' ? 25 : 100;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _readerWeight() {
|
|
|
|
|
|
const step = _readerWeightStep();
|
|
|
|
|
|
const w = readerSettings.fontWeight
|
|
|
|
|
|
|| parseInt(getComputedStyle($('reader-content')).fontWeight, 10) || 400;
|
|
|
|
|
|
return Math.round(w / step) * step;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
|
// "Scrollen | Seiten" and, in pages, whether the notes stand at the page's foot
|
|
|
|
|
|
// and whether two pages lie side by side.
|
|
|
|
|
|
// The apps' e-reader mode always reads in pages: no choice there.
|
|
|
|
|
|
function _readerModeButtons() {
|
|
|
|
|
|
if (!window.DioraPages || DioraPages.isForced()) return '';
|
|
|
|
|
|
const pages = DioraPages.isOn();
|
|
|
|
|
|
return `
|
|
|
|
|
|
<button class="btn btn-sm ${pages ? '' : 'active'}" data-rs-mode="scroll">Scrollen</button>
|
|
|
|
|
|
<button class="btn btn-sm ${pages ? 'active' : ''}" data-rs-mode="pages">Seiten</button>
|
|
|
|
|
|
<button class="btn btn-sm ${DioraPages.pageNotes() ? 'active' : ''}" id="rs-page-notes" style="${pages ? '' : 'display:none'}"
|
|
|
|
|
|
title="Die Fußnoten stehen unten auf der Seite, auf der auf sie verwiesen wird">Fußnoten unten</button>
|
|
|
|
|
|
<button class="btn btn-sm ${DioraPages.spread() ? 'active' : ''}" id="rs-page-spread" style="${pages ? '' : 'display:none'}"
|
|
|
|
|
|
title="Zwei Seiten nebeneinander wie ein aufgeschlagenes Buch — ab einer Breite von 900 Pixeln">Doppelseite</button>`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
function toggleSettingsPanel() {
|
|
|
|
|
|
const overlay = $('reader-overlay');
|
|
|
|
|
|
const contentEl = $('reader-content');
|
|
|
|
|
|
if (!overlay || !contentEl) return;
|
|
|
|
|
|
|
|
|
|
|
|
const existing = document.getElementById('reader-settings-panel');
|
|
|
|
|
|
if (existing) {
|
|
|
|
|
|
existing.remove();
|
|
|
|
|
|
readerSettingsPanelOpen = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readerSettingsPanelOpen = true;
|
|
|
|
|
|
const isPdf = !!currentPdfDoc;
|
|
|
|
|
|
|
|
|
|
|
|
const panel = document.createElement('div');
|
|
|
|
|
|
panel.id = 'reader-settings-panel';
|
|
|
|
|
|
panel.className = 'reader-settings-panel';
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPdf) {
|
|
|
|
|
|
panel.innerHTML = `
|
|
|
|
|
|
<label>Schrift <button class="btn btn-sm" id="rs-font-minus">−</button> <input type="range" id="rs-font" min="12" max="24" step="1" value="${readerSettings.fontSize}"> <button class="btn btn-sm" id="rs-font-plus">+</button> <span id="rs-font-val">${readerSettings.fontSize}px</span></label>
|
|
|
|
|
|
<label>Zeilen <button class="btn btn-sm" id="rs-line-minus">−</button> <input type="range" id="rs-line" min="12" max="30" step="1" value="${Math.round(readerSettings.lineHeight * 10)}"> <button class="btn btn-sm" id="rs-line-plus">+</button> <span id="rs-line-val">${readerSettings.lineHeight}</span></label>
|
|
|
|
|
|
<label>Breite <button class="btn btn-sm" id="rs-width-minus">−</button> <input type="range" id="rs-width" min="40" max="${_READER_WIDTH_MAX}" step="5" value="${Math.min(readerSettings.maxWidth, _READER_WIDTH_MAX)}"> <button class="btn btn-sm" id="rs-width-plus">+</button> <span id="rs-width-val">${readerSettings.maxWidth}ch</span></label>
|
|
|
|
|
|
<button class="btn btn-sm" id="rs-width-full">Volle Breite</button>
|
|
|
|
|
|
<label>Stärke <button class="btn btn-sm" id="rs-weight-minus">−</button> <input type="range" id="rs-weight" min="200" max="800" step="${_readerWeightStep()}" value="${_readerWeight()}"> <button class="btn btn-sm" id="rs-weight-plus">+</button> <span id="rs-weight-val">${_readerWeight()}</span></label>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.fontFamily === 'serif' ? 'active' : ''}" data-rs-font="serif">Serif</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.fontFamily === 'sans' ? 'active' : ''}" data-rs-font="sans">Sans</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.fontFamily === 'humanist' ? 'active' : ''}" data-rs-font="humanist">Verdana</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.fontFamily === 'mono' ? 'active' : ''}" data-rs-font="mono">Mono</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.noBold ? 'active' : ''}" id="rs-no-bold">Kein Fett</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.theme === 'app' ? 'active' : ''}" data-rs-theme="app">Wie die App</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.theme === 'dark' ? 'active' : ''}" data-rs-theme="dark">Dunkel</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.theme === 'sepia' ? 'active' : ''}" data-rs-theme="sepia">Sepia</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.theme === 'bright' ? 'active' : ''}" data-rs-theme="bright">Hell</button>
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
|
${_readerModeButtons()}
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
`;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
panel.innerHTML = `
|
|
|
|
|
|
<label>Zoom <button class="btn btn-sm" id="rs-zoom-minus">−</button> <input type="range" id="rs-zoom" min="50" max="200" step="10" value="${readerSettings.pdfZoom}"> <button class="btn btn-sm" id="rs-zoom-plus">+</button> <span id="rs-zoom-val">${readerSettings.pdfZoom}%</span></label>
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
<button class="btn btn-sm ${readerSettings.pdfPaginated ? '' : 'active'}" data-rs-pdfmode="scroll">Scrollen</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.pdfPaginated ? 'active' : ''}" data-rs-pdfmode="pages">Seiten</button>
|
PDF: öffnet an der gespeicherten Seite, Leserfarben, Seitenzahlen wie im Buch (sw CACHE v166)
Der Lesestand wird gleich beim Öffnen erfragt (parallel zur Datei), ein PDF zeichnet zuerst
die Seite, an der es weitergeht, statt Seite 1; Titel, Inhaltsverzeichnis und Seitenzahlen
kommen nebenher und halten das Öffnen nicht mehr auf. Eine Zeichnung, die schon läuft, wird
abgewartet statt neu begonnen.
„Leserfarben“ (neben Originalfarben und Invertieren): die Seite in den Farben des Lesers
(Dunkel, Sepia) per SVG-Filter, Bilder darüber wie gedruckt (ihre Lage aus den
Zeichenbefehlen); ein Bild, das die halbe Seite füllt, ist ein Scan und wird mit umgefärbt.
pdf.js' eigene pageColors färben die Bilder mit um. Ein anderes Design ändert nur die Farben
des Filters.
Seitenzahlen des Buchs (PageLabels: „iv“, „A-3“) im Kopf mit der Seite der Datei daneben,
eingeben lässt sich beides; Lesezeichen und der Zurück-Knopf nennen sie. Das Test-PDF hat
dafür Seitenzahlen und ein farbiges Bild bekommen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:42:26 +01:00
|
|
|
|
<button class="btn btn-sm ${!readerSettings.pdfInverted && !readerSettings.pdfPageColors ? 'active' : ''}" data-rs-pdfcolors="original"
|
|
|
|
|
|
title="Die Seiten wie gedruckt">Originalfarben</button>
|
|
|
|
|
|
<button class="btn btn-sm ${!readerSettings.pdfInverted && readerSettings.pdfPageColors ? 'active' : ''}" data-rs-pdfcolors="reader"
|
|
|
|
|
|
title="Text und Hintergrund in den Farben des Lesers (Dunkel, Sepia), Bilder bleiben, wie sie sind">Leserfarben</button>
|
|
|
|
|
|
<button class="btn btn-sm ${readerSettings.pdfInverted ? 'active' : ''}" data-rs-pdfcolors="invert"
|
|
|
|
|
|
title="Die ganze Seite umgekehrt, auch Bilder (Farben bleiben ungefähr)">Invertieren</button>
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
<button class="btn btn-sm ${readerSettings.pdfSpread ? 'active' : ''}" id="rs-spread"${readerSettings.pdfPaginated ? ' style="display:none"' : ''}>Doppelseite</button>
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
overlay.insertBefore(panel, $('reader-body-row'));
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPdf) {
|
|
|
|
|
|
const fontRange = panel.querySelector('#rs-font');
|
|
|
|
|
|
const fontVal = panel.querySelector('#rs-font-val');
|
|
|
|
|
|
fontRange.addEventListener('input', () => {
|
|
|
|
|
|
readerSettings.fontSize = parseInt(fontRange.value, 10);
|
|
|
|
|
|
fontVal.textContent = readerSettings.fontSize + 'px';
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-font-minus').addEventListener('click', () => {
|
|
|
|
|
|
fontRange.value = Math.max(+fontRange.min, parseInt(fontRange.value, 10) - 1);
|
|
|
|
|
|
fontRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-font-plus').addEventListener('click', () => {
|
|
|
|
|
|
fontRange.value = Math.min(+fontRange.max, parseInt(fontRange.value, 10) + 1);
|
|
|
|
|
|
fontRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const lineRange = panel.querySelector('#rs-line');
|
|
|
|
|
|
const lineVal = panel.querySelector('#rs-line-val');
|
|
|
|
|
|
lineRange.addEventListener('input', () => {
|
|
|
|
|
|
readerSettings.lineHeight = (parseInt(lineRange.value, 10) / 10).toFixed(1);
|
|
|
|
|
|
lineVal.textContent = readerSettings.lineHeight;
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-line-minus').addEventListener('click', () => {
|
|
|
|
|
|
lineRange.value = Math.max(+lineRange.min, parseInt(lineRange.value, 10) - 1);
|
|
|
|
|
|
lineRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-line-plus').addEventListener('click', () => {
|
|
|
|
|
|
lineRange.value = Math.min(+lineRange.max, parseInt(lineRange.value, 10) + 1);
|
|
|
|
|
|
lineRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const widthRange = panel.querySelector('#rs-width');
|
|
|
|
|
|
const widthVal = panel.querySelector('#rs-width-val');
|
|
|
|
|
|
widthRange.addEventListener('input', () => {
|
|
|
|
|
|
readerSettings.maxWidth = parseInt(widthRange.value, 10);
|
|
|
|
|
|
widthVal.textContent = readerSettings.maxWidth + 'ch';
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-width-minus').addEventListener('click', () => {
|
|
|
|
|
|
widthRange.value = Math.max(+widthRange.min, parseInt(widthRange.value, 10) - 5);
|
|
|
|
|
|
widthRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-width-plus').addEventListener('click', () => {
|
|
|
|
|
|
widthRange.value = Math.min(+widthRange.max, parseInt(widthRange.value, 10) + 5);
|
|
|
|
|
|
widthRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
panel.querySelector('#rs-width-full').addEventListener('click', () => {
|
|
|
|
|
|
readerSettings.maxWidth = 999;
|
|
|
|
|
|
widthRange.value = 90;
|
|
|
|
|
|
widthVal.textContent = 'full';
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const weightRange = panel.querySelector('#rs-weight');
|
|
|
|
|
|
const weightVal = panel.querySelector('#rs-weight-val');
|
|
|
|
|
|
weightRange.addEventListener('input', () => {
|
|
|
|
|
|
readerSettings.fontWeight = parseInt(weightRange.value, 10);
|
|
|
|
|
|
weightVal.textContent = readerSettings.fontWeight;
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-weight-minus').addEventListener('click', () => {
|
|
|
|
|
|
weightRange.value = Math.max(+weightRange.min, parseInt(weightRange.value, 10) - +weightRange.step);
|
|
|
|
|
|
weightRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-weight-plus').addEventListener('click', () => {
|
|
|
|
|
|
weightRange.value = Math.min(+weightRange.max, parseInt(weightRange.value, 10) + +weightRange.step);
|
|
|
|
|
|
weightRange.dispatchEvent(new Event('input'));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-font]').forEach(btn => {
|
|
|
|
|
|
btn.addEventListener('click', () => {
|
|
|
|
|
|
readerSettings.fontFamily = btn.dataset.rsFont;
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-font]').forEach(b => b.classList.toggle('active', b === btn));
|
|
|
|
|
|
// The system fonts only have cuts at multiples of 100.
|
|
|
|
|
|
weightRange.step = _readerWeightStep();
|
|
|
|
|
|
if (readerSettings.fontWeight) {
|
|
|
|
|
|
readerSettings.fontWeight = Math.round(readerSettings.fontWeight / weightRange.step) * weightRange.step;
|
|
|
|
|
|
}
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
weightRange.value = _readerWeight();
|
|
|
|
|
|
weightVal.textContent = _readerWeight();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
panel.querySelector('#rs-no-bold').addEventListener('click', function () {
|
|
|
|
|
|
readerSettings.noBold = !readerSettings.noBold;
|
|
|
|
|
|
this.classList.toggle('active', readerSettings.noBold);
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-theme]').forEach(btn => {
|
|
|
|
|
|
btn.addEventListener('click', () => {
|
|
|
|
|
|
readerSettings.theme = btn.dataset.rsTheme;
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-theme]').forEach(b => b.classList.toggle('active', b === btn));
|
|
|
|
|
|
applyReaderSettings(false);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
Lesen in Seiten auch im Browser und auf dem Desktop, mit Fußnoten unten auf der Seite und Doppelseite
63-pages.js (DioraPages): die Seitenansicht des E-Reader-Modus der Android-Apps, jetzt für alle –
Seitenumbrüche vor angeschnittenen Zeilen, ein Kapitel auf einmal, Fußnoten am Seitenfuß wie im
gedruckten Buch, Blättern per Tippen/Klick am Rand, Wischen, Pfeil-/Bild-/Leertaste und Mausrad.
Neu: Doppelseite (zwei Seiten nebeneinander ab 900 px Breite). Einstellung „Scrollen | Seiten“
(+ „Fußnoten unten“, „Doppelseite“) im Schrift-&-Layout-Panel, je Gerät.
Fußnoten: Erkennung und Auflösung aus diora-android native-ui.js übernommen (40-epub.js,
78-footnotes.js) – die Notiz wird im richtigen Kapitel gesucht (IDs wiederholen sich je Datei),
auch das Popover zeigt jetzt genau die Notiz. Vorbereitete Bücher werden einmal neu aufbereitet.
Behoben gegenüber der App-Fassung: ein Verweis in der ersten Zeile einer Seite (hochgestellt)
zählte zur Vorseite, und ein Verweis, der samt Notiz nicht mehr passte, blieb ohne Notiz stehen –
jetzt wandert er mit ihr auf die nächste Seite. Schnelles Blättern löst „Weit gescrollt“ nicht mehr aus.
sw CACHE v157
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:41:27 +01:00
|
|
|
|
|
|
|
|
|
|
// Scrolling or pages (63-pages.js): per device, for every book.
|
|
|
|
|
|
const syncMode = () => {
|
|
|
|
|
|
const pages = DioraPages.isOn();
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-mode]').forEach(b => b.classList.toggle('active', (b.dataset.rsMode === 'pages') === pages));
|
|
|
|
|
|
const notes = panel.querySelector('#rs-page-notes');
|
|
|
|
|
|
if (notes) {
|
|
|
|
|
|
notes.style.display = pages ? '' : 'none';
|
|
|
|
|
|
notes.classList.toggle('active', DioraPages.pageNotes());
|
|
|
|
|
|
}
|
|
|
|
|
|
const spread = panel.querySelector('#rs-page-spread');
|
|
|
|
|
|
if (spread) {
|
|
|
|
|
|
spread.style.display = pages ? '' : 'none';
|
|
|
|
|
|
spread.classList.toggle('active', DioraPages.spread());
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-mode]').forEach(btn => {
|
|
|
|
|
|
btn.addEventListener('click', () => { DioraPages.setOn(btn.dataset.rsMode === 'pages'); syncMode(); });
|
|
|
|
|
|
});
|
|
|
|
|
|
panel.querySelector('#rs-page-notes')?.addEventListener('click', () => { DioraPages.togglePageNotes(); syncMode(); });
|
|
|
|
|
|
panel.querySelector('#rs-page-spread')?.addEventListener('click', () => { DioraPages.setSpread(!DioraPages.spread()); syncMode(); });
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
} else {
|
|
|
|
|
|
const zoomRange = panel.querySelector('#rs-zoom');
|
|
|
|
|
|
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
// While the slider moves only the number follows; the pages are drawn anew once it rests.
|
|
|
|
|
|
let zoomTimer = 0;
|
|
|
|
|
|
zoomRange.addEventListener('input', () => {
|
|
|
|
|
|
const z = parseInt(zoomRange.value, 10);
|
|
|
|
|
|
const val = panel.querySelector('#rs-zoom-val');
|
|
|
|
|
|
if (val) val.textContent = z + '%';
|
|
|
|
|
|
clearTimeout(zoomTimer);
|
|
|
|
|
|
zoomTimer = setTimeout(() => applyPdfZoom(z), 250);
|
|
|
|
|
|
});
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
panel.querySelector('#rs-zoom-minus').addEventListener('click', () =>
|
|
|
|
|
|
applyPdfZoom(Math.max(50, readerSettings.pdfZoom - 10)));
|
|
|
|
|
|
panel.querySelector('#rs-zoom-plus').addEventListener('click', () =>
|
|
|
|
|
|
applyPdfZoom(Math.min(200, readerSettings.pdfZoom + 10)));
|
|
|
|
|
|
|
PDF: öffnet an der gespeicherten Seite, Leserfarben, Seitenzahlen wie im Buch (sw CACHE v166)
Der Lesestand wird gleich beim Öffnen erfragt (parallel zur Datei), ein PDF zeichnet zuerst
die Seite, an der es weitergeht, statt Seite 1; Titel, Inhaltsverzeichnis und Seitenzahlen
kommen nebenher und halten das Öffnen nicht mehr auf. Eine Zeichnung, die schon läuft, wird
abgewartet statt neu begonnen.
„Leserfarben“ (neben Originalfarben und Invertieren): die Seite in den Farben des Lesers
(Dunkel, Sepia) per SVG-Filter, Bilder darüber wie gedruckt (ihre Lage aus den
Zeichenbefehlen); ein Bild, das die halbe Seite füllt, ist ein Scan und wird mit umgefärbt.
pdf.js' eigene pageColors färben die Bilder mit um. Ein anderes Design ändert nur die Farben
des Filters.
Seitenzahlen des Buchs (PageLabels: „iv“, „A-3“) im Kopf mit der Seite der Datei daneben,
eingeben lässt sich beides; Lesezeichen und der Zurück-Knopf nennen sie. Das Test-PDF hat
dafür Seitenzahlen und ein farbiges Bild bekommen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:42:26 +01:00
|
|
|
|
// The pages' colours: as printed, in the reader's colours, or inverted.
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-pdfcolors]').forEach(btn => {
|
|
|
|
|
|
btn.addEventListener('click', () => {
|
|
|
|
|
|
const which = btn.dataset.rsPdfcolors;
|
|
|
|
|
|
readerSettings.pdfInverted = which === 'invert';
|
|
|
|
|
|
readerSettings.pdfPageColors = which === 'reader';
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-pdfcolors]').forEach(b => b.classList.toggle('active', b === btn));
|
|
|
|
|
|
applyReaderSettings(true);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
});
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
});
|
|
|
|
|
|
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
// Scrolling or page by page (phones and e-readers start with pages).
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-pdfmode]').forEach(btn => {
|
|
|
|
|
|
btn.addEventListener('click', () => {
|
|
|
|
|
|
const pages = btn.dataset.rsPdfmode === 'pages';
|
|
|
|
|
|
if (pages === !!readerSettings.pdfPaginated || !currentPdfDoc) return;
|
|
|
|
|
|
const contentEl = $('reader-content');
|
|
|
|
|
|
const page = pages ? _pdfTopPage(contentEl) : pdfCurrentPage;
|
|
|
|
|
|
readerSettings.pdfPaginated = pages;
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
panel.querySelectorAll('[data-rs-pdfmode]').forEach(b => b.classList.toggle('active', b === btn));
|
|
|
|
|
|
const spread = panel.querySelector('#rs-spread');
|
|
|
|
|
|
if (spread) spread.style.display = pages ? 'none' : '';
|
|
|
|
|
|
if (pages) {
|
|
|
|
|
|
pdfCurrentPage = page;
|
|
|
|
|
|
// Spreads are a scrolling thing: one page at a time here.
|
|
|
|
|
|
if (readerSettings.pdfSpread) reRenderPdf(page).then(() => enterPdfPaginatedMode());
|
|
|
|
|
|
else enterPdfPaginatedMode();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
exitPdfPaginatedMode(page);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
panel.querySelector('#rs-spread').addEventListener('click', function () {
|
|
|
|
|
|
readerSettings.pdfSpread = !readerSettings.pdfSpread;
|
|
|
|
|
|
this.classList.toggle('active', readerSettings.pdfSpread);
|
|
|
|
|
|
saveReaderSettings();
|
|
|
|
|
|
reRenderPdf();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-11-04 15:37:12 +01:00
|
|
|
|
/**
|
|
|
|
|
|
* The PDF at another zoom (%). Scrolling, [anchor] (_pdfPointAt: where the fingers were) stays
|
|
|
|
|
|
* in place, else the middle of the screen; page by page, the page is fitted anew (_pdfFitPage).
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function applyPdfZoom(newZoom, anchor) {
|
|
|
|
|
|
const old = readerSettings.pdfZoom;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
readerSettings.pdfZoom = newZoom;
|
|
|
|
|
|
const zoomRange = document.getElementById('rs-zoom');
|
|
|
|
|
|
const zoomVal = document.getElementById('rs-zoom-val');
|
|
|
|
|
|
if (zoomRange) zoomRange.value = newZoom;
|
|
|
|
|
|
if (zoomVal) zoomVal.textContent = newZoom + '%';
|
|
|
|
|
|
saveReaderSettings();
|
2026-11-04 15:37:12 +01:00
|
|
|
|
if (!currentPdfDoc) return;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
if (readerSettings.pdfPaginated) {
|
2026-11-04 15:37:12 +01:00
|
|
|
|
await _pdfShowPage(pdfCurrentPage);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (newZoom === old) return;
|
|
|
|
|
|
if (!anchor) {
|
|
|
|
|
|
const r = $('reader-content').getBoundingClientRect();
|
|
|
|
|
|
anchor = _pdfPointAt(r.left + r.width / 2, r.top + r.height / 2);
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
}
|
2026-11-04 15:37:12 +01:00
|
|
|
|
if (!_pdfRezoomScroll(newZoom / old, anchor)) await reRenderPdf();
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
}
|
|
|
|
|
|
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
// The page at the top of the view (scrolling) — 58-pdf.js keeps the pages in order.
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
function _currentScrollPage(contentEl) {
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
return _pdfTopPage(contentEl);
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
}
|
|
|
|
|
|
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
/** Lay the open PDF out again (zoom, spreads, another width), at [pivot] or the page shown now. */
|
|
|
|
|
|
async function reRenderPdf(pivot) {
|
|
|
|
|
|
if (!currentPdfDoc) return;
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
const contentEl = $('reader-content');
|
|
|
|
|
|
if (!contentEl) return;
|
PDF-Reader: ein Zeichenweg, Seitenmodus neu, Seitensprung für beide Modi (WIP, ungetestet)
- 58-pdf.js: _pdfDraw – eine Zeichnung je Canvas (die vorige wird
abgebrochen und abgewartet), Pixeldichte, höchstens 16,7 MP; Seiten, die
gehen, geben auch pdf.js' Seitendaten frei; ein gemeinsamer pdf.js-Worker
(_pdfLoad) auch für Uploads, Seitenzahl, Hefte und Cover; Inhalts-
verzeichnis parallel aufgelöst, auch mit Seitenindex als Ziel;
ResizeObserver: Drehen, Breite, Leisten – neu an derselben Seite.
- 66-pdf-paginated.js: Seitenmodus auf _pdfDraw, Zuschnitt in
Bildschirmkoordinaten (gedrehte Seiten) und höchstens 2,5× der ganzen
Seite (eine fast leere Seite wird nicht unendlich groß); nächste und
vorige Seite vorgezeichnet; Tippen zum Blättern blendet die Leisten
nicht mehr ein; Wischen nur deutlich seitwärts; Mausrad; Pinch setzt die
Vorschau zurück; nach dem Blättern wird gespeichert und 'diora-pdf-turn'
gemeldet (E-Ink-Refresh).
- pdfGoToPage für beide Modi: Inhaltsverzeichnis, Seitenzahl im Kopf,
Lesezeichen, Tasten (Seitenmodus jetzt auch Leertaste, Bild auf/ab).
- Beim Scrollen wird die aktuelle Seite mitgeführt (Lesezeichen sagten
immer „Seite 1“).
- Schalter Scrollen | Seiten im PDF-Panel; Zoom-Regler zeichnet erst neu,
wenn er ruht.
- openBook hängt seine Listener über _readerListen an; closeReader nimmt
sie ab (vorher sammelten sie sich bei jedem Öffnen an). Abbrechen und
ein zweites Buch geben das alte Dokument frei; der entschlüsselte
PDF-Puffer wird nicht mehr gehalten.
- Invertieren dreht die Farbtöne zurück (Fotos keine Negative).
- e2e/fixtures/make_test_pdf.py: Test-PDF mit gemischten Formaten,
Outline, Links und einer fast leeren Seite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:52:28 +01:00
|
|
|
|
if (!pivot) pivot = readerSettings.pdfPaginated ? pdfCurrentPage : _pdfTopPage(contentEl);
|
|
|
|
|
|
await renderPdf(null, contentEl, undefined, pivot);
|
Refactoring Schritt 2: app.js nach Bereichen in static/js/app/ aufgeteilt; sw v106
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
|
|
|
|
if (readerSettings.pdfPaginated) enterPdfPaginatedMode();
|
|
|
|
|
|
}
|