From 0f51a3c5dfdf54e2f73e4e42939bf9ae08fbfd81 Mon Sep 17 00:00:00 2001 From: Danish Date: Fri, 26 Aug 2022 02:55:58 +0530 Subject: [PATCH] Refactoring and style fixes --- app/containers/EmojiPicker/EmojiCategory.tsx | 21 +++---- .../EmojiPicker/frequentlyUsedEmojis.ts | 32 ++++++++++- app/containers/EmojiPicker/index.tsx | 48 ++-------------- app/containers/EmojiPicker/styles.ts | 9 ++- app/containers/MessageBox/EmojiSearchbar.tsx | 55 ++++++++++++------- app/containers/MessageBox/styles.ts | 9 +++ app/definitions/IEmoji.ts | 1 - app/views/RoomView/styles.ts | 3 +- 8 files changed, 98 insertions(+), 80 deletions(-) diff --git a/app/containers/EmojiPicker/EmojiCategory.tsx b/app/containers/EmojiPicker/EmojiCategory.tsx index 1f5e74829..8be880ebf 100644 --- a/app/containers/EmojiPicker/EmojiCategory.tsx +++ b/app/containers/EmojiPicker/EmojiCategory.tsx @@ -3,14 +3,13 @@ import { Text, Pressable } from 'react-native'; import { FlatList } from 'react-native-gesture-handler'; import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode'; -import styles from './styles'; +import styles, { MIN_EMOJI_SIZE, MAX_EMOJI_SIZE } from './styles'; import CustomEmoji from './CustomEmoji'; import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps'; import { IEmoji, IEmojiCategory } from '../../definitions/IEmoji'; import { useTheme } from '../../theme'; import { isIOS } from '../../lib/methods/helpers'; - -const MAX_EMOJI_SIZE = 50; +import { useDimensions } from '../../dimensions'; interface IEmojiProps { emoji: string | IEmoji; @@ -18,7 +17,7 @@ interface IEmojiProps { baseUrl: string; } -const Emoji = React.memo(({ emoji, size, baseUrl }: IEmojiProps) => { +const Emoji = ({ emoji, size, baseUrl }: IEmojiProps): React.ReactElement => { if (typeof emoji === 'string') return ( @@ -28,12 +27,14 @@ const Emoji = React.memo(({ emoji, size, baseUrl }: IEmojiProps) => { return ( ); -}); +}; -const EmojiCategory = ({ baseUrl, onEmojiSelected, emojis, width, tabsCount }: IEmojiCategory): React.ReactElement | null => { - const emojiSize = width ? Math.min(width / tabsCount, MAX_EMOJI_SIZE) : MAX_EMOJI_SIZE; - const numColumns = Math.trunc(width ? width / emojiSize : tabsCount); +const EmojiCategory = ({ baseUrl, onEmojiSelected, emojis, tabsCount }: IEmojiCategory): React.ReactElement | null => { const { colors } = useTheme(); + const { width } = useDimensions(); + const emojiSize = Math.min(Math.max(width / tabsCount, MIN_EMOJI_SIZE), MAX_EMOJI_SIZE); + const numColumns = Math.trunc(width / emojiSize); + const marginHorizontal = (width - numColumns * emojiSize) / 2; const renderItem = (emoji: IEmoji | string) => ( (item?.isCustom && item.content) || item} + keyExtractor={item => (typeof item === 'string' ? item : item.content)} data={emojis} extraData={{ baseUrl, width }} renderItem={({ item }) => renderItem(item)} numColumns={numColumns} initialNumToRender={45} removeClippedSubviews + contentContainerStyle={{ marginHorizontal }} {...scrollPersistTaps} keyboardDismissMode={'none'} /> diff --git a/app/containers/EmojiPicker/frequentlyUsedEmojis.ts b/app/containers/EmojiPicker/frequentlyUsedEmojis.ts index 6b6b574ca..89bb15787 100644 --- a/app/containers/EmojiPicker/frequentlyUsedEmojis.ts +++ b/app/containers/EmojiPicker/frequentlyUsedEmojis.ts @@ -1,11 +1,12 @@ import { useEffect, useState } from 'react'; import orderBy from 'lodash/orderBy'; +import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import database from '../../lib/database'; import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode'; -import { IEmoji } from '../../definitions'; +import { IEmoji, TFrequentlyUsedEmojiModel } from '../../definitions'; -const useFrequentlyUsedEmoji = (): { +export const useFrequentlyUsedEmoji = (): { frequentlyUsed: (string | IEmoji)[]; loaded: boolean; } => { @@ -30,4 +31,29 @@ const useFrequentlyUsedEmoji = (): { return { frequentlyUsed, loaded }; }; -export default useFrequentlyUsedEmoji; +export const addFrequentlyUsed = async (emoji: IEmoji) => { + const db = database.active; + const freqEmojiCollection = db.get('frequently_used_emojis'); + let freqEmojiRecord: TFrequentlyUsedEmojiModel; + try { + freqEmojiRecord = await freqEmojiCollection.find(emoji.content || emoji.name); + } catch (error) { + // Do nothing + } + + await db.write(async () => { + if (freqEmojiRecord) { + await freqEmojiRecord.update(f => { + if (f.count) { + f.count += 1; + } + }); + } else { + await freqEmojiCollection.create(f => { + f._raw = sanitizedRaw({ id: emoji.content || emoji.name }, freqEmojiCollection.schema); + Object.assign(f, emoji); + f.count = 1; + }); + } + }); +}; diff --git a/app/containers/EmojiPicker/index.tsx b/app/containers/EmojiPicker/index.tsx index 293363b90..c99a78bae 100644 --- a/app/containers/EmojiPicker/index.tsx +++ b/app/containers/EmojiPicker/index.tsx @@ -1,7 +1,6 @@ -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { View } from 'react-native'; import ScrollableTabView from 'react-native-scrollable-tab-view'; -import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { shallowEqual } from 'react-redux'; import TabBar from './TabBar'; @@ -9,15 +8,14 @@ import EmojiCategory from './EmojiCategory'; import Footer from './Footer'; import styles from './styles'; import categories from './categories'; -import database from '../../lib/database'; import { emojisByCategory } from './emojis'; import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode'; import log from '../../lib/methods/helpers/log'; import { useTheme } from '../../theme'; -import { IEmoji, ICustomEmojis, TFrequentlyUsedEmojiModel } from '../../definitions'; +import { IEmoji, ICustomEmojis } from '../../definitions'; import { useAppSelector } from '../../lib/hooks'; import { IEmojiPickerProps, EventTypes } from './interfaces'; -import useFrequentlyUsedEmoji from './frequentlyUsedEmojis'; +import { useFrequentlyUsedEmoji, addFrequentlyUsed } from './frequentlyUsedEmojis'; const EmojiPicker = ({ onItemClicked, @@ -26,7 +24,6 @@ const EmojiPicker = ({ searching = false, searchedEmojis = [] }: IEmojiPickerProps): React.ReactElement | null => { - const [width, setWidth] = useState(null); const { colors } = useTheme(); const { frequentlyUsed, loaded } = useFrequentlyUsedEmoji(); @@ -45,33 +42,6 @@ const EmojiPicker = ({ [allCustomEmojis] ); - const addFrequentlyUsed = async (emoji: IEmoji) => { - const db = database.active; - const freqEmojiCollection = db.get('frequently_used_emojis'); - let freqEmojiRecord: TFrequentlyUsedEmojiModel; - try { - freqEmojiRecord = await freqEmojiCollection.find(emoji.content); - } catch (error) { - // Do nothing - } - - await db.write(async () => { - if (freqEmojiRecord) { - await freqEmojiRecord.update(f => { - if (f.count) { - f.count += 1; - } - }); - } else { - await freqEmojiCollection.create(f => { - f._raw = sanitizedRaw({ id: emoji.content }, freqEmojiCollection.schema); - Object.assign(f, emoji); - f.count = 1; - }); - } - }); - }; - const handleEmojiSelect = (emoji: IEmoji | string) => { try { if (typeof emoji === 'string') { @@ -81,7 +51,7 @@ const EmojiPicker = ({ } else { addFrequentlyUsed({ content: emoji.content, - name: emoji.content, + name: emoji.name, extension: emoji.extension, isCustom: true }); @@ -92,12 +62,6 @@ const EmojiPicker = ({ } }; - const onLayout = ({ - nativeEvent: { - layout: { width } - } - }: any) => setWidth(width); - const renderCategory = (category: keyof typeof emojisByCategory, i: number, label: string, tabsCount: number) => { let emojis = []; if (i === 0) { @@ -112,7 +76,6 @@ const EmojiPicker = ({ emojis={emojis} onEmojiSelected={(emoji: IEmoji | string) => handleEmojiSelect(emoji)} style={styles.categoryContainer} - width={width} baseUrl={baseUrl} tabLabel={label} tabsCount={tabsCount} @@ -127,13 +90,12 @@ const EmojiPicker = ({ const tabsCount = frequentlyUsed.length === 0 ? categories.tabs.length - 1 : categories.tabs.length; return ( - + {searching ? ( handleEmojiSelect(emoji)} style={styles.categoryContainer} - width={width} baseUrl={baseUrl} tabLabel={'searching'} tabsCount={tabsCount} diff --git a/app/containers/EmojiPicker/styles.ts b/app/containers/EmojiPicker/styles.ts index 073a226f1..d104d4cb9 100644 --- a/app/containers/EmojiPicker/styles.ts +++ b/app/containers/EmojiPicker/styles.ts @@ -2,6 +2,9 @@ import { StyleSheet } from 'react-native'; import sharedStyles from '../../views/Styles'; +export const MAX_EMOJI_SIZE = 50; +export const MIN_EMOJI_SIZE = 42; + export default StyleSheet.create({ container: { flex: 1 @@ -14,7 +17,8 @@ export default StyleSheet.create({ flex: 1, alignItems: 'center', justifyContent: 'center', - paddingVertical: 10 + paddingVertical: 10, + width: 44 }, tabEmoji: { fontSize: 20, @@ -66,5 +70,6 @@ export default StyleSheet.create({ width: 44, justifyContent: 'center', alignItems: 'center' - } + }, + emojiPickerContainer: { flex: 1 } }); diff --git a/app/containers/MessageBox/EmojiSearchbar.tsx b/app/containers/MessageBox/EmojiSearchbar.tsx index 074f1150e..69fadaf31 100644 --- a/app/containers/MessageBox/EmojiSearchbar.tsx +++ b/app/containers/MessageBox/EmojiSearchbar.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { View, Text, Pressable, TextInput, FlatList } from 'react-native'; import { FormTextInput } from '../TextInput/FormTextInput'; @@ -9,7 +9,7 @@ import { IEmoji } from '../../definitions'; import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode'; import CustomEmoji from '../EmojiPicker/CustomEmoji'; import styles from './styles'; -import useFrequentlyUsedEmoji from '../EmojiPicker/frequentlyUsedEmojis'; +import { useFrequentlyUsedEmoji, addFrequentlyUsed } from '../EmojiPicker/frequentlyUsedEmojis'; import { DEFAULT_EMOJIS } from '../EmojiPicker/emojis'; const BUTTON_HIT_SLOP = { top: 4, right: 4, bottom: 4, left: 4 }; @@ -37,14 +37,33 @@ const Emoji = ({ emoji, baseUrl }: { emoji: IEmoji | string; baseUrl: string }): ); } - return ; + return ( + + ); }; const ListItem = ({ emoji, onEmojiSelected, baseUrl }: IListItem): React.ReactElement => { const key = typeof emoji === 'string' ? emoji : emoji?.name || emoji?.content; + const onPress = () => { + onEmojiSelected(emoji); + if (typeof emoji === 'string') { + addFrequentlyUsed({ content: emoji, name: emoji, isCustom: false }); + } else { + addFrequentlyUsed({ + content: emoji?.content || emoji?.name, + name: emoji?.name, + extension: emoji.extension, + isCustom: true + }); + } + }; return ( - onEmojiSelected(emoji)}> + @@ -55,20 +74,14 @@ const EmojiSearchBar = React.forwardRef( ({ openEmoji, onChangeText, emojis, onEmojiSelected, baseUrl }, ref) => { const { colors } = useTheme(); const [searchText, setSearchText] = useState(''); - const [frequentlyUsedEmojis, setFrequentlyUsed] = useState<(string | IEmoji)[]>(); - const { frequentlyUsed, loaded } = useFrequentlyUsedEmoji(); + const { frequentlyUsed } = useFrequentlyUsedEmoji(); - useEffect(() => { - if (loaded) { - const frequentlyUsedWithDefaultEmojis = frequentlyUsed - .filter(emoji => { - if (typeof emoji === 'string') return !DEFAULT_EMOJIS.includes(emoji); - return !DEFAULT_EMOJIS.includes(emoji.name); - }) - .concat(DEFAULT_EMOJIS); - setFrequentlyUsed(frequentlyUsedWithDefaultEmojis); - } - }, [loaded]); + const frequentlyUsedWithDefaultEmojis = frequentlyUsed + .filter(emoji => { + if (typeof emoji === 'string') return !DEFAULT_EMOJIS.includes(emoji); + return !DEFAULT_EMOJIS.includes(emoji.name); + }) + .concat(DEFAULT_EMOJIS); const handleTextChange = (text: string) => { setSearchText(text); @@ -76,10 +89,12 @@ const EmojiSearchBar = React.forwardRef( }; return ( - + } showsHorizontalScrollIndicator={false} ListEmptyComponent={() => ( @@ -101,7 +116,7 @@ const EmojiSearchBar = React.forwardRef( > - + void; - width: number | null; style: StyleProp; tabLabel: string; tabsCount: number; diff --git a/app/views/RoomView/styles.ts b/app/views/RoomView/styles.ts index da52e8f37..ef9d03eb2 100644 --- a/app/views/RoomView/styles.ts +++ b/app/views/RoomView/styles.ts @@ -69,6 +69,7 @@ export default StyleSheet.create({ paddingHorizontal: 15 }, reactionPickerSearchbar: { - paddingHorizontal: 20 + paddingHorizontal: 20, + minHeight: 48 } });