@@ -2,14 +2,12 @@ import {Str} from 'expensify-common';
22import lodashSortBy from 'lodash/sortBy' ;
33import React from 'react' ;
44import type { StyleProp , TextStyle } from 'react-native' ;
5- import Onyx from 'react-native-onyx' ;
65import type { OnyxEntry } from 'react-native-onyx' ;
76import * as Emojis from '@assets/emojis' ;
87import type { Emoji , HeaderEmoji , PickerEmojis } from '@assets/emojis/types' ;
98import Text from '@components/Text' ;
109import CONST from '@src/CONST' ;
1110import { isFullySupportedLocale } from '@src/CONST/LOCALES' ;
12- import ONYXKEYS from '@src/ONYXKEYS' ;
1311import type { FrequentlyUsedEmoji , Locale } from '@src/types/onyx' ;
1412import type { ReportActionReaction , UsersReactions } from '@src/types/onyx/ReportActionReactions' ;
1513import type IconAsset from '@src/types/utils/IconAsset' ;
@@ -33,52 +31,48 @@ const findEmojiByCode = (code: string): Emoji => Emojis.emojiCodeTableWithSkinTo
3331
3432const sortByName = ( emoji : Emoji , emojiData : RegExpMatchArray ) => ! emoji . name . includes ( emojiData [ 0 ] . toLowerCase ( ) . slice ( 1 ) ) ;
3533
36- let frequentlyUsedEmojis : FrequentlyUsedEmoji [ ] = [ ] ;
37- Onyx . connect ( {
38- key : ONYXKEYS . FREQUENTLY_USED_EMOJIS ,
39- callback : ( val ) => {
40- if ( ! val ) {
41- return ;
34+ const processFrequentlyUsedEmojis = ( emojiList ?: FrequentlyUsedEmoji [ ] ) => {
35+ if ( ! emojiList ) {
36+ return [ ] ;
37+ }
38+ const processedFrequentlyUsedEmojis =
39+ emojiList
40+ ?. map ( ( item ) => {
41+ let emoji = item ;
42+ if ( ! item . code ) {
43+ emoji = { ...emoji , ...findEmojiByName ( item . name ) } ;
44+ }
45+ if ( ! item . name ) {
46+ emoji = { ...emoji , ...findEmojiByCode ( item . code ) } ;
47+ }
48+ const emojiWithSkinTones = Emojis . emojiCodeTableWithSkinTones [ emoji . code ] ;
49+ if ( ! emojiWithSkinTones ) {
50+ return null ;
51+ }
52+ return { ...emojiWithSkinTones , count : item . count , lastUpdatedAt : item . lastUpdatedAt } ;
53+ } )
54+ . filter ( ( emoji ) : emoji is FrequentlyUsedEmoji => ! ! emoji ) ?? [ ] ;
55+
56+ // On AddComment API response, each variant of the same emoji (with different skin tones) is
57+ // treated as a separate entry due to unique emoji codes for each variant.
58+ // So merge duplicate emojis, sum their counts, and use the latest lastUpdatedAt timestamp, then sort accordingly.
59+ const frequentlyUsedEmojiCodesToObjects = new Map < string , FrequentlyUsedEmoji > ( ) ;
60+ processedFrequentlyUsedEmojis . forEach ( ( emoji ) => {
61+ const existingEmoji = frequentlyUsedEmojiCodesToObjects . get ( emoji . code ) ;
62+ if ( existingEmoji ) {
63+ existingEmoji . count += emoji . count ;
64+ existingEmoji . lastUpdatedAt = Math . max ( existingEmoji . lastUpdatedAt , emoji . lastUpdatedAt ) ;
65+ } else {
66+ frequentlyUsedEmojiCodesToObjects . set ( emoji . code , emoji ) ;
4267 }
43- frequentlyUsedEmojis =
44- val
45- ?. map ( ( item ) => {
46- let emoji = item ;
47- if ( ! item . code ) {
48- emoji = { ...emoji , ...findEmojiByName ( item . name ) } ;
49- }
50- if ( ! item . name ) {
51- emoji = { ...emoji , ...findEmojiByCode ( item . code ) } ;
52- }
53- const emojiWithSkinTones = Emojis . emojiCodeTableWithSkinTones [ emoji . code ] ;
54- if ( ! emojiWithSkinTones ) {
55- return null ;
56- }
57- return { ...emojiWithSkinTones , count : item . count , lastUpdatedAt : item . lastUpdatedAt } ;
58- } )
59- . filter ( ( emoji ) : emoji is FrequentlyUsedEmoji => ! ! emoji ) ?? [ ] ;
60-
61- // On AddComment API response, each variant of the same emoji (with different skin tones) is
62- // treated as a separate entry due to unique emoji codes for each variant.
63- // So merge duplicate emojis, sum their counts, and use the latest lastUpdatedAt timestamp, then sort accordingly.
64- const frequentlyUsedEmojiCodesToObjects = new Map < string , FrequentlyUsedEmoji > ( ) ;
65- frequentlyUsedEmojis . forEach ( ( emoji ) => {
66- const existingEmoji = frequentlyUsedEmojiCodesToObjects . get ( emoji . code ) ;
67- if ( existingEmoji ) {
68- existingEmoji . count += emoji . count ;
69- existingEmoji . lastUpdatedAt = Math . max ( existingEmoji . lastUpdatedAt , emoji . lastUpdatedAt ) ;
70- } else {
71- frequentlyUsedEmojiCodesToObjects . set ( emoji . code , emoji ) ;
72- }
73- } ) ;
74- frequentlyUsedEmojis = Array . from ( frequentlyUsedEmojiCodesToObjects . values ( ) ) . sort ( ( a , b ) => {
75- if ( a . count !== b . count ) {
76- return b . count - a . count ;
77- }
78- return b . lastUpdatedAt - a . lastUpdatedAt ;
79- } ) ;
80- } ,
81- } ) ;
68+ } ) ;
69+ return Array . from ( frequentlyUsedEmojiCodesToObjects . values ( ) ) . sort ( ( a , b ) => {
70+ if ( a . count !== b . count ) {
71+ return b . count - a . count ;
72+ }
73+ return b . lastUpdatedAt - a . lastUpdatedAt ;
74+ } ) ;
75+ } ;
8276
8377/**
8478 * Given an English emoji name, get its localized version
@@ -232,7 +226,7 @@ function addSpacesToEmojiCategories(emojis: PickerEmojis): EmojiPickerList {
232226/**
233227 * Get a merged array with frequently used emojis
234228 */
235- function mergeEmojisWithFrequentlyUsedEmojis ( emojis : PickerEmojis ) : EmojiPickerList {
229+ function mergeEmojisWithFrequentlyUsedEmojis ( emojis : PickerEmojis , frequentlyUsedEmojis : FrequentlyUsedEmoji [ ] ) : EmojiPickerList {
236230 if ( frequentlyUsedEmojis . length === 0 ) {
237231 return addSpacesToEmojiCategories ( emojis ) ;
238232 }
@@ -706,4 +700,5 @@ export {
706700 splitTextWithEmojis ,
707701 containsCustomEmoji ,
708702 containsOnlyCustomEmoji ,
703+ processFrequentlyUsedEmojis ,
709704} ;
0 commit comments