🏷️ Search for custom tailnet name offers with keywords.
1import { useCallback, useEffect, useRef } from 'react';
2import type { RuntimeMessage } from '$types/messages';
3import type { Token } from '$types/tokens';
4
5export const useModal = (
6 showAlert: boolean,
7 setShowAlert: (v: boolean) => void,
8 setAlertMessage: (v: string) => void,
9 claimedToken: string | null,
10 setClaimedToken: (v: string | null) => void,
11 setTokens: (fn: (prevTokens: Token[]) => Token[]) => void,
12 setTailnetNames: (v: string[]) => void,
13) => {
14 const alertModalRef = useRef<HTMLDivElement>(null);
15 const alertCloseBtnRef = useRef<HTMLButtonElement>(null);
16
17 const handleAlertCloseModal = useCallback(() => {
18 setShowAlert(false);
19 setTimeout(() => {
20 setAlertMessage('');
21 }, 300);
22 browser.runtime.sendMessage({ action: 'userAcknowledgedRedirect' });
23 if (claimedToken) {
24 setTokens((prevTokens: Token[]) =>
25 prevTokens.filter((t) => t.token !== claimedToken),
26 );
27 browser.storage.local.get(['tailscaleTokens'], (result) => {
28 const updatedTokens = (result.tailscaleTokens || []).filter(
29 (t: Token) => t.token !== claimedToken,
30 );
31 browser.storage.local.set({ tailscaleTokens: updatedTokens }, () => {
32 browser.runtime.sendMessage({ action: 'updateBadge' });
33 });
34 });
35 browser.storage.local.get(['tailnetNames'], (result) => {
36 const tailnetName = claimedToken.split('.')[0];
37 const updatedNames = (result.tailnetNames || []).filter(
38 (n: string) => n !== tailnetName,
39 );
40 setTailnetNames(updatedNames);
41 browser.storage.local.set({ tailnetNames: updatedNames });
42 });
43 setClaimedToken(null);
44 }
45 }, [
46 setShowAlert,
47 setAlertMessage,
48 claimedToken,
49 setTokens,
50 setTailnetNames,
51 setClaimedToken,
52 ]);
53
54 useEffect(() => {
55 if (showAlert && alertModalRef.current && alertCloseBtnRef.current) {
56 const focusableEls = [alertCloseBtnRef.current];
57 const handleKeyDown = (e: KeyboardEvent) => {
58 if (e.key === 'Tab') {
59 e.preventDefault();
60 focusableEls[0].focus();
61 }
62 if (e.key === 'Escape') {
63 handleAlertCloseModal();
64 }
65 };
66 alertModalRef.current.focus();
67 alertModalRef.current.addEventListener('keydown', handleKeyDown);
68 return () => {
69 alertModalRef.current?.removeEventListener('keydown', handleKeyDown);
70 };
71 }
72 }, [showAlert, handleAlertCloseModal]);
73
74 useEffect(() => {
75 const listener = (message: RuntimeMessage<{ message?: string }>) => {
76 if (message.action === 'showCustomAlert' && message.message) {
77 setAlertMessage(message.message);
78 setShowAlert(true);
79 }
80 };
81 browser.runtime.onMessage.addListener(listener);
82 return () => browser.runtime.onMessage.removeListener(listener);
83 }, [setAlertMessage, setShowAlert]);
84
85 return { alertModalRef, alertCloseBtnRef, handleAlertCloseModal };
86};