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}">
{tagDisplay} <span>
{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}
</div> {:else}
<div class="column box"> <div class="skeleton-block">
</div>
{/if}
</div>
<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.
@ -101,15 +108,19 @@
<ShiorikoImage alt={post.id} src={post.preview_path} /> <ShiorikoImage alt={post.id} src={post.preview_path} />
</figure> </figure>
{:else} {:else}
<div class="notification is-primary"> <div class="notification is-primary">
Currently viewing original image. Currently viewing original image.
</div> </div>
<figure class="image"> <figure class="image">
<ShiorikoImage alt={post.id} src={post.image_path} /> <ShiorikoImage alt={post.id} src={post.image_path} />
</figure> </figure>
{/if} {/if}
</div> {:else}
<div class="skeleton-block">
</div>
{/if}
</div> </div>
</section> </div>
</div> </section>
{/if} </div>

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,21 +131,30 @@
</form> </form>
</div> </div>
<div class="panel-block column"> <div class="panel-block column">
<div class="menu"> {#if !loading}
<ul class="menu-list"> <div class="row">
{#each tags as tag (tag)} <strong>Tags:</strong>
<li> </div>
<TagLinkNumbered <div class="row">
class="" <div class="menu">
tag={tag.tagType + <ul class="menu-list">
":" + {#each tags as tag (tag)}
tag.tagName} <li>
num={tag.postCount} <TagLinkNumbered
/> class=""
</li> tag={tag.tagType +
{/each} ":" +
</ul> tag.tagName}
</div> num={tag.postCount}
/>
</li>
{/each}
</ul>
</div>
</div>
{:else}
<div class="skeleton-block"></div>
{/if}
</div> </div>
</div> </div>
{#if tagInfo} {#if tagInfo}
@ -169,55 +181,64 @@
</div> </div>
<div class="column is-two-thirds"> <div class="column is-two-thirds">
<div class="columns is-multiline"> <div class="columns is-multiline">
<div class="column is-full"> {#if !loading}
<PostGallery {posts} /> <div class="column is-full">
</div> <PostGallery {posts} />
</div>
<div class="column is-full"> <div class="column is-full">
<nav <nav
class="pagination is-centered" class="pagination is-centered"
aria-label="pagination" aria-label="pagination"
>
<a
href={null}
onclick={() => changePage(page - 1)}
class="pagination-previous"
class:is-disabled={page == 1}>Previous</a
> >
<a <a
href={null} href={null}
onclick={() => changePage(page + 1)} onclick={() => changePage(page - 1)}
class="pagination-next" class="pagination-previous"
class:is-disabled={page == totalPages} class:is-disabled={page == 1}
>Next</a >Previous</a
> >
<ul class="pagination-list"> <a
{#each pagination as pageEntry} href={null}
{#if pageEntry == "..."} onclick={() => changePage(page + 1)}
<li> class="pagination-next"
<span class:is-disabled={page == totalPages}
class="pagination-ellipsis" >Next</a
>&hellip;</span >
> <ul class="pagination-list">
</li> {#each pagination as pageEntry}
{:else} {#if pageEntry == "..."}
<li> <li>
<a <span
href={null} class="pagination-ellipsis"
onclick={() => >&hellip;</span
changePage(pageEntry)} >
class="pagination-link" </li>
class:is-current={page == {:else}
pageEntry} <li>
aria-label="Goto page {pageEntry}" <a
>{pageEntry}</a href={null}
> onclick={() =>
</li> changePage(
{/if} pageEntry,
{/each} )}
</ul> class="pagination-link"
</nav> class:is-current={page ==
</div> pageEntry}
aria-label="Goto page {pageEntry}"
>{pageEntry}</a
>
</li>
{/if}
{/each}
</ul>
</nav>
</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}
</div> {:else}
<div class="column is-two-thirds"> <div class="skeleton-block"></div>
{/if}
</div>
<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 class="skeleton-block"></div>
{/if}
</div> </div>
{/if} </div>
</div> </div>
</section> </section>