feat: smoother loading when checking auth status
This commit is contained in:
parent
cae360fc0e
commit
7a0c0a9007
@ -501,14 +501,48 @@
|
||||
}
|
||||
|
||||
/* Loading spinner */
|
||||
.loading-container {
|
||||
@apply pointer-events-none flex h-screen w-full items-center justify-center;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
@apply relative h-10 w-10;
|
||||
}
|
||||
|
||||
.spinner-dot {
|
||||
@apply bg-[var(--light-accent)];
|
||||
@apply absolute top-[37.5%] inline-block h-1/4 w-1/4 rounded-full bg-[var(--light-accent)];
|
||||
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
|
||||
}
|
||||
|
||||
.dark .spinner-dot {
|
||||
@apply bg-[var(--dark-accent)];
|
||||
}
|
||||
|
||||
.spinner .bounce1 {
|
||||
@apply left-0;
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.spinner .bounce2 {
|
||||
@apply left-[37.5%];
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.spinner .bounce3 {
|
||||
@apply left-3/4;
|
||||
}
|
||||
|
||||
@keyframes sk-bouncedelay {
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main layout */
|
||||
.main-layout-container {
|
||||
@apply flex h-screen bg-[var(--light-background)];
|
||||
|
@ -5,6 +5,15 @@
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
<script>
|
||||
const darkMode = localStorage.getItem("darkMode") === "true" ||
|
||||
(localStorage.getItem("darkMode") === null &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
|
||||
if (darkMode) {
|
||||
document.documentElement.classList.add("dark")
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
|
@ -1,51 +1,7 @@
|
||||
<script>
|
||||
export let size = "40px"
|
||||
// export let useDarkAccent = false
|
||||
</script>
|
||||
|
||||
<div class="spinner" style="width: {size}; height: {size};">
|
||||
<div class="loading-container">
|
||||
<div class="spinner">
|
||||
<div class="bounce1 spinner-dot"></div>
|
||||
<div class="bounce2 spinner-dot"></div>
|
||||
<div class="bounce3 spinner-dot"></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.spinner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
width: 25%;
|
||||
height: 25%;
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
|
||||
position: absolute;
|
||||
top: 37.5%;
|
||||
}
|
||||
|
||||
.spinner .bounce1 {
|
||||
left: 0;
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.spinner .bounce2 {
|
||||
left: 37.5%;
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.spinner .bounce3 {
|
||||
left: 75%;
|
||||
}
|
||||
|
||||
@keyframes sk-bouncedelay {
|
||||
0%,
|
||||
80%,
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
|
@ -17,18 +17,14 @@
|
||||
import ToggleSidebar from "$lib/icons/ToggleSidebar.svelte"
|
||||
import VersionArrow from "$lib/icons/VersionArrow.svelte"
|
||||
|
||||
// Props
|
||||
export let isLoading = false
|
||||
|
||||
// State
|
||||
let isComponentReady = false
|
||||
let sidebarOpen = window.innerWidth > 768
|
||||
let showSettings = false
|
||||
let showVersionsDropdown = false
|
||||
let isEditing = false
|
||||
|
||||
onMount(async (): Promise<any> => {
|
||||
isLoading = true
|
||||
|
||||
try {
|
||||
// The following fetch attempts to refresh any expired tokens automatically
|
||||
await apiClient.getCurrentUser()
|
||||
@ -44,8 +40,6 @@
|
||||
} catch (error) {
|
||||
console.error(`error during auth: ${error}`)
|
||||
goto("/login")
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
// Default to sidebar closed on mobile
|
||||
@ -60,6 +54,8 @@
|
||||
// Keep listening to browser's resize events
|
||||
window.addEventListener("resize", handleResize)
|
||||
|
||||
isComponentReady = true
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize)
|
||||
}
|
||||
@ -173,6 +169,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if isComponentReady}
|
||||
<div class="main-layout-container">
|
||||
<!-- Error notification -->
|
||||
{#if $cError}
|
||||
@ -249,8 +246,8 @@
|
||||
<span class="versions-dropdown-item-text"
|
||||
>{version.createdAt.toLocaleString()}</span
|
||||
>
|
||||
{#if version.isActive}<span class="versions-dropdown-item-text ml-2 opacity-70"
|
||||
>(active)</span
|
||||
{#if version.isActive}<span
|
||||
class="versions-dropdown-item-text ml-2 opacity-70">(active)</span
|
||||
>{/if}
|
||||
</button>
|
||||
{/each}
|
||||
@ -283,3 +280,4 @@
|
||||
<SettingsModal onClose={toggleSettings} />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -10,25 +10,6 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<script lang="ts">
|
||||
if (document) {
|
||||
let darkMode = false
|
||||
const savedTheme = localStorage.getItem("darkMode")
|
||||
|
||||
if (savedTheme !== null) {
|
||||
darkMode = savedTheme === "true"
|
||||
} else {
|
||||
// Fallback to system preference
|
||||
darkMode = window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
localStorage.setItem("darkMode", darkMode ? "true" : "false")
|
||||
}
|
||||
|
||||
document.documentElement.classList.toggle("dark", darkMode)
|
||||
}
|
||||
</script>
|
||||
</svelte:head>
|
||||
|
||||
<button
|
||||
on:click={() => {
|
||||
themeState.isDarkMode = !themeState.isDarkMode
|
||||
|
@ -1,34 +1,21 @@
|
||||
<script>
|
||||
import NoteView from "$lib/components/NoteView.svelte"
|
||||
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte"
|
||||
import NoteView from "$lib/components/NoteView.svelte"
|
||||
import { onMount } from "svelte"
|
||||
import { fade } from "svelte/transition"
|
||||
|
||||
let isLoading = true
|
||||
|
||||
onMount(() => {
|
||||
// Set a small timeout to ensure the loading state shows
|
||||
// -> Prevents component flickering during auth checks
|
||||
// `NoteView` requires a small timeout as it utilizes `window` during init, additionally
|
||||
// especially in prod. we need to give some time for the auth check request
|
||||
setTimeout(() => {
|
||||
isLoading = false
|
||||
}, 500)
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if isLoading}
|
||||
<div class="loading-container" transition:fade={{ duration: 200 }}>
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{:else}
|
||||
<NoteView />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.loading-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user