From cd963d91d33e89799e7eda3b677a521fecc6f0b5 Mon Sep 17 00:00:00 2001
From: Ajay Bura <32841439+ajbura@users.noreply.github.com>
Date: Sat, 13 Sep 2025 15:10:48 +0530
Subject: [PATCH] separate emojis and sticker groups logic
---
src/app/components/emoji-board/EmojiBoard.tsx | 378 +++++++++---------
1 file changed, 187 insertions(+), 191 deletions(-)
diff --git a/src/app/components/emoji-board/EmojiBoard.tsx b/src/app/components/emoji-board/EmojiBoard.tsx
index 0419c798..d7beb2e9 100644
--- a/src/app/components/emoji-board/EmojiBoard.tsx
+++ b/src/app/components/emoji-board/EmojiBoard.tsx
@@ -4,7 +4,6 @@ import React, {
MouseEventHandler,
UIEventHandler,
ReactNode,
- memo,
useCallback,
useEffect,
useMemo,
@@ -15,10 +14,10 @@ import FocusTrap from 'focus-trap-react';
import { isKeyHotkey } from 'is-hotkey';
import classNames from 'classnames';
import { MatrixClient, Room } from 'matrix-js-sdk';
-import { atom, useAtomValue, useSetAtom } from 'jotai';
+import { Atom, atom, useAtomValue, useSetAtom } from 'jotai';
import * as css from './EmojiBoard.css';
-import { EmojiGroupId, IEmoji, IEmojiGroup, emojiGroups, emojis } from '../../plugins/emoji';
+import { IEmoji, IEmojiGroup, emojiGroups, emojis } from '../../plugins/emoji';
import { IEmojiGroupLabels, useEmojiGroupLabels } from './useEmojiGroupLabels';
import { IEmojiGroupIcons, useEmojiGroupIcons } from './useEmojiGroupIcons';
import { preventScrollWithArrowKey, stopPropagation } from '../../utils/keyboard';
@@ -129,109 +128,120 @@ export const EmojiGroup = as<
));
-function RecentEmojiSidebarStack({ onItemClick }: { onItemClick: (id: string) => void }) {
- const activeGroupId = useAtomValue(activeGroupIdAtom);
-
- return (
-
-
-
- );
-}
-
-function ImagePackSidebarStack({
- mx,
- packs,
- usage,
- onItemClick,
- useAuthentication,
-}: {
- mx: MatrixClient;
+type EmojiSidebarProps = {
+ activeGroupAtom: Atom;
+ handleOpenGroup: (groupId: string) => void;
packs: ImagePack[];
- usage: ImageUsage;
- onItemClick: (id: string) => void;
- useAuthentication?: boolean;
-}) {
- const activeGroupId = useAtomValue(activeGroupIdAtom);
- return (
-
- {usage === ImageUsage.Emoticon && }
- {packs.map((pack) => {
- let label = pack.meta.name;
- if (!label) label = isUserId(pack.id) ? 'Personal Pack' : mx.getRoom(pack.id)?.name;
-
- const url =
- mxcUrlToHttp(mx, pack.getAvatarUrl(usage) ?? '', useAuthentication) || pack.meta.avatar;
-
- return (
-
- );
- })}
-
- );
-}
-
-function NativeEmojiSidebarStack({
- groups,
- icons,
- labels,
- onItemClick,
-}: {
groups: IEmojiGroup[];
icons: IEmojiGroupIcons;
labels: IEmojiGroupLabels;
- onItemClick: (id: EmojiGroupId) => void;
-}) {
- const activeGroupId = useAtomValue(activeGroupIdAtom);
+};
+function EmojiSidebar({
+ activeGroupAtom,
+ handleOpenGroup,
+ packs,
+ groups,
+ icons,
+ labels,
+}: EmojiSidebarProps) {
+ const mx = useMatrixClient();
+ const useAuthentication = useMediaAuthentication();
+
+ const activeGroupId = useAtomValue(activeGroupAtom);
+ const usage = ImageUsage.Emoticon;
+
return (
-
-
- {groups.map((group) => (
+
+
- ))}
-
+
+ {packs.length > 0 && (
+
+
+ {packs.map((pack) => {
+ let label = pack.meta.name;
+ if (!label) label = isUserId(pack.id) ? 'Personal Pack' : mx.getRoom(pack.id)?.name;
+
+ const url =
+ mxcUrlToHttp(mx, pack.getAvatarUrl(usage) ?? '', useAuthentication) ||
+ pack.meta.avatar;
+
+ return (
+
+ );
+ })}
+
+ )}
+
+
+ {groups.map((group) => (
+
+ ))}
+
+
);
}
-export function RecentEmojiGroup({
- label,
- id,
- emojis: recentEmojis,
-}: {
- label: string;
- id: string;
- emojis: IEmoji[];
-}) {
+type StickerSidebarProps = {
+ activeGroupAtom: Atom;
+ handleOpenGroup: (groupId: string) => void;
+ packs: ImagePack[];
+};
+function StickerSidebar({ activeGroupAtom, handleOpenGroup, packs }: StickerSidebarProps) {
+ const mx = useMatrixClient();
+ const useAuthentication = useMediaAuthentication();
+
+ const activeGroupId = useAtomValue(activeGroupAtom);
+ const usage = ImageUsage.Sticker;
+
return (
-
- {recentEmojis.map((emoji) => (
-
- ))}
-
+
+
+
+ {packs.map((pack) => {
+ let label = pack.meta.name;
+ if (!label) label = isUserId(pack.id) ? 'Personal Pack' : mx.getRoom(pack.id)?.name;
+
+ const url =
+ mxcUrlToHttp(mx, pack.getAvatarUrl(usage) ?? '', useAuthentication) || pack.meta.avatar;
+
+ return (
+
+ );
+ })}
+
+
);
}
-export function SearchEmojiGroup({
+export function SearchGroup({
mx,
tab,
label,
@@ -275,18 +285,51 @@ export function SearchEmojiGroup({
);
}
-export const CustomEmojiGroups = memo(
- ({
- mx,
- groups,
- useAuthentication,
- }: {
- mx: MatrixClient;
- groups: ImagePack[];
- useAuthentication?: boolean;
- }) => (
+type StickerGroupsProps = {
+ packs: ImagePack[];
+};
+function StickerGroups({ packs }: StickerGroupsProps) {
+ const mx = useMatrixClient();
+ const useAuthentication = useMediaAuthentication();
+
+ if (packs.length === 0) {
+ return ;
+ }
+ return packs.map((pack) => (
+
+ {pack
+ .getImages(ImageUsage.Sticker)
+ .sort((a, b) => a.shortcode.localeCompare(b.shortcode))
+ .map((image) => (
+
+ ))}
+
+ ));
+}
+
+type EmojiGroupsProps = {
+ recentEmojis: IEmoji[];
+ packs: ImagePack[];
+ groups: IEmojiGroup[];
+ labels: IEmojiGroupLabels;
+};
+export function EmojiGroups({ recentEmojis, packs, groups, labels }: EmojiGroupsProps) {
+ const mx = useMatrixClient();
+ const useAuthentication = useMediaAuthentication();
+
+ return (
<>
- {groups.map((pack) => (
+
+ {recentEmojis.map((emoji) => (
+
+ ))}
+
+ {packs.map((pack) => (
{pack
.getImages(ImageUsage.Emoticon)
@@ -301,44 +344,6 @@ export const CustomEmojiGroups = memo(
))}
))}
- >
- )
-);
-
-export const StickerGroups = memo(
- ({
- mx,
- groups,
- useAuthentication,
- }: {
- mx: MatrixClient;
- groups: ImagePack[];
- useAuthentication?: boolean;
- }) =>
- groups.length === 0 ? (
-
- ) : (
- groups.map((pack) => (
-
- {pack
- .getImages(ImageUsage.Sticker)
- .sort((a, b) => a.shortcode.localeCompare(b.shortcode))
- .map((image) => (
-
- ))}
-
- ))
- )
-);
-
-export const NativeEmojiGroups = memo(
- ({ groups, labels }: { groups: IEmojiGroup[]; labels: IEmojiGroupLabels }) => (
- <>
{groups.map((emojiGroup) => (
{emojiGroup.emojis.map((emoji) => (
@@ -347,8 +352,8 @@ export const NativeEmojiGroups = memo(
))}
>
- )
-);
+ );
+}
const DefaultEmojiPreview: PreviewData = { key: '🙂', shortcode: 'slight_smile' };
@@ -359,6 +364,19 @@ const SEARCH_OPTIONS: UseAsyncSearchOptions = {
},
};
+type EmojiBoardProps = {
+ tab?: EmojiBoardTab;
+ onTabChange?: (tab: EmojiBoardTab) => void;
+ imagePackRooms: Room[];
+ requestClose: () => void;
+ returnFocusOnDeactivate?: boolean;
+ onEmojiSelect?: (unicode: string, shortcode: string) => void;
+ onCustomEmojiSelect?: (mxc: string, shortcode: string) => void;
+ onStickerSelect?: (mxc: string, shortcode: string, label: string) => void;
+ allowTextCustomEmoji?: boolean;
+ addToRecentEmoji?: boolean;
+};
+
export function EmojiBoard({
tab = EmojiBoardTab.Emoji,
onTabChange,
@@ -370,20 +388,8 @@ export function EmojiBoard({
onStickerSelect,
allowTextCustomEmoji,
addToRecentEmoji = true,
-}: {
- tab?: EmojiBoardTab;
- onTabChange?: (tab: EmojiBoardTab) => void;
- imagePackRooms: Room[];
- requestClose: () => void;
- returnFocusOnDeactivate?: boolean;
- onEmojiSelect?: (unicode: string, shortcode: string) => void;
- onCustomEmojiSelect?: (mxc: string, shortcode: string) => void;
- onStickerSelect?: (mxc: string, shortcode: string, label: string) => void;
- allowTextCustomEmoji?: boolean;
- addToRecentEmoji?: boolean;
-}) {
+}: EmojiBoardProps) {
const emojiTab = tab === EmojiBoardTab.Emoji;
- const stickerTab = tab === EmojiBoardTab.Sticker;
const usage = emojiTab ? ImageUsage.Emoticon : ImageUsage.Sticker;
const previewAtom = useMemo(
@@ -541,28 +547,22 @@ export function EmojiBoard({
}
sidebar={
-
- {emojiTab && recentEmojis.length > 0 && (
-
- )}
- {imagePacks.length > 0 && (
-
- )}
- {emojiTab && (
-
- )}
-
+ emojiTab ? (
+
+ ) : (
+
+ )
}
>
@@ -581,7 +581,7 @@ export function EmojiBoard({
gap="200"
>
{searchedItems && (
-
)}
- {emojiTab && recentEmojis.length > 0 && (
-
- )}
- {emojiTab && (
-
+ ) : (
+
)}
- {stickerTab && (
-
- )}
- {emojiTab && }