Skip to content

Commit

Permalink
Merge pull request #23153 from jeet-dhandha/fix-emoji-paste-issue
Browse files Browse the repository at this point in the history
Extract emojis from paste text
  • Loading branch information
marcaaron authored Aug 22, 2023
2 parents f929159 + f4e916a commit 44eb88a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 8 deletions.
9 changes: 7 additions & 2 deletions assets/emojis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ const emojiNameTable = _.reduce(
{},
);

const emojiCodeTable = _.reduce(
const emojiCodeTableWithSkinTones = _.reduce(
emojis,
(prev, cur) => {
const newValue = prev;
if (!cur.header) {
newValue[cur.code] = cur;
}
if (cur.types) {
cur.types.forEach((type) => {
newValue[type] = cur;
});
}
return newValue;
},
{},
Expand All @@ -32,5 +37,5 @@ const localeEmojis = {
es: esEmojis,
};

export {emojiNameTable, emojiCodeTable, localeEmojis};
export {emojiNameTable, emojiCodeTableWithSkinTones, localeEmojis};
export {skinTones, categoryFrequentlyUsed, default} from './common';
3 changes: 2 additions & 1 deletion src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,8 @@ const CONST = {
ROOM_NAME: /^#[a-z0-9à-ÿ-]{1,80}$/,

// eslint-disable-next-line max-len, no-misleading-character-class
EMOJIS: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu,
EMOJIS: /[\p{Extended_Pictographic}](\u200D[\p{Extended_Pictographic}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/gu,

TAX_ID: /^\d{9}$/,
NON_NUMERIC: /\D/g,

Expand Down
60 changes: 57 additions & 3 deletions src/libs/EmojiUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Onyx.connect({
key: ONYXKEYS.FREQUENTLY_USED_EMOJIS,
callback: (val) => {
frequentlyUsedEmojis = _.map(val, (item) => {
const emoji = Emojis.emojiCodeTable[item.code];
const emoji = Emojis.emojiCodeTableWithSkinTones[item.code];
if (emoji) {
return {...emoji, count: item.count, lastUpdatedAt: item.lastUpdatedAt};
}
Expand All @@ -33,7 +33,7 @@ const findEmojiByName = (name) => Emojis.emojiNameTable[name];
* @param {String} code
* @returns {Object}
*/
const findEmojiByCode = (code) => Emojis.emojiCodeTable[code];
const findEmojiByCode = (code) => Emojis.emojiCodeTableWithSkinTones[code];

/**
*
Expand Down Expand Up @@ -229,7 +229,7 @@ function getFrequentlyUsedEmojis(newEmoji) {
frequentEmojiList.splice(emojiIndex, 1);
}

const updatedEmoji = {...Emojis.emojiCodeTable[emoji.code], count: currentEmojiCount, lastUpdatedAt: currentTimestamp};
const updatedEmoji = {...Emojis.emojiCodeTableWithSkinTones[emoji.code], count: currentEmojiCount, lastUpdatedAt: currentTimestamp};

// We want to make sure the current emoji is added to the list
// Hence, we take one less than the current frequent used emojis
Expand Down Expand Up @@ -259,6 +259,43 @@ const getEmojiCodeWithSkinColor = (item, preferredSkinToneIndex) => {
return code;
};

/**
* Extracts emojis from a given text.
*
* @param {String} text - The text to extract emojis from.
* @returns {Object[]} An array of emoji codes.
*/
function extractEmojis(text) {
if (!text) {
return [];
}

// Parse Emojis including skin tones - Eg: ['👩🏻', '👩🏻', '👩🏼', '👩🏻', '👩🏼', '👩']
const parsedEmojis = text.match(CONST.REGEX.EMOJIS);

if (!parsedEmojis) {
return [];
}

const emojis = [];

// Text can contain similar emojis as well as their skin tone variants. Create a Set to remove duplicate emojis from the search.
const foundEmojiCodes = new Set();

for (let i = 0; i < parsedEmojis.length; i++) {
const character = parsedEmojis[i];
const emoji = Emojis.emojiCodeTableWithSkinTones[character];

// Add the parsed emoji to the final emojis if not already present.
if (emoji && !foundEmojiCodes.has(emoji.code)) {
foundEmojiCodes.add(emoji.code);
emojis.push(emoji);
}
}

return emojis;
}

/**
* Replace any emoji name in a text with the emoji icon.
* If we're on mobile, we also add a space after the emoji granted there's no text after it.
Expand Down Expand Up @@ -304,6 +341,22 @@ function replaceEmojis(text, preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE,
return {text: newText, emojis};
}

/**
* Find all emojis in a text and replace them with their code.
* @param {String} text
* @param {Number} preferredSkinTone
* @param {String} lang
* @returns {Object}
*/
function replaceAndExtractEmojis(text, preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, lang = CONST.LOCALES.DEFAULT) {
const {text: convertedText = '', emojis = []} = replaceEmojis(text, preferredSkinTone, lang);

return {
text: convertedText,
emojis: emojis.concat(extractEmojis(text)),
};
}

/**
* Suggest emojis when typing emojis prefix after colon
* @param {String} text
Expand Down Expand Up @@ -421,4 +474,5 @@ export {
getPreferredSkinToneIndex,
getPreferredEmojiCode,
getUniqueEmojiCodes,
replaceAndExtractEmojis,
};
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionCompose.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ function ReportActionCompose({
*/
const updateComment = useCallback(
(commentValue, shouldDebounceSaveComment) => {
const {text: newComment = '', emojis = []} = EmojiUtils.replaceEmojis(commentValue, preferredSkinTone, preferredLocale);
const {text: newComment, emojis} = EmojiUtils.replaceAndExtractEmojis(commentValue, preferredSkinTone, preferredLocale);

if (!_.isEmpty(emojis)) {
insertedEmojisRef.current = [...insertedEmojisRef.current, ...emojis];
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionItemMessageEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function ReportActionItemMessageEdit(props) {
*/
const updateDraft = useCallback(
(newDraftInput) => {
const {text: newDraft = '', emojis = []} = EmojiUtils.replaceEmojis(newDraftInput, props.preferredSkinTone, props.preferredLocale);
const {text: newDraft, emojis} = EmojiUtils.replaceAndExtractEmojis(newDraftInput, props.preferredSkinTone, props.preferredLocale);

if (!_.isEmpty(emojis)) {
insertedEmojis.current = [...insertedEmojis.current, ...emojis];
Expand Down

0 comments on commit 44eb88a

Please sign in to comment.