[FIX] Reactions list isn't scrollable

This commit is contained in:
Reinaldo Neto 2023-02-06 11:13:06 -03:00
parent 68f6eb40de
commit 92bbf4726a
5 changed files with 53 additions and 19 deletions

View File

@ -27,7 +27,7 @@ const ANIMATION_CONFIG = {
};
const ActionSheet = React.memo(
forwardRef(({ children }: { children: React.ReactElement }, ref) => {
forwardRef(({ children, onChange }: { children: React.ReactElement; onChange(index: number): void }, ref) => {
const { colors } = useTheme();
const bottomSheetRef = useRef<BottomSheet>(null);
const [data, setData] = useState<TActionSheetOptions>({} as TActionSheetOptions);
@ -125,6 +125,11 @@ const ActionSheet = React.memo(
// when is android tablet and the input text is focused
const androidTablet: any = isTablet && isLandscape && !isIOS ? { android_keyboardInputMode: 'adjustResize' } : {};
const handleOnChange = (index: number) => {
onChange(index);
index === -1 && onClose();
};
return (
<>
{children}
@ -139,7 +144,7 @@ const ActionSheet = React.memo(
enablePanDownToClose
style={{ ...styles.container, ...bottomSheet }}
backgroundStyle={{ backgroundColor: colors.focusedBackground }}
onChange={index => index === -1 && onClose()}
onChange={handleOnChange}
// We need this to allow horizontal swipe gesture inside the bottom sheet like in reaction picker
enableContentPanningGesture={data?.enableContentPanningGesture ?? true}
{...androidTablet}

View File

@ -1,5 +1,5 @@
import hoistNonReactStatics from 'hoist-non-react-statics';
import React, { ForwardedRef, forwardRef, useContext, useRef } from 'react';
import React, { ForwardedRef, forwardRef, useContext, useRef, useState } from 'react';
import { TIconsName } from '../CustomIcon';
import ActionSheet from './ActionSheet';
@ -27,11 +27,13 @@ export type TActionSheetOptions = {
export interface IActionSheetProvider {
showActionSheet: (item: TActionSheetOptions) => void;
hideActionSheet: () => void;
indexPosition: number;
}
const context = React.createContext<IActionSheetProvider>({
showActionSheet: () => {},
hideActionSheet: () => {}
hideActionSheet: () => {},
indexPosition: -1
});
export const useActionSheet = () => useContext(context);
@ -48,20 +50,24 @@ export const withActionSheet = (Component: React.ComponentType<any>): typeof Com
};
export const ActionSheetProvider = React.memo(({ children }: { children: React.ReactElement | React.ReactElement[] }) => {
const [indexPosition, setIndexPosition] = useState(-1);
const ref: ForwardedRef<IActionSheetProvider> = useRef(null);
const onChange = (index: number) => setIndexPosition(index);
const getContext = () => ({
showActionSheet: (options: TActionSheetOptions) => {
ref.current?.showActionSheet(options);
},
hideActionSheet: () => {
ref.current?.hideActionSheet();
}
},
indexPosition
});
return (
<Provider value={getContext()}>
<ActionSheet ref={ref}>
<ActionSheet ref={ref} onChange={onChange}>
<>{children}</>
</ActionSheet>
</Provider>

View File

@ -1,6 +1,7 @@
import React from 'react';
import { Text, View, FlatList } from 'react-native';
import { Text, View, FlatList, useWindowDimensions } from 'react-native';
import { useActionSheet } from '../ActionSheet';
import Emoji from '../message/Emoji';
import { useTheme } from '../../theme';
import { IReaction } from '../../definitions';
@ -8,6 +9,7 @@ import { TGetCustomEmoji } from '../../definitions/IEmoji';
import I18n from '../../i18n';
import styles from './styles';
import { useAppSelector } from '../../lib/hooks';
import { calculatePadding } from './calculatePadding';
interface IAllReactionsListItemProps {
getCustomEmoji: TGetCustomEmoji;
@ -61,15 +63,21 @@ const AllReactionsListItem = ({ item, getCustomEmoji }: IAllReactionsListItemPro
);
};
const AllTab = ({ reactions, getCustomEmoji }: IAllTabProps): React.ReactElement => (
<View style={styles.allTabContainer} testID='reactionsListAllTab'>
<FlatList
data={reactions}
contentContainerStyle={styles.listContainer}
renderItem={({ item }) => <AllReactionsListItem item={item} getCustomEmoji={getCustomEmoji} />}
keyExtractor={item => item.emoji}
/>
</View>
);
const AllTab = ({ reactions, getCustomEmoji }: IAllTabProps): React.ReactElement => {
const { height } = useWindowDimensions();
const paddingBottom = calculatePadding(height);
const { indexPosition } = useActionSheet();
return (
<View style={styles.allTabContainer} testID='reactionsListAllTab'>
<FlatList
data={reactions}
contentContainerStyle={[styles.listContainer, indexPosition === 0 && { paddingBottom }]}
renderItem={({ item }) => <AllReactionsListItem item={item} getCustomEmoji={getCustomEmoji} />}
keyExtractor={item => item.emoji}
/>
</View>
);
};
export default AllTab;

View File

@ -1,15 +1,20 @@
import React from 'react';
import { Text, View, FlatList } from 'react-native';
import { Text, View, FlatList, useWindowDimensions } from 'react-native';
import { useSelector } from 'react-redux';
import { useTheme } from '../../theme';
import { IReaction, IApplicationState } from '../../definitions';
import Avatar from '../Avatar';
import styles from './styles';
import { useActionSheet } from '../ActionSheet';
import { calculatePadding } from './calculatePadding';
const UsersList = ({ tabLabel }: { tabLabel: IReaction }): React.ReactElement => {
const { colors } = useTheme();
const useRealName = useSelector((state: IApplicationState) => state.settings.UI_Use_Real_Name);
const { indexPosition } = useActionSheet();
const { height } = useWindowDimensions();
const paddingBottom = calculatePadding(height);
const { emoji, usernames, names } = tabLabel;
const users =
@ -20,7 +25,7 @@ const UsersList = ({ tabLabel }: { tabLabel: IReaction }): React.ReactElement =>
return (
<FlatList
data={users}
contentContainerStyle={styles.listContainer}
contentContainerStyle={[styles.listContainer, indexPosition === 0 && { paddingBottom }]}
ListHeaderComponent={
<View style={styles.emojiNameContainer}>
<Text style={[styles.emojiName, { color: colors.auxiliaryText }]} testID='usersListEmojiName'>

View File

@ -0,0 +1,10 @@
const HEADER_HEIGHT = 48;
const SNAP_PERCENTAGE = 0.4;
/**
* This function is required for the ReactionsList to see the full list and the scroll enables,
* because there are two snaps 50% and 80%, and the content size of the flatlist is measured by the 80%,
* for either snaps and the header height is the height of the first line of the list.
* @param height
* @returns
*/
export const calculatePadding = (height: number) => height * SNAP_PERCENTAGE - HEADER_HEIGHT;