Files
cinny/src/app/state/serverStatus.ts
T

51 lines
1.5 KiB
TypeScript
Raw Normal View History

import { atom } from 'jotai';
import { ServerStatus } from '../utils/kumaStatus';
/**
* [Gitea #124] The homeserver's status from its Kuma status page (null: none
* configured, not fetched yet, or Kuma unreachable — all mean "no banner"),
* plus whether this client's own connection is currently lost.
*/
export const serverStatusAtom = atom<{
status: ServerStatus | null;
syncLost: boolean;
/** When this client's connection dropped (ms), null while connected. */
lostAt: number | null;
}>({
status: null,
syncLost: false,
lostAt: null,
});
const DISMISS_KEY = 'lotus-status-banner-dismissed';
const DISMISS_MAX = 50;
const readDismissed = (): string[] => {
try {
const v = JSON.parse(localStorage.getItem(DISMISS_KEY) ?? '[]');
return Array.isArray(v) ? v.filter((k): k is string => typeof k === 'string') : [];
} catch {
return [];
}
};
const baseDismissedAtom = atom<string[]>(readDismissed());
/**
* [Gitea #307] Status strips the user dismissed (by banner key), shared so
* the security nudge knows a dismissed announcement isn't on screen.
* Persisted to localStorage; session-only if storage is unavailable.
*/
export const statusDismissedAtom = atom(
(get) => get(baseDismissedAtom),
(get, set, key: string) => {
const next = [...get(baseDismissedAtom).filter((k) => k !== key), key].slice(-DISMISS_MAX);
try {
localStorage.setItem(DISMISS_KEY, JSON.stringify(next));
} catch {
// storage unavailable — dismissed for this session only
}
set(baseDismissedAtom, next);
},
);