diff --git a/app/containers/ActionSheet/ActionSheet.tsx b/app/containers/ActionSheet/ActionSheet.tsx index a1785d7a3..886d8aca8 100644 --- a/app/containers/ActionSheet/ActionSheet.tsx +++ b/app/containers/ActionSheet/ActionSheet.tsx @@ -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(null); const [data, setData] = useState({} 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} diff --git a/app/containers/ActionSheet/Provider.tsx b/app/containers/ActionSheet/Provider.tsx index 4b21726bc..5e034f3fb 100644 --- a/app/containers/ActionSheet/Provider.tsx +++ b/app/containers/ActionSheet/Provider.tsx @@ -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({ showActionSheet: () => {}, - hideActionSheet: () => {} + hideActionSheet: () => {}, + indexPosition: -1 }); export const useActionSheet = () => useContext(context); @@ -48,20 +50,24 @@ export const withActionSheet = (Component: React.ComponentType): typeof Com }; export const ActionSheetProvider = React.memo(({ children }: { children: React.ReactElement | React.ReactElement[] }) => { + const [indexPosition, setIndexPosition] = useState(-1); const ref: ForwardedRef = useRef(null); + const onChange = (index: number) => setIndexPosition(index); + const getContext = () => ({ showActionSheet: (options: TActionSheetOptions) => { ref.current?.showActionSheet(options); }, hideActionSheet: () => { ref.current?.hideActionSheet(); - } + }, + indexPosition }); return ( - + <>{children} diff --git a/app/containers/ReactionsList/AllTab.tsx b/app/containers/ReactionsList/AllTab.tsx index 1696bc30b..1d48bb863 100644 --- a/app/containers/ReactionsList/AllTab.tsx +++ b/app/containers/ReactionsList/AllTab.tsx @@ -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 => ( - - } - keyExtractor={item => item.emoji} - /> - -); +const AllTab = ({ reactions, getCustomEmoji }: IAllTabProps): React.ReactElement => { + const { height } = useWindowDimensions(); + const paddingBottom = calculatePadding(height); + const { indexPosition } = useActionSheet(); + + return ( + + } + keyExtractor={item => item.emoji} + /> + + ); +}; export default AllTab; diff --git a/app/containers/ReactionsList/UsersList.tsx b/app/containers/ReactionsList/UsersList.tsx index 9723b051f..4c65c15e5 100644 --- a/app/containers/ReactionsList/UsersList.tsx +++ b/app/containers/ReactionsList/UsersList.tsx @@ -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 ( diff --git a/app/containers/ReactionsList/calculatePadding.ts b/app/containers/ReactionsList/calculatePadding.ts new file mode 100644 index 000000000..74d930686 --- /dev/null +++ b/app/containers/ReactionsList/calculatePadding.ts @@ -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;