improved session management
- separated session data to `stores.ts` - save session data to local storage to prevent flickering
This commit is contained in:
parent
bee735e239
commit
463108694f
4 changed files with 112 additions and 18 deletions
|
@ -1,18 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { page } from "$app/stores"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
let isLoggedIn = false
|
||||
let userData: UserData = undefined
|
||||
|
||||
onMount(() => {
|
||||
fetch("/api/user-data", { credentials: "same-origin" })
|
||||
.then((data) => data.json())
|
||||
.then((data) => {
|
||||
isLoggedIn = true
|
||||
userData = data
|
||||
})
|
||||
})
|
||||
import { userData } from "../stores"
|
||||
</script>
|
||||
|
||||
<header>
|
||||
|
@ -41,19 +29,19 @@
|
|||
</div>
|
||||
|
||||
<div class="login-logout">
|
||||
{#if isLoggedIn}
|
||||
{#if $userData}
|
||||
<div class="user">
|
||||
<img
|
||||
alt="user pfp"
|
||||
src={`https://cdn.discordapp.com/avatars/${userData.id}/${userData.avatar}.png`}
|
||||
src={`https://cdn.discordapp.com/avatars/${$userData.id}/${$userData.avatar}.png`}
|
||||
/>
|
||||
{userData.username}#{userData.discriminator}
|
||||
{$userData.username}#{$userData.discriminator}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="login-logout-button">
|
||||
<a href={isLoggedIn ? "/api/logout" : "/api/login"}>
|
||||
{isLoggedIn ? "Logout" : "Login"}
|
||||
<a href={$userData ? "/api/logout" : "/api/login"}>
|
||||
{$userData ? "Logout" : "Login"}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
84
frontend/src/local-storage-store.ts
Normal file
84
frontend/src/local-storage-store.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Code taken from https://github.com/joshnuss/svelte-local-storage-store
|
||||
*/
|
||||
|
||||
import { writable as internal, get } from "svelte/store"
|
||||
import type { Writable } from "svelte/store"
|
||||
|
||||
declare type Updater<T> = (value: T) => T
|
||||
declare type StoreDict<T> = { [key: string]: Writable<T> }
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const stores: StoreDict<any> = {}
|
||||
|
||||
function stringify(value: any): string {
|
||||
switch (value) {
|
||||
case undefined: {
|
||||
return "undefined"
|
||||
}
|
||||
|
||||
case null: {
|
||||
return "null"
|
||||
}
|
||||
|
||||
default: {
|
||||
return JSON.stringify(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parse<T>(value: string) {
|
||||
switch (value) {
|
||||
case "undefined": {
|
||||
return undefined
|
||||
}
|
||||
|
||||
case "null": {
|
||||
return null
|
||||
}
|
||||
|
||||
default: {
|
||||
return <T>JSON.parse(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function writable<T>(key: string, initialValue: T): Writable<T> {
|
||||
if (!stores[key]) {
|
||||
const store = internal(initialValue, (set) => {
|
||||
const json = localStorage.getItem(key)
|
||||
|
||||
if (json) set(parse<T>(json))
|
||||
|
||||
const handleStorage = (event: StorageEvent) => {
|
||||
if (event.key === key) {
|
||||
set(event.newValue ? <T>parse(event.newValue) : null)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("storage", handleStorage)
|
||||
|
||||
return () => window.removeEventListener("storage", handleStorage)
|
||||
})
|
||||
|
||||
const { subscribe, set } = store
|
||||
|
||||
stores[key] = {
|
||||
set(value: T) {
|
||||
localStorage.setItem(key, stringify(value))
|
||||
set(value)
|
||||
},
|
||||
|
||||
update(updater: Updater<T>) {
|
||||
const value = updater(get(store))
|
||||
|
||||
localStorage.setItem(key, stringify(value))
|
||||
set(value)
|
||||
},
|
||||
|
||||
subscribe,
|
||||
}
|
||||
}
|
||||
|
||||
return stores[key]
|
||||
}
|
|
@ -1,8 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { updateUserData } from "../stores"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
import Header from "$lib/Header.svelte"
|
||||
import Footer from "$lib/Footer.svelte"
|
||||
|
||||
import { Circle2 } from "svelte-loading-spinners"
|
||||
|
||||
// load user data on page load
|
||||
onMount(() => {
|
||||
updateUserData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<Header />
|
||||
|
|
14
frontend/src/stores.ts
Normal file
14
frontend/src/stores.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { writable } from "./local-storage-store"
|
||||
|
||||
export const userData = writable<UserData>("userData", undefined)
|
||||
|
||||
export async function updateUserData() {
|
||||
fetch("/api/user-data", { credentials: "same-origin" })
|
||||
.then((data) => data.json())
|
||||
.then((data) => {
|
||||
userData.set(data)
|
||||
})
|
||||
.catch(() => {
|
||||
userData.set(undefined)
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue