diff --git a/ui/src/routes/books/[slug]/chapters/[n]/+page.svelte b/ui/src/routes/books/[slug]/chapters/[n]/+page.svelte index d5eb3c4..ebfac2d 100644 --- a/ui/src/routes/books/[slug]/chapters/[n]/+page.svelte +++ b/ui/src/routes/books/[slug]/chapters/[n]/+page.svelte @@ -53,6 +53,8 @@ type ReadWidth = 'narrow' | 'normal' | 'wide'; type ParaStyle = 'spaced' | 'indented'; type PlayerStyle = 'standard' | 'compact'; + /** Controls how many lines fit on a page by adjusting the container height offset. */ + type PageLines = 'less' | 'normal' | 'more'; interface LayoutPrefs { readMode: ReadMode; @@ -61,12 +63,19 @@ paraStyle: ParaStyle; focusMode: boolean; playerStyle: PlayerStyle; + pageLines: PageLines; } const LAYOUT_KEY = 'reader_layout_v1'; - const LINE_HEIGHTS: Record = { compact: 1.55, normal: 1.85, relaxed: 2.2 }; - const READ_WIDTHS: Record = { narrow: '58ch', normal: '72ch', wide: 'min(90ch, 100%)' }; - const DEFAULT_LAYOUT: LayoutPrefs = { readMode: 'scroll', lineSpacing: 'normal', readWidth: 'normal', paraStyle: 'spaced', focusMode: false, playerStyle: 'standard' }; + const LINE_HEIGHTS: Record = { compact: 1.55, normal: 1.85, relaxed: 2.2 }; + const READ_WIDTHS: Record = { narrow: '58ch', normal: '72ch', wide: 'min(90ch, 100%)' }; + /** + * Extra rem subtracted from (or added to) the paginated container height. + * Normal (0rem) keeps the existing calc(); Less (-4rem) makes the container + * shorter so fewer lines fit per page; More (+4rem) grows it for more lines. + */ + const PAGE_LINES_OFFSET: Record = { less: '4rem', normal: '0rem', more: '-4rem' }; + const DEFAULT_LAYOUT: LayoutPrefs = { readMode: 'scroll', lineSpacing: 'normal', readWidth: 'normal', paraStyle: 'spaced', focusMode: false, playerStyle: 'standard', pageLines: 'normal' }; function loadLayout(): LayoutPrefs { if (!browser) return DEFAULT_LAYOUT; @@ -114,8 +123,10 @@ $effect(() => { if (layout.readMode !== 'paginated') { pageIndex = 0; totalPages = 1; return; } - // Re-run when html changes or container is bound + // Re-run when html, container refs, or mini-player visibility changes + // (mini-player adds pb-24 which reduces the available viewport height) void html; void paginatedContainerEl; void paginatedContentEl; + void audioStore.active; void audioExpanded; requestAnimationFrame(() => { if (!paginatedContainerEl || !paginatedContentEl) return; const h = paginatedContainerEl.clientHeight; @@ -542,7 +553,9 @@ role="none" bind:this={paginatedContainerEl} class="paginated-container mt-8" - style="height: {layout.focusMode ? 'calc(100svh - 8rem)' : 'calc(100svh - 26rem)'};" + style="height: {layout.focusMode + ? 'calc(100svh - 8rem)' + : `calc(100svh - 26rem - ${PAGE_LINES_OFFSET[layout.pageLines]})`};" onclick={handlePaginatedClick} >
+ {#if layout.readMode === 'paginated'} +
+ Lines +
+ {#each ([['less', 'Few'], ['normal', 'Normal'], ['more', 'Many']] as const) as [v, lbl]} + + {/each} +
+
+ {/if} +
Spacing