Fix problems with BottomSheet
and the report dialog (#3297)
* 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
This commit is contained in:
parent
c649ee1afa
commit
ad3dd9f6dc
11 changed files with 138 additions and 126 deletions
|
@ -1,59 +1,58 @@
|
|||
import 'react-native-url-polyfill/auto'
|
||||
import 'lib/sentry' // must be near top
|
||||
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import {RootSiblingParent} from 'react-native-root-siblings'
|
||||
import * as SplashScreen from 'expo-splash-screen'
|
||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
||||
import {PersistQueryClientProvider} from '@tanstack/react-query-persist-client'
|
||||
import {
|
||||
SafeAreaProvider,
|
||||
initialWindowMetrics,
|
||||
} from 'react-native-safe-area-context'
|
||||
|
||||
import 'view/icons'
|
||||
|
||||
import {ThemeProvider as Alf} from '#/alf'
|
||||
import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
|
||||
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 notifications from 'lib/notifications/notifications'
|
||||
import * as Toast from 'view/com/util/Toast'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
||||
import {RootSiblingParent} from 'react-native-root-siblings'
|
||||
import {
|
||||
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 {Provider as StatsigProvider} from '#/lib/statsig/statsig'
|
||||
import {init as initPersistedState} from '#/state/persisted'
|
||||
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 {
|
||||
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 LightboxStateProvider} from 'state/lightbox'
|
||||
import {Provider as MutedThreadsProvider} from 'state/muted-threads'
|
||||
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 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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -122,7 +122,6 @@ export function Outer({
|
|||
)
|
||||
|
||||
const onCloseInner = React.useCallback(() => {
|
||||
Keyboard.dismiss()
|
||||
try {
|
||||
closeCallback.current?.()
|
||||
} catch (e: any) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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 {atoms as a} from '#/alf'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {AppBskyLabelerDefs} from '@atproto/api'
|
||||
import {BottomSheetScrollViewMethods} from '@discord/bottom-sheet/src'
|
||||
|
||||
import {ReportDialogProps} from './types'
|
||||
import {atoms as a} from '#/alf'
|
||||
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 {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 (
|
||||
|
@ -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" />
|
||||
|
@ -55,8 +60,6 @@ function ReportDialogInner(props: ReportDialogProps) {
|
|||
) : (
|
||||
<ReportDialogLoaded labelers={labelers} {...props} />
|
||||
)}
|
||||
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
|
|
12
src/components/hooks/useOnKeyboard.ts
Normal file
12
src/components/hooks/useOnKeyboard.ts
Normal file
|
@ -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])
|
||||
}
|
|
@ -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 ChangeHandleModal from './ChangeHandle'
|
||||
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 ChangeHandleModal from './ChangeHandle'
|
||||
import * as ChangePasswordModal from './ChangePassword'
|
||||
import * as SwitchAccountModal from './SwitchAccount'
|
||||
import * as LinkWarningModal from './LinkWarning'
|
||||
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 ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings'
|
||||
import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings'
|
||||
import * as LinkWarningModal from './LinkWarning'
|
||||
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
|
||||
|
|
|
@ -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%']
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export {
|
||||
BottomSheetScrollView as ScrollView,
|
||||
BottomSheetTextInput as TextInput,
|
||||
} from '@gorhom/bottom-sheet'
|
||||
} from '@discord/bottom-sheet/src'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, {useMemo} from 'react'
|
||||
import {TouchableWithoutFeedback} from 'react-native'
|
||||
import {BottomSheetBackdropProps} from '@gorhom/bottom-sheet'
|
||||
import Animated, {
|
||||
Extrapolate,
|
||||
interpolate,
|
||||
useAnimatedStyle,
|
||||
} from 'react-native-reanimated'
|
||||
import {BottomSheetBackdropProps} from '@discord/bottom-sheet/src'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue