diff --git a/matrixgw_frontend/package-lock.json b/matrixgw_frontend/package-lock.json index e91bab4..8da93cc 100644 --- a/matrixgw_frontend/package-lock.json +++ b/matrixgw_frontend/package-lock.json @@ -19,6 +19,7 @@ "@mui/x-date-pickers": "^8.17.0", "date-and-time": "^4.1.0", "dayjs": "^1.11.19", + "emoji-picker-react": "^4.16.1", "is-cidr": "^6.0.1", "qrcode.react": "^4.2.0", "react": "^19.1.1", @@ -2362,6 +2363,21 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-picker-react": { + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.16.1.tgz", + "integrity": "sha512-MrPX0tOCfRL3uYI4of/2GRZ7S6qS7YlacKiF78uFH84/C62vcuHE2DZyv5b4ZJMk0e06es1jjB4e31Bb+YSM8w==", + "license": "MIT", + "dependencies": { + "flairup": "1.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16" + } + }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -2680,6 +2696,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flairup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz", + "integrity": "sha512-IKlE+pNvL2R+kVL1kEhUYqRxVqeFnjiIvHWDMLFXNaqyUdFXQM2wte44EfMYJNHkW16X991t2Zg8apKkhv7OBA==", + "license": "MIT" + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", diff --git a/matrixgw_frontend/package.json b/matrixgw_frontend/package.json index 4d8f1b0..7beadb3 100644 --- a/matrixgw_frontend/package.json +++ b/matrixgw_frontend/package.json @@ -21,6 +21,7 @@ "@mui/x-date-pickers": "^8.17.0", "date-and-time": "^4.1.0", "dayjs": "^1.11.19", + "emoji-picker-react": "^4.16.1", "is-cidr": "^6.0.1", "qrcode.react": "^4.2.0", "react": "^19.1.1", diff --git a/matrixgw_frontend/src/api/matrix/MatrixApiEvent.ts b/matrixgw_frontend/src/api/matrix/MatrixApiEvent.ts index 5fdf43b..35bc1d6 100644 --- a/matrixgw_frontend/src/api/matrix/MatrixApiEvent.ts +++ b/matrixgw_frontend/src/api/matrix/MatrixApiEvent.ts @@ -107,6 +107,21 @@ export class MatrixApiEvent { }); } + /** + * React to event + */ + static async ReactToEvent( + room: Room, + event_id: string, + key: string + ): Promise { + await APIClient.exec({ + method: "POST", + uri: `/matrix/room/${room.id}/event/${event_id}/react`, + jsonData: { key }, + }); + } + /** * Delete an event */ diff --git a/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx b/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx index 5fa5d7d..aeb29ce 100644 --- a/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx +++ b/matrixgw_frontend/src/widgets/messages/RoomMessagesList.tsx @@ -1,3 +1,4 @@ +import AddReactionIcon from "@mui/icons-material/AddReaction"; import DeleteIcon from "@mui/icons-material/Delete"; import EditIcon from "@mui/icons-material/Edit"; import { @@ -13,6 +14,7 @@ import { Typography, useTheme, } from "@mui/material"; +import EmojiPicker, { EmojiStyle, Theme } from "emoji-picker-react"; import React from "react"; import { MatrixApiEvent } from "../../api/matrix/MatrixApiEvent"; import type { UsersMap } from "../../api/matrix/MatrixApiProfile"; @@ -86,6 +88,7 @@ function RoomMessage(p: { const [showImageFullScreen, setShowImageFullScreen] = React.useState(false); const [editMessage, setEditMessage] = React.useState(); + const [pickReaction, setPickReaction] = React.useState(false); const closeImageFullScreen = () => setShowImageFullScreen(false); @@ -122,6 +125,21 @@ function RoomMessage(p: { } }; + const handleAddReaction = () => setPickReaction(true); + const handleCancelAddReaction = () => setPickReaction(false); + const handleSelectEmoji = async (key: string) => { + loadingMessage.show("Setting reaction..."); + try { + await MatrixApiEvent.ReactToEvent(p.room, p.message.event_id, key); + setPickReaction(false); + } catch (e) { + console.error("Failed to select emoji!", e); + alert(`Failed to select emoji! ${e}`); + } finally { + loadingMessage.hide(); + } + }; + return ( <> {/* Print date if required */} @@ -201,12 +219,18 @@ function RoomMessage(p: { right: "0px", }} > + {/* Add reaction */} + + {/* Edit text message */} {p.message.account === user.info.matrix_user_id && !p.message.image && ( )} + {/* Delete message */} {p.message.account === user.info.matrix_user_id && (