Skip to content

Commit 58a98b1

Browse files
committed
fix(msc4459): emoji discoverable as per MSC4459
1 parent 3d1b102 commit 58a98b1

4 files changed

Lines changed: 53 additions & 16 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: minor
3+
---
4+
5+
# add initial support for sending discoverable emojis and sticker

src/app/features/room/RoomInput.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import {
6060
ANYWHERE_AUTOCOMPLETE_PREFIXES,
6161
BEGINNING_AUTOCOMPLETE_PREFIXES,
6262
getLinks,
63+
replaceWithElement,
6364
} from '$components/editor';
6465
import { EmojiBoard, EmojiBoardTab } from '$components/emoji-board';
6566
import { UseStateProvider } from '$components/UseStateProvider';
@@ -129,8 +130,11 @@ import { sanitizeText } from '$utils/sanitize';
129130
import { PKitCommandMessageHandler } from '$plugins/pluralkit-handler/PKitCommandMessageHandler';
130131
import { PKitProxyMessageHandler } from '$plugins/pluralkit-handler/PKitProxyMessageHandler';
131132
import { MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME } from '$types/matrix/common';
132-
import type {IGenericMSC4459, MSC4459ImagePackReference} from '$types/matrix/common'
133-
import { getImagePackReferencesForMxc } from '$utils/msc4459helper';
133+
import type { IGenericMSC4459, MSC4459ImagePackReference } from '$types/matrix/common';
134+
import {
135+
getImagePackReferencesForMxc,
136+
getImagePackReferencesForMxcWrappedInMap,
137+
} from '$utils/msc4459helper';
134138
import { ImageUsage } from '$plugins/custom-emoji';
135139
import { SerializableMap } from '$types/wrapper/SerializableMap';
136140
import { useSettingsLinkBaseUrl } from '$features/settings/useSettingsLinkBaseUrl';
@@ -171,7 +175,7 @@ const getLatestThreadEventId = (room: Room, threadRootId: string): string => {
171175
ev.threadRootId === threadRootId && ev.getId() !== threadRootId && !reactionOrEditEvent(ev)
172176
);
173177
if (liveEvents.length > 0) {
174-
return liveEvents[liveEvents.length - 1]!.getId() ?? threadRootId;
178+
return liveEvents.at(-1)!.getId() ?? threadRootId;
175179
}
176180
return threadRootId;
177181
};
@@ -749,6 +753,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
749753
nickNameReplacement: nicknameReplacement,
750754
})
751755
);
756+
752757
let msgType = MsgType.Text;
753758

754759
// quick text react
@@ -809,6 +814,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
809814
}
810815

811816
content['m.mentions'] = getMentionContent(Array.from(mentionData.users), mentionData.room);
817+
content[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME] = imagePacksUsedRef.current.toJSON();
812818

813819
const links = getLinks(serializedChildren);
814820
content['com.beeper.linkpreviews'] = [];
@@ -1122,8 +1128,19 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
11221128
);
11231129

11241130
const handleEmoticonSelect = (key: string, shortcode: string) => {
1125-
editor.insertNode(createEmoticonElement(key, shortcode));
1131+
const emoticonEl = createEmoticonElement(key, shortcode);
1132+
if (autocompleteQuery) {
1133+
replaceWithElement(editor, autocompleteQuery.range, emoticonEl);
1134+
} else {
1135+
editor.insertNode(emoticonEl);
1136+
}
1137+
if (!imagePacksUsedRef.current.has(key))
1138+
imagePacksUsedRef.current.set(
1139+
key,
1140+
getImagePackReferencesForMxc(key, mx, ImageUsage.Emoticon)
1141+
);
11261142
moveCursor(editor);
1143+
handleCloseAutocomplete();
11271144
};
11281145

11291146
const handleStickerSelect = async (mxc: string, shortcode: string, label: string) => {
@@ -1142,7 +1159,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
11421159
};
11431160

11441161
// add the image pack reference
1145-
content[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME] = getImagePackReferencesForMxc(
1162+
content[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME] = getImagePackReferencesForMxcWrappedInMap(
11461163
mxc,
11471164
mx,
11481165
ImageUsage.Sticker
@@ -1161,6 +1178,11 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
11611178
false
11621179
);
11631180
}
1181+
content[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME] = getImagePackReferencesForMxcWrappedInMap(
1182+
mxc,
1183+
mx,
1184+
ImageUsage.Sticker
1185+
);
11641186

11651187
if (replyDraft) {
11661188
content['m.relates_to'] = getReplyContent(replyDraft, room);
@@ -1259,6 +1281,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
12591281
editor={editor}
12601282
query={autocompleteQuery}
12611283
requestClose={handleCloseAutocomplete}
1284+
onEmoticonSelected={handleEmoticonSelect}
12621285
/>
12631286
)}
12641287
{autocompleteQuery?.prefix === AutocompletePrefix.Reaction &&

src/app/utils/messageReaction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME } from '$types/matrix/common';
22
import type { MatrixReactionEvent } from '$types/matrix/common';
33
import type { MatrixClient } from 'matrix-js-sdk';
44
import { ImageUsage } from '$plugins/custom-emoji';
5-
import { getImagePackReferencesForMxc } from './msc4459helper';
5+
import { getImagePackReferencesForMxcWrappedInMap } from './msc4459helper';
66

77
export const getReactionContent = (
88
eventId: string,
@@ -17,7 +17,7 @@ export const getReactionContent = (
1717
},
1818
shortcode,
1919
'com.beeper.reaction.shortcode': shortcode,
20-
[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME]: getImagePackReferencesForMxc(
20+
[MATRIX_IMAGE_SOURCE_PACK_PROPERTY_NAME]: getImagePackReferencesForMxcWrappedInMap(
2121
key,
2222
matrixClient,
2323
ImageUsage.Emoticon

src/app/utils/msc4459helper.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,26 @@ import { getViaServers } from '$plugins/via-servers';
99
import { getMxIdServer } from './mxIdHelper';
1010
import { isRoomPrivate } from './roomVisibility';
1111

12-
export function getImagePackReferencesForMxc(
12+
export function getImagePackReferencesForMxcWrappedInMap(
1313
mxcUrl: string,
1414
matrixClient: MatrixClient,
1515
imageUsage: ImageUsage
1616
): SerializableMap<string, MSC4459ImagePackReference> {
17+
const retMap = new SerializableMap<string, MSC4459ImagePackReference>();
18+
retMap.set(mxcUrl, getImagePackReferencesForMxc(mxcUrl, matrixClient, imageUsage));
19+
return retMap;
20+
}
21+
22+
export function getImagePackReferencesForMxc(
23+
mxcUrl: string,
24+
matrixClient: MatrixClient,
25+
imageUsage: ImageUsage
26+
): MSC4459ImagePackReference {
1727
const globalImgPacks: ImagePack[] = getGlobalImagePacks(matrixClient);
18-
if (!mxcUrl.startsWith('mxc')) return new SerializableMap<string, MSC4459ImagePackReference>();
19-
const imagePackReferences = new SerializableMap<string, MSC4459ImagePackReference>();
20-
globalImgPacks
28+
if (!mxcUrl.startsWith('mxc')) return {};
29+
const imgPkRef = globalImgPacks
2130
.filter((val) => val.getImages(imageUsage).find((img) => img.url === mxcUrl))
22-
.forEach((pack) => {
31+
.map((pack) => {
2332
const img = pack.getImages(imageUsage).find((val) => val.url === mxcUrl);
2433
const room = matrixClient.getRoom(pack.address?.roomId);
2534
if (!room || isRoomPrivate(matrixClient, room)) return;
@@ -31,13 +40,13 @@ export function getImagePackReferencesForMxc(
3140
// add ones own hs as via server, as that server evidently is alive
3241
const ownViaHS = getMxIdServer(matrixClient.getSafeUserId());
3342
if (ownViaHS) viaServers.add(ownViaHS);
34-
const imgPkRef = {
43+
return {
3544
room_id: pack.address?.roomId,
3645
state_key: pack.address?.stateKey,
3746
via: viaServers,
3847
shortcode: img?.shortcode,
3948
} satisfies MSC4459ImagePackReference;
40-
imagePackReferences.set(mxcUrl, imgPkRef);
41-
});
42-
return imagePackReferences;
49+
})
50+
.at(0);
51+
return imgPkRef ?? {};
4352
}

0 commit comments

Comments
 (0)