From fe12f4be76feeaa72e2cfc58bd9d099adc451da7 Mon Sep 17 00:00:00 2001 From: patrick Date: Tue, 11 Aug 2026 22:27:04 -0400 Subject: [PATCH] feat: add the reader settings panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typeface, size, weight, line height, letter spacing, justify and hyphenate, plus flow, columns, line width, gap and margins — persisted in localStorage and applied live. Fixed-layout books hide the typography and column controls: they render through foliate-fxl, which has no setStyles and ignores the paginator's attributes, so those sliders would do nothing. --- .../lib/components/reader/epub-reader.svelte | 28 +- .../components/reader/reader-settings.svelte | 265 ++++++++++++++++++ .../src/lib/components/ui/slider/index.ts | 7 + .../lib/components/ui/slider/slider.svelte | 52 ++++ 4 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 frontend/src/lib/components/reader/reader-settings.svelte create mode 100644 frontend/src/lib/components/ui/slider/index.ts create mode 100644 frontend/src/lib/components/ui/slider/slider.svelte diff --git a/frontend/src/lib/components/reader/epub-reader.svelte b/frontend/src/lib/components/reader/epub-reader.svelte index 3cd4577..bd38bcb 100644 --- a/frontend/src/lib/components/reader/epub-reader.svelte +++ b/frontend/src/lib/components/reader/epub-reader.svelte @@ -1,7 +1,14 @@ + + + + + Reading + + {isFixedLayout + ? 'This book has a fixed layout, so its typography is set by the publisher.' + : 'Applies to every book you read.'} + + + +
+ {#if !isFixedLayout} +
+

+ Typography +

+ +
+ + state.set('fontFamily', event.currentTarget.value)} + > + {#each READER_FONT_OPTIONS as font (font.value)} + + {/each} + +
+ +
+
+ + + {state.settings.fontSize}px + +
+ +
+ +
+
+ + + {state.settings.fontWeight} + +
+ +
+ +
+
+ + + {state.settings.lineHeight.toFixed(2)} + +
+ +
+ +
+
+ + + {state.settings.letterSpacing.toFixed(2)}em + +
+ +
+ +
+ + state.set('justify', checked)} + /> +
+ +
+ + state.set('hyphenate', checked)} + /> +
+
+ + + {/if} + +
+

+ Layout +

+ +
+ + value && state.set('flow', value as ReaderFlow)} + class="justify-start" + > + Pages + Scroll + +
+ + {#if !isFixedLayout} +
+ + value && state.set('maxColumnCount', Number(value))} + class="justify-start" + > + Single + Spread + +

+ A spread needs the window to be wide enough for two columns. +

+
+ +
+
+ + + {state.settings.maxInlineSize}px + +
+ +
+ +
+
+ + + {state.settings.gap}% + +
+ +
+ {/if} + +
+
+ + + {state.settings.margin}px + +
+ +
+
+ + + + +
+
+
diff --git a/frontend/src/lib/components/ui/slider/index.ts b/frontend/src/lib/components/ui/slider/index.ts new file mode 100644 index 0000000..820f209 --- /dev/null +++ b/frontend/src/lib/components/ui/slider/index.ts @@ -0,0 +1,7 @@ +import Root from "./slider.svelte"; + +export { + Root, + // + Root as Slider, +}; diff --git a/frontend/src/lib/components/ui/slider/slider.svelte b/frontend/src/lib/components/ui/slider/slider.svelte new file mode 100644 index 0000000..ebfa45f --- /dev/null +++ b/frontend/src/lib/components/ui/slider/slider.svelte @@ -0,0 +1,52 @@ + + + + + {#snippet children({ thumbItems })} + + + + {#each thumbItems as thumb (thumb.index)} + + {/each} + {/snippet} +