Skip to content

Commit

Permalink
Handle Chrome double escape behaviour (#4396)
Browse files Browse the repository at this point in the history
resolves #4365

Pressing escape key twice will close open dialogs in Chrome no matter
how onCancel is configured https://issues.chromium.org/issues/346597066

To handle that we move the onClickBackButton function one component
higher to add it as onClose prop to the Dialog and handle the event
the same way a BackButton Click would be handled
  • Loading branch information
nicodh authored Dec 8, 2024
1 parent c574dd4 commit f507eee
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## Changed

## Fixed
- handle double escape on Dialog #4365

<a id="1_49_0"></a>

Expand Down
11 changes: 10 additions & 1 deletion packages/frontend/src/ScreenController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,16 @@ export default class ScreenController extends Component {
this.changeScreen(Screens.NoAccountSelected)
}
} else {
this.changeScreen(Screens.NoAccountSelected)
const accounts = await BackendRemote.rpc.getAllAccountIds()
if (accounts.length > 0) {
this.changeScreen(Screens.NoAccountSelected)
} else {
// special case: there is no account at all
// we should avoid a state with no selected
// account, since instant onboarding expects
// at least an unconfigured account to exist
this.addAndSelectAccount()
}
}
this.lastAccountBeforeAddingNewAccount = null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import React from 'react'

import AlertDialog from '../../dialogs/AlertDialog'
import AlternativeSetupsDialog from './AlternativeSetupsDialog'
import Button from '../../Button'
import useDialog from '../../../hooks/dialog/useDialog'
import useTranslationFunction from '../../../hooks/useTranslationFunction'
import { BackendRemote, EffectfulBackendActions } from '../../../backend-com'
import { DialogBody, DialogContent, DialogHeader } from '../../Dialog'
import { getLogger } from '../../../../../shared/logger'

import styles from './styles.module.scss'

type Props = {
onExitWelcomeScreen: () => Promise<void>
onNextStep: () => void
onUnSelectAccount: () => Promise<void>
onClickBackButton: () => Promise<void>
selectedAccountId: number
showBackButton: boolean
hasConfiguredAccounts: boolean
}

const log = getLogger('renderer/components/OnboardingScreen')

export default function OnboardingScreen(props: Props) {
const tx = useTranslationFunction()
const { openDialog } = useDialog()
Expand All @@ -32,34 +28,10 @@ export default function OnboardingScreen(props: Props) {
})
}

const onClickBackButton = async () => {
try {
const acInfo = await BackendRemote.rpc.getAccountInfo(
props.selectedAccountId
)
if (acInfo.kind === 'Unconfigured') {
await props.onUnSelectAccount()
await EffectfulBackendActions.removeAccount(props.selectedAccountId)
}

props.onExitWelcomeScreen()
} catch (error) {
if (error instanceof Error) {
openDialog(AlertDialog, {
message: error?.message,
cb: () => {},
})
} else {
log.error('unexpected error type', error)
throw error
}
}
}

return (
<>
<DialogHeader
onClickBack={props.showBackButton ? onClickBackButton : undefined}
onClickBack={props.showBackButton ? props.onClickBackButton : undefined}
title={
props.hasConfiguredAccounts
? tx('add_account')
Expand Down
39 changes: 39 additions & 0 deletions packages/frontend/src/components/screens/WelcomeScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import InstantOnboardingScreen from './InstantOnboardingScreen'
import OnboardingScreen from './OnboardingScreen'
import useInstantOnboarding from '../../../hooks/useInstantOnboarding'
import { getConfiguredAccounts } from '../../../backend/account'
import { BackendRemote, EffectfulBackendActions } from '../../../backend-com'
import useDialog from '../../../hooks/dialog/useDialog'
import AlertDialog from '../../dialogs/AlertDialog'
import { getLogger } from '@deltachat-desktop/shared/logger'

const log = getLogger('renderer/components/screens/WelcomScreen')

type Props = {
selectedAccountId: number
Expand All @@ -20,6 +26,7 @@ export default function WelcomeScreen({ selectedAccountId, ...props }: Props) {
startInstantOnboardingFlow,
} = useInstantOnboarding()
const [hasConfiguredAccounts, setHasConfiguredAccounts] = useState(false)
const { openDialog } = useDialog()
const showBackButton = hasConfiguredAccounts

useLayoutEffect(() => {
Expand All @@ -35,20 +42,52 @@ export default function WelcomeScreen({ selectedAccountId, ...props }: Props) {
checkAccounts()
}, [])

/**
* this function is called when the back button is clicked
* but also if the dialog is closed by pressing esc multiple
* times, which will force Chrome to close the dialog
* see https://issues.chromium.org/issues/346597066
*
* it will cancel the account creation process and call
* onExitWelcomeScreen
*/
const onClickBackButton = async () => {
try {
const acInfo = await BackendRemote.rpc.getAccountInfo(selectedAccountId)
if (acInfo.kind === 'Unconfigured') {
await props.onUnSelectAccount()
await EffectfulBackendActions.removeAccount(selectedAccountId)
}
props.onExitWelcomeScreen()
} catch (error) {
if (error instanceof Error) {
openDialog(AlertDialog, {
message: error?.message,
cb: () => {},
})
} else {
log.error('unexpected error type', error)
throw error
}
}
}

return (
<ImageBackdrop variant='welcome'>
<Dialog
fixed
width={400}
canEscapeKeyClose={false}
canOutsideClickClose={false}
onClose={onClickBackButton}
>
{!showInstantOnboarding ? (
<OnboardingScreen
onNextStep={() => startInstantOnboardingFlow()}
selectedAccountId={selectedAccountId}
showBackButton={showBackButton}
hasConfiguredAccounts={hasConfiguredAccounts}
onClickBackButton={onClickBackButton}
{...props}
/>
) : (
Expand Down

0 comments on commit f507eee

Please sign in to comment.