diff options
| author | Hank <hank@mullvad.net> | 2022-10-11 15:52:03 +0200 |
|---|---|---|
| committer | Hank <hank@mullvad.net> | 2022-10-13 13:48:17 +0200 |
| commit | 44c6c9fc42440d015ef7f15919079f8a844afb75 (patch) | |
| tree | 6f252f7e47741e2b985d8ab775bf5f9362120033 /gui/src/renderer | |
| parent | 2a8bd8b9cfbc06b41596c2333f8a39ecc8c987cf (diff) | |
| download | mullvadvpn-44c6c9fc42440d015ef7f15919079f8a844afb75.tar.xz mullvadvpn-44c6c9fc42440d015ef7f15919079f8a844afb75.zip | |
Use context to share logic
Undo fix wording in translator comment
Diffstat (limited to 'gui/src/renderer')
| -rw-r--r-- | gui/src/renderer/components/Account.tsx | 155 |
1 files changed, 98 insertions, 57 deletions
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx index d46b9e3a03..75141e2564 100644 --- a/gui/src/renderer/components/Account.tsx +++ b/gui/src/renderer/components/Account.tsx @@ -1,4 +1,12 @@ -import { useCallback, useEffect, useState } from 'react'; +import { + createContext, + ReactNode, + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from 'react'; import { links } from '../../config.json'; import { formatDate, hasExpired } from '../../shared/account-expiry'; @@ -32,49 +40,24 @@ import SettingsHeader, { HeaderTitle } from './SettingsHeader'; type LogoutDialogStage = 'checking-ports' | 'confirm' | undefined; export default function Account() { + return ( + <LogoutContextProvider> + <AccountComponent /> + </LogoutContextProvider> + ); +} + +function AccountComponent() { const history = useHistory(); - const [logoutDialogStage, setLogoutDialogStage] = useState<LogoutDialogStage>(); - const [logoutDialogVisible, setLogoutDialogVisible] = useState(false); const isOffline = useSelector((state) => state.connection.isBlocked); + const { updateAccountData, openLinkWithAuth } = useAppContext(); - const { logout, updateAccountData, openLinkWithAuth, getDeviceState } = useAppContext(); - - const { cancelLogout, prepareLogout } = useActions(account); - - const confirmLogout = useCallback(async () => { - onHideLogoutConfirmationDialog(); - await logout(); - }, []); - - const onCancelLogout = useCallback(() => { - cancelLogout(); - onHideLogoutConfirmationDialog(); - }, []); + const { onTryLogout } = useLogoutContext(); const onBuyMore = useCallback(async () => { await openLinkWithAuth(links.purchase); }, []); - const onHideLogoutConfirmationDialog = () => setLogoutDialogVisible(false); - - const onTryLogout = useCallback(async () => { - setLogoutDialogVisible(true); - setLogoutDialogStage('checking-ports'); - prepareLogout(); - - const deviceState = await getDeviceState(); - - if ( - deviceState?.type === 'logged in' && - deviceState.accountAndDevice.device?.ports !== undefined && - deviceState.accountAndDevice.device.ports.length > 0 - ) { - setLogoutDialogStage('confirm'); - } else { - await confirmLogout(); - } - }, []); - useEffect(() => { updateAccountData(); }, []); @@ -150,31 +133,22 @@ export default function Account() { </AccountContainer> </SettingsContainer> - <LogoutDialog - logoutDialogStage={logoutDialogStage} - logoutDialogVisible={logoutDialogVisible} - confirmLogout={confirmLogout} - cancelLogout={onCancelLogout} - /> + <LogoutDialog /> </Layout> </BackAction> ); } -type LogoutDialogProps = { - logoutDialogStage: LogoutDialogStage; - logoutDialogVisible: boolean; - confirmLogout: () => void; - cancelLogout: () => void; -}; +function LogoutDialog() { + const { + logoutDialogStage, + logoutDialogVisible, + onConfirmLogout, + onCancelLogout, + } = useLogoutContext(); -function LogoutDialog({ - logoutDialogStage, - logoutDialogVisible, - confirmLogout, - cancelLogout, -}: LogoutDialogProps) { const modalType = logoutDialogStage === 'checking-ports' ? undefined : ModalAlertType.warning; + const message = logoutDialogStage === 'checking-ports' ? ( <StyledSpinnerContainer> @@ -183,7 +157,7 @@ function LogoutDialog({ ) : ( <ModalMessage> { - // TRANSLATORS: This is a further explanation of what happens when logging out. + // TRANSLATORS: This is is a further explanation of what happens when logging out. messages.pgettext( 'device-management', 'The ports forwarded to this device will be deleted if you log out.', @@ -196,13 +170,13 @@ function LogoutDialog({ logoutDialogStage === 'checking-ports' ? [] : [ - <AppButton.RedButton key="logout" onClick={confirmLogout}> + <AppButton.RedButton key="logout" onClick={onConfirmLogout}> { // TRANSLATORS: Confirmation button when logging out messages.pgettext('device-management', 'Log out anyway') } </AppButton.RedButton>, - <AppButton.BlueButton key="back" onClick={cancelLogout}> + <AppButton.BlueButton key="back" onClick={onCancelLogout}> {messages.gettext('Back')} </AppButton.BlueButton>, ]; @@ -246,3 +220,70 @@ function FormattedAccountExpiry(props: { expiry?: string; locale: string }) { ); } } + +type LogoutContextType = { + logoutDialogStage: LogoutDialogStage; + logoutDialogVisible: boolean; + onConfirmLogout: () => void; + onCancelLogout: () => void; + onTryLogout: () => Promise<void>; +}; + +const LogoutContext = createContext<LogoutContextType | undefined>(undefined); + +const LogoutContextProvider = ({ children }: { children: ReactNode }) => { + const onHideLogoutConfirmationDialog = () => setLogoutDialogVisible(false); + const { cancelLogout, prepareLogout } = useActions(account); + const { logout, getDeviceState } = useAppContext(); + + const [logoutDialogStage, setLogoutDialogStage] = useState<LogoutDialogStage>(); + const [logoutDialogVisible, setLogoutDialogVisible] = useState(false); + + const onConfirmLogout = useCallback(async () => { + onHideLogoutConfirmationDialog(); + await logout(); + }, []); + + const onTryLogout = useCallback(async () => { + setLogoutDialogVisible(true); + setLogoutDialogStage('checking-ports'); + prepareLogout(); + + const deviceState = await getDeviceState(); + + if ( + deviceState?.type === 'logged in' && + deviceState.accountAndDevice.device?.ports !== undefined && + deviceState.accountAndDevice.device.ports.length > 0 + ) { + setLogoutDialogStage('confirm'); + } else { + await onConfirmLogout(); + } + }, [onConfirmLogout]); + + const onCancelLogout = useCallback(() => { + cancelLogout(); + onHideLogoutConfirmationDialog(); + }, []); + + const value: LogoutContextType = useMemo( + () => ({ + logoutDialogStage, + logoutDialogVisible, + onConfirmLogout, + onCancelLogout, + onTryLogout, + }), + [logoutDialogVisible, logoutDialogStage, onConfirmLogout, onCancelLogout, onTryLogout], + ); + return <LogoutContext.Provider value={value}>{children}</LogoutContext.Provider>; +}; + +const useLogoutContext = () => { + const context = useContext(LogoutContext); + if (!context) { + throw new Error('useAccount must be used within an LogoutContextProvider'); + } + return context; +}; |
