1
0
Fork 0

improved session management

- separated session data to `stores.ts`
- save session data to local storage to prevent flickering
This commit is contained in:
Kim, Jimin 2022-02-26 20:47:17 +09:00
parent bee735e239
commit 463108694f
4 changed files with 112 additions and 18 deletions

View file

@ -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>

View 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]
}

View file

@ -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
View 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)
})
}