diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/pager/PagerHeaderContext.tsx | 30 | ||||
-rw-r--r-- | src/view/com/pager/PagerWithHeader.tsx | 25 | ||||
-rw-r--r-- | src/view/com/pager/PagerWithHeader.web.tsx | 16 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 10 | ||||
-rw-r--r-- | src/view/shell/index.tsx | 6 |
5 files changed, 65 insertions, 22 deletions
diff --git a/src/view/com/pager/PagerHeaderContext.tsx b/src/view/com/pager/PagerHeaderContext.tsx index fd4cc7463..c979f7a6d 100644 --- a/src/view/com/pager/PagerHeaderContext.tsx +++ b/src/view/com/pager/PagerHeaderContext.tsx @@ -1,40 +1,48 @@ import React, {useContext} from 'react' import {SharedValue} from 'react-native-reanimated' -import {isIOS} from '#/platform/detection' +import {isNative} from '#/platform/detection' -export const PagerHeaderContext = - React.createContext<SharedValue<number> | null>(null) +export const PagerHeaderContext = React.createContext<{ + scrollY: SharedValue<number> + headerHeight: number +} | null>(null) /** - * Passes the scrollY value to the pager header's banner, so it can grow on - * overscroll on iOS. Not necessary to use this context provider on other platforms. + * Passes information about the scroll position and header height down via + * context for the pager header to consume. * - * @platform ios + * @platform ios, android */ export function PagerHeaderProvider({ scrollY, + headerHeight, children, }: { scrollY: SharedValue<number> + headerHeight: number children: React.ReactNode }) { + const value = React.useMemo( + () => ({scrollY, headerHeight}), + [scrollY, headerHeight], + ) return ( - <PagerHeaderContext.Provider value={scrollY}> + <PagerHeaderContext.Provider value={value}> {children} </PagerHeaderContext.Provider> ) } export function usePagerHeaderContext() { - const scrollY = useContext(PagerHeaderContext) - if (isIOS) { - if (!scrollY) { + const ctx = useContext(PagerHeaderContext) + if (isNative) { + if (!ctx) { throw new Error( 'usePagerHeaderContext must be used within a HeaderProvider', ) } - return {scrollY} + return ctx } else { return null } diff --git a/src/view/com/pager/PagerWithHeader.tsx b/src/view/com/pager/PagerWithHeader.tsx index 617445964..dcf141f84 100644 --- a/src/view/com/pager/PagerWithHeader.tsx +++ b/src/view/com/pager/PagerWithHeader.tsx @@ -38,7 +38,11 @@ export interface PagerWithHeaderProps { | ((props: PagerWithHeaderChildParams) => JSX.Element) items: string[] isHeaderReady: boolean - renderHeader?: () => JSX.Element + renderHeader?: ({ + setMinimumHeight, + }: { + setMinimumHeight: (height: number) => void + }) => JSX.Element initialPage?: number onPageSelected?: (index: number) => void onCurrentPageSelected?: (index: number) => void @@ -83,7 +87,9 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>( const renderTabBar = React.useCallback( (props: RenderTabBarFnProps) => { return ( - <PagerHeaderProvider scrollY={scrollY}> + <PagerHeaderProvider + scrollY={scrollY} + headerHeight={headerOnlyHeight}> <PagerTabBar headerOnlyHeight={headerOnlyHeight} items={items} @@ -237,7 +243,11 @@ let PagerTabBar = ({ items: string[] testID?: string scrollY: SharedValue<number> - renderHeader?: () => JSX.Element + renderHeader?: ({ + setMinimumHeight, + }: { + setMinimumHeight: (height: number) => void + }) => JSX.Element onHeaderOnlyLayout: (height: number) => void onTabBarLayout: (e: LayoutChangeEvent) => void onCurrentPageSelected?: (index: number) => void @@ -246,8 +256,13 @@ let PagerTabBar = ({ dragProgress: SharedValue<number> dragState: SharedValue<'idle' | 'dragging' | 'settling'> }): React.ReactNode => { + const [minimumHeaderHeight, setMinimumHeaderHeight] = React.useState(0) const headerTransform = useAnimatedStyle(() => { - const translateY = Math.min(scrollY.get(), headerOnlyHeight) * -1 + const translateY = + Math.min( + scrollY.get(), + Math.max(headerOnlyHeight - minimumHeaderHeight, 0), + ) * -1 return { transform: [ { @@ -267,7 +282,7 @@ let PagerTabBar = ({ ref={headerRef} pointerEvents={isIOS ? 'auto' : 'box-none'} collapsable={false}> - {renderHeader?.()} + {renderHeader?.({setMinimumHeight: setMinimumHeaderHeight})} { // It wouldn't be enough to place `onLayout` on the parent node because // this would risk measuring before `isHeaderReady` has turned `true`. diff --git a/src/view/com/pager/PagerWithHeader.web.tsx b/src/view/com/pager/PagerWithHeader.web.tsx index 3335532b3..98b32b347 100644 --- a/src/view/com/pager/PagerWithHeader.web.tsx +++ b/src/view/com/pager/PagerWithHeader.web.tsx @@ -21,7 +21,11 @@ export interface PagerWithHeaderProps { | ((props: PagerWithHeaderChildParams) => JSX.Element) items: string[] isHeaderReady: boolean - renderHeader?: () => JSX.Element + renderHeader?: ({ + setMinimumHeight, + }: { + setMinimumHeight: () => void + }) => JSX.Element initialPage?: number onPageSelected?: (index: number) => void onCurrentPageSelected?: (index: number) => void @@ -115,7 +119,11 @@ let PagerTabBar = ({ currentPage: number items: string[] testID?: string - renderHeader?: () => JSX.Element + renderHeader?: ({ + setMinimumHeight, + }: { + setMinimumHeight: () => void + }) => JSX.Element isHeaderReady: boolean onCurrentPageSelected?: (index: number) => void onSelect?: (index: number) => void @@ -123,7 +131,7 @@ let PagerTabBar = ({ }): React.ReactNode => { return ( <> - <Layout.Center>{renderHeader?.()}</Layout.Center> + <Layout.Center>{renderHeader?.({setMinimumHeight: noop})}</Layout.Center> {tabBarAnchor} <Layout.Center style={web([ @@ -175,3 +183,5 @@ function toArray<T>(v: T | T[]): T[] { } return [v] } + +function noop() {} diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 782e9b9c8..ebf1d955d 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -43,6 +43,7 @@ import {ListRef} from '#/view/com/util/List' import {ProfileHeader, ProfileHeaderLoading} from '#/screens/Profile/Header' import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed' import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels' +import {atoms as a} from '#/alf' import * as Layout from '#/components/Layout' import {ScreenHider} from '#/components/moderation/ScreenHider' import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks' @@ -56,7 +57,7 @@ interface SectionRef { type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'> export function ProfileScreen(props: Props) { return ( - <Layout.Screen testID="profileScreen"> + <Layout.Screen testID="profileScreen" style={[a.pt_0]}> <ProfileScreenInner {...props} /> </Layout.Screen> ) @@ -329,7 +330,11 @@ function ProfileScreenLoaded({ // rendering // = - const renderHeader = () => { + const renderHeader = ({ + setMinimumHeight, + }: { + setMinimumHeight: (height: number) => void + }) => { return ( <ExpoScrollForwarderView scrollViewTag={scrollViewTag}> <ProfileHeader @@ -339,6 +344,7 @@ function ProfileScreenLoaded({ moderationOpts={moderationOpts} hideBackButton={hideBackButton} isPlaceholderProfile={showPlaceholder} + setMinimumHeight={setMinimumHeight} /> </ExpoScrollForwarderView> ) diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 179e8858e..a5e97610d 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -18,6 +18,7 @@ import { useIsDrawerSwipeDisabled, useSetDrawerOpen, } from '#/state/shell' +import {useLightStatusBar} from '#/state/shell/light-status-bar' import {useCloseAnyActiveElement} from '#/state/util' import {Lightbox} from '#/view/com/lightbox/Lightbox' import {ModalsContainer} from '#/view/com/modals/Modal' @@ -154,6 +155,7 @@ function ShellInner() { export const Shell: React.FC = function ShellImpl() { const {fullyExpandedCount} = useDialogStateControlContext() + const lightStatusBar = useLightStatusBar() const t = useTheme() useIntentHandler() @@ -165,7 +167,9 @@ export const Shell: React.FC = function ShellImpl() { <View testID="mobileShellView" style={[a.h_full, t.atoms.bg]}> <StatusBar style={ - t.name !== 'light' || (isIOS && fullyExpandedCount > 0) + t.name !== 'light' || + (isIOS && fullyExpandedCount > 0) || + lightStatusBar ? 'light' : 'dark' } |