diff --git a/frontend/index.html b/frontend/index.html index 97b7829..2654fa3 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -49,9 +49,8 @@ - - - + + diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/@types/dom.d.ts b/frontend/src/@types/dom.d.ts index 1c35dd9..49c1fcf 100644 --- a/frontend/src/@types/dom.d.ts +++ b/frontend/src/@types/dom.d.ts @@ -1,14 +1,27 @@ +import { type State } from "ft_state"; + interface CustomEventMap { - "ft:pageChange": CustomEvent<{}>; + "ft:pageChange": CustomEvent<{}>; } declare global { - interface Document { //adds definition to Document, but you can do the same with HTMLElement - addEventListener(type: K, - listener: (this: Document, ev: CustomEventMap[K]) => void): void; - dispatchEvent(ev: CustomEventMap[K]): void; - } + interface Document { + //adds definition to Document, but you can do the same with HTMLElement + addEventListener( + type: K, + listener: (this: Document, ev: CustomEventMap[K]) => void, + ): void; + dispatchEvent( + ev: CustomEventMap[K], + ): void; + } } +declare global { + interface Window { + __state: State; + } +} export { }; //keep that for TS compiler. + diff --git a/frontend/src/@types/ft_state.d.ts b/frontend/src/@types/ft_state.d.ts new file mode 100644 index 0000000..d79360a --- /dev/null +++ b/frontend/src/@types/ft_state.d.ts @@ -0,0 +1,4 @@ +declare module 'ft_state' { + interface GlobalState { + }; +}; diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 6f09284..581a0e2 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -1,6 +1,14 @@ +import { ensureWindowState } from '@app/utils'; import { Configuration, OpenapiOtherApi } from './generated'; export * from './generated' +ensureWindowState(); + +declare module 'ft_state' { + interface State { + client: OpenapiOtherApi; + } +} const basePath = (() => { let u = new URL(location.href); @@ -8,11 +16,9 @@ const basePath = (() => { u.hash = ""; u.search = ""; return u.toString().replace(/\/+$/, ''); - })(); export const client = new OpenapiOtherApi(new Configuration({ basePath })); export default client; -Object.assign(window as any, { apiClient: client }); - +window.__state.client ??= client; diff --git a/frontend/src/auth/index.ts b/frontend/src/auth.ts similarity index 79% rename from frontend/src/auth/index.ts rename to frontend/src/auth.ts index 008e94d..8fdedb6 100644 --- a/frontend/src/auth/index.ts +++ b/frontend/src/auth.ts @@ -1,9 +1,13 @@ import { showError } from "@app/toast"; import client from '@app/api'; import cookie from 'js-cookie'; +import { ensureWindowState } from "@app/utils"; cookie.remove('pkce'); +ensureWindowState(); +window.__state.user ??= null; + export type User = { id: string; guest: boolean; @@ -15,18 +19,22 @@ export type User = { } }; -let currentUser: User | null = null; +declare module 'ft_state' { + interface State { + user: User | null, + } +}; export function getUser(): Readonly | null { - return currentUser; + return window.__state.user; } export function isLogged(): boolean { - return currentUser !== null; + return window.__state.user !== null; } export function setUser(newUser: User | null) { - currentUser = newUser; + window.__state.user = newUser; } export async function updateUser(): Promise | null> { diff --git a/frontend/src/chat/index.ts b/frontend/src/chat/index.ts deleted file mode 100644 index 0ff997d..0000000 --- a/frontend/src/chat/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -import './chat.css'; - \ No newline at end of file diff --git a/frontend/src/chat/chat.css b/frontend/src/pages/chat/chat.css similarity index 99% rename from frontend/src/chat/chat.css rename to frontend/src/pages/chat/chat.css index 29f0274..d71cb55 100644 --- a/frontend/src/chat/chat.css +++ b/frontend/src/pages/chat/chat.css @@ -282,4 +282,4 @@ div-private { .hidden{ display: none; -} \ No newline at end of file +} diff --git a/frontend/src/pages/chat/chat.ts b/frontend/src/pages/chat/chat.ts index 2880b4e..07f4537 100644 --- a/frontend/src/pages/chat/chat.ts +++ b/frontend/src/pages/chat/chat.ts @@ -1,3 +1,4 @@ +import "./chat.css"; import { addRoute, setTitle, type RouteHandlerParams, type RouteHandlerReturn } from "@app/routing"; import { showError } from "@app/toast"; import authHtml from './chat.html?raw'; diff --git a/frontend/src/pages/profile/profile.ts b/frontend/src/pages/profile/profile.ts index 7241eeb..b6f573f 100644 --- a/frontend/src/pages/profile/profile.ts +++ b/frontend/src/pages/profile/profile.ts @@ -1,4 +1,4 @@ -import { addRoute, getRoute, handleRoute, navigateTo, setTitle } from "@app/routing"; +import { addRoute, handleRoute, navigateTo, setTitle } from "@app/routing"; import { showError, showSuccess } from "@app/toast"; import page from "./profile.html?raw"; import { updateUser } from "@app/auth"; diff --git a/frontend/src/routing/index.ts b/frontend/src/routing/index.ts index 02cd433..677e3fb 100644 --- a/frontend/src/routing/index.ts +++ b/frontend/src/routing/index.ts @@ -1,6 +1,20 @@ import { updateUser } from '@app/auth'; import { route_404 } from './special_routes' +import { ensureWindowState } from '@app/utils'; +ensureWindowState(); + +declare module 'ft_state' { + interface State { + routes: Map, + title: string, + titleElem: HTMLDivElement, + } +}; + +window.__state.routes ??= new Map(); +window.__state.title ??= ""; +window.__state.titleElem ??= document.querySelector('#header-title')!; // ---- Router logic ---- export function navigateTo(url: string) { @@ -101,44 +115,18 @@ function urlToParts(url: string): string[] { return parts.filter(p => p.length !== 0); } -function setupRoutes(): [ - () => Routes, - (url: string, handler: RouteHandler, args?: Partial) => void -] { - const routes = new Map(); - - return [ - () => routes, - (url: string, handler: RouteHandler | string, args?: Partial) => { - let d = new RouteHandlerData(url, handler, args ?? {}); - if (routes.has(d.url)) - throw `Tried to insert route ${url}, but it already exists`; - routes.set(d.url, d); - } - ]; -} - -function setupTitle(): [ - () => string, - (title: string) => void, -] { - let title = ""; - let titleElem = document.querySelector('#header-title')!; - return [ - () => title, - (new_title) => { - title = new_title; - titleElem.innerText = title; - } - ] +export function addRoute(url: string, handler: RouteHandler | string, args?: Partial) { + let d = new RouteHandlerData(url, handler, args ?? {}); + if (window.__state.routes.has(d.url)) + throw `Tried to insert route ${url}, but it already exists`; + window.__state.routes.set(d.url, d); } -export const [getRoute, addRoute] = setupRoutes(); - -export const [getTitle, setTitle] = setupTitle(); - -(window as any).getRoute = getRoute; +export function setTitle(title: string) { + window.__state.title = title; + window.__state.titleElem.innerText = window.__state.title; +} const executeRouteHandler = async (handler: RouteHandlerData, ...args: Parameters): Promise => { // handler may be a raw string literal, if yes => return it directly @@ -169,7 +157,7 @@ function parts_match(route_parts: (string | null)[], parts: string[]): boolean { } export async function handleRoute() { - let routes = getRoute(); + let routes = window.__state.routes; let parts = urlToParts(window.location.pathname); let routes_all = routes.entries(); @@ -222,4 +210,4 @@ document.addEventListener('click', e => { // ---- Handle browser navigation (back/forward) ---- window.addEventListener('popstate', handleRoute); -Object.assign((window as any), { getTitle, setTitle, getRoute, addRoute, navigateTo }) +Object.assign((window as any), { setTitle, addRoute, navigateTo }) diff --git a/frontend/src/routing/special_routes.ts b/frontend/src/routing/special_routes.ts index 5b7b7f6..dbda9d1 100644 --- a/frontend/src/routing/special_routes.ts +++ b/frontend/src/routing/special_routes.ts @@ -1,5 +1,5 @@ import { escapeHTML } from "@app/utils"; -import { getRoute, type RouteHandlerParams } from "@app/routing"; +import { type RouteHandlerParams } from "@app/routing"; export async function route_404(url: string, _args: RouteHandlerParams): Promise { return ` diff --git a/frontend/src/signin/alreadyLoggedin.html b/frontend/src/signin/alreadyLoggedin.html deleted file mode 100644 index 5d8b1dc..0000000 --- a/frontend/src/signin/alreadyLoggedin.html +++ /dev/null @@ -1,24 +0,0 @@ -
-
-

You are already logged in

- -

Want to logout ? Click the big button bellow !

- -

Otherwise, here is a cute cat picture

- -
-
diff --git a/frontend/src/toast/index.ts b/frontend/src/toast.ts similarity index 100% rename from frontend/src/toast/index.ts rename to frontend/src/toast.ts diff --git a/frontend/src/typescript.svg b/frontend/src/typescript.svg deleted file mode 100644 index d91c910..0000000 --- a/frontend/src/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts index d35bb00..80a3888 100644 --- a/frontend/src/utils.ts +++ b/frontend/src/utils.ts @@ -6,3 +6,8 @@ export function escapeHTML(str: string): string { export function isNullish(v: T | undefined | null): v is (null | undefined) { return v === null || v === undefined; } + +// MAKE SURE YOU DO WANT TO CALL THIS FUNCTION +export function ensureWindowState() { + window.__state = window.__state ?? {}; +}