fix: NavBottomFAB position (#5555)

This commit is contained in:
Diego Mello 2024-02-08 14:49:09 -03:00 committed by GitHub
parent c8e1f20d1e
commit b189f59950
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 115 additions and 63 deletions

View File

@ -30,6 +30,7 @@ import log from '../../lib/methods/helpers/log';
import { prepareQuoteMessage } from './helpers';
import { RecordAudio } from './components/RecordAudio';
import { useKeyboardListener } from './hooks';
import { emitter } from '../../lib/methods/helpers/emitter';
const styles = StyleSheet.create({
container: {
@ -193,6 +194,7 @@ export const MessageComposer = ({
const onHeightChanged = (height: number) => {
setTrackingViewHeight(height);
emitter.emit(`setComposerHeight${tmid ? 'Thread' : ''}`, height);
};
const backgroundColor = action === 'edit' ? colors.statusBackgroundWarning2 : colors.surfaceLight;

View File

@ -16,7 +16,7 @@ import { getRoomTitle, parseJson } from '../../../lib/methods/helpers';
import { MAX_HEIGHT, MIN_HEIGHT, NO_CANNED_RESPONSES, MARKDOWN_STYLES } from '../constants';
import database from '../../../lib/database';
import Navigation from '../../../lib/navigation/appNavigation';
import { emitter } from '../emitter';
import { emitter } from '../../../lib/methods/helpers/emitter';
import { useRoomContext } from '../../../views/RoomView/context';
import { getMessageById } from '../../../lib/database/services/Message';
import { generateTriggerId } from '../../../lib/methods';

View File

@ -3,7 +3,7 @@ import React, { ReactElement } from 'react';
import { ActionsButton, BaseButton } from '..';
import { useMessageComposerApi } from '../../context';
import { Gap } from '../Gap';
import { emitter } from '../../emitter';
import { emitter } from '../../../../lib/methods/helpers/emitter';
import { useRoomContext } from '../../../../views/RoomView/context';
export const Default = (): ReactElement | null => {

View File

@ -4,7 +4,7 @@ import { BaseButton } from '..';
import { useMessageComposerApi } from '../../context';
import { Gap } from '../Gap';
import { TMarkdownStyle } from '../../interfaces';
import { emitter } from '../../emitter';
import { emitter } from '../../../../lib/methods/helpers/emitter';
export const Markdown = (): ReactElement => {
const { setMarkdownToolbar } = useMessageComposerApi();

View File

@ -1,14 +0,0 @@
import mitt from 'mitt';
import { TMarkdownStyle } from './interfaces';
type Events = {
toolbarMention: undefined;
addMarkdown: {
style: TMarkdownStyle;
};
};
export const emitter = mitt<Events>();
emitter.on('*', (type, e) => console.log(type, e));

View File

@ -1,26 +1,37 @@
import { MutableRefObject, useEffect } from 'react';
import { Keyboard } from 'react-native';
import { useIsFocused } from '@react-navigation/native';
import { useMessageComposerApi } from '../context';
import { ITrackingView } from '../interfaces';
import { TKeyEmitterEvent, emitter } from '../../../lib/methods/helpers/emitter';
import { useRoomContext } from '../../../views/RoomView/context';
export const useKeyboardListener = (ref: MutableRefObject<ITrackingView>) => {
const { setKeyboardHeight } = useMessageComposerApi();
const { tmid } = useRoomContext();
const isFocused = useIsFocused();
useEffect(() => {
if (!isFocused) {
return;
}
const keyboardEvent: TKeyEmitterEvent = `setKeyboardHeight${tmid ? 'Thread' : ''}`;
const showListener = Keyboard.addListener('keyboardWillShow', async () => {
if (ref?.current) {
const props = await ref.current.getNativeProps();
setKeyboardHeight(props.keyboardHeight);
emitter.emit(keyboardEvent, props.keyboardHeight);
}
});
const hideListener = Keyboard.addListener('keyboardWillHide', () => {
setKeyboardHeight(0);
emitter.emit(keyboardEvent, 0);
});
return () => {
showListener.remove();
hideListener.remove();
};
}, [ref, setKeyboardHeight]);
}, [ref, setKeyboardHeight, tmid, isFocused]);
};

View File

@ -0,0 +1,20 @@
import mitt from 'mitt';
import { TMarkdownStyle } from '../../../containers/MessageComposer/interfaces';
export type TEmitterEvents = {
toolbarMention: undefined;
addMarkdown: {
style: TMarkdownStyle;
};
setKeyboardHeight: number;
setKeyboardHeightThread: number;
setComposerHeight: number;
setComposerHeightThread: number;
};
export type TKeyEmitterEvent = keyof TEmitterEvents;
export const emitter = mitt<TEmitterEvents>();
emitter.on('*', (type, e) => console.log(type, e));

View File

@ -42,6 +42,9 @@ class EventEmitter {
}
}
/**
* @deprecated use lib/methods/helpers/emitter.ts
*/
emit(event: string, ...args: TEventEmitterEmmitArgs[]) {
if (typeof this.events[event] === 'object') {
this.events[event].forEach((listener: Function) => {

View File

@ -16,4 +16,5 @@ export * from './isValidEmail';
export * from './random';
export * from './image';
export * from './askAndroidMediaPermissions';
export * from './emitter';
export * from './parseJson';

View File

@ -1,14 +1,16 @@
import React from 'react';
import { StyleSheet, View, Platform } from 'react-native';
import React, { memo } from 'react';
import { StyleSheet, View } from 'react-native';
import { CustomIcon } from '../../../../containers/CustomIcon';
import { useTheme } from '../../../../theme';
import Touch from '../../../../containers/Touch';
import { useNavBottomStyle } from '../hooks';
import { EDGE_DISTANCE } from '../constants';
const styles = StyleSheet.create({
container: {
position: 'absolute',
right: 15
right: EDGE_DISTANCE
},
button: {
borderRadius: 25
@ -23,46 +25,25 @@ const styles = StyleSheet.create({
}
});
const NavBottomFAB = ({
visible,
onPress,
isThread
}: {
visible: boolean;
onPress: Function;
isThread: boolean;
}): React.ReactElement | null => {
const { colors } = useTheme();
const NavBottomFAB = memo(
({ visible, onPress, isThread }: { visible: boolean; onPress: Function; isThread: boolean }): React.ReactElement | null => {
const { colors } = useTheme();
const positionStyle = useNavBottomStyle(isThread);
if (!visible) {
return null;
if (!visible) {
return null;
}
return (
<View style={[styles.container, positionStyle]} testID='nav-jump-to-bottom'>
<Touch onPress={() => onPress()} style={[styles.button, { backgroundColor: colors.backgroundColor }]}>
<View style={[styles.content, { borderColor: colors.borderColor }]}>
<CustomIcon name='chevron-down' color={colors.auxiliaryTintColor} size={36} />
</View>
</Touch>
</View>
);
}
return (
<View
style={[
styles.container,
{
...Platform.select({
ios: {
bottom: 100 + (isThread ? 40 : 0)
},
android: {
top: 15,
scaleY: -1
}
})
}
]}
testID='nav-jump-to-bottom'
>
<Touch onPress={() => onPress()} style={[styles.button, { backgroundColor: colors.backgroundColor }]}>
<View style={[styles.content, { borderColor: colors.borderColor }]}>
<CustomIcon name='chevron-down' color={colors.auxiliaryTintColor} size={36} />
</View>
</Touch>
</View>
);
};
);
export default NavBottomFAB;

View File

@ -5,3 +5,5 @@ export const VIEWABILITY_CONFIG = {
};
export const SCROLL_LIMIT = 200;
export const EDGE_DISTANCE = 15;

View File

@ -1,2 +1,3 @@
export * from './useNavBottomStyle';
export * from './useMessages';
export * from './useScroll';

View File

@ -0,0 +1 @@
export * from './useNavBottomStyle';

View File

@ -0,0 +1,8 @@
import { ViewStyle } from 'react-native';
import { EDGE_DISTANCE } from '../../constants';
export const useNavBottomStyle = (): ViewStyle => ({
top: EDGE_DISTANCE,
scaleY: -1
});

View File

@ -0,0 +1,36 @@
import { useEffect, useState } from 'react';
import { ViewStyle } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { TKeyEmitterEvent, emitter } from '../../../../../lib/methods/helpers';
import { EDGE_DISTANCE } from '../../constants';
export const useNavBottomStyle = (isThread: boolean): ViewStyle => {
const [keyboardHeight, setKeyboardHeight] = useState(0);
const [composerHeight, setComposerHeight] = useState(0);
const { bottom } = useSafeAreaInsets();
useEffect(() => {
const keyboardEvent: TKeyEmitterEvent = `setKeyboardHeight${isThread ? 'Thread' : ''}`;
const composerEvent: TKeyEmitterEvent = `setComposerHeight${isThread ? 'Thread' : ''}`;
emitter.on(keyboardEvent, height => {
if (height !== keyboardHeight) {
setKeyboardHeight(height);
}
});
emitter.on(composerEvent, height => {
if (height !== composerHeight) {
setComposerHeight(height);
}
});
return () => {
emitter.off(keyboardEvent);
emitter.off(composerEvent);
};
}, [isThread, keyboardHeight, composerHeight]);
return {
bottom: keyboardHeight + composerHeight + (keyboardHeight ? 0 : bottom) + EDGE_DISTANCE
};
};

View File

@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { ViewToken, ViewabilityConfigCallbackPairs } from 'react-native';
import { IListContainerRef, IListProps, TListRef, TMessagesIdsRef } from '../definitions';
@ -20,9 +20,9 @@ export const useScroll = ({ listRef, messagesIds }: { listRef: TListRef; message
[]
);
const jumpToBottom = () => {
const jumpToBottom = useCallback(() => {
listRef.current?.scrollToOffset({ offset: -100 });
};
}, [listRef]);
const onViewableItemsChanged: IListProps['onViewableItemsChanged'] = ({ viewableItems: vi }) => {
viewableItems.current = vi;