🏷️ Search for custom tailnet name offers with keywords.
at master 86 lines 2.8 kB view raw
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};