Skip to content

Commit

Permalink
Pagination mostly working
Browse files Browse the repository at this point in the history
  • Loading branch information
eyeseast committed May 15, 2024
1 parent c747a5c commit 647628b
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 21 deletions.
16 changes: 14 additions & 2 deletions src/lib/components/documents/PDFPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ Selectable text can be rendered in one of two ways:
// keep track of this to avoid overlapping renders
let renderTask;
// visibility, for loading optimization
let visible: boolean = false;
$: aspect = height / width;
$: orientation = height > width ? "vertical" : "horizontal";
$: numericScale = fitPage(width, height, container, scale);
Expand All @@ -43,8 +46,10 @@ Selectable text can be rendered in one of two ways:
/**
* Return a numeric scale based on intrinsic page size and container size
* @param page
* @param width Original document width
* @param height Original document height
* @param container
* @param scale
*/
function fitPage(
width: number,
Expand Down Expand Up @@ -136,10 +141,17 @@ Selectable text can be rendered in one of two ways:

<svelte:window on:resize={onResize} />

<Page {page_number} wide={scale === "width"} tall={scale === "height"}>
<Page
{page_number}
wide={scale === "width"}
tall={scale === "height"}
track
let:visible
>
<div
bind:this={container}
class="page-container scale-{scale} {orientation}"
class:visible
style:--aspect={aspect}
style:--scale-factor={numericScale.toFixed(2)}
style:--width="{width}px"
Expand Down
70 changes: 67 additions & 3 deletions src/lib/components/documents/Page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts">
import type { ViewerMode } from "@/lib/api/types";
import { createEventDispatcher, getContext, onMount } from "svelte";
import type { Writable } from "svelte/store";
import { _ } from "svelte-i18n";
import { pageHashUrl } from "$lib/api/documents";
Expand All @@ -9,19 +11,81 @@
export let mode: ViewerMode = "document";
export let wide = false;
export let tall = false;
export let track: boolean | "once" = false;
const currentPage: Writable<number> = getContext("currentPage");
const dispatch = createEventDispatcher();
let io: IntersectionObserver;
let container: HTMLElement;
let heading: HTMLElement;
let visible: boolean;
$: id = pageHashUrl(page_number).replace("#", "");
$: href = `?mode=${mode}` + pageHashUrl(page_number);
function watch(el: HTMLElement, once = false): IntersectionObserver {
const io = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// update state
visible = true;
dispatch("visible");
if (once) {
observer.unobserve(el);
}
} else {
visible = false;
}
const { boundingClientRect, rootBounds } = entry;
if (
boundingClientRect.top > rootBounds.top &&
boundingClientRect.top < rootBounds.height / 2
) {
$currentPage = page_number;
}
});
},
{
// [0, 0.1, 0.2, ...]
threshold: Array(11)
.fill(undefined)
.map((n, i) => i / 10),
},
);
io.observe(el);
return io;
}
function unwatch(io: IntersectionObserver, el: HTMLElement) {
io?.unobserve(el);
}
onMount(() => {
if (track) {
io = watch(container, track === "once");
}
return () => {
unwatch(io, container);
};
});
</script>

<div class="page" class:wide class:tall>
<h4 {id}>
<div bind:this={container} class="page" class:wide class:tall>
<h4 bind:this={heading} {id}>
<a {href}>
{$_("documents.pageAbbrev")}
{page_number}
</a>
</h4>
<slot {id} {href} />
<slot {id} {href} {visible} />
</div>

<style>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/documents/TextPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
export let contents: string;
</script>

<Page page_number={page + 1} mode="text">
<Page page_number={page + 1} mode="text" track>
<pre>
{contents}
</pre>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/documents/[id]-[slug]/+layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getPinnedAddons } from "$lib/api/addons";
import { breadcrumbTrail, getPrivateAsset } from "$lib/utils/index";

function documentPath(document: Document) {
return `/documents/${document.id}-${document.slug}`;
return `/documents/${document.id}-${document.slug}/`;
}

/** @type {import('./$types').PageLoad} */
Expand All @@ -30,7 +30,7 @@ export async function load({ fetch, params, parent }) {
}

const breadcrumbs = await breadcrumbTrail(parent, [
{ href: "/app", title: "Documents" }, // TODO: move document manager to `/documents` route
{ href: "/app/", title: "Documents" }, // TODO: move document manager to `/documents` route
{ href: documentPath(document), title: document.title },
]);

Expand Down
41 changes: 28 additions & 13 deletions src/routes/documents/[id]-[slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import type { Sizes, ViewerMode } from "@/lib/api/types.js";
import { browser } from "$app/environment";
import { afterNavigate, goto } from "$app/navigation";
import { afterNavigate, goto, replaceState } from "$app/navigation";
import { page } from "$app/stores";
import { setContext } from "svelte";
import { writable, type Writable } from "svelte/store";
import { _ } from "svelte-i18n";
// icons
Expand Down Expand Up @@ -42,8 +44,10 @@
notes: NotesIcon,
};
// internal state
let currentPage = 1;
// pagination store, available via context
const currentPage: Writable<number> = writable(1);
setContext("currentPage", currentPage);
$: document = data.document;
$: mode = data.mode;
Expand All @@ -55,10 +59,10 @@
afterNavigate(() => {
const { hash } = $page.url;
currentPage = pageFromHash(hash);
$currentPage = pageFromHash(hash);
if (currentPage > 1) {
scrollToPage(currentPage);
if ($currentPage > 1) {
scrollToPage($currentPage);
}
});
Expand All @@ -73,24 +77,33 @@
// pagination
function next() {
currentPage = Math.min(currentPage + 1, document.page_count);
$currentPage = Math.min($currentPage + 1, document.page_count);
scrollToPage($currentPage);
}
function previous() {
currentPage = Math.max(currentPage - 1, 1);
$currentPage = Math.max($currentPage - 1, 1);
scrollToPage($currentPage);
}
function onHashChange(e: HashChangeEvent) {
const { hash } = new URL(e.newURL);
$currentPage = pageFromHash(hash);
scrollToPage($currentPage);
}
// scroll to a page
function scrollToPage(n: number) {
currentPage = n;
if (!browser) return;
const pageId = pageHashUrl(n).replace("#", "");
const heading = window.document.getElementById(pageId);
if (!heading) return console.error(`Missing page ${n}`);
heading.scrollIntoView();
// push or replace?
replaceState(pageHashUrl(n), {});
}
/**
Expand Down Expand Up @@ -170,6 +183,8 @@
}
</script>

<svelte:window on:hashchange={onHashChange} />

<ContentLayout>
<PageToolbar slot="header">
<Search slot="center" />
Expand Down Expand Up @@ -211,10 +226,10 @@
on:goTo={(e) => scrollToPage(e.detail)}
on:next={next}
on:previous={previous}
bind:page={currentPage}
bind:page={$currentPage}
totalPages={document.page_count}
has_next={currentPage < document.page_count}
has_previous={currentPage > 1}
has_next={$currentPage < document.page_count}
has_previous={$currentPage > 1}
/>
{/if}
</svelte:fragment>
Expand Down

0 comments on commit 647628b

Please sign in to comment.