[GIFs] Add error boundary to GIF picker (#3643)

* error boundary on gif picker

* add dialog.close for web users

* fix size of dialog on web

* Safer coercion

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
zio/stable
Samuel Newman 2024-04-22 22:07:48 +01:00 committed by GitHub
parent 27c4054fcb
commit f4e72cc83c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 4 deletions

View File

@ -13,6 +13,8 @@ import {
useSetExternalEmbedPref, useSetExternalEmbedPref,
} from '#/state/preferences' } from '#/state/preferences'
import {Gif, useGifphySearch, useGiphyTrending} from '#/state/queries/giphy' import {Gif, useGifphySearch, useGiphyTrending} from '#/state/queries/giphy'
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import * as TextField from '#/components/forms/TextField' import * as TextField from '#/components/forms/TextField'
@ -54,13 +56,18 @@ export function GifSelectDialog({
break break
} }
const renderErrorBoundary = useCallback(
(error: any) => <DialogError details={String(error)} />,
[],
)
return ( return (
<Dialog.Outer <Dialog.Outer
control={control} control={control}
nativeOptions={{sheet: {snapPoints}}} nativeOptions={{sheet: {snapPoints}}}
onClose={onClose}> onClose={onClose}>
<Dialog.Handle /> <Dialog.Handle />
{content} <ErrorBoundary renderError={renderErrorBoundary}>{content}</ErrorBoundary>
</Dialog.Outer> </Dialog.Outer>
) )
} }
@ -357,3 +364,31 @@ function GiphyConsentPrompt({control}: {control: Dialog.DialogControlProps}) {
</Dialog.ScrollableInner> </Dialog.ScrollableInner>
) )
} }
function DialogError({details}: {details?: string}) {
const {_} = useLingui()
const control = Dialog.useDialogContext()
return (
<Dialog.ScrollableInner style={a.gap_md} label={_(msg`An error occured`)}>
<Dialog.Close />
<ErrorScreen
title={_(msg`Oh no!`)}
message={_(
msg`There was an unexpected issue in the application. Please let us know if this happened to you!`,
)}
details={details}
/>
<Button
label={_(msg`Close dialog`)}
onPress={() => control.close()}
color="primary"
size="medium"
variant="solid">
<ButtonText>
<Trans>Close</Trans>
</ButtonText>
</Button>
</Dialog.ScrollableInner>
)
}

View File

@ -1,12 +1,14 @@
import React, {Component, ErrorInfo, ReactNode} from 'react' import React, {Component, ErrorInfo, ReactNode} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {logger} from '#/logger'
import {ErrorScreen} from './error/ErrorScreen' import {ErrorScreen} from './error/ErrorScreen'
import {CenteredView} from './Views' import {CenteredView} from './Views'
import {msg} from '@lingui/macro'
import {logger} from '#/logger'
import {useLingui} from '@lingui/react'
interface Props { interface Props {
children?: ReactNode children?: ReactNode
renderError?: (error: any) => ReactNode
} }
interface State { interface State {
@ -30,6 +32,10 @@ export class ErrorBoundary extends Component<Props, State> {
public render() { public render() {
if (this.state.hasError) { if (this.state.hasError) {
if (this.props.renderError) {
return this.props.renderError(this.state.error)
}
return ( return (
<CenteredView style={{height: '100%', flex: 1}}> <CenteredView style={{height: '100%', flex: 1}}>
<TranslatedErrorScreen details={this.state.error.toString()} /> <TranslatedErrorScreen details={this.state.error.toString()} />