1import { useCallback, useMemo } from "react";
2import * as Schema from "effect/Schema";
3
4import { getLocalStorageItem, setLocalStorageItem, useLocalStorage } from "./hooks/useLocalStorage";
5
6export const PROVIDER_UPDATE_DISMISSALS_STORAGE_KEY = "t3code:provider-update-dismissals:v1";
7
8const ProviderUpdateDismissalsSchema = Schema.Struct({
9 keys: Schema.Array(Schema.String),
10});
11
12type ProviderUpdateDismissals = typeof ProviderUpdateDismissalsSchema.Type;
13
14function readProviderUpdateDismissals(): ProviderUpdateDismissals {
15 try {
16 return (
17 getLocalStorageItem(
18 PROVIDER_UPDATE_DISMISSALS_STORAGE_KEY,
19 ProviderUpdateDismissalsSchema,
20 ) ?? {
21 keys: [],
22 }
23 );
24 } catch (error) {
25 console.error("Could not read provider-update dismissals.", error);
26 return { keys: [] };
27 }
28}
29
30function writeProviderUpdateDismissals(document: ProviderUpdateDismissals): void {
31 try {
32 setLocalStorageItem(
33 PROVIDER_UPDATE_DISMISSALS_STORAGE_KEY,
34 document,
35 ProviderUpdateDismissalsSchema,
36 );
37 } catch (error) {
38 console.error("Could not persist provider-update dismissals.", error);
39 }
40}
41
42export function isProviderUpdateNotificationDismissed(
43 dismissalKey: string | null | undefined,
44): boolean {
45 if (!dismissalKey) {
46 return false;
47 }
48 return readProviderUpdateDismissals().keys.includes(dismissalKey);
49}
50
51export function dismissProviderUpdateNotification(dismissalKey: string | null | undefined): void {
52 const trimmedKey = dismissalKey?.trim();
53 if (!trimmedKey) {
54 return;
55 }
56 const document = readProviderUpdateDismissals();
57 if (document.keys.includes(trimmedKey)) {
58 return;
59 }
60 writeProviderUpdateDismissals({
61 keys: [...document.keys, trimmedKey],
62 });
63}
64
65export function useDismissedProviderUpdateNotificationKeys() {
66 const [dismissals, setDismissals] = useLocalStorage(
67 PROVIDER_UPDATE_DISMISSALS_STORAGE_KEY,
68 { keys: [] },
69 ProviderUpdateDismissalsSchema,
70 );
71 const dismissedKeys = dismissals.keys;
72
73 const dismissedKeySet = useMemo(() => new Set(dismissedKeys), [dismissedKeys]);
74
75 const dismissNotificationKey = useCallback(
76 (key: string) => {
77 const trimmedKey = key.trim();
78 if (trimmedKey.length === 0 || dismissedKeySet.has(trimmedKey)) {
79 return;
80 }
81
82 setDismissals({
83 keys: [...dismissedKeys, trimmedKey],
84 });
85 },
86 [dismissedKeySet, dismissedKeys, setDismissals],
87 );
88
89 return {
90 dismissedNotificationKeys: dismissedKeySet,
91 dismissNotificationKey,
92 };
93}