Skip to content

Commit

Permalink
Fix profile preview jump (#1693)
Browse files Browse the repository at this point in the history
* Add top inset for profile preview to match target screen

* Avoid flicker by waiting for profile screen navigation

* Fix glimmer to align with the content

* A more reliable (but non-scientific) fix for the flash

* Lower the timeout
  • Loading branch information
gaearon authored Oct 13, 2023
1 parent d5ccbd7 commit f447eaa
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 18 deletions.
16 changes: 14 additions & 2 deletions src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,21 @@ function navigate<K extends keyof AllNavigatorParams>(
params?: AllNavigatorParams[K],
) {
if (navigationRef.isReady()) {
// @ts-ignore I dont know what would make typescript happy but I have a life -prf
navigationRef.navigate(name, params)
return Promise.race([
new Promise<void>(resolve => {
const handler = () => {
resolve()
navigationRef.removeListener('state', handler)
}
navigationRef.addListener('state', handler)

// @ts-ignore I dont know what would make typescript happy but I have a life -prf
navigationRef.navigate(name, params)
}),
timeout(1e3),
])
}
return Promise.resolve()
}

function resetToTab(tabName: 'HomeTab' | 'SearchTab' | 'NotificationsTab') {
Expand Down
20 changes: 16 additions & 4 deletions src/view/com/modals/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, {useRef, useEffect} from 'react'
import {StyleSheet} from 'react-native'
import {SafeAreaView} from 'react-native-safe-area-context'
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context'
import {observer} from 'mobx-react-lite'
import BottomSheet from '@gorhom/bottom-sheet'
import {useStores} from 'state/index'
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'

Expand Down Expand Up @@ -36,11 +37,13 @@ import * as SwitchAccountModal from './SwitchAccount'
import * as LinkWarningModal from './LinkWarning'

const DEFAULT_SNAPPOINTS = ['90%']
const HANDLE_HEIGHT = 24

export const ModalsContainer = observer(function ModalsContainer() {
const store = useStores()
const bottomSheetRef = useRef<BottomSheet>(null)
const pal = usePalette('default')
const safeAreaInsets = useSafeAreaInsets()

const activeModal =
store.shell.activeModals[store.shell.activeModals.length - 1]
Expand All @@ -53,12 +56,16 @@ export const ModalsContainer = observer(function ModalsContainer() {
navigateOnce('Profile', {name: activeModal.did})
}
}
const onBottomSheetChange = (snapPoint: number) => {
const onBottomSheetChange = async (snapPoint: number) => {
if (snapPoint === -1) {
store.shell.closeModal()
} else if (activeModal?.name === 'profile-preview' && snapPoint === 1) {
// ensure we navigate to Profile and close the modal
navigateOnce('Profile', {name: activeModal.did})
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)
store.shell.closeModal()
}
}
Expand All @@ -75,6 +82,7 @@ export const ModalsContainer = observer(function ModalsContainer() {
}
}, [store.shell.isModalActive, bottomSheetRef, activeModal?.name])

let needsSafeTopInset = false
let snapPoints: (string | number)[] = DEFAULT_SNAPPOINTS
let element
if (activeModal?.name === 'confirm') {
Expand All @@ -86,6 +94,7 @@ export const ModalsContainer = observer(function ModalsContainer() {
} 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} />
Expand Down Expand Up @@ -164,10 +173,13 @@ export const ModalsContainer = observer(function ModalsContainer() {
)
}

const topInset = needsSafeTopInset ? safeAreaInsets.top - HANDLE_HEIGHT : 0
return (
<BottomSheet
ref={bottomSheetRef}
snapPoints={snapPoints}
topInset={topInset}
handleHeight={HANDLE_HEIGHT}
index={store.shell.isModalActive ? 0 : -1}
enablePanDownToClose
android_keyboardInputMode="adjustResize"
Expand Down
11 changes: 1 addition & 10 deletions src/view/com/modals/ProfilePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {useAnalytics} from 'lib/analytics/analytics'
import {ProfileHeader} from '../profile/ProfileHeader'
import {InfoCircleIcon} from 'lib/icons'
import {useNavigationState} from '@react-navigation/native'
import {isIOS} from 'platform/detection'
import {s} from 'lib/styles'

export const snapPoints = [520, '100%']
Expand All @@ -36,11 +35,7 @@ export const Component = observer(function ProfilePreviewImpl({

return (
<View testID="profilePreview" style={[pal.view, s.flex1]}>
<View
style={[
styles.headerWrapper,
isLoading && isIOS && styles.headerPositionAdjust,
]}>
<View style={[styles.headerWrapper]}>
<ProfileHeader
view={model}
hideBackButton
Expand Down Expand Up @@ -70,10 +65,6 @@ const styles = StyleSheet.create({
headerWrapper: {
height: 440,
},
headerPositionAdjust: {
// HACK align the header for the profilescreen transition -prf
paddingTop: 23,
},
hintWrapper: {
height: 80,
},
Expand Down
4 changes: 2 additions & 2 deletions src/view/com/profile/ProfileHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ export const ProfileHeader = observer(function ProfileHeaderImpl({
if (!view || !view.hasLoaded) {
return (
<View style={pal.view}>
<LoadingPlaceholder width="100%" height={120} />
<LoadingPlaceholder width="100%" height={153} />
<View
style={[pal.view, {borderColor: pal.colors.background}, styles.avi]}>
<LoadingPlaceholder width={80} height={80} style={styles.br40} />
</View>
<View style={styles.content}>
<View style={[styles.buttonsLine]}>
<LoadingPlaceholder width={100} height={31} style={styles.br50} />
<LoadingPlaceholder width={167} height={31} style={styles.br50} />
</View>
<View>
<Text type="title-2xl" style={[pal.text, styles.title]}>
Expand Down

0 comments on commit f447eaa

Please sign in to comment.