refactor: optimization

This commit is contained in:
Jakub Grzywacz 2021-07-09 21:22:56 +02:00
parent f6f9d40647
commit 64f0d5afb3
No known key found for this signature in database
GPG Key ID: 5BBB685871FF63C4
6 changed files with 9122 additions and 56 deletions

View File

@ -7,10 +7,11 @@ import {
useWindowDimensions,
Animated,
} from 'react-native';
import { CATEGORIES, CategoryTypes } from './types';
import type { CategoryTypes, EmojisByCategory } from './types';
import { EmojiCategory } from './components/EmojiCategory';
import { KeyboardContext } from './KeyboardContext';
import { Categories } from './components/Categories';
import emojisByGroup from './assets/data-by-group.json';
export const EmojiKeyboard = () => {
const { width } = useWindowDimensions();
@ -18,7 +19,6 @@ export const EmojiKeyboard = () => {
const flatListRef = React.useRef<FlatList>(null);
// const scrollX = React.useRef(new Animated.Value(0)).current;
const scrollNav = React.useRef(new Animated.Value(0)).current;
const getItemLayout = (
@ -34,24 +34,6 @@ export const EmojiKeyboard = () => {
(props) => <EmojiCategory {...props} />,
[]
);
// const onScroll = Animated.event(
// [{ nativeEvent: { contentOffset: { x: scrollX } } }],
// {
// listener: ({
// nativeEvent: {
// contentOffset: { x },
// },
// }: NativeSyntheticEvent<NativeScrollEvent>) => {
// console.log(Math.round(x / width));
// ctx.setActiveCategoryIndex(Math.round(x / width));
// // Animated.spring(scrollNav, {
// // toValue: (x / width) * (28 + 9),
// // useNativeDriver: true,
// // }).start();
// },
// useNativeDriver: true,
// }
// );
React.useEffect(() => {
Animated.spring(scrollNav, {
toValue: ctx.activeCategoryIndex * (28 + 9),
@ -64,8 +46,8 @@ export const EmojiKeyboard = () => {
style={[styles.container, styles.containerShadow, ctx.containerStyles]}
>
<Animated.FlatList
data={CATEGORIES}
keyExtractor={(item: CategoryTypes) => item}
data={emojisByGroup}
keyExtractor={(item: EmojisByCategory) => item.title}
renderItem={renderItem}
removeClippedSubviews={true}
ref={flatListRef}
@ -74,12 +56,10 @@ export const EmojiKeyboard = () => {
showsHorizontalScrollIndicator={false}
pagingEnabled
scrollEventThrottle={16}
decelerationRate="fast"
getItemLayout={getItemLayout}
scrollEnabled={false}
// onScroll={onScroll}
initialNumToRender={1}
windowSize={1}
windowSize={2}
maxToRenderPerBatch={1}
/>
<Categories flatListRef={flatListRef} scrollNav={scrollNav} />

View File

@ -24,6 +24,7 @@ export type ContextValues = {
activeCategoryIndex: number;
setActiveCategoryIndex: (index: number) => void;
numberOfColumns: number;
width: number;
};
export const KeyboardContext = React.createContext<

View File

@ -1,4 +1,5 @@
import * as React from 'react';
import { useWindowDimensions } from 'react-native';
import {
KeyboardProps,
ContextValues,
@ -29,11 +30,21 @@ export const defaultKeyboardValues: ContextValues = {
activeCategoryIndex: 0,
setActiveCategoryIndex: () => {},
numberOfColumns: 5,
width: 0,
};
export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
const { width } = useWindowDimensions();
const [activeCategoryIndex, setActiveCategoryIndex] = React.useState(0);
const numberOfColumns = React.useRef<number>(
Math.floor(
width /
((props.emojiSize
? props.emojiSize
: defaultKeyboardContext.emojiSize) *
2)
)
);
React.useEffect(() => {
if (props.open) setActiveCategoryIndex(0);
}, [props.open]);
@ -44,6 +55,8 @@ export const KeyboardProvider: React.FC<ProviderProps> = React.memo((props) => {
...props,
activeCategoryIndex,
setActiveCategoryIndex,
numberOfColumns: numberOfColumns.current,
width,
};
return (
<KeyboardContext.Provider value={value}>

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,7 @@
import * as React from 'react';
import {
StyleSheet,
View,
Text,
FlatList,
useWindowDimensions,
} from 'react-native';
import emojisByGroup from 'unicode-emoji-json/data-by-group.json';
import type { CategoryTypes, EmojiType } from 'src/types';
import { StyleSheet, View, Text, FlatList } from 'react-native';
import type { EmojisByCategory, EmojiType } from 'src/types';
import { SingleEmoji } from './SingleEmoji';
import { KeyboardContext } from '../KeyboardContext';
@ -21,25 +14,24 @@ const emptyEmoji = {
emoji_version: '0',
};
export const EmojiCategory = ({ item }: { item: CategoryTypes }) => {
const { width } = useWindowDimensions();
const ctx = React.useContext(KeyboardContext);
const numberOfColumns = React.useRef<number>(
Math.floor(width / (ctx.emojiSize * 2))
);
export const EmojiCategory = ({ item }: { item: EmojisByCategory }) => {
const { onEmojiSelected, emojiSize, ...ctx } =
React.useContext(KeyboardContext);
const [empty, setEmpty] = React.useState<EmojiType[]>([]);
React.useEffect(() => {
const fillWithEmpty = new Array(
numberOfColumns.current -
(emojisByGroup[item].length % numberOfColumns.current)
).fill(emptyEmoji);
setEmpty(fillWithEmpty);
}, [item]);
if (item.data.length % ctx.numberOfColumns) {
const fillWithEmpty = new Array(
ctx.numberOfColumns - (item.data.length % ctx.numberOfColumns)
).fill(emptyEmoji);
setEmpty(fillWithEmpty);
}
}, [ctx.numberOfColumns, item]);
const getItemLayout = (_: EmojiType[] | null | undefined, index: number) => ({
length: ctx.emojiSize ? ctx.emojiSize : 0,
offset: ctx.emojiSize * Math.ceil(index / ctx.numberOfColumns),
length: emojiSize ? emojiSize : 0,
offset: emojiSize * Math.ceil(index / ctx.numberOfColumns),
index,
});
@ -47,26 +39,29 @@ export const EmojiCategory = ({ item }: { item: CategoryTypes }) => {
(props) => (
<SingleEmoji
{...props}
onPress={() => ctx.onEmojiSelected(props.item)}
emojiSize={ctx.emojiSize}
onPress={() => onEmojiSelected(props.item)}
emojiSize={emojiSize}
/>
),
[ctx]
[onEmojiSelected, emojiSize]
);
return (
<View style={[styles.container, { width: width }]}>
<View style={[styles.container, { width: ctx.width }]}>
{!ctx.hideHeader && (
<Text style={[styles.sectionTitle, ctx.headerStyles]}>{item}</Text>
<Text style={[styles.sectionTitle, ctx.headerStyles]}>
{item.title}
</Text>
)}
<FlatList
data={[...emojisByGroup[item], ...empty]}
data={[...item.data, ...empty]}
keyExtractor={(emoji) => emoji.name}
numColumns={numberOfColumns.current}
numColumns={ctx.numberOfColumns}
renderItem={renderItem}
removeClippedSubviews={true}
getItemLayout={getItemLayout}
ListFooterComponent={() => <View style={styles.footer} />}
windowSize={1}
/>
</View>
);

View File

@ -58,3 +58,8 @@ export const CATEGORIES_NAVIGATION: CategoryNavigationItem[] = [
// { icon: '🏧', category: 'Symbols' },
// { icon: '🏁', category: 'Flags' },
// ];
export type EmojisByCategory = {
title: CategoryTypes;
data: EmojiType[];
};