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';
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Tabs
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
Abos & Quellen: alle Abos an einem Ort (Navigation Phase 2)
Ein neuer Abschnitt (docs/sources.md, static/js/sources.js) für Podcasts,
YouTube-Kanäle, Hörbücher, Nachrichten und Blogs:
- ein Feld zum Hinzufügen: Adresse (Feed, Seite, YouTube) oder Name eines
Podcasts; die Art ist wählbar (Podcast, Hörbuch, Nachrichten, Blog);
/feeds/discover/ erkennt dafür Podcasts (Folgen mit Ton oder Video);
- eine Liste aller Abos mit Filtern (auch „Probleme“) und Suche;
- je Abo: Inhalt öffnen, Einstellungen (die vorhandenen Editoren), Art ändern,
abbestellen; OPML-Import und -Export.
In der Seitenleiste unten, auf dem Telefon im App-Menü; ⚙ in den Feeds führt
hierher. Abschnitte, die beim Laden schon gezeigt werden, füllen sich jetzt
auch (nav.js zeigt sie nach dem Laden aller Skripte noch einmal).
Podcast-UI aus diora-android 50c6f9c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:23:12 +02:00
|
|
|
const TOP_TABS = ['home', 'radio', 'focus', 'podcasts', 'books', 'feeds', 'ambient', 'audiobooks', 'sources'];
|
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 RADIO_SUB_TABS = ['search', 'saved', 'history'];
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// URL hash routing — makes tabs deep-linkable/shareable and lets the browser
|
|
|
|
|
// back/forward buttons move between them. Deliberately hash-based rather
|
|
|
|
|
// than real paths: /podcasts/ and /books/ etc. are already taken by the
|
|
|
|
|
// JSON API, so this avoids touching Django's urls.py at all.
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
let _routingFromHash = false;
|
|
|
|
|
let _currentTopTab = 'radio';
|
|
|
|
|
|
|
|
|
|
function _syncHash() {
|
Navigation: Lesen und Hören (Phase 1, noch nicht veröffentlicht)
Die Bereiche nach dem, was man tut (docs/navigation.md): Home; Lesen mit
Bücher, Zeitschriften, Nachrichten, Blogs; Hören mit Hörbücher, Podcasts,
Radio, Ambient. static/js/nav.js ist die eine Definition für alle Plattformen
(DioraNav: Abschnitte, Gruppen, go, Hash, zuletzt gewählter Abschnitt je
Gruppe). Die Webseite zeichnet ihre Leiste daraus: breit alle Abschnitte unter
ihrer Gruppe, schmal Home · Lesen · Hören mit einer Abschnittszeile oben.
- Hörbücher haben ein eigenes Panel (#tab-audiobooks), nicht mehr über den E-Books.
- Zeitschriften: die Bücher im Ordner „Zeitschriften“ (oder „Magazine“).
- Nachrichten/Blogs wählt die Navigation; der eigene Umschalter verschwindet dann.
- Ein Link auf einen Abschnitt (#news …) schlägt die Startseite.
Die Apps zeichnen ihre Leiste (native-radio.js, diora-android) bald ebenfalls
daraus; bis dahin bleibt das hier unveröffentlicht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:31:58 +02:00
|
|
|
if (_routingFromHash || window.DioraNav) return; // the navigation keeps the hash (static/js/nav.js)
|
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
|
|
|
let hash = _currentTopTab;
|
|
|
|
|
if (_currentTopTab === 'radio') {
|
|
|
|
|
hash += '/' + (localStorage.getItem('diora_active_radio_tab') || 'saved');
|
|
|
|
|
}
|
|
|
|
|
if (location.hash.slice(1) !== hash) history.pushState(null, '', '#' + hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _routeFromHash() {
|
Navigation: Lesen und Hören (Phase 1, noch nicht veröffentlicht)
Die Bereiche nach dem, was man tut (docs/navigation.md): Home; Lesen mit
Bücher, Zeitschriften, Nachrichten, Blogs; Hören mit Hörbücher, Podcasts,
Radio, Ambient. static/js/nav.js ist die eine Definition für alle Plattformen
(DioraNav: Abschnitte, Gruppen, go, Hash, zuletzt gewählter Abschnitt je
Gruppe). Die Webseite zeichnet ihre Leiste daraus: breit alle Abschnitte unter
ihrer Gruppe, schmal Home · Lesen · Hören mit einer Abschnittszeile oben.
- Hörbücher haben ein eigenes Panel (#tab-audiobooks), nicht mehr über den E-Books.
- Zeitschriften: die Bücher im Ordner „Zeitschriften“ (oder „Magazine“).
- Nachrichten/Blogs wählt die Navigation; der eigene Umschalter verschwindet dann.
- Ein Link auf einen Abschnitt (#news …) schlägt die Startseite.
Die Apps zeichnen ihre Leiste (native-radio.js, diora-android) bald ebenfalls
daraus; bis dahin bleibt das hier unveröffentlicht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:31:58 +02:00
|
|
|
if (window.DioraNav) return; // nav.js routes (#news, #audiobooks …)
|
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 [tab, sub] = (location.hash || '').replace(/^#/, '').split('/').filter(Boolean);
|
|
|
|
|
if (!TOP_TABS.includes(tab)) return;
|
|
|
|
|
_routingFromHash = true;
|
|
|
|
|
try {
|
|
|
|
|
showTab(tab);
|
|
|
|
|
if (tab === 'radio' && RADIO_SUB_TABS.includes(sub)) showRadioTab(sub);
|
|
|
|
|
} finally {
|
|
|
|
|
_routingFromHash = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.addEventListener('popstate', _routeFromHash);
|
|
|
|
|
window.addEventListener('hashchange', _routeFromHash);
|
|
|
|
|
|
|
|
|
|
function showOfflineBanner(offline) {
|
|
|
|
|
document.body.classList.toggle('app-offline', offline);
|
|
|
|
|
const uploadArea = $('book-upload-area');
|
|
|
|
|
if (uploadArea) uploadArea.style.display = offline ? 'none' : '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showTab(name) {
|
|
|
|
|
TOP_TABS.forEach(p => {
|
|
|
|
|
const panel = $(`tab-${p}`);
|
|
|
|
|
if (panel) panel.style.display = (p === name) ? '' : 'none';
|
|
|
|
|
});
|
|
|
|
|
|
Navigation: Lesen und Hören (Phase 1, noch nicht veröffentlicht)
Die Bereiche nach dem, was man tut (docs/navigation.md): Home; Lesen mit
Bücher, Zeitschriften, Nachrichten, Blogs; Hören mit Hörbücher, Podcasts,
Radio, Ambient. static/js/nav.js ist die eine Definition für alle Plattformen
(DioraNav: Abschnitte, Gruppen, go, Hash, zuletzt gewählter Abschnitt je
Gruppe). Die Webseite zeichnet ihre Leiste daraus: breit alle Abschnitte unter
ihrer Gruppe, schmal Home · Lesen · Hören mit einer Abschnittszeile oben.
- Hörbücher haben ein eigenes Panel (#tab-audiobooks), nicht mehr über den E-Books.
- Zeitschriften: die Bücher im Ordner „Zeitschriften“ (oder „Magazine“).
- Nachrichten/Blogs wählt die Navigation; der eigene Umschalter verschwindet dann.
- Ein Link auf einen Abschnitt (#news …) schlägt die Startseite.
Die Apps zeichnen ihre Leiste (native-radio.js, diora-android) bald ebenfalls
daraus; bis dahin bleibt das hier unveröffentlicht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:31:58 +02:00
|
|
|
if (!window.DioraNav) { // else nav.js marks its own buttons
|
|
|
|
|
document.querySelectorAll('#tabs .tab-btn').forEach((btn, i) => {
|
|
|
|
|
btn.classList.toggle('active', TOP_TABS[i] === name);
|
|
|
|
|
});
|
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
localStorage.setItem('diora_active_tab', name);
|
|
|
|
|
_currentTopTab = name;
|
|
|
|
|
_syncHash();
|
|
|
|
|
|
|
|
|
|
if (name === 'books') loadBookList();
|
|
|
|
|
if (name === 'ambient') _ambientLoad();
|
|
|
|
|
if (name === 'home' && window.__dioraHomeShow) window.__dioraHomeShow(); // static/js/home.js
|
|
|
|
|
if (name === 'feeds' && window.__dioraFeedsShow) window.__dioraFeedsShow(); // static/js/feeds.js
|
|
|
|
|
}
|