Skip to content

Commit

Permalink
Fix problems with BottomSheet and the report dialog (#3297)
Browse files Browse the repository at this point in the history
* use @discord/bottom-sheet

* add @types/invariant

* some progress on keyboard dialog

* rework

rework

add a comment

use discord bottom sheet

* remove `@gorhom/bottom-sheet`

* remove android specific code

* organize imports
  • Loading branch information
haileyok authored Mar 21, 2024
1 parent c649ee1 commit ad3dd9f
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 116 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@
"@atproto/api": "^0.12.2",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "https://github.com/bluesky-social/react-native-bottom-sheet.git#discord-fork-4.6.1",
"@emoji-mart/react": "^1.1.1",
"@expo/html-elements": "^0.4.2",
"@expo/webpack-config": "^19.0.0",
"@fortawesome/fontawesome-svg-core": "^6.1.1",
"@fortawesome/free-regular-svg-icons": "^6.1.1",
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/react-native-fontawesome": "^0.3.0",
"@gorhom/bottom-sheet": "^4.5.1",
"@lingui/react": "^4.5.0",
"@mattermost/react-native-paste-input": "^0.6.4",
"@miblanchard/react-native-slider": "^2.3.1",
Expand Down Expand Up @@ -93,6 +93,7 @@
"@tiptap/pm": "^2.0.0-beta.220",
"@tiptap/react": "^2.0.0-beta.220",
"@tiptap/suggestion": "^2.0.0-beta.220",
"@types/invariant": "^2.2.37",
"@types/node": "^18.16.2",
"@zxing/text-encoding": "^0.9.0",
"array.prototype.findlast": "^1.2.3",
Expand Down
63 changes: 31 additions & 32 deletions src/App.native.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,58 @@
import 'react-native-url-polyfill/auto'
import 'lib/sentry' // must be near top
import 'view/icons'

import React, {useState, useEffect} from 'react'
import {RootSiblingParent} from 'react-native-root-siblings'
import * as SplashScreen from 'expo-splash-screen'
import React, {useEffect, useState} from 'react'
import {GestureHandlerRootView} from 'react-native-gesture-handler'
import {PersistQueryClientProvider} from '@tanstack/react-query-persist-client'
import {RootSiblingParent} from 'react-native-root-siblings'
import {
SafeAreaProvider,
initialWindowMetrics,
SafeAreaProvider,
} from 'react-native-safe-area-context'
import * as SplashScreen from 'expo-splash-screen'
import {StatusBar} from 'expo-status-bar'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {PersistQueryClientProvider} from '@tanstack/react-query-persist-client'

import 'view/icons'

import {ThemeProvider as Alf} from '#/alf'
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
import {init as initPersistedState} from '#/state/persisted'
import {listenSessionDropped} from './state/events'
import {ThemeProvider} from 'lib/ThemeContext'
import {s} from 'lib/styles'
import {Shell} from 'view/shell'
import * as persisted from '#/state/persisted'
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
import {useIntentHandler} from 'lib/hooks/useIntentHandler'
import * as notifications from 'lib/notifications/notifications'
import * as Toast from 'view/com/util/Toast'
import {
queryClient,
asyncStoragePersister,
dehydrateOptions,
queryClient,
} from 'lib/react-query'
import {TestCtrls} from 'view/com/testing/TestCtrls'
import {Provider as ShellStateProvider} from 'state/shell'
import {Provider as ModalStateProvider} from 'state/modals'
import {s} from 'lib/styles'
import {ThemeProvider} from 'lib/ThemeContext'
import {isAndroid} from 'platform/detection'
import {Provider as DialogStateProvider} from 'state/dialogs'
import {Provider as InvitesStateProvider} from 'state/invites'
import {Provider as LightboxStateProvider} from 'state/lightbox'
import {Provider as ModalStateProvider} from 'state/modals'
import {Provider as MutedThreadsProvider} from 'state/muted-threads'
import {Provider as InvitesStateProvider} from 'state/invites'
import {Provider as PrefsStateProvider} from 'state/preferences'
import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
import {Provider as SelectedFeedProvider} from 'state/shell/selected-feed'
import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
import I18nProvider from './locale/i18nProvider'
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
import {
Provider as SessionProvider,
useSession,
useSessionApi,
} from 'state/session'
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
import * as persisted from '#/state/persisted'
import {Splash} from '#/Splash'
import {Provider as ShellStateProvider} from 'state/shell'
import {Provider as LoggedOutViewProvider} from 'state/shell/logged-out'
import {Provider as SelectedFeedProvider} from 'state/shell/selected-feed'
import {TestCtrls} from 'view/com/testing/TestCtrls'
import * as Toast from 'view/com/util/Toast'
import {Shell} from 'view/shell'
import {ThemeProvider as Alf} from '#/alf'
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
import {Provider as PortalProvider} from '#/components/Portal'
import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useIntentHandler} from 'lib/hooks/useIntentHandler'
import {StatusBar} from 'expo-status-bar'
import {isAndroid} from 'platform/detection'
import {Splash} from '#/Splash'
import I18nProvider from './locale/i18nProvider'
import {listenSessionDropped} from './state/events'

SplashScreen.preventAutoHideAsync()

Expand Down
48 changes: 20 additions & 28 deletions src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import React, {useImperativeHandle} from 'react'
import {View, Dimensions, Keyboard, Pressable} from 'react-native'
import {Dimensions, Pressable, View} from 'react-native'
import Animated, {useAnimatedStyle} from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import BottomSheet, {
BottomSheetBackdropProps,
BottomSheetScrollView,
BottomSheetScrollViewMethods,
BottomSheetTextInput,
BottomSheetView,
useBottomSheet,
WINDOW_HEIGHT,
} from '@gorhom/bottom-sheet'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import Animated, {useAnimatedStyle} from 'react-native-reanimated'
} from '@discord/bottom-sheet/src'

import {useTheme, atoms as a, flatten} from '#/alf'
import {Portal} from '#/components/Portal'
import {createInput} from '#/components/forms/TextField'
import {logger} from '#/logger'
import {useDialogStateControlContext} from '#/state/dialogs'

import {isNative} from 'platform/detection'
import {atoms as a, flatten, useTheme} from '#/alf'
import {Context} from '#/components/Dialog/context'
import {
DialogOuterProps,
DialogControlProps,
DialogInnerProps,
DialogOuterProps,
} from '#/components/Dialog/types'
import {Context} from '#/components/Dialog/context'
import {isNative} from 'platform/detection'
import {createInput} from '#/components/forms/TextField'
import {Portal} from '#/components/Portal'

export {useDialogControl, useDialogContext} from '#/components/Dialog/context'
export {useDialogContext, useDialogControl} from '#/components/Dialog/context'
export * from '#/components/Dialog/types'
// @ts-ignore
export const Input = createInput(BottomSheetTextInput)
Expand Down Expand Up @@ -122,7 +122,6 @@ export function Outer({
)

const onCloseInner = React.useCallback(() => {
Keyboard.dismiss()
try {
closeCallback.current?.()
} catch (e: any) {
Expand Down Expand Up @@ -206,16 +205,14 @@ export function Inner({children, style}: DialogInnerProps) {
)
}

export function ScrollableInner({
children,
keyboardDismissMode,
style,
}: DialogInnerProps) {
export const ScrollableInner = React.forwardRef<
BottomSheetScrollViewMethods,
DialogInnerProps
>(function ScrollableInner({children, style}, ref) {
const insets = useSafeAreaInsets()
return (
<BottomSheetScrollView
keyboardShouldPersistTaps="handled"
keyboardDismissMode={keyboardDismissMode || 'on-drag'}
style={[
a.flex_1, // main diff is this
a.p_xl,
Expand All @@ -227,24 +224,19 @@ export function ScrollableInner({
},
flatten(style),
]}
contentContainerStyle={isNative ? a.pb_4xl : undefined}>
contentContainerStyle={isNative ? a.pb_4xl : undefined}
ref={ref}>
{children}
<View style={{height: insets.bottom + a.pt_5xl.paddingTop}} />
</BottomSheetScrollView>
)
}
})

export function Handle() {
const t = useTheme()

const onTouchStart = React.useCallback(() => {
Keyboard.dismiss()
}, [])

return (
<View
style={[a.absolute, a.w_full, a.align_center, a.z_10, {height: 40}]}
onTouchStart={onTouchStart}>
<View style={[a.absolute, a.w_full, a.align_center, a.z_10, {height: 40}]}>
<View
style={[
a.rounded_sm,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dialog/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
GestureResponderEvent,
ScrollViewProps,
} from 'react-native'
import {BottomSheetProps} from '@gorhom/bottom-sheet'
import {BottomSheetProps} from '@discord/bottom-sheet/src'

import {ViewStyleProp} from '#/alf'

Expand Down
27 changes: 15 additions & 12 deletions src/components/ReportDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import React from 'react'
import {View, Pressable} from 'react-native'
import {Pressable, View} from 'react-native'
import {Trans} from '@lingui/macro'

import {useMyLabelersQuery} from '#/state/queries/preferences'
import {ReportOption} from '#/lib/moderation/useReportOptions'
import {useMyLabelersQuery} from '#/state/queries/preferences'
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'

import {AppBskyLabelerDefs} from '@atproto/api'
import {BottomSheetScrollViewMethods} from '@discord/bottom-sheet/src'

import {atoms as a} from '#/alf'
import {Loader} from '#/components/Loader'
import * as Dialog from '#/components/Dialog'
import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
import {useOnKeyboardDidShow} from '#/components/hooks/useOnKeyboard'
import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography'

import {ReportDialogProps} from './types'
import {SelectLabelerView} from './SelectLabelerView'
import {SelectReportOptionView} from './SelectReportOptionView'
import {SubmitView} from './SubmitView'
import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
import {AppBskyLabelerDefs} from '@atproto/api'
import {ReportDialogProps} from './types'

export function ReportDialog(props: ReportDialogProps) {
return (
Expand All @@ -36,10 +38,13 @@ function ReportDialogInner(props: ReportDialogProps) {
} = useMyLabelersQuery()
const isLoading = useDelayedLoading(500, isLabelerLoading)

const ref = React.useRef<BottomSheetScrollViewMethods>(null)
useOnKeyboardDidShow(() => {
ref.current?.scrollToEnd({animated: true})
})

return (
<Dialog.ScrollableInner
label="Report Dialog"
keyboardDismissMode="interactive">
<Dialog.ScrollableInner label="Report Dialog" ref={ref}>
{isLoading ? (
<View style={[a.align_center, {height: 100}]}>
<Loader size="xl" />
Expand All @@ -55,8 +60,6 @@ function ReportDialogInner(props: ReportDialogProps) {
) : (
<ReportDialogLoaded labelers={labelers} {...props} />
)}

<Dialog.Close />
</Dialog.ScrollableInner>
)
}
Expand Down
12 changes: 12 additions & 0 deletions src/components/hooks/useOnKeyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import {Keyboard} from 'react-native'

export function useOnKeyboardDidShow(cb: () => unknown) {
React.useEffect(() => {
const subscription = Keyboard.addListener('keyboardDidShow', cb)

return () => {
subscription.remove()
}
}, [cb])
}
40 changes: 20 additions & 20 deletions src/view/com/modals/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import React, {useRef, useEffect} from 'react'
import React, {useEffect, useRef} from 'react'
import {StyleSheet} from 'react-native'
import {SafeAreaView} from 'react-native-safe-area-context'
import BottomSheet from '@gorhom/bottom-sheet'
import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop'
import {usePalette} from 'lib/hooks/usePalette'
import BottomSheet from '@discord/bottom-sheet/src'

import {useModals, useModalControls} from '#/state/modals'
import * as EditProfileModal from './EditProfile'
import * as RepostModal from './Repost'
import * as SelfLabelModal from './SelfLabel'
import * as ThreadgateModal from './Threadgate'
import * as CreateOrEditListModal from './CreateOrEditList'
import * as UserAddRemoveListsModal from './UserAddRemoveLists'
import * as ListAddUserModal from './ListAddRemoveUsers'
import {useModalControls, useModals} from '#/state/modals'
import {usePalette} from 'lib/hooks/usePalette'
import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop'
import * as AddAppPassword from './AddAppPasswords'
import * as AltImageModal from './AltImage'
import * as EditImageModal from './AltImage'
import * as DeleteAccountModal from './DeleteAccount'
import * as ChangeEmailModal from './ChangeEmail'
import * as ChangeHandleModal from './ChangeHandle'
import * as ChangePasswordModal from './ChangePassword'
import * as CreateOrEditListModal from './CreateOrEditList'
import * as DeleteAccountModal from './DeleteAccount'
import * as EditProfileModal from './EditProfile'
import * as EmbedConsentModal from './EmbedConsent'
import * as InAppBrowserConsentModal from './InAppBrowserConsent'
import * as InviteCodesModal from './InviteCodes'
import * as AddAppPassword from './AddAppPasswords'
import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings'
import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings'
import * as VerifyEmailModal from './VerifyEmail'
import * as ChangeEmailModal from './ChangeEmail'
import * as ChangePasswordModal from './ChangePassword'
import * as SwitchAccountModal from './SwitchAccount'
import * as LinkWarningModal from './LinkWarning'
import * as EmbedConsentModal from './EmbedConsent'
import * as InAppBrowserConsentModal from './InAppBrowserConsent'
import * as ListAddUserModal from './ListAddRemoveUsers'
import * as RepostModal from './Repost'
import * as SelfLabelModal from './SelfLabel'
import * as SwitchAccountModal from './SwitchAccount'
import * as ThreadgateModal from './Threadgate'
import * as UserAddRemoveListsModal from './UserAddRemoveLists'
import * as VerifyEmailModal from './VerifyEmail'

const DEFAULT_SNAPPOINTS = ['90%']
const HANDLE_HEIGHT = 24
Expand Down
25 changes: 13 additions & 12 deletions src/view/com/modals/SwitchAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import {
TouchableOpacity,
View,
} from 'react-native'
import {Text} from '../util/text/Text'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {BottomSheetScrollView} from '@discord/bottom-sheet/src'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'

import {useProfileQuery} from '#/state/queries/profile'
import {SessionAccount, useSession, useSessionApi} from '#/state/session'
import {useCloseAllActiveElements} from '#/state/util'
import {useAnalytics} from 'lib/analytics/analytics'
import {Haptics} from 'lib/haptics'
import {useAccountSwitcher} from 'lib/hooks/useAccountSwitcher'
import {UserAvatar} from '../util/UserAvatar'
import {usePalette} from 'lib/hooks/usePalette'
import {makeProfileLink} from 'lib/routes/links'
import {s} from 'lib/styles'
import {AccountDropdownBtn} from '../util/AccountDropdownBtn'
import {Link} from '../util/Link'
import {makeProfileLink} from 'lib/routes/links'
import {BottomSheetScrollView} from '@gorhom/bottom-sheet'
import {Haptics} from 'lib/haptics'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useSession, useSessionApi, SessionAccount} from '#/state/session'
import {useProfileQuery} from '#/state/queries/profile'
import {useCloseAllActiveElements} from '#/state/util'
import {Text} from '../util/text/Text'
import {UserAvatar} from '../util/UserAvatar'

export const snapPoints = ['40%', '90%']

Expand Down
2 changes: 1 addition & 1 deletion src/view/com/modals/util.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export {
BottomSheetScrollView as ScrollView,
BottomSheetTextInput as TextInput,
} from '@gorhom/bottom-sheet'
} from '@discord/bottom-sheet/src'
Loading

0 comments on commit ad3dd9f

Please sign in to comment.