From 20cdd8e68888665bcdecbbc612b3787facc65c46 Mon Sep 17 00:00:00 2001 From: Max Nuding Date: Fri, 7 Apr 2023 09:50:02 +0200 Subject: [PATCH] Animate loading button and new posts arriving --- src/lib/components/LoadMoreComponent.svelte | 26 ++++++++- .../components/LoadingSpinnerComponent.svelte | 38 +++++++++++++ src/routes/+page.svelte | 54 ++++++++++++++++--- 3 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 src/lib/components/LoadingSpinnerComponent.svelte diff --git a/src/lib/components/LoadMoreComponent.svelte b/src/lib/components/LoadMoreComponent.svelte index 3ed2f49..0af7935 100644 --- a/src/lib/components/LoadMoreComponent.svelte +++ b/src/lib/components/LoadMoreComponent.svelte @@ -1,5 +1,6 @@ - + \ No newline at end of file diff --git a/src/lib/components/LoadingSpinnerComponent.svelte b/src/lib/components/LoadingSpinnerComponent.svelte new file mode 100644 index 0000000..e41ec9f --- /dev/null +++ b/src/lib/components/LoadingSpinnerComponent.svelte @@ -0,0 +1,38 @@ + + +
+ \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 9ff2b00..82d4b89 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -5,20 +5,52 @@ import type { Post } from '$lib/mastodon/response'; import { PUBLIC_REFRESH_INTERVAL, PUBLIC_MASTODON_INSTANCE_DISPLAY_NAME } from '$env/static/public'; import PostComponent from '$lib/components/PostComponent.svelte'; import LoadMoreComponent from '$lib/components/LoadMoreComponent.svelte'; +import { fly, type FlyParams } from 'svelte/transition'; +import { cubicInOut } from 'svelte/easing'; + export let data: PageData; -const refreshInterval = parseInt(PUBLIC_REFRESH_INTERVAL); -let interval: NodeJS.Timer | null = null; -let moreOlderPostsAvailable = true; -let loadingOlderPosts = false; - interface FetchOptions { since?: string, before?: string, count?: number } +interface EdgeFlyParams extends FlyParams { + created_at: string +} + +const refreshInterval = parseInt(PUBLIC_REFRESH_INTERVAL) * 10; +let interval: NodeJS.Timer | null = null; +let moreOlderPostsAvailable = true; +let loadingOlderPosts = false; + +// Needed, so that edgeFly() can do its thing: +// To determine whether a newly loaded post is older than the existing ones, is required to know what the oldest +// post was, before the fetch happened. +let oldestBeforeLastFetch: number | null = null; + +/** + * Animate either from the top, or the bottom of the window, depending if the post is + * newer than the existing ones or older. + */ +function edgeFly(node: Element, opts: EdgeFlyParams) { + const createdAt = new Date(opts.created_at).getTime(); + const diffNewest = Math.abs(new Date(data.posts[0].created_at).getTime() - createdAt); + const oldest = oldestBeforeLastFetch !== null + ? oldestBeforeLastFetch + : new Date(data.posts[data.posts.length - 1].created_at).getTime(); + const diffOldest = Math.abs(oldest - createdAt); + const fromTop = diffNewest <= diffOldest; + + const rect = node.getBoundingClientRect(); + const paramY = +`${opts.y}`; + let offset = isNaN(paramY) ? 0 : paramY + rect.height; + opts.y = fromTop ? -offset : window.innerHeight + offset; + return fly(node, opts); +} + async function fetchPosts(options: FetchOptions): Promise { const params = new URLSearchParams(); if (options?.since !== undefined) { @@ -60,6 +92,9 @@ function refresh() { } onMount(async () => { + if (data.posts.length > 0) { + oldestBeforeLastFetch = new Date(data.posts[data.posts.length - 1].created_at).getTime(); + } interval = setInterval(refresh, refreshInterval); // - If the page is hidden, slow down refresh rate @@ -84,6 +119,7 @@ function loadOlderPosts() { const filter: FetchOptions = { count: 20 }; if (data.posts.length > 0) { filter.before = data.posts[data.posts.length - 1].created_at; + oldestBeforeLastFetch = new Date(filter.before).getTime(); } @@ -119,7 +155,12 @@ function loadOlderPosts() { Sorry, no posts recommending music aave been found yet {/if} {#each data.posts as post (post.url)} -
+
+ +
{/each} \ No newline at end of file