Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/src/screens/usage/FlatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const FlatList: React.FC<FlatListUsageScreenNavigationProps> = () => {
data={data}
renderItem={renderItem}
windowSize={10}
automaticallyAdjustsScrollIndicatorInsets={false}
getItemLayout={(_, index) => ({ index, length: ITEM_HEIGHT, offset: index * ITEM_HEIGHT })}
initialNumToRender={50}
maxToRenderPerBatch={100}
Expand Down
17 changes: 10 additions & 7 deletions example/src/screens/usage/Inverted.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { randParagraph, randUuid } from '@ngneat/falso';
import { BlurView } from 'expo-blur';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar';
import {
Header,
ScrollHeaderProps,
FlatListWithHeaders,
SurfaceComponentProps,
FlashListWithHeaders,
} from '@codeherence/react-native-header';
import { Avatar, BackButton } from '../../components';
import { RANDOM_IMAGE_NUM } from '../../constants';
Expand Down Expand Up @@ -68,20 +67,23 @@ const ChatMessage: React.FC<ChatMessage> = ({ message, type }) => {
};

const Inverted: React.FC<InvertedUsageScreenNavigationProps> = () => {
const { bottom } = useSafeAreaInsets();

return (
<>
<StatusBar style="light" />
<FlatListWithHeaders
<FlashListWithHeaders
data={data}
renderItem={({ item }) => <ChatMessage {...item} />}
HeaderComponent={HeaderComponent}
keyExtractor={(item) => item.id}
inverted
// inverted
absoluteHeader
containerStyle={styles.container}
contentContainerStyle={[styles.contentContainer, { paddingTop: bottom }]}
maintainVisibleContentPosition={{
startRenderingFromBottom: true,
}}
automaticallyAdjustsScrollIndicatorInsets={false}
// eslint-disable-next-line react-native/no-inline-styles
contentContainerStyle={{ paddingHorizontal: 12 }}
showsVerticalScrollIndicator
indicatorStyle={'white'}
/>
Expand All @@ -93,6 +95,7 @@ export default Inverted;

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'black',
},
contentContainer: {
Expand Down
18 changes: 15 additions & 3 deletions src/components/containers/FlashList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useImperativeHandle } from 'react';
import React, { useImperativeHandle, useMemo } from 'react';
import { StyleSheet, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Animated, { AnimatedProps, useAnimatedRef } from 'react-native-reanimated';
import Animated, { AnimatedProps, isSharedValue, useAnimatedRef } from 'react-native-reanimated';
import { FlashList, FlashListProps, FlashListRef } from '@shopify/flash-list';

import type { SharedScrollContainerProps } from '.';
Expand Down Expand Up @@ -60,6 +60,17 @@ const FlashListWithHeadersInputComp = <ItemT extends any = any>(
const scrollRef = useAnimatedRef<any>();
useImperativeHandle(ref, () => scrollRef.current);

const { maintainVisibleContentPosition } = rest;
const inverted = useMemo(() => {
if (maintainVisibleContentPosition === undefined) return false;
if (isSharedValue(maintainVisibleContentPosition)) return false;

return (
(maintainVisibleContentPosition as FlashListProps<ItemT>['maintainVisibleContentPosition'])
?.startRenderingFromBottom ?? false
);
}, [maintainVisibleContentPosition]);

const {
scrollY,
showNavBar,
Expand All @@ -77,8 +88,9 @@ const FlashListWithHeadersInputComp = <ItemT extends any = any>(
absoluteHeader,
initialAbsoluteHeaderHeight,
headerFadeInThreshold,
inverted: false,
inverted,
onScrollWorklet,
isFlashList: true,
});

return (
Expand Down
24 changes: 23 additions & 1 deletion src/components/containers/useScrollContainerLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from 'react-native-reanimated';
import { useDebouncedCallback } from 'use-debounce';
import type { SharedScrollContainerProps } from './types';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

/**
* The arguments for the useScrollContainerLogic hook.
Expand Down Expand Up @@ -77,6 +78,12 @@ interface UseScrollContainerLogicArgs {
* ensure that this function is a [worklet](https://docs.swmansion.com/react-native-reanimated/docs/2.x/fundamentals/worklets/).
*/
onScrollWorklet?: (evt: NativeScrollEvent) => void;
/**
* Whether or not the scroll container is a FlashList. This is used because FlashList actually
* implements the inverted property differently and requires a different approach to compute the
* scroll indicator insets and content container style.
*/
isFlashList?: boolean;
}

/**
Expand All @@ -96,7 +103,9 @@ export const useScrollContainerLogic = ({
headerFadeInThreshold = 1,
inverted,
onScrollWorklet,
isFlashList = false,
}: UseScrollContainerLogicArgs) => {
const insets = useSafeAreaInsets();
const [absoluteHeaderHeight, setAbsoluteHeaderHeight] = useState(initialAbsoluteHeaderHeight);
const scrollY = useSharedValue(0);
const largeHeaderHeight = useSharedValue(0);
Expand Down Expand Up @@ -162,6 +171,19 @@ export const useScrollContainerLogic = ({
);

const scrollViewAdjustments = useMemo(() => {
if (isFlashList) {
return {
scrollIndicatorInsets: {
top: absoluteHeader && inverted ? absoluteHeaderHeight : 0,
bottom: insets.bottom,
},
contentContainerStyle: {
paddingTop: absoluteHeader && inverted ? absoluteHeaderHeight : 0,
paddingBottom: insets.bottom,
},
};
}

return {
scrollIndicatorInsets: {
top: absoluteHeader && !inverted ? absoluteHeaderHeight : 0,
Expand All @@ -172,7 +194,7 @@ export const useScrollContainerLogic = ({
paddingBottom: absoluteHeader && inverted ? absoluteHeaderHeight : 0,
},
};
}, [inverted, absoluteHeaderHeight, absoluteHeader]);
}, [inverted, absoluteHeaderHeight, absoluteHeader, isFlashList, insets]);

return {
scrollY,
Expand Down