From 15d72b68a0bc56b5550807c101f9efaf3c920bae Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Thu, 26 Dec 2024 17:40:02 +0530 Subject: [PATCH] add more custom emojis hooks --- .../autocomplete/EmoticonAutocomplete.tsx | 2 +- src/app/components/emoji-board/EmojiBoard.tsx | 2 +- src/app/hooks/useImagePacks.ts | 165 ++++++++++++++---- src/app/plugins/custom-emoji/utils.ts | 18 -- 4 files changed, 129 insertions(+), 58 deletions(-) diff --git a/src/app/components/editor/autocomplete/EmoticonAutocomplete.tsx b/src/app/components/editor/autocomplete/EmoticonAutocomplete.tsx index d791d988..9479a698 100644 --- a/src/app/components/editor/autocomplete/EmoticonAutocomplete.tsx +++ b/src/app/components/editor/autocomplete/EmoticonAutocomplete.tsx @@ -52,7 +52,7 @@ export function EmoticonAutocomplete({ const mx = useMatrixClient(); const useAuthentication = useMediaAuthentication(); - const imagePacks = useRelevantImagePacks(mx, ImageUsage.Emoticon, imagePackRooms); + const imagePacks = useRelevantImagePacks(ImageUsage.Emoticon, imagePackRooms); const recentEmoji = useRecentEmoji(mx, 20); const searchList = useMemo(() => { diff --git a/src/app/components/emoji-board/EmojiBoard.tsx b/src/app/components/emoji-board/EmojiBoard.tsx index 7f4db0e1..d52b1d00 100644 --- a/src/app/components/emoji-board/EmojiBoard.tsx +++ b/src/app/components/emoji-board/EmojiBoard.tsx @@ -674,7 +674,7 @@ export function EmojiBoard({ const useAuthentication = useMediaAuthentication(); const emojiGroupLabels = useEmojiGroupLabels(); const emojiGroupIcons = useEmojiGroupIcons(); - const imagePacks = useRelevantImagePacks(mx, usage, imagePackRooms); + const imagePacks = useRelevantImagePacks(usage, imagePackRooms); const recentEmojis = useRecentEmoji(mx, 21); const contentScrollRef = useRef(null); diff --git a/src/app/hooks/useImagePacks.ts b/src/app/hooks/useImagePacks.ts index 7f47bae7..d5f0e01f 100644 --- a/src/app/hooks/useImagePacks.ts +++ b/src/app/hooks/useImagePacks.ts @@ -1,48 +1,137 @@ -import { ClientEvent, MatrixClient, MatrixEvent, Room, RoomStateEvent } from 'matrix-js-sdk'; -import { useEffect, useMemo } from 'react'; +import { Room } from 'matrix-js-sdk'; +import { useCallback, useMemo, useState } from 'react'; import { AccountDataEvent } from '../../types/matrix/accountData'; import { StateEvent } from '../../types/matrix/room'; -import { useForceUpdate } from './useForceUpdate'; -import { getRelevantPacks, ImagePack, ImageUsage } from '../plugins/custom-emoji'; +import { + getGlobalImagePacks, + getRoomImagePacks, + getUserImagePack, + ImagePack, + ImageUsage, +} from '../plugins/custom-emoji'; +import { useMatrixClient } from './useMatrixClient'; +import { useAccountDataCallback } from './useAccountDataCallback'; +import { useStateEventCallback } from './useStateEventCallback'; -export const useRelevantImagePacks = ( - mx: MatrixClient, - usage: ImageUsage, - rooms: Room[] -): ImagePack[] => { - const [forceCount, forceUpdate] = useForceUpdate(); +export const useUserImagePack = (): ImagePack | undefined => { + const mx = useMatrixClient(); + const [userPack, setUserPack] = useState(() => getUserImagePack(mx)); - const relevantPacks = useMemo( - () => getRelevantPacks(mx, rooms).filter((pack) => pack.getImages(usage).length > 0), - // eslint-disable-next-line react-hooks/exhaustive-deps - [mx, usage, rooms, forceCount] + useAccountDataCallback( + mx, + useCallback( + (mEvent) => { + if (mEvent.getType() === AccountDataEvent.PoniesUserEmotes) { + setUserPack(getUserImagePack(mx)); + } + }, + [mx] + ) ); - useEffect(() => { - const handleUpdate = (event: MatrixEvent) => { - if ( - event.getType() === AccountDataEvent.PoniesEmoteRooms || - event.getType() === AccountDataEvent.PoniesUserEmotes - ) { - forceUpdate(); - } - const eventRoomId = event.getRoomId(); - if ( - eventRoomId && - event.getType() === StateEvent.PoniesRoomEmotes && - rooms.find((room) => room.roomId === eventRoomId) - ) { - forceUpdate(); - } - }; + return userPack; +}; - mx.on(ClientEvent.AccountData, handleUpdate); - mx.on(RoomStateEvent.Events, handleUpdate); - return () => { - mx.removeListener(ClientEvent.AccountData, handleUpdate); - mx.removeListener(RoomStateEvent.Events, handleUpdate); - }; - }, [mx, rooms, forceUpdate]); +export const useGlobalImagePacks = (): ImagePack[] => { + const mx = useMatrixClient(); + const [globalPacks, setGlobalPacks] = useState(() => getGlobalImagePacks(mx)); + + useAccountDataCallback( + mx, + useCallback( + (mEvent) => { + if (mEvent.getType() === AccountDataEvent.PoniesEmoteRooms) { + setGlobalPacks(getGlobalImagePacks(mx)); + } + }, + [mx] + ) + ); + + useStateEventCallback( + mx, + useCallback( + (mEvent) => { + const eventType = mEvent.getType(); + const roomId = mEvent.getRoomId(); + const stateKey = mEvent.getStateKey(); + if (eventType === StateEvent.PoniesRoomEmotes && roomId && typeof stateKey === 'string') { + const global = !!globalPacks.find( + (pack) => + pack.address && pack.address.roomId === roomId && pack.address.stateKey === stateKey + ); + if (global) { + setGlobalPacks(getGlobalImagePacks(mx)); + } + } + }, + [mx, globalPacks] + ) + ); + + return globalPacks; +}; + +export const useRoomImagePacks = (room: Room): ImagePack[] => { + const mx = useMatrixClient(); + const [roomPacks, setRoomPacks] = useState(() => getRoomImagePacks(room)); + + useStateEventCallback( + mx, + useCallback( + (mEvent) => { + if ( + mEvent.getRoomId() === room.roomId && + mEvent.getType() === StateEvent.PoniesRoomEmotes + ) { + setRoomPacks(getRoomImagePacks(room)); + } + }, + [room] + ) + ); + + return roomPacks; +}; + +export const useRoomsImagePacks = (rooms: Room[]) => { + const mx = useMatrixClient(); + const [roomPacks, setRoomPacks] = useState(() => rooms.flatMap(getRoomImagePacks)); + + useStateEventCallback( + mx, + useCallback( + (mEvent) => { + if ( + rooms.find((room) => room.roomId === mEvent.getRoomId()) && + mEvent.getType() === StateEvent.PoniesRoomEmotes + ) { + setRoomPacks(rooms.flatMap(getRoomImagePacks)); + } + }, + [rooms] + ) + ); + + return roomPacks; +}; + +export const useRelevantImagePacks = (usage: ImageUsage, rooms: Room[]): ImagePack[] => { + const userPack = useUserImagePack(); + const globalPacks = useGlobalImagePacks(); + const roomsPacks = useRoomsImagePacks(rooms); + + const relevantPacks = useMemo(() => { + const packs = userPack ? [userPack] : []; + const globalPackIds = new Set(globalPacks.map((pack) => pack.id)); + + const relPacks = packs.concat( + globalPacks, + roomsPacks.filter((pack) => !globalPackIds.has(pack.id)) + ); + + return relPacks.filter((pack) => pack.getImages(usage).length > 0); + }, [userPack, globalPacks, roomsPacks, usage]); return relevantPacks; }; diff --git a/src/app/plugins/custom-emoji/utils.ts b/src/app/plugins/custom-emoji/utils.ts index 2544c4c5..068127af 100644 --- a/src/app/plugins/custom-emoji/utils.ts +++ b/src/app/plugins/custom-emoji/utils.ts @@ -57,21 +57,3 @@ export function getUserImagePack(mx: MatrixClient): ImagePack | undefined { const userImagePack = ImagePack.fromMatrixEvent(userId, packEvent); return userImagePack; } - -/** - * @param {MatrixClient} mx Provide if you want to include user personal/global pack - * @param {Room[]} rooms Provide rooms if you want to include rooms pack - * @returns {ImagePack[]} packs - */ -export function getRelevantPacks(mx?: MatrixClient, rooms?: Room[]): ImagePack[] { - const userPack = mx && getUserImagePack(mx); - const userPacks = userPack ? [userPack] : []; - const globalPacks = mx ? getGlobalImagePacks(mx) : []; - const globalPackIds = new Set(globalPacks.map((pack) => pack.id)); - const roomsPack = rooms?.flatMap(getRoomImagePacks) ?? []; - - return userPacks.concat( - globalPacks, - roomsPack.filter((pack) => !globalPackIds.has(pack.id)) - ); -}