[FIX] Reactions list isn't scrollable
This commit is contained in:
parent
68f6eb40de
commit
92bbf4726a
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'>
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue