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>
54 lines
2.1 KiB
JavaScript
54 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Encrypted wallpaper
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function uploadBackground(file) {
|
|
if (!file) return;
|
|
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
|
|
if (!allowedTypes.includes(file.type)) {
|
|
await customAlert('Nur JPEG-, PNG- oder WebP-Bilder sind erlaubt.');
|
|
return;
|
|
}
|
|
if (file.size > DIORA_CONFIG.bgMaxBytes) {
|
|
await customAlert(`Das Bild darf höchstens ${DIORA_CONFIG.bgMaxBytes / 1024 / 1024} MB groß sein.`);
|
|
return;
|
|
}
|
|
|
|
const key = await getOrCreateEncKey();
|
|
const buf = await file.arrayBuffer();
|
|
const {iv, ciphertext} = await encryptBytes(key, buf);
|
|
|
|
const res = await fetch('/accounts/background/upload/', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json', 'X-CSRFToken': getCsrfToken()},
|
|
body: JSON.stringify({iv, ciphertext, mime_type: file.type, file_size: file.size}),
|
|
});
|
|
const data = await res.json();
|
|
if (!data.ok) throw new Error(data.error || 'upload failed');
|
|
}
|
|
|
|
async function applyEncryptedBackground() {
|
|
if (typeof ENCRYPTED_BG === 'undefined' || !ENCRYPTED_BG.ciphertext) return;
|
|
try {
|
|
const key = await getOrCreateEncKey();
|
|
const plain = await decryptBytes(key, ENCRYPTED_BG.iv, ENCRYPTED_BG.ciphertext);
|
|
const blob = new Blob([plain], {type: ENCRYPTED_BG.mime || 'image/jpeg'});
|
|
const url = URL.createObjectURL(blob);
|
|
document.body.style.backgroundImage = `url('${url}')`;
|
|
const contrastBtn = document.getElementById('contrast-toggle');
|
|
if (contrastBtn) contrastBtn.hidden = false; // only with a picture behind the page
|
|
document.body.style.backgroundSize = 'cover';
|
|
document.body.style.backgroundPosition = 'center';
|
|
document.body.style.backgroundAttachment = 'fixed';
|
|
|
|
// Analyze brightness for accent/scheme
|
|
analyzeBackground(url).then(({bright, bgLuminance}) => {
|
|
setScheme(bright);
|
|
applyAccent(pickBestAccent(bgLuminance));
|
|
});
|
|
} catch (e) {
|
|
console.warn('Could not decrypt background:', e);
|
|
}
|
|
}
|