diff --git a/native/profile/delete-account.react.js b/native/profile/delete-account.react.js index ce6bb16cb..41c319e1a 100644 --- a/native/profile/delete-account.react.js +++ b/native/profile/delete-account.react.js @@ -1,167 +1,119 @@ // @flow import * as React from 'react'; import { Text, View, ActivityIndicator } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; import { deleteAccountActionTypes, deleteAccount, } from 'lib/actions/user-actions.js'; import { preRequestUserStateSelector } from 'lib/selectors/account-selectors.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import type { LogOutResult } from 'lib/types/account-types.js'; -import type { LoadingStatus } from 'lib/types/loading-types.js'; -import type { PreRequestUserState } from 'lib/types/session-types.js'; -import type { DispatchActionPromise } from 'lib/utils/action-utils.js'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; import { deleteNativeCredentialsFor } from '../account/native-credentials.js'; import Button from '../components/button.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; import Alert from '../utils/alert.js'; -type Props = { - // Redux state - +loadingStatus: LoadingStatus, - +preRequestUserState: PreRequestUserState, - +styles: typeof unboundStyles, - // Redux dispatch functions - +dispatchActionPromise: DispatchActionPromise, - // async functions that hit server APIs - +deleteAccount: ( - preRequestUserState: PreRequestUserState, - ) => Promise, -}; -class DeleteAccount extends React.PureComponent { - render() { +const loadingStatusSelector = createLoadingStatusSelector( + deleteAccountActionTypes, +); + +const DeleteAccount: React.ComponentType<{ ... }> = React.memo<{ ... }>( + function DeleteAccount() { + const loadingStatus = useSelector(loadingStatusSelector); + const preRequestUserState = useSelector(preRequestUserStateSelector); + const styles = useStyles(unboundStyles); + + const dispatchActionPromise = useDispatchActionPromise(); + const callDeleteAccount = useServerCall(deleteAccount); + const buttonContent = - this.props.loadingStatus === 'loading' ? ( + loadingStatus === 'loading' ? ( ) : ( - Delete account + Delete account ); + const noWayToReverseThisStyles = React.useMemo( + () => [styles.warningText, styles.lastWarningText], + [styles.warningText, styles.lastWarningText], + ); + + const deleteAction = React.useCallback(async () => { + try { + await deleteNativeCredentialsFor(); + return await callDeleteAccount(preRequestUserState); + } catch (e) { + Alert.alert('Unknown error', 'Uhh... try again?', [{ text: 'OK' }], { + cancelable: false, + }); + throw e; + } + }, [callDeleteAccount, preRequestUserState]); + + const onDelete = React.useCallback(() => { + dispatchActionPromise(deleteAccountActionTypes, deleteAction()); + }, [dispatchActionPromise, deleteAction]); + return ( - + Your account will be permanently deleted. - + There is no way to reverse this. - ); - } - - submitDeletion = () => { - this.props.dispatchActionPromise( - deleteAccountActionTypes, - this.deleteAccount(), - ); - }; - - async deleteAccount() { - try { - await deleteNativeCredentialsFor(); - const result = await this.props.deleteAccount( - this.props.preRequestUserState, - ); - return result; - } catch (e) { - if (e.message === 'invalid_credentials') { - Alert.alert( - 'Incorrect password', - 'The password you entered is incorrect', - [{ text: 'OK' }], - { cancelable: false }, - ); - } else { - Alert.alert('Unknown error', 'Uhh... try again?', [{ text: 'OK' }], { - cancelable: false, - }); - } - throw e; - } - } -} + }, +); const unboundStyles = { deleteButton: { backgroundColor: 'vibrantRedButton', borderRadius: 5, flex: 1, marginHorizontal: 24, marginVertical: 12, padding: 12, }, lastWarningText: { marginBottom: 24, }, saveText: { color: 'white', fontSize: 18, textAlign: 'center', }, scrollView: { backgroundColor: 'panelBackground', }, scrollViewContentContainer: { paddingTop: 24, }, warningText: { color: 'panelForegroundLabel', fontSize: 16, marginHorizontal: 24, textAlign: 'center', }, }; -const loadingStatusSelector = createLoadingStatusSelector( - deleteAccountActionTypes, -); - -const ConnectedDeleteAccount: React.ComponentType<{ ... }> = React.memo<{ - ... -}>(function ConnectedDeleteAccount() { - const loadingStatus = useSelector(loadingStatusSelector); - const preRequestUserState = useSelector(preRequestUserStateSelector); - const styles = useStyles(unboundStyles); - - const dispatchActionPromise = useDispatchActionPromise(); - const callDeleteAccount = useServerCall(deleteAccount); - - return ( - - ); -}); - -export default ConnectedDeleteAccount; +export default DeleteAccount; diff --git a/web/settings/account-delete-modal.react.js b/web/settings/account-delete-modal.react.js index ea944fa0b..b2db0a06e 100644 --- a/web/settings/account-delete-modal.react.js +++ b/web/settings/account-delete-modal.react.js @@ -1,129 +1,93 @@ // @flow import * as React from 'react'; import { deleteAccount, deleteAccountActionTypes, } from 'lib/actions/user-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { preRequestUserStateSelector } from 'lib/selectors/account-selectors.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import type { LogOutResult } from 'lib/types/account-types.js'; -import type { PreRequestUserState } from 'lib/types/session-types.js'; -import type { DispatchActionPromise } from 'lib/utils/action-utils.js'; import { useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils.js'; import css from './account-delete-modal.css'; import Button, { buttonThemes } from '../components/button.react.js'; import Modal from '../modals/modal.react.js'; import { useSelector } from '../redux/redux-utils.js'; -type Props = { - +preRequestUserState: PreRequestUserState, - +inputDisabled: boolean, - +dispatchActionPromise: DispatchActionPromise, - +deleteAccount: ( - preRequestUserState: PreRequestUserState, - ) => Promise, - +popModal: () => void, -}; -type State = { - +errorMessage: string, -}; +const deleteAccountLoadingStatusSelector = createLoadingStatusSelector( + deleteAccountActionTypes, +); -class AccountDeleteModal extends React.PureComponent { - state = { - errorMessage: '', - }; +const AccountDeleteModal: React.ComponentType<{}> = React.memo<{}>( + function AccountDeleteModal(): React.Node { + const preRequestUserState = useSelector(preRequestUserStateSelector); + const inputDisabled = useSelector( + state => deleteAccountLoadingStatusSelector(state) === 'loading', + ); + const callDeleteAccount = useServerCall(deleteAccount); + const dispatchActionPromise = useDispatchActionPromise(); + + const { popModal } = useModalContext(); + + const [errorMessage, setErrorMessage] = React.useState(''); - render() { let errorMsg; - if (this.state.errorMessage) { - errorMsg = ( -
{this.state.errorMessage}
- ); + if (errorMessage) { + errorMsg =
{errorMessage}
; } - const { inputDisabled } = this.props; + const deleteAction = React.useCallback(async () => { + try { + setErrorMessage(''); + const response = await callDeleteAccount(preRequestUserState); + popModal(); + return response; + } catch (e) { + setErrorMessage('unknown error'); + throw e; + } + }, [callDeleteAccount, preRequestUserState, popModal]); + + const onDelete = React.useCallback( + (event: SyntheticEvent) => { + event.preventDefault(); + dispatchActionPromise(deleteAccountActionTypes, deleteAction()); + }, + [dispatchActionPromise, deleteAction], + ); + return ( - +

Your account will be permanently deleted. There is no way to reverse this.

{errorMsg}
); - } - - onDelete = (event: SyntheticEvent) => { - event.preventDefault(); - this.props.dispatchActionPromise( - deleteAccountActionTypes, - this.deleteAction(), - ); - }; - - async deleteAction() { - try { - const response = await this.props.deleteAccount( - this.props.preRequestUserState, - ); - this.props.popModal(); - return response; - } catch (e) { - this.setState({ errorMessage: 'unknown error' }); - throw e; - } - } -} - -const deleteAccountLoadingStatusSelector = createLoadingStatusSelector( - deleteAccountActionTypes, -); - -const ConnectedAccountDeleteModal: React.ComponentType<{}> = React.memo<{}>( - function ConnectedAccountDeleteModal(): React.Node { - const preRequestUserState = useSelector(preRequestUserStateSelector); - const inputDisabled = useSelector( - state => deleteAccountLoadingStatusSelector(state) === 'loading', - ); - const callDeleteAccount = useServerCall(deleteAccount); - const dispatchActionPromise = useDispatchActionPromise(); - - const modalContext = useModalContext(); - - return ( - - ); }, ); -export default ConnectedAccountDeleteModal; +export default AccountDeleteModal;