Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
This commit is contained in:
commit
aa5e262f3a
880 changed files with 111042 additions and 0 deletions
31
apps/web/src/lib/session-token.ts
Normal file
31
apps/web/src/lib/session-token.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Session token holder: memory first, mirrored to localStorage so a reload
|
||||
* keeps the session. Listeners let the auth store react when the API client
|
||||
* clears a token (401) or a mutation hands back a re-issued one.
|
||||
*/
|
||||
|
||||
const STORAGE_KEY = "tmbh.session";
|
||||
|
||||
let memory: string | null | undefined;
|
||||
const listeners = new Set<(token: string | null) => void>();
|
||||
|
||||
export function getSessionToken(): string | null {
|
||||
if (memory !== undefined) return memory;
|
||||
if (typeof window === "undefined") return null;
|
||||
memory = window.localStorage.getItem(STORAGE_KEY);
|
||||
return memory;
|
||||
}
|
||||
|
||||
export function setSessionToken(token: string | null): void {
|
||||
memory = token;
|
||||
if (typeof window !== "undefined") {
|
||||
if (token === null) window.localStorage.removeItem(STORAGE_KEY);
|
||||
else window.localStorage.setItem(STORAGE_KEY, token);
|
||||
}
|
||||
for (const listener of listeners) listener(token);
|
||||
}
|
||||
|
||||
export function onSessionTokenChange(listener: (token: string | null) => void): () => void {
|
||||
listeners.add(listener);
|
||||
return () => listeners.delete(listener);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue