Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/fix-emoji-type-standardization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/core-typings': patch
'@rocket.chat/meteor': patch
---

Fixes the `IEmoji` type to reflect the real shape of custom emoji data, and standardizes the `emoji.list` entry types (native, custom, and alias) into a shared `IEmojiPackEntry` type, removing unsafe type casts.
27 changes: 2 additions & 25 deletions apps/meteor/app/emoji/lib/rocketchat.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { IEmojiPackEntry } from '@rocket.chat/core-typings';
import type { TranslationKey } from '@rocket.chat/ui-contexts';

export type EmojiPackage = {
Expand All @@ -19,30 +20,6 @@ export type EmojiPackages = {
[key: string]: EmojiPackage;
};
list: {
[key: keyof NonNullable<EmojiPackages['packages']>]:
| {
name?: string;
category: string;
emojiPackage: string;
shortnames: string[];
uc_base: string;
uc_greedy: string;
uc_match: string;
uc_output: string;
aliases?: string[];
aliasOf?: undefined;
extension?: string;
etag?: string;
unicode?: string;
}
| {
name?: undefined;
emojiPackage: string;
aliasOf: string;
extension?: undefined;
aliases?: undefined;
shortnames?: undefined;
etag?: string;
};
[key: keyof NonNullable<EmojiPackages['packages']>]: IEmojiPackEntry;
};
};
59 changes: 25 additions & 34 deletions apps/meteor/client/lib/customEmoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,11 @@ import { escapeRegExp } from '@rocket.chat/tools';
import { emoji, removeFromRecent, replaceEmojiInRecent } from '../../app/emoji/client';
import { getURL } from '../../app/utils/client';

const isSetNotNull = (fn: () => unknown) => {
let value;
try {
value = fn();
} catch (e) {
value = null;
}
return value !== null && value !== undefined;
};

export const updateEmojiCustom = (emojiData: IEmoji) => {
const previousExists = isSetNotNull(() => emojiData.previousName);
const currentAliases = isSetNotNull(() => emojiData.aliases);
const { previousName, aliases = [] } = emojiData;

if (previousExists && isSetNotNull(() => emoji.list[`:${emojiData.previousName}:`].aliases)) {
for (const alias of emoji.list[`:${emojiData.previousName}:`].aliases ?? []) {
if (previousName && emoji.list[`:${previousName}:`]?.aliases) {
for (const alias of emoji.list[`:${previousName}:`].aliases ?? []) {
delete emoji.list[`:${alias}:`];
const aliasIndex = emoji.packages.emojiCustom.list?.indexOf(`:${alias}:`) ?? -1;
if (aliasIndex !== -1) {
Expand All @@ -28,41 +17,43 @@ export const updateEmojiCustom = (emojiData: IEmoji) => {
}
}

if (previousExists && emojiData.name !== emojiData.previousName) {
const arrayIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.previousName);
if (previousName && emojiData.name !== previousName) {
const arrayIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(previousName);
if (arrayIndex !== -1) {
emoji.packages.emojiCustom.emojisByCategory.rocket.splice(arrayIndex, 1);
}
const arrayIndexList = emoji.packages.emojiCustom.list?.indexOf(`:${emojiData.previousName}:`) ?? -1;
const arrayIndexList = emoji.packages.emojiCustom.list?.indexOf(`:${previousName}:`) ?? -1;
if (arrayIndexList !== -1) {
emoji.packages.emojiCustom.list?.splice(arrayIndexList, 1);
}
delete emoji.list[`:${emojiData.previousName}:`];
delete emoji.list[`:${previousName}:`];
}

const categoryIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(`${emojiData.name}`);
const categoryIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.name);
if (categoryIndex === -1) {
emoji.packages.emojiCustom.emojisByCategory.rocket.push(`${emojiData.name}`);
emoji.packages.emojiCustom.emojisByCategory.rocket.push(emojiData.name);
emoji.packages.emojiCustom.list?.push(`:${emojiData.name}:`);
}
// Don't inherit fields from a native emoji being overridden (e.g. its unicode), or the pick would output the native emoji
// TODO: Fix the IEmoji type and standardize the emoji packs types

// Don't inherit fields from a native emoji being overridden (e.g. its unicode), or the picker would output the native emoji
emoji.list[`:${emojiData.name}:`] = {
...emojiData,
name: emojiData.name,
extension: emojiData.extension,
etag: emojiData.etag,
aliases,
emojiPackage: 'emojiCustom',
} as unknown as (typeof emoji.list)[keyof typeof emoji.list];
if (currentAliases) {
for (const alias of emojiData.aliases) {
emoji.packages.emojiCustom.list?.push(`:${alias}:`);
emoji.list[`:${alias}:`] = {
emojiPackage: 'emojiCustom',
aliasOf: emojiData.name,
};
}
};

for (const alias of aliases) {
emoji.packages.emojiCustom.list?.push(`:${alias}:`);
emoji.list[`:${alias}:`] = {
emojiPackage: 'emojiCustom',
aliasOf: emojiData.name,
};
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if (previousExists) {
replaceEmojiInRecent({ oldEmoji: emojiData.previousName, newEmoji: emojiData.name });
if (previousName) {
replaceEmojiInRecent({ oldEmoji: previousName, newEmoji: emojiData.name });
}

emoji.dispatchUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ export const useCustomEmoji = () => {
for (const currentEmoji of customEmojis) {
emoji.packages.emojiCustom.emojisByCategory.rocket.push(currentEmoji.name);
emoji.packages.emojiCustom.list?.push(`:${currentEmoji.name}:`);
emoji.list[`:${currentEmoji.name}:`] = { ...currentEmoji, emojiPackage: 'emojiCustom' } as any;
emoji.list[`:${currentEmoji.name}:`] = {
name: currentEmoji.name,
extension: currentEmoji.extension,
etag: currentEmoji.etag,
aliases: currentEmoji.aliases,
emojiPackage: 'emojiCustom',
};
for (const alias of currentEmoji.aliases) {
emoji.packages.emojiCustom.list?.push(`:${alias}:`);
emoji.list[`:${alias}:`] = {
Expand Down
13 changes: 12 additions & 1 deletion packages/core-typings/src/IEmoji.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
// Shape of the data broadcast for a custom emoji create/update/delete (see `emoji.updateCustom` /
// `emoji.deleteCustom` events and the `updateEmojiCustom` / `deleteEmojiCustom` notification streams).
// It is a superset of the fields sent from the different call sites that publish these events, so most
// fields besides `name` and `extension` are optional.
export interface IEmoji {
[x: string]: any;
_id?: string;
name: string;
aliases?: string[];
extension: string;
etag?: string;
previousName?: string;
previousExtension?: string;
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
newFile?: boolean;
}
39 changes: 39 additions & 0 deletions packages/core-typings/src/IEmojiPackEntry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// An entry of `emoji.list`, i.e. a single renderable emoji or emoji alias registered by an emoji pack
// (native/unicode, custom, or any package added through the emoji Apps-Engine hooks).
export type INativeEmojiPackEntry = {
name?: string;
category: string;
emojiPackage: string;
shortnames: string[];
uc_base: string;
uc_greedy: string;
uc_match: string;
uc_output: string;
aliases?: string[];
aliasOf?: undefined;
extension?: string;
etag?: string;
unicode?: string;
};

export type ICustomEmojiPackEntry = {
name: string;
emojiPackage: string;
extension: string;
aliases?: string[];
aliasOf?: undefined;
shortnames?: undefined;
etag?: string;
};

export type IEmojiAliasPackEntry = {
name?: undefined;
emojiPackage: string;
aliasOf: string;
extension?: undefined;
aliases?: undefined;
shortnames?: undefined;
etag?: string;
};

export type IEmojiPackEntry = INativeEmojiPackEntry | ICustomEmojiPackEntry | IEmojiAliasPackEntry;
1 change: 1 addition & 0 deletions packages/core-typings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export * from './INps';

export type * from './ISession';
export type * from './IEmoji';
export type * from './IEmojiPackEntry';
export type * from './IEmojiCustom';
export type * from './ICustomEmojiDescriptor';
export type * from './IAnalytics';
Expand Down