feat: loading spinner and re-add hydration

This commit is contained in:
Ax333l
2022-10-22 13:06:55 +02:00
committed by afn
parent aac71915e5
commit 9b97f062c6
7 changed files with 91 additions and 70 deletions

View File

@ -0,0 +1,23 @@
<div class="spin-container">
<img src="/logo.svg" class="logo-image" alt="ReVanced Logo" />
</div>
<style>
.spin-container {
position:absolute;
top:50%;
left:50%;
transform:translate(-50%, -50%);
z-index: 1000;
}
.logo-image {
animation: rotate 2s linear infinite;
width: 75vmin;
height: 75vmin;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,16 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import type { Contributor } from 'src/data/types';
import type { ContribData } from '../../../data/ContributorsStore'; export let repositories: Contributor[];
import { ContributorsStore } from '../../../data/ContributorsStore';
let data: ContribData;
onMount(() => {
ContributorsStore.subscribe(async (e: Promise<ContribData>) => {
data = await e;
});
});
</script> </script>
<hr /> <hr />
@ -37,8 +28,7 @@
</div> </div>
<div class="link-column"> <div class="link-column">
<h5>Repos</h5> <h5>Repos</h5>
{#if data} {#each repositories as { name }}
{#each data.repositories as { name }}
<a href="https://github.com/{name}" target="_blank" rel="noreferrer"> <a href="https://github.com/{name}" target="_blank" rel="noreferrer">
<div> <div>
<h6> <h6>
@ -52,7 +42,6 @@
</div> </div>
</a> </a>
{/each} {/each}
{/if}
</div> </div>
<div class="link-column"> <div class="link-column">
<!-- to replace --> <!-- to replace -->

View File

@ -1,6 +1,31 @@
<script lang="ts"> <script lang="ts">
import NavHost from "$lib/components/molecules/NavHost.svelte"; import NavHost from "$lib/components/molecules/NavHost.svelte";
import '../app.css'; import '../app.css';
import { navigating } from '$app/stores'
import { onMount } from "svelte";
import Spinner from '$lib/components/atoms/Spinner.svelte';
let timeout = 0;
let is_navigating = false;
onMount(() => {
// Show spinner if we are still waiting for navigation after 150ms
navigating.subscribe(nav => {
// cancel current timer, if any
clearTimeout(timeout);
// null after navigation finishes
if (nav != null) {
timeout = setTimeout(() => {
is_navigating = true;
}, 150);
} else {
// navigation finished
is_navigating = false;
}
});
});
</script> </script>
<svelte:head> <svelte:head>
@ -17,4 +42,8 @@
</svelte:head> </svelte:head>
<NavHost/> <NavHost/>
<slot /> {#if is_navigating}
<Spinner />
{:else}
<slot />
{/if}

View File

@ -1,12 +1,11 @@
import { readable } from 'svelte/store';
import type { Repository } from 'src/data/types'; import type { Repository } from 'src/data/types';
export type ContribData = { repositories: Repository[] }; export type ContribData = { repositories: Repository[] };
const fetchContributors = async (): Promise<ContribData> => { export async function load({
fetch
}): Promise<ContribData> {
const response = await fetch('https://releases.rvcd.win/contributors'); const response = await fetch('https://releases.rvcd.win/contributors');
const data = await response.json(); const data = await response.json();
return data; return data;
}; };
export const ContributorsStore = readable(fetchContributors());

View File

@ -1,33 +1,22 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
import type { ContribData } from '../../data/ContributorsStore'; import type { ContribData } from '../+layout';
import { ContributorsStore } from '../../data/ContributorsStore';
import ContributorHost from '$lib/components/molecules/ContributorHost.svelte'; import ContributorHost from '$lib/components/molecules/ContributorHost.svelte';
import Footer from '$lib/components/molecules/Footer.svelte'; import Footer from '$lib/components/molecules/Footer.svelte';
let data: ContribData; // From the layout hydration. See +layout.ts
export let data: ContribData;
onMount(() => {
ContributorsStore.subscribe(async (e: Promise<ContribData>) => {
data = await e;
});
});
</script> </script>
<div class="wrapper contrib-grid"> <div class="wrapper contrib-grid">
{#if data} {#each data.repositories as { contributors, name }}
{#each data.repositories as { contributors, name }} <div in:fly={{ y: 10, easing: quintOut, duration: 750 }}>
<div in:fly={{ y: 10, easing: quintOut, duration: 750 }}> <ContributorHost contribs={contributors} repo={name} />
<ContributorHost contribs={contributors} repo={name} /> </div>
</div> {/each}
{/each}
{/if}
</div> </div>
<style> <style>
@ -39,4 +28,4 @@
} }
</style> </style>
<Footer /> <Footer {...data} />

View File

@ -1,26 +1,22 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import type { PatchesData } from './+page';
import type { ContribData } from '../+layout';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing'; import { quintOut } from 'svelte/easing';
import type { CompatiblePackage, Patch } from 'src/data/types'; import type { CompatiblePackage, Patch } from 'src/data/types';
import type { PatchesData } from '../../data/PatchesStore';
import { PatchesStore } from '../../data/PatchesStore';
import TreeMenu from '$lib/components/molecules/TreeMenu.svelte'; import TreeMenu from '$lib/components/molecules/TreeMenu.svelte';
import TreeMenuButton from '$lib/components/atoms/TreeMenuButton.svelte'; import TreeMenuButton from '$lib/components/atoms/TreeMenuButton.svelte';
import PatchCell from '$lib/components/atoms/PatchCell.svelte'; import PatchCell from '$lib/components/atoms/PatchCell.svelte';
import Footer from '$lib/components/molecules/Footer.svelte'; import Footer from '$lib/components/molecules/Footer.svelte';
let patches: Patch[]; export let data: PatchesData & ContribData;
let packages: string[];
let current: boolean = false;
onMount(() => { let { patches, packages } = data;
PatchesStore.subscribe(async (e: Promise<PatchesData>) => {
({ patches, packages } = await e); let current: boolean = false;
});
});
function search(findTerm: string | boolean, array: CompatiblePackage[]) { function search(findTerm: string | boolean, array: CompatiblePackage[]) {
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
@ -41,27 +37,23 @@
<section> <section>
<aside in:fly={{ y: 10, easing: quintOut, duration: 750 }}> <aside in:fly={{ y: 10, easing: quintOut, duration: 750 }}>
<TreeMenu title="packages"> <TreeMenu title="packages">
{#if packages} {#each packages as pkg}
{#each packages as pkg} <TreeMenuButton bind:current name={pkg} />
<TreeMenuButton bind:current name={pkg} /> {/each}
{/each}
{/if}
</TreeMenu> </TreeMenu>
</aside> </aside>
<div class="patches-container"> <div class="patches-container">
{#if patches} {#each patches as patch, i}
{#each patches as patch, i} {#if search(current, patch.compatiblePackages) || !current}
{#if search(current, patch.compatiblePackages) || !current} <div in:fly={{ x: 10, easing: quintOut, duration: 750, delay: -(300 * 0.85 ** i) + 300 }}>
<div in:fly={{ x: 10, easing: quintOut, duration: 750, delay: -(300 * 0.85 ** i) + 300 }}> <PatchCell bind:current {patch} />
<PatchCell bind:current {patch} /> </div>
</div> {/if}
{/if} {/each}
{/each}
{/if}
</div> </div>
</section> </section>
<Footer /> <Footer repositories={data.repositories} />
<style> <style>
section { section {

View File

@ -3,7 +3,9 @@ import type { Patch } from 'src/data/types';
export type PatchesData = { patches: Patch[]; packages: string[] }; export type PatchesData = { patches: Patch[]; packages: string[] };
const fetchPatches = async (): Promise<PatchesData> => { export async function load({
fetch
}): Promise<PatchesData> {
const response = await fetch('https://releases.rvcd.win/patches'); const response = await fetch('https://releases.rvcd.win/patches');
const patches = await response.json(); const patches = await response.json();
let packages: string[] = []; let packages: string[] = [];
@ -19,5 +21,3 @@ const fetchPatches = async (): Promise<PatchesData> => {
} }
return { patches, packages }; return { patches, packages };
}; };
export const PatchesStore = readable(fetchPatches());