Remove Profile Preview modal (#2790)

zio/stable
dan 2024-02-08 23:41:02 +00:00 committed by GitHub
parent 06f81d6948
commit d9b62955b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 14 additions and 211 deletions

View File

@ -144,7 +144,6 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
getComponent={() => ProfileScreen}
options={({route}) => ({
title: bskyTitle(`@${route.params.name}`, unreadCountLabel),
animation: 'none',
})}
/>
<Stack.Screen

View File

@ -26,11 +26,6 @@ export interface EditProfileModal {
onUpdate?: () => void
}
export interface ProfilePreviewModal {
name: 'profile-preview'
did: string
}
export interface ServerInputModal {
name: 'server-input'
initialService: string
@ -202,7 +197,6 @@ export type Modal =
| ChangeHandleModal
| DeleteAccountModal
| EditProfileModal
| ProfilePreviewModal
| BirthDateSettingsModal
| VerifyEmailModal
| ChangeEmailModal

View File

@ -1,18 +1,13 @@
import React, {useRef, useEffect} from 'react'
import {StyleSheet} from 'react-native'
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context'
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 {timeout} from 'lib/async/timeout'
import {navigate} from '../../../Navigation'
import once from 'lodash.once'
import {useModals, useModalControls} from '#/state/modals'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import * as ConfirmModal from './Confirm'
import * as EditProfileModal from './EditProfile'
import * as ProfilePreviewModal from './ProfilePreview'
import * as ServerInputModal from './ServerInput'
import * as RepostModal from './Repost'
import * as SelfLabelModal from './SelfLabel'
@ -50,34 +45,14 @@ export function ModalsContainer() {
const {closeModal} = useModalControls()
const bottomSheetRef = useRef<BottomSheet>(null)
const pal = usePalette('default')
const safeAreaInsets = useSafeAreaInsets()
const activeModal = activeModals[activeModals.length - 1]
const navigateOnce = once(navigate)
// It seems like the bottom sheet bugs out when this callback changes.
const onBottomSheetAnimate = useNonReactiveCallback(
(_fromIndex: number, toIndex: number) => {
if (activeModal?.name === 'profile-preview' && toIndex === 1) {
// begin loading the profile screen behind the scenes
navigateOnce('Profile', {name: activeModal.did})
}
},
)
const onBottomSheetChange = async (snapPoint: number) => {
if (snapPoint === -1) {
closeModal()
} else if (activeModal?.name === 'profile-preview' && snapPoint === 1) {
await navigateOnce('Profile', {name: activeModal.did})
// There is no particular callback for when the view has actually been presented.
// This delay gives us a decent chance the navigation has flushed *and* images have loaded.
// It's acceptable because the data is already being fetched + it usually takes longer anyway.
// TODO: Figure out why avatar/cover don't always show instantly from cache.
await timeout(200)
closeModal()
}
}
const onClose = () => {
bottomSheetRef.current?.close()
closeModal()
@ -91,7 +66,6 @@ export function ModalsContainer() {
}
}, [isModalActive, bottomSheetRef, activeModal?.name])
let needsSafeTopInset = false
let snapPoints: (string | number)[] = DEFAULT_SNAPPOINTS
let element
if (activeModal?.name === 'confirm') {
@ -100,10 +74,6 @@ export function ModalsContainer() {
} else if (activeModal?.name === 'edit-profile') {
snapPoints = EditProfileModal.snapPoints
element = <EditProfileModal.Component {...activeModal} />
} else if (activeModal?.name === 'profile-preview') {
snapPoints = ProfilePreviewModal.snapPoints
element = <ProfilePreviewModal.Component {...activeModal} />
needsSafeTopInset = true // Need to align with the target profile screen.
} else if (activeModal?.name === 'server-input') {
snapPoints = ServerInputModal.snapPoints
element = <ServerInputModal.Component {...activeModal} />
@ -200,12 +170,10 @@ export function ModalsContainer() {
)
}
const topInset = needsSafeTopInset ? safeAreaInsets.top - HANDLE_HEIGHT : 0
return (
<BottomSheet
ref={bottomSheetRef}
snapPoints={snapPoints}
topInset={topInset}
handleHeight={HANDLE_HEIGHT}
index={isModalActive ? 0 : -1}
enablePanDownToClose
@ -216,7 +184,6 @@ export function ModalsContainer() {
}
handleIndicatorStyle={{backgroundColor: pal.text.color}}
handleStyle={[styles.handle, pal.view]}
onAnimate={onBottomSheetAnimate}
onChange={onBottomSheetChange}>
{element}
</BottomSheet>

View File

@ -9,7 +9,6 @@ import {useModals, useModalControls} from '#/state/modals'
import type {Modal as ModalIface} from '#/state/modals'
import * as ConfirmModal from './Confirm'
import * as EditProfileModal from './EditProfile'
import * as ProfilePreviewModal from './ProfilePreview'
import * as ServerInputModal from './ServerInput'
import * as ReportModal from './report/Modal'
import * as AppealLabelModal from './AppealLabel'
@ -85,8 +84,6 @@ function Modal({modal}: {modal: ModalIface}) {
element = <ConfirmModal.Component {...modal} />
} else if (modal.name === 'edit-profile') {
element = <EditProfileModal.Component {...modal} />
} else if (modal.name === 'profile-preview') {
element = <ProfilePreviewModal.Component {...modal} />
} else if (modal.name === 'server-input') {
element = <ServerInputModal.Component {...modal} />
} else if (modal.name === 'report') {

View File

@ -1,134 +0,0 @@
import React, {useState, useEffect} from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {AppBskyActorDefs, ModerationOpts, moderateProfile} from '@atproto/api'
import {ThemedText} from '../util/text/ThemedText'
import {usePalette} from 'lib/hooks/usePalette'
import {useAnalytics} from 'lib/analytics/analytics'
import {ProfileHeader} from '../profile/ProfileHeader'
import {InfoCircleIcon} from 'lib/icons'
import {useNavigationState} from '@react-navigation/native'
import {s} from 'lib/styles'
import {useModerationOpts} from '#/state/queries/preferences'
import {useProfileQuery} from '#/state/queries/profile'
import {ErrorScreen} from '../util/error/ErrorScreen'
import {CenteredView} from '../util/Views'
import {cleanError} from '#/lib/strings/errors'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
export const snapPoints = [520, '100%']
export function Component({did}: {did: string}) {
const pal = usePalette('default')
const {_} = useLingui()
const moderationOpts = useModerationOpts()
const {
data: profile,
error: profileError,
refetch: refetchProfile,
isLoading: isLoadingProfile,
} = useProfileQuery({
did: did,
})
if (isLoadingProfile || !moderationOpts) {
return (
<CenteredView style={[pal.view, s.flex1]}>
<ProfileHeader
profile={null}
moderation={null}
isProfilePreview={true}
/>
</CenteredView>
)
}
if (profileError) {
return (
<ErrorScreen
title={_(msg`Not Found`)}
message={cleanError(profileError)}
onPressTryAgain={refetchProfile}
/>
)
}
if (profile && moderationOpts) {
return <ComponentLoaded profile={profile} moderationOpts={moderationOpts} />
}
// should never happen
return (
<ErrorScreen
title={_(msg`Oops!`)}
message={_(msg`Something went wrong and we're not sure what.`)}
onPressTryAgain={refetchProfile}
/>
)
}
function ComponentLoaded({
profile: profileUnshadowed,
moderationOpts,
}: {
profile: AppBskyActorDefs.ProfileViewDetailed
moderationOpts: ModerationOpts
}) {
const pal = usePalette('default')
const profile = useProfileShadow(profileUnshadowed)
const {screen} = useAnalytics()
const moderation = React.useMemo(
() => moderateProfile(profile, moderationOpts),
[profile, moderationOpts],
)
// track the navigator state to detect if a page-load occurred
const navState = useNavigationState(state => state)
const [initNavState] = useState(navState)
const isLoading = initNavState !== navState
useEffect(() => {
screen('Profile:Preview')
}, [screen])
return (
<View testID="profilePreview" style={[pal.view, s.flex1]}>
<View style={[styles.headerWrapper]}>
<ProfileHeader
profile={profile}
moderation={moderation}
hideBackButton
isProfilePreview
/>
</View>
<View style={[styles.hintWrapper, pal.view]}>
<View style={styles.hint}>
{isLoading ? (
<ActivityIndicator />
) : (
<>
<InfoCircleIcon size={21} style={pal.textLight} />
<ThemedText type="xl" fg="light">
<Trans>Swipe up to see more</Trans>
</ThemedText>
</>
)}
</View>
</View>
</View>
)
}
const styles = StyleSheet.create({
headerWrapper: {
height: 440,
},
hintWrapper: {
height: 80,
},
hint: {
flexDirection: 'row',
justifyContent: 'center',
gap: 8,
paddingHorizontal: 14,
borderRadius: 6,
},
})

View File

@ -1,9 +1,8 @@
import React from 'react'
import {Pressable, StyleProp, ViewStyle} from 'react-native'
import {StyleProp, ViewStyle} from 'react-native'
import {Link} from './Link'
import {isAndroid, isWeb} from 'platform/detection'
import {isWeb} from 'platform/detection'
import {makeProfileLink} from 'lib/routes/links'
import {useModalControls} from '#/state/modals'
import {usePrefetchProfileQuery} from '#/state/queries/profile'
interface UserPreviewLinkProps {
@ -14,38 +13,19 @@ interface UserPreviewLinkProps {
export function UserPreviewLink(
props: React.PropsWithChildren<UserPreviewLinkProps>,
) {
const {openModal} = useModalControls()
const prefetchProfileQuery = usePrefetchProfileQuery()
if (isWeb || isAndroid) {
return (
<Link
onPointerEnter={() => {
if (isWeb) {
prefetchProfileQuery(props.did)
}
}}
href={makeProfileLink(props)}
title={props.handle}
asAnchor
style={props.style}>
{props.children}
</Link>
)
}
return (
<Pressable
onPress={() =>
openModal({
name: 'profile-preview',
did: props.did,
})
}
accessibilityRole="button"
accessibilityLabel={props.handle}
accessibilityHint=""
<Link
onPointerEnter={() => {
if (isWeb) {
prefetchProfileQuery(props.did)
}
}}
href={makeProfileLink(props)}
title={props.handle}
asAnchor
style={props.style}>
{props.children}
</Pressable>
</Link>
)
}