425 lines
21 KiB
JavaScript
425 lines
21 KiB
JavaScript
'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;
|
||
}
|
||
|
||
// Where the settings shown are kept: the book's id, or 'article' (all articles, 65-article.js).
|
||
let _readerSettingsKey = null;
|
||
|
||
function loadReaderSettings(bookId) {
|
||
_readerSettingsKey = bookId;
|
||
// Reset to defaults, then apply per-book overrides
|
||
Object.assign(readerSettings, { theme: 'app', fontFamily: 'serif', noBold: false,
|
||
pdfZoom: 100, pdfInverted: false, pdfPageColors: false, pdfPaginated: false, pdfSpread: false },
|
||
_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() {
|
||
const key = currentBookId || _readerSettingsKey;
|
||
if (key) {
|
||
localStorage.setItem(`diora_reader_settings_${key}`, JSON.stringify({ ...readerSettings, v: 3 }));
|
||
}
|
||
}
|
||
|
||
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');
|
||
// 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();
|
||
}
|
||
|
||
// 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();
|
||
// Line length or font changed: the column's place next to an open margin too.
|
||
if (readerAnnotationsMarginOpen) _centerReaderColumn();
|
||
}
|
||
|
||
// 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;
|
||
}
|
||
|
||
// "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>`;
|
||
}
|
||
|
||
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>
|
||
${_readerModeButtons()}
|
||
`;
|
||
} 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>
|
||
<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>
|
||
<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>
|
||
<button class="btn btn-sm ${readerSettings.pdfSpread ? 'active' : ''}" id="rs-spread"${readerSettings.pdfPaginated ? ' style="display:none"' : ''}>Doppelseite</button>
|
||
`;
|
||
}
|
||
|
||
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();
|
||
});
|
||
});
|
||
|
||
// 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(); });
|
||
} else {
|
||
const zoomRange = panel.querySelector('#rs-zoom');
|
||
|
||
// 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);
|
||
});
|
||
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)));
|
||
|
||
// 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();
|
||
});
|
||
});
|
||
|
||
// 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);
|
||
}
|
||
});
|
||
});
|
||
|
||
panel.querySelector('#rs-spread').addEventListener('click', function () {
|
||
readerSettings.pdfSpread = !readerSettings.pdfSpread;
|
||
this.classList.toggle('active', readerSettings.pdfSpread);
|
||
saveReaderSettings();
|
||
reRenderPdf();
|
||
});
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
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();
|
||
if (!currentPdfDoc) return;
|
||
if (readerSettings.pdfPaginated) {
|
||
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);
|
||
}
|
||
if (!_pdfRezoomScroll(newZoom / old, anchor)) await reRenderPdf();
|
||
}
|
||
|
||
// The page at the top of the view (scrolling) — 58-pdf.js keeps the pages in order.
|
||
function _currentScrollPage(contentEl) {
|
||
return _pdfTopPage(contentEl);
|
||
}
|
||
|
||
/** Lay the open PDF out again (zoom, spreads, another width), at [pivot] or the page shown now. */
|
||
async function reRenderPdf(pivot) {
|
||
if (!currentPdfDoc) return;
|
||
const contentEl = $('reader-content');
|
||
if (!contentEl) return;
|
||
if (!pivot) pivot = readerSettings.pdfPaginated ? pdfCurrentPage : _pdfTopPage(contentEl);
|
||
await renderPdf(null, contentEl, undefined, pivot);
|
||
if (readerSettings.pdfPaginated) enterPdfPaginatedMode();
|
||
}
|