feat(reader): wire double-page spread setting into web reader

The double_page_spread checkbox in the reader settings panel was inert:
it had no Alpine binding, no apply logic, and no persistence. Default
was also inconsistent (false in settings-manager, absent from server
defaults).

- Add doublePageSpread state to the reader Alpine component, loaded
  from saved settings (default true)
- Add applyDoublePageSpread() which sets the renderer's 'spread'
  attribute to auto/none and persists the setting via saveSettings
- Apply the spread attribute during fixed-layout renderer init
- Bind the settings checkbox with x-model and @change
- Add double_page_spread: true to ReaderService server defaults so
  new users get the same starting value the client expects
- Also improve the PDF pan/select toolbar button: distinct smart-
  select vs pan icons, highlighted state while pan mode is active,
  and dynamic tooltips/aria-labels explaining each mode
This commit is contained in:
2026-08-14 08:17:25 -04:00
parent 04e2a069d6
commit f5d9578375
5 changed files with 29 additions and 12 deletions
+11
View File
@@ -371,6 +371,7 @@ document.addEventListener("alpine:init", () => {
isPDF: false,
interactionMode: "select" as string,
magnifierEnabled: false,
doublePageSpread: true as boolean,
progressText: "",
progressLabel: "",
progressMain: "",
@@ -454,6 +455,7 @@ document.addEventListener("alpine:init", () => {
this.readingFont = this.settings.reading_font || "literata";
this.fontSize = this.settings.font_size || 18;
this.lineHeight = this.settings.line_height || 1.6;
this.doublePageSpread = this.settings.double_page_spread ?? true;
if (this.settings.reading_mode) {
this.readingMode = this.settings.reading_mode;
} else {
@@ -492,6 +494,7 @@ document.addEventListener("alpine:init", () => {
this.zoomPercent = this.renderer.zoomPercent;
});
this.computeFixedLayoutChapterBoundaries();
this.applyDoublePageSpread();
} else {
this.renderer.setStyles?.(this.buildCSS());
}
@@ -692,6 +695,14 @@ document.addEventListener("alpine:init", () => {
this.renderer.setAttribute("interaction-mode", next);
this.interactionMode = next;
},
applyDoublePageSpread() {
if (!this.isFixedLayout || !this.renderer) return;
this.renderer.setAttribute(
"spread",
this.doublePageSpread ? "auto" : "none",
);
saveSettings({ double_page_spread: this.doublePageSpread });
},
goLeft() {
this.view?.goLeft?.();
},
+1 -1
View File
@@ -78,7 +78,7 @@ export function getDefaultSettings(): ReaderSettings {
font_size: 18,
line_height: 1.6,
margin_width: 20,
double_page_spread: false,
double_page_spread: true,
reading_direction: "ltr",
hardware_acceleration: true,
panel_layout: {