diff options
Diffstat (limited to '')
-rw-r--r-- | frontend/src/lib/reader/PageView.svelte | 26 | ||||
-rw-r--r-- | frontend/src/lib/reader/Reader.svelte | 6 | ||||
-rw-r--r-- | frontend/src/lib/reader/ReaderPage.svelte | 35 | ||||
-rw-r--r-- | frontend/src/lib/reader/components/PageIndicator.svelte | 9 |
4 files changed, 71 insertions, 5 deletions
diff --git a/frontend/src/lib/reader/PageView.svelte b/frontend/src/lib/reader/PageView.svelte index cc4d10e..08764b7 100644 --- a/frontend/src/lib/reader/PageView.svelte +++ b/frontend/src/lib/reader/PageView.svelte @@ -2,6 +2,7 @@ import { Direction, Layout, type PageFragment } from '$gql/graphql'; import { getReaderContext, partition, type Chunk } from '$lib/Reader'; import { binds } from '$lib/Shortcuts'; + import { src } from '$lib/Utils'; import ReaderPage from './ReaderPage.svelte'; const reader = getReaderContext(); @@ -21,6 +22,22 @@ $reader.page = chunks[to].index; } + function pagesAround(around: number) { + const peek = (at: number) => { + if (at < 0 || at >= chunks.length) return []; + + const pages = [chunks[at].main]; + + if (chunks[at].secondary) { + pages.push(chunks[at].secondary); + } + + return pages; + }; + + return [...peek(lookup[around] + 1), ...peek(lookup[around] - 1)]; + } + const next = () => gotoChunk(lookup[$reader.page] + 1); const prev = () => gotoChunk(lookup[$reader.page] - 1); @@ -52,7 +69,9 @@ ['PageUp', prev], ['PageDown', next], [' ', next], - ['Backspace', prev] + ['Backspace', prev], + ['Home', () => gotoChunk(0)], + ['End', () => gotoChunk(chunks.length - 1)] ]} /> @@ -65,3 +84,8 @@ <ReaderPage page={secondary} on:click={next} --justify="flex-end" /> <ReaderPage page={main} on:click={prev} --justify="flex-start" /> {/if} +<div class="invisible absolute"> + {#each pagesAround($reader.page) as page} + <img src={src(page.image, 'full')} alt="" /> + {/each} +</div> diff --git a/frontend/src/lib/reader/Reader.svelte b/frontend/src/lib/reader/Reader.svelte index 0b1450a..15ebdf4 100644 --- a/frontend/src/lib/reader/Reader.svelte +++ b/frontend/src/lib/reader/Reader.svelte @@ -4,6 +4,7 @@ import { fadeDefault, slideXDefault } from '$lib/Transitions'; import { fade, slide } from 'svelte/transition'; import CloseReaderButton from './components/CloseReaderButton.svelte'; + import PageIndicator from './components/PageIndicator.svelte'; import ReaderMenuButton from './components/ReaderMenuButton.svelte'; const reader = getReaderContext(); @@ -24,12 +25,15 @@ </aside> {/if} <main class="relative flex grow"> - <div class="absolute flex w-full p-1 text-lg [&>*:last-child]:ml-auto"> + <div class="absolute z-10 flex w-full p-1 text-lg [&>*:last-child]:ml-auto"> {#if $$slots.sidebar} <ReaderMenuButton /> {/if} <CloseReaderButton /> </div> + <div class="absolute bottom-0 right-0 z-10 flex p-1 text-lg"> + <PageIndicator /> + </div> <div class="flex grow"> <slot /> diff --git a/frontend/src/lib/reader/ReaderPage.svelte b/frontend/src/lib/reader/ReaderPage.svelte index fb3e780..c86414d 100644 --- a/frontend/src/lib/reader/ReaderPage.svelte +++ b/frontend/src/lib/reader/ReaderPage.svelte @@ -1,19 +1,48 @@ <script lang="ts"> import type { PageFragment } from '$gql/graphql'; + import Spinner from '$lib/components/Spinner.svelte'; import { src } from '$lib/Utils'; + import { onDestroy } from 'svelte'; export let page: PageFragment; + + let loading = false; + let loadingTimeout: NodeJS.Timeout; + let lastId = -1; + + $: page.id, updateLoadingState(); + + function updateLoadingState() { + if (page.id === lastId) return; + lastId = page.id; + + loadingTimeout = setTimeout(() => (loading = true), 150); + } + + function finishLoading() { + clearTimeout(loadingTimeout); + loading = false; + } + + onDestroy(() => clearTimeout(loadingTimeout)); </script> <!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-no-static-element-interactions --> -<div class="flex grow" on:click> +<div class="relative flex grow" on:click> + <div class="absolute right-0 top-0 z-0 h-full w-full"> + {#if loading} + <Spinner /> + {/if} + </div> <img - class="h-auto w-auto object-contain" + class="h-auto w-auto object-contain transition-opacity duration-200" + class:opacity-0={loading} width={page.image.width} height={page.image.height} src={src(page.image, 'full')} - alt={page.path} + alt="" + on:load={finishLoading} /> </div> diff --git a/frontend/src/lib/reader/components/PageIndicator.svelte b/frontend/src/lib/reader/components/PageIndicator.svelte new file mode 100644 index 0000000..f79fc00 --- /dev/null +++ b/frontend/src/lib/reader/components/PageIndicator.svelte @@ -0,0 +1,9 @@ +<script lang="ts"> + import { getReaderContext } from '$lib/Reader'; + + const reader = getReaderContext(); +</script> + +<div class="floating !p-2"> + {$reader.page + 1}/{$reader.pages.length} +</div> |