Skip to content

Commit b3433a4

Browse files
committed
add LoadingSpinner with placeholder tips (see desc
the old tips.json was simple, but it made it so english text was always on the page if something was loading, regardless of language i also heard early on that some translators wanted to make tips for their language too, which wasnt possible with the old tips.json for now, this uses a placeholder list of tips built into loadingspinner, but later ill figure out a better place to put tips
1 parent 4f444ca commit b3433a4

4 files changed

Lines changed: 135 additions & 4 deletions

File tree

src/lib/components/CategoryHome/MyFeed.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// components
66
import { Category, UserDisplay } from "PenguinMod-SvelteUI";
77
import Icon from "$lib/components/Icon/Component.svelte";
8+
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
89
import LocalizedString from "$lib/components/Localization/LocalizedString.svelte";
910
1011
import { CACHE_USER_FEED } from "$lib/resources/cache/cache-time";
@@ -102,7 +103,9 @@
102103
</div>
103104
{:else}
104105
{#if loading}
105-
<p>TODO: Loading spinner</p>
106+
<div class="category-textdisplay">
107+
<LoadingSpinner />
108+
</div>
106109
{:else if failed}
107110
<div class="category-textdisplay" style="color:red">
108111
<p>

src/lib/components/CategoryHome/WhatsNew.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// components
55
import { Category, UserDisplay } from "PenguinMod-SvelteUI";
66
import Icon from "$lib/components/Icon/Component.svelte";
7+
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
78
import LocalizedString from "$lib/components/Localization/LocalizedString.svelte";
89
910
import { CACHE_BASIC_API_UPDATES } from "$lib/resources/cache/cache-time";
@@ -65,7 +66,9 @@
6566
</a>
6667
{/snippet}
6768
{#if loading}
68-
<p>TODO: Loading spinner</p>
69+
<div class="single-container">
70+
<LoadingSpinner />
71+
</div>
6972
{:else if failed}
7073
<div class="single-container" style="color:red">
7174
<!-- TODO: UNIMPORTANT: PenguinSVG: server down icon -->
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<script>
2+
import { onMount } from "svelte";
3+
import { browser } from "$app/environment";
4+
5+
// components
6+
import LocalizedAlt from "./Localization/LocalizedAlt.svelte";
7+
import LocalizedTooltip from "./Localization/LocalizedTooltip.svelte";
8+
9+
import delay from "$lib/resources/delay.js";
10+
11+
import StoreSettings from "$lib/stores/settings";
12+
13+
let props = $props();
14+
15+
// TODO: I do not want to have the same Tips.json structure as legacy home, so this is just a placeholder. What I *really* want is to figure out how to structure a list of tips that can be translated. Translators really wanna make tips too.
16+
const tips = [
17+
"This is a tip.",
18+
"This is also a tip.",
19+
"Did you know this list of tips is going to be replaced?",
20+
"Fun fact: This is a tip.",
21+
"Fun fact: You are waiting for something to load.",
22+
"Good job ianyourgod",
23+
"Good job jwklong",
24+
"Good job JeremyGamer13",
25+
"Good job godslayerakp",
26+
];
27+
28+
/** @type {HTMLSpanElement} */
29+
// svelte-ignore non_reactive_update
30+
let tipsSpan = null;
31+
let tipsLast = null;
32+
let tipsText = $state("");
33+
let tipsMounted = $state(true);
34+
const tipsEnabled = $derived(props.tips !== false);
35+
const tipsSwap = async () => {
36+
if (!browser) return;
37+
if (!tipsMounted) return;
38+
if (!tipsEnabled) return;
39+
if (!tipsSpan) return;
40+
41+
// we fade out, swap tip, then fade in
42+
console.log("changing tips"); // TODO: Temp
43+
if (tipsSpan.dataset.swapped === "true") {
44+
tipsSpan.animate([{ opacity: "0" }], { duration: 1000, fill: "forwards" });
45+
await delay(1000);
46+
}
47+
48+
// swap tip
49+
const possibleTips = tips.filter(value => value !== tipsLast);
50+
tipsText = possibleTips[Math.floor(Math.random() * possibleTips.length)];
51+
tipsSpan.dataset.swapped = true;
52+
53+
// fade in
54+
tipsSpan.animate([{ opacity: "1" }], { duration: 1000, fill: "forwards" });
55+
};
56+
const tipsLoop = async () => {
57+
// NOTE: wait a second so we dont show a tip if there's no reason to
58+
await delay(1000);
59+
60+
// swap tips every 7 seconds
61+
tipsSwap();
62+
const interval = setInterval(() => {
63+
if (!tipsMounted) clearInterval(interval);
64+
tipsSwap();
65+
}, 7000);
66+
};
67+
onMount(() => {
68+
if (!tipsEnabled) return;
69+
tipsLoop();
70+
return () => {
71+
tipsMounted = false;
72+
};
73+
});
74+
</script>
75+
76+
<div class="loading">
77+
<img
78+
src={$StoreSettings.appTheme === "light" ? "/asset/icons/loading-blue.svg" : "/asset/icons/loading-white.svg"}
79+
alt="Loading"
80+
{@attach LocalizedAlt("generic.loading")}
81+
{@attach LocalizedTooltip("generic.loading")}
82+
/>
83+
{#if tipsEnabled}
84+
<span
85+
style="opacity:0"
86+
data-swapped={false}
87+
bind:this={tipsSpan}
88+
>
89+
{tipsText}
90+
</span>
91+
{/if}
92+
</div>
93+
94+
<style>
95+
.loading {
96+
width: 100%;
97+
98+
display: flex;
99+
flex-direction: column;
100+
align-items: center;
101+
}
102+
.loading img {
103+
animation-name: loading;
104+
animation-delay: 0s;
105+
animation-duration: 1s;
106+
animation-iteration-count: infinite;
107+
animation-timing-function: linear;
108+
109+
user-select: none;
110+
}
111+
.loading span {
112+
margin-top: 8px;
113+
114+
user-select: none;
115+
}
116+
117+
@keyframes loading {
118+
0% { transform: rotate(0deg); }
119+
50% { transform: rotate(180deg); }
120+
100% { transform: rotate(360deg); }
121+
}
122+
</style>

src/routes/+page.svelte

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { Button, Category, SwappableHolder, Project } from "PenguinMod-SvelteUI";
99
import Icon from "$lib/components/Icon/Component.svelte";
1010
import MyFeed from "$lib/components/CategoryHome/MyFeed.svelte";
11+
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
1112
import WhatsNew from "$lib/components/CategoryHome/WhatsNew.svelte";
1213
import PenguinNews from "$lib/components/CategoryHome/PenguinNews.svelte";
1314
import LocalizedString from "$lib/components/Localization/LocalizedString.svelte";
@@ -287,7 +288,9 @@
287288
<!-- snippet for each section to reuse -->
288289
{#snippet projectRow(section)}
289290
{#if frontPageLoading}
290-
TODO: Loading spinner
291+
<div class="section-categories-projects-rowtext">
292+
<LoadingSpinner />
293+
</div>
291294
{:else if frontPageError}
292295
<div
293296
class="section-categories-projects-rowtext"
@@ -842,7 +845,7 @@
842845
}
843846
.section-categories-projects-rowtext {
844847
width: 100%;
845-
height: 100%;
848+
height: 200px;
846849
847850
display: flex;
848851
flex-direction: column;

0 commit comments

Comments
 (0)