Compare commits

...

5 Commits

Author SHA1 Message Date
Reinaldo Neto 85118e1129
Merge branch 'develop' into fix.add-hislop-reactions 2023-02-16 15:36:17 -03:00
Reinaldo Neto 8cde82a3b4 add commit 2023-02-07 15:05:18 -03:00
Reinaldo Neto cad724f36a minor tweak 2023-02-06 15:23:38 -03:00
Reinaldo Neto 9cb719658c update test 2023-02-06 11:38:49 -03:00
Reinaldo Neto 92bbf4726a [FIX] Reactions list isn't scrollable 2023-02-06 11:13:06 -03:00
6 changed files with 64 additions and 22 deletions

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@ import React, { forwardRef, isValidElement, useEffect, useImperativeHandle, useR
import { Keyboard } from 'react-native'; import { Keyboard } from 'react-native';
import { Easing } from 'react-native-reanimated'; import { Easing } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import BottomSheet, { BottomSheetBackdrop } from '@gorhom/bottom-sheet'; import BottomSheet, { BottomSheetBackdrop, BottomSheetProps } from '@gorhom/bottom-sheet';
import { useDimensions, useOrientation } from '../../dimensions'; import { useDimensions, useOrientation } from '../../dimensions';
import { useTheme } from '../../theme'; import { useTheme } from '../../theme';
@ -27,7 +27,7 @@ const ANIMATION_CONFIG = {
}; };
const ActionSheet = React.memo( 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 { colors } = useTheme();
const bottomSheetRef = useRef<BottomSheet>(null); const bottomSheetRef = useRef<BottomSheet>(null);
const [data, setData] = useState<TActionSheetOptions>({} as TActionSheetOptions); const [data, setData] = useState<TActionSheetOptions>({} as TActionSheetOptions);
@ -125,6 +125,13 @@ const ActionSheet = React.memo(
// when is android tablet and the input text is focused // when is android tablet and the input text is focused
const androidTablet: any = isTablet && isLandscape && !isIOS ? { android_keyboardInputMode: 'adjustResize' } : {}; const androidTablet: any = isTablet && isLandscape && !isIOS ? { android_keyboardInputMode: 'adjustResize' } : {};
const handleOnChange: BottomSheetProps['onChange'] = index => {
onChange(index);
if (index === -1) {
return onClose();
}
};
return ( return (
<> <>
{children} {children}
@ -139,7 +146,7 @@ const ActionSheet = React.memo(
enablePanDownToClose enablePanDownToClose
style={{ ...styles.container, ...bottomSheet }} style={{ ...styles.container, ...bottomSheet }}
backgroundStyle={{ backgroundColor: colors.focusedBackground }} 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 // We need this to allow horizontal swipe gesture inside the bottom sheet like in reaction picker
enableContentPanningGesture={data?.enableContentPanningGesture ?? true} enableContentPanningGesture={data?.enableContentPanningGesture ?? true}
{...androidTablet} {...androidTablet}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,15 @@
const HEADER_HEIGHT = 48;
/**
* This SNAP_PERCENTAGE is calculate between the snaps: ['50%', '80%']
* so considering the content size is set to 80% and the first snap is 50%
* we need to 50% * 80% = 40%
*/
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;