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 && }