feat: add loading states

This commit is contained in:
Damillora 2025-02-22 15:29:20 +00:00
parent 413579e08d
commit 7bb7a3389b
6 changed files with 142 additions and 86 deletions

View File

@ -3,6 +3,7 @@
let { alt, src } = $props(); let { alt, src } = $props();
let loading = $state(false); let loading = $state(false);
let failed = $state(false);
onMount(() => { onMount(() => {
const img = new Image(); const img = new Image();
@ -11,13 +12,22 @@
img.onload = () => { img.onload = () => {
loading = false; loading = false;
failed = false;
}; };
img.onerror = () => { img.onerror = () => {
loading = true; loading = true;
failed = true;
}; };
}) })
</script> </script>
{#if !failed}
<figure class:is-skeleton="{loading}"> <figure class:is-skeleton="{loading}">
<img {src} {alt} /> <img {src} {alt} />
</figure> </figure>
{:else}
<div class="notification is-danger is-light">
There was an error loading this image.
</div>
{/if}

View File

@ -9,7 +9,9 @@
</script> </script>
<a href="/posts?tags={tagName}"> <a href="/posts?tags={tagName}">
<span>
{tagDisplay} {tagDisplay}
</span>
<TagTypeIndicator tagType={tagType}></TagTypeIndicator> <TagTypeIndicator tagType={tagType}></TagTypeIndicator>
<span class="is-pulled-right">{num}</span> <span class="is-pulled-right">{num}</span>
</a> </a>

View File

@ -15,6 +15,7 @@
post = data; post = data;
imagePercentage = ((1000 * 100) / post.width).toFixed(0) + "%"; imagePercentage = ((1000 * 100) / post.width).toFixed(0) + "%";
}; };
let loading = $state(false);
let isOriginal = $state(false); let isOriginal = $state(false);
const trimUrl = (str: string) => { const trimUrl = (str: string) => {
@ -53,11 +54,11 @@
let imagePercentage = $state("0%"); let imagePercentage = $state("0%");
</script> </script>
{#if post}
<div class="container"> <div class="container">
<section class="section"> <section class="section">
<div class="columns"> <div class="columns">
<div class="column is-one-third"> <div class="column is-one-third">
{#if post}
{#if editMenuShown == false && deleteMenuShown == false} {#if editMenuShown == false && deleteMenuShown == false}
<ViewPostPanel <ViewPostPanel
{post} {post}
@ -88,8 +89,14 @@
</div> </div>
</div> </div>
{/if} {/if}
{:else}
<div class="skeleton-block">
</div>
{/if}
</div> </div>
<div class="column box"> <div class="column box">
{#if post}
{#if post.width > 1000 && isOriginal == false} {#if post.width > 1000 && isOriginal == false}
<div class="notification is-info"> <div class="notification is-info">
Resized to {imagePercentage} of the original image. Resized to {imagePercentage} of the original image.
@ -108,8 +115,12 @@
<ShiorikoImage alt={post.id} src={post.image_path} /> <ShiorikoImage alt={post.id} src={post.image_path} />
</figure> </figure>
{/if} {/if}
{:else}
<div class="skeleton-block">
</div>
{/if}
</div> </div>
</div> </div>
</section> </section>
</div> </div>
{/if}

View File

@ -23,6 +23,7 @@
let tags = $state([]); let tags = $state([]);
let tagInfo = $state(null); let tagInfo = $state(null);
let categorizedTags = {}; let categorizedTags = {};
let loading = $state(false);
const getData = async () => { const getData = async () => {
const data = await getPosts({ page, q: searchTerms.join("+") }); const data = await getPosts({ page, q: searchTerms.join("+") });
@ -49,6 +50,7 @@
if (searchTerms.filter((x) => !x.startsWith("-")).length == 1) { if (searchTerms.filter((x) => !x.startsWith("-")).length == 1) {
tagInfo = await getTag({ tag: searchTerms[0] }); tagInfo = await getTag({ tag: searchTerms[0] });
} }
loading = false;
}; };
let tagQuery = $state(); let tagQuery = $state();
@ -62,6 +64,7 @@
}; };
afterNavigate(() => { afterNavigate(() => {
loading = true;
tagQuery = url.searchParams.get("tags"); tagQuery = url.searchParams.get("tags");
if (tagQuery) { if (tagQuery) {
searchTerms = tagQuery.split(" "); searchTerms = tagQuery.split(" ");
@ -99,7 +102,7 @@
</div> </div>
<div class="column is-one-third"> <div class="column is-one-third">
<div class="panel is-primary"> <div class="panel is-primary">
<div class="panel-heading">Tags</div> <div class="panel-heading">Menu</div>
<div class="panel-block column"> <div class="panel-block column">
<form onsubmit={onSearch}> <form onsubmit={onSearch}>
<div class="field"> <div class="field">
@ -128,6 +131,11 @@
</form> </form>
</div> </div>
<div class="panel-block column"> <div class="panel-block column">
{#if !loading}
<div class="row">
<strong>Tags:</strong>
</div>
<div class="row">
<div class="menu"> <div class="menu">
<ul class="menu-list"> <ul class="menu-list">
{#each tags as tag (tag)} {#each tags as tag (tag)}
@ -144,6 +152,10 @@
</ul> </ul>
</div> </div>
</div> </div>
{:else}
<div class="skeleton-block"></div>
{/if}
</div>
</div> </div>
{#if tagInfo} {#if tagInfo}
<div class="panel is-info"> <div class="panel is-info">
@ -169,6 +181,7 @@
</div> </div>
<div class="column is-two-thirds"> <div class="column is-two-thirds">
<div class="columns is-multiline"> <div class="columns is-multiline">
{#if !loading}
<div class="column is-full"> <div class="column is-full">
<PostGallery {posts} /> <PostGallery {posts} />
</div> </div>
@ -182,7 +195,8 @@
href={null} href={null}
onclick={() => changePage(page - 1)} onclick={() => changePage(page - 1)}
class="pagination-previous" class="pagination-previous"
class:is-disabled={page == 1}>Previous</a class:is-disabled={page == 1}
>Previous</a
> >
<a <a
href={null} href={null}
@ -205,7 +219,9 @@
<a <a
href={null} href={null}
onclick={() => onclick={() =>
changePage(pageEntry)} changePage(
pageEntry,
)}
class="pagination-link" class="pagination-link"
class:is-current={page == class:is-current={page ==
pageEntry} pageEntry}
@ -218,6 +234,11 @@
</ul> </ul>
</nav> </nav>
</div> </div>
{:else}
<div class="column">
<div class="skeleton-block"></div>
</div>
{/if}
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,13 +6,16 @@
import TagTypeIndicator from '$lib/components/ui/TagTypeIndicator.svelte'; import TagTypeIndicator from '$lib/components/ui/TagTypeIndicator.svelte';
let tags = $state([]); let tags = $state([]);
let loading = $state(false);
const getData = async () => { const getData = async () => {
const data = await getTags(); const data = await getTags();
tags = data; tags = data;
loading = false;
}; };
afterNavigate(() => { afterNavigate(() => {
loading = true;
getData(); getData();
}) })
</script> </script>
@ -21,6 +24,7 @@
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<h1 class="title">Tag List</h1> <h1 class="title">Tag List</h1>
{#if !loading}
<table class="table is-fullwidth"> <table class="table is-fullwidth">
<thead> <thead>
<tr> <tr>
@ -41,5 +45,8 @@
{/each} {/each}
</tbody> </tbody>
</table> </table>
{:else}
<div class="skeleton-block"></div>
{/if}
</div> </div>
</section> </section>

View File

@ -8,7 +8,6 @@
import EditTagPanel from "$lib/components/panels/EditTagPanel.svelte"; import EditTagPanel from "$lib/components/panels/EditTagPanel.svelte";
import PostGallery from "$lib/components/ui/PostGallery.svelte"; import PostGallery from "$lib/components/ui/PostGallery.svelte";
import { page } from "$app/stores"; import { page } from "$app/stores";
let { tag } = $state($page.params); let { tag } = $state($page.params);
@ -51,9 +50,9 @@
<section class="section"> <section class="section">
<div class="container"> <div class="container">
{#if data}
<div class="columns"> <div class="columns">
<div class="column is-one-third"> <div class="column is-one-third">
{#if data}
{#if renameMenuShown} {#if renameMenuShown}
<EditTagPanel <EditTagPanel
{tag} {tag}
@ -64,8 +63,12 @@
{:else} {:else}
<ViewTagPanel {tag} {data} {toggleRenameMenu} /> <ViewTagPanel {tag} {data} {toggleRenameMenu} />
{/if} {/if}
{:else}
<div class="skeleton-block"></div>
{/if}
</div> </div>
<div class="column is-two-thirds"> <div class="column is-two-thirds">
{#if data}
{#if editMenuShown} {#if editMenuShown}
<EditTagNotesPanel <EditTagNotesPanel
{tag} {tag}
@ -78,8 +81,10 @@
{/if} {/if}
<h1 class="title">Posts</h1> <h1 class="title">Posts</h1>
<PostGallery {posts} /> <PostGallery {posts} />
</div> {:else}
</div> <div class="skeleton-block"></div>
{/if} {/if}
</div> </div>
</div>
</div>
</section> </section>