Migrate to react-native-tab-view

This commit is contained in:
Danish 2022-08-26 19:03:09 +05:30
parent 0f51a3c5df
commit 359171ed03
7 changed files with 109 additions and 74 deletions

View File

@ -7,16 +7,17 @@ import { ITabBarProps } from './interfaces';
import { isIOS } from '../../lib/methods/helpers';
import { CustomIcon } from '../CustomIcon';
const TabBar = ({ activeTab, tabs, goToPage }: ITabBarProps): React.ReactElement => {
const TabBar = ({ tabs, activeTab, onPress, showFrequentlyUsed }: ITabBarProps): React.ReactElement => {
const { colors } = useTheme();
return (
<View style={styles.tabsContainer}>
{tabs?.map((tab, i) => (
{tabs?.map((tab, i) => {
if (i === 0 && !showFrequentlyUsed) return null;
return (
<Pressable
key={tab}
onPress={() => goToPage?.(i)}
testID={`emoji-picker-tab-${tab}`}
key={tab.key}
onPress={() => onPress(tab.key)}
testID={`emoji-picker-tab-${tab.key}`}
android_ripple={{ color: colors.bannerBackground }}
style={({ pressed }: { pressed: boolean }) => [
styles.tab,
@ -25,10 +26,11 @@ const TabBar = ({ activeTab, tabs, goToPage }: ITabBarProps): React.ReactElement
}
]}
>
<CustomIcon name={tab} size={24} color={activeTab === i ? colors.tintColor : colors.auxiliaryTintColor} />
<CustomIcon name={tab.key} size={24} color={activeTab === i ? colors.tintColor : colors.auxiliaryTintColor} />
<View style={activeTab === i ? [styles.activeTabLine, { backgroundColor: colors.tintColor }] : styles.tabLine} />
</Pressable>
))}
);
})}
</View>
);
};

View File

@ -1,44 +1,59 @@
const list = ['frequentlyUsed', 'custom', 'people', 'nature', 'food', 'activity', 'travel', 'objects', 'symbols', 'flags'];
const tabs = [
import { TIconsName } from '../CustomIcon';
export type IEmojiCategory =
| 'frequentlyUsed'
| 'custom'
| 'people'
| 'nature'
| 'food'
| 'activity'
| 'travel'
| 'objects'
| 'symbols'
| 'flags';
const tabs: {
key: TIconsName;
title: IEmojiCategory;
}[] = [
{
tabLabel: 'clock',
category: list[0]
key: 'clock',
title: 'frequentlyUsed'
},
{
tabLabel: 'rocket',
category: list[1]
key: 'rocket',
title: 'custom'
},
{
tabLabel: 'emoji',
category: list[2]
key: 'emoji',
title: 'people'
},
{
tabLabel: 'leaf',
category: list[3]
key: 'leaf',
title: 'nature'
},
{
tabLabel: 'burger',
category: list[4]
key: 'burger',
title: 'food'
},
{
tabLabel: 'basketball',
category: list[5]
key: 'basketball',
title: 'activity'
},
{
tabLabel: 'airplane',
category: list[6]
key: 'airplane',
title: 'travel'
},
{
tabLabel: 'lamp-bulb',
category: list[7]
key: 'lamp-bulb',
title: 'objects'
},
{
tabLabel: 'percentage',
category: list[8]
key: 'percentage',
title: 'symbols'
},
{
tabLabel: 'flag',
category: list[9]
key: 'flag',
title: 'flags'
}
];
export default { list, tabs };
export default tabs;

View File

@ -1,13 +1,13 @@
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { View } from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import { TabView, SceneRendererProps, NavigationState } from 'react-native-tab-view';
import { shallowEqual } from 'react-redux';
import TabBar from './TabBar';
import EmojiCategory from './EmojiCategory';
import Footer from './Footer';
import styles from './styles';
import categories from './categories';
import categories, { IEmojiCategory } from './categories';
import { emojisByCategory } from './emojis';
import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode';
import log from '../../lib/methods/helpers/log';
@ -16,16 +16,18 @@ import { IEmoji, ICustomEmojis } from '../../definitions';
import { useAppSelector } from '../../lib/hooks';
import { IEmojiPickerProps, EventTypes } from './interfaces';
import { useFrequentlyUsedEmoji, addFrequentlyUsed } from './frequentlyUsedEmojis';
import { TIconsName } from '../CustomIcon';
const EmojiPicker = ({
onItemClicked,
tabEmojiStyle,
isEmojiKeyboard = false,
searching = false,
searchedEmojis = []
}: IEmojiPickerProps): React.ReactElement | null => {
const { colors } = useTheme();
const { frequentlyUsed, loaded } = useFrequentlyUsedEmoji();
const [index, setIndex] = useState(0);
const [routes] = useState(categories);
const baseUrl = useAppSelector(state => state.server?.server);
const allCustomEmojis: ICustomEmojis = useAppSelector(state => state.customEmojis, shallowEqual);
@ -62,14 +64,16 @@ const EmojiPicker = ({
}
};
const renderCategory = (category: keyof typeof emojisByCategory, i: number, label: string, tabsCount: number) => {
const tabsCount = frequentlyUsed.length === 0 ? categories.length - 1 : categories.length;
const Category = React.memo(({ title }: { title: IEmojiCategory }) => {
let emojis = [];
if (i === 0) {
if (title === 'frequentlyUsed') {
emojis = frequentlyUsed;
} else if (i === 1) {
} else if (title === 'custom') {
emojis = customEmojis;
} else {
emojis = emojisByCategory[category];
emojis = emojisByCategory[title];
}
return (
<EmojiCategory
@ -77,18 +81,24 @@ const EmojiPicker = ({
onEmojiSelected={(emoji: IEmoji | string) => handleEmojiSelect(emoji)}
style={styles.categoryContainer}
baseUrl={baseUrl}
tabLabel={label}
tabsCount={tabsCount}
/>
);
});
type Route = {
key: string;
title: string;
};
type State = NavigationState<Route>;
const renderTabBar = (props: SceneRendererProps & { navigationState: State }) => (
<TabBar tabs={categories} onPress={props.jumpTo} activeTab={index} showFrequentlyUsed={frequentlyUsed.length > 0} />
);
if (!loaded) {
return null;
}
const tabsCount = frequentlyUsed.length === 0 ? categories.tabs.length - 1 : categories.tabs.length;
return (
<View style={styles.emojiPickerContainer}>
{searching ? (
@ -97,24 +107,24 @@ const EmojiPicker = ({
onEmojiSelected={(emoji: IEmoji | string) => handleEmojiSelect(emoji)}
style={styles.categoryContainer}
baseUrl={baseUrl}
tabLabel={'searching'}
tabsCount={tabsCount}
/>
) : (
<ScrollableTabView
renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} />}
contentProps={{
keyboardShouldPersistTaps: 'always',
keyboardDismissMode: 'none'
}}
<TabView
lazy
navigationState={{ index, routes }}
renderScene={({
route
}: {
route: {
key: TIconsName;
title: IEmojiCategory;
};
}) => <Category key={route.key} title={route.title} />}
onIndexChange={setIndex}
style={{ backgroundColor: colors.focusedBackground }}
>
{categories.tabs.map((tab: any, i) =>
i === 0 && frequentlyUsed.length === 0
? null // when no frequentlyUsed don't show the tab
: renderCategory(tab.category, i, tab.tabLabel, tabsCount)
)}
</ScrollableTabView>
renderTabBar={renderTabBar}
/>
)}
{isEmojiKeyboard && (
<Footer

View File

@ -1,5 +1,3 @@
import { StyleProp, TextStyle } from 'react-native';
import { TIconsName } from '../CustomIcon';
import { IEmoji } from '../../definitions';
@ -11,7 +9,6 @@ export enum EventTypes {
export interface IEmojiPickerProps {
onItemClicked: (event: EventTypes, emoji?: string, shortname?: string) => void;
tabEmojiStyle?: StyleProp<TextStyle>;
isEmojiKeyboard?: boolean;
searching?: boolean;
searchedEmojis?: (string | IEmoji)[];
@ -23,8 +20,8 @@ export interface IFooterProps {
}
export interface ITabBarProps {
goToPage?: (page: number) => void;
activeTab?: number;
tabs?: TIconsName[];
tabEmojiStyle: StyleProp<TextStyle>;
tabs?: { key: TIconsName; title: string }[];
onPress: (ket: string) => void;
showFrequentlyUsed?: boolean;
}

View File

@ -33,7 +33,6 @@ export interface IEmojiCategory {
emojis: (IEmoji | string)[];
onEmojiSelected: (emoji: IEmoji | string) => void;
style: StyleProp<ImageStyle>;
tabLabel: string;
tabsCount: number;
}

View File

@ -105,6 +105,7 @@
"react-native-notifications": "^4.2.4",
"react-native-notifier": "1.6.1",
"react-native-orientation-locker": "1.1.8",
"react-native-pager-view": "^5.4.25",
"react-native-picker-select": "^8.0.4",
"react-native-platform-touchable": "1.1.1",
"react-native-popover-view": "4.0.1",
@ -118,6 +119,7 @@
"react-native-simple-crypto": "RocketChat/react-native-simple-crypto#0.5.1",
"react-native-slowlog": "^1.0.2",
"react-native-svg": "^12.3.0",
"react-native-tab-view": "^3.1.1",
"react-native-ui-lib": "RocketChat/react-native-ui-lib",
"react-native-vector-icons": "9.1.0",
"react-native-webview": "10.3.2",

View File

@ -17096,6 +17096,11 @@ react-native-orientation-locker@1.1.8:
resolved "https://registry.yarnpkg.com/react-native-orientation-locker/-/react-native-orientation-locker-1.1.8.tgz#45d1c9e002496b8d286ec8932d6e3e7d341f9c85"
integrity sha512-+Vd7x6O/3zGqYIMXpeDlaw3ma074Dtnocm8ryT9v5SvaiEcWSzII4frPgXaUcc/MiCq4OWZ1JtVoyw75mdomQw==
react-native-pager-view@^5.4.25:
version "5.4.25"
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-5.4.25.tgz#cd639d5387a7f3d5581b55a33c5faa1cbc200f97"
integrity sha512-3drrYwaLat2fYszymZe3nHMPASJ4aJMaxiejfA1V5SK3OygYmdtmV2u5prX7TnjueJzGSyyaCYEr2JlrRt4YPg==
react-native-picker-select@^8.0.4:
version "8.0.4"
resolved "https://registry.yarnpkg.com/react-native-picker-select/-/react-native-picker-select-8.0.4.tgz#3f7f1f42df69b06e7d2c10338288332a6c40fd10"
@ -17217,6 +17222,11 @@ react-native-swipe-gestures@^1.0.5:
resolved "https://registry.yarnpkg.com/react-native-swipe-gestures/-/react-native-swipe-gestures-1.0.5.tgz#a172cb0f3e7478ccd681fd36b8bfbcdd098bde7c"
integrity sha512-Ns7Bn9H/Tyw278+5SQx9oAblDZ7JixyzeOczcBK8dipQk2pD7Djkcfnf1nB/8RErAmMLL9iXgW0QHqiII8AhKw==
react-native-tab-view@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-3.1.1.tgz#1f8d7a835ab4f5b1b1407ec8dddc1053b53fa3c6"
integrity sha512-M5pRN6utQfytKWoKlKVzg5NbkYu308qNoW1khGTtEOTs1k14p2dHJ/BWOJoJYHKbPVUyZldbG9MFT7gUl4YHnw==
react-native-text-size@4.0.0-rc.1:
version "4.0.0-rc.1"
resolved "https://registry.yarnpkg.com/react-native-text-size/-/react-native-text-size-4.0.0-rc.1.tgz#1e048d345dd6a5a8e1269e0585c1a5948c478da5"