<script lang="ts"> import { Direction, Layout, type PageFragment } from '$gql/graphql'; import { binds } from '$lib/Shortcuts'; import { src } from '$lib/Utils'; import { getReaderContext, partition, type Chunk } from './Reader.svelte'; import ReaderPage from './ReaderPage.svelte'; const reader = getReaderContext(); export let direction: Direction; export let layout: Layout; let chunks: Chunk[] = []; let lookup: number[] = []; let main: PageFragment; let secondary: PageFragment | undefined; function gotoChunk(to: number) { if (to < 0 || to >= chunks.length) return; reader.page = chunks[to].index; } function pagesAround(around: number) { const pages: PageFragment[] = []; const push = (at: number) => { if (at < 0 || at >= chunks.length) return; pages.push(chunks[at].main); if (chunks[at].secondary) { pages.push(chunks[at].secondary); } }; for (let i = 1; i <= 2; i++) { push(lookup[around] + i); push(lookup[around] - i); } return pages; } const next = () => gotoChunk(lookup[reader.page] + 1); const prev = () => gotoChunk(lookup[reader.page] - 1); const clickLeft = () => (direction === Direction.LeftToRight ? prev() : next()); const clickRight = () => (direction === Direction.RightToLeft ? prev() : next()); function clickMain(event: MouseEvent & { currentTarget: EventTarget | null }) { if (event.currentTarget instanceof Element) { const rect = event.currentTarget.getBoundingClientRect(); if (event.clientX - rect.left < rect.width / 2) { clickLeft(); } else { clickRight(); } } } $: [chunks, lookup] = partition(reader.pages, layout); $: layout, ({ main, secondary } = chunks[lookup[reader.page]]); </script> <svelte:document use:binds={[ ['ArrowLeft', clickLeft], ['ArrowRight', clickRight], ['ArrowUp', prev], ['ArrowDown', next], ['PageUp', prev], ['PageDown', next], [' ', next], ['Backspace', prev], ['Home', () => gotoChunk(0)], ['End', () => gotoChunk(chunks.length - 1)] ]} /> {#if !secondary} <ReaderPage page={main} onclick={clickMain} --justify="center" /> {:else if direction === Direction.LeftToRight} <ReaderPage page={main} onclick={prev} --justify="flex-end" /> <ReaderPage page={secondary} onclick={next} --justify="flex-start" /> {:else} <ReaderPage page={secondary} onclick={next} --justify="flex-end" /> <ReaderPage page={main} onclick={prev} --justify="flex-start" /> {/if} <div class="invisible absolute"> {#each pagesAround(reader.page) as page} <img src={src(page.image, 'full')} alt="" /> {/each} </div>