mirror of
https://github.com/revanced/revanced-website.git
synced 2025-06-13 13:47:39 +02:00
feat: loading spinner and re-add hydration
This commit is contained in:
23
src/lib/components/atoms/Spinner.svelte
Normal file
23
src/lib/components/atoms/Spinner.svelte
Normal 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>
|
@ -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 -->
|
||||||
|
@ -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}
|
||||||
|
@ -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());
|
|
@ -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} />
|
||||||
|
@ -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 {
|
||||||
|
@ -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());
|
|
Reference in New Issue
Block a user