summaryrefslogtreecommitdiffstatshomepage
path: root/frontend/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/lib')
-rw-r--r--frontend/src/lib/components/Select.svelte22
-rw-r--r--frontend/src/lib/reader/PageView.svelte26
-rw-r--r--frontend/src/lib/reader/Reader.svelte6
-rw-r--r--frontend/src/lib/reader/ReaderPage.svelte35
-rw-r--r--frontend/src/lib/reader/components/PageIndicator.svelte9
5 files changed, 72 insertions, 26 deletions
diff --git a/frontend/src/lib/components/Select.svelte b/frontend/src/lib/components/Select.svelte
index f7e87a4..dece4a5 100644
--- a/frontend/src/lib/components/Select.svelte
+++ b/frontend/src/lib/components/Select.svelte
@@ -1,7 +1,5 @@
<script lang="ts">
import type { ListItem } from '$lib/Utils';
-
- // @ts-expect-error Svelecte 3 does not have types, and 4 (which does) is pending stabilization
import Svelecte from 'svelecte';
let inputId: string;
@@ -17,12 +15,6 @@
export let value: Value;
export { inputId as id, valueAsObject as object, multiple as multi };
-
- function optionsPlaceholder(from: Value): Item[] {
- if (from === undefined || from === null) return [];
-
- return Array.isArray(from) ? from : [from];
- }
</script>
{#if options !== null && options !== undefined}
@@ -39,17 +31,5 @@
bind:value
/>
{:else}
- <Svelecte
- virtualList
- valueField="id"
- labelField="name"
- disabled
- options={optionsPlaceholder(value)}
- {multiple}
- {clearable}
- {inputId}
- {valueAsObject}
- {placeholder}
- {value}
- />
+ <Svelecte {placeholder} />
{/if}
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>