Skip to content

Commit 46ded84

Browse files
authored
feat: add 15-minute restriction on message edit/delete options (#717)
1 parent 1c12240 commit 46ded84

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

client/src/components/Chat/DropDownOption.jsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { BiDotsVerticalRounded } from 'react-icons/bi';
22
import Dropdown from 'rsuite/Dropdown';
33
import PropTypes from 'prop-types';
4-
import React from 'react';
4+
import React, { useMemo } from 'react';
55
import chatHelper from 'src/lib/chatHelper';
66
import { socket } from 'src/lib/socketConnection';
77
import { useApp } from 'src/context/AppContext';
88
import { useChat } from 'src/context/ChatContext';
99
import useChatUtils from 'src/lib/chatSocket';
1010
import useCryptoKeys from 'src/hooks/useCryptoKeys';
1111

12+
import { FIFTEEN_MINUTES } from '../../../../constants.json';
13+
14+
1215
const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setReplyId }) => {
1316
const { app } = useApp();
1417

@@ -17,7 +20,17 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
1720
const { getMessage, messageExists, handleCopyToClipBoard } = chatHelper(state, app);
1821
const { deleteMessage } = useChatUtils(socket);
1922

23+
const message = getMessage(id, state, app);
24+
25+
const isWithin15Minutes = useMemo(() => {
26+
return Date.now() - new Date(message.time).getTime() <= FIFTEEN_MINUTES;
27+
}, [message.time])
28+
2029
const handleEdit = (id) => {
30+
if (!isWithin15Minutes) {
31+
return;
32+
}
33+
2134
inputRef.current.focus();
2235
const { message } = getMessage(id, state, app);
2336

@@ -31,7 +44,7 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
3144
};
3245

3346
const handleDelete = async (id) => {
34-
if (!messageExists(id)) {
47+
if (!messageExists(id) || !isWithin15Minutes) {
3548
return;
3649
}
3750

@@ -78,13 +91,22 @@ const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setRe
7891
renderToggle={renderIconButton}
7992
NoCaret
8093
>
81-
<Dropdown.Item onClick={() => handleEdit(id)}>Edit</Dropdown.Item>
94+
{
95+
isWithin15Minutes && (
96+
<Dropdown.Item onClick={() => handleEdit(id)}>Edit</Dropdown.Item>
97+
)
98+
}
8299

83100
<Dropdown.Item onClick={() => handleCopyToClipBoard(id, importedPrivateKey)}>
84101
Copy
85102
</Dropdown.Item>
86103
<Dropdown.Item onClick={() => setReplyId(id)}>Reply</Dropdown.Item>
87-
<Dropdown.Item onClick={() => handleDelete(id)}>Delete</Dropdown.Item>
104+
105+
{
106+
isWithin15Minutes && (
107+
<Dropdown.Item onClick={() => handleDelete(id)}>Delete</Dropdown.Item>
108+
)
109+
}
88110
</Dropdown>
89111
);
90112
} else if (!isSender) {

constants.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@
1919
"NEW_EVENT_CREATE_ROOM": "createRoom",
2020
"NEW_EVENT_READ_MESSAGE": "read_message",
2121
"NEW_EVENT_ONLINE_STATUS": "online_status",
22-
"NEW_EVENT_REQUEST_PUBLIC_KEY": "requestPublicKey"
22+
"NEW_EVENT_REQUEST_PUBLIC_KEY": "requestPublicKey",
23+
24+
"FIFTEEN_MINUTES": 900000
2325
}

server/sockets/deleteMessage.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { NEW_EVENT_DELETE_MESSAGE } = require('../../constants.json');
2-
const { getActiveUser, removeMessage } = require('../utils/lib');
2+
const { getActiveUser, removeMessage, isMessageEditableOrDeletable } = require('../utils/lib');
33

44
module.exports = (socket) => {
55
socket.on(
@@ -14,6 +14,12 @@ module.exports = (socket) => {
1414
return;
1515
}
1616

17+
// Check if message exists and is within the 15-minute editable window
18+
if (!isMessageEditableOrDeletable(chatId, messageId)) {
19+
messageWasDeletedSuccessfully(false);
20+
return;
21+
}
22+
1723
const messageDeleted = await removeMessage(chatId, messageId);
1824

1925
socket.broadcast

server/sockets/editMessage.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ module.exports = (socket) => {
1717
return;
1818
}
1919

20+
// Check if message exists and is within the 15-minute editable window
21+
if (!isMessageEditableOrDeletable(chatId, messageId)) {
22+
messageWasEditedSuccessfully(false);
23+
return;
24+
}
25+
2026
const messageEdited = await editMessage(chatId, {
2127
id: messageId,
2228
message: newMessage,

server/utils/lib.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const User = require('../models/UserModel');
88
const Message = require('../models/MessageModel');
99
const { generateObjectId } = require('./helper');
1010

11+
const { FIFTEEN_MINUTES } = require('../../constants.json');
12+
13+
1114
/**
1215
* @typedef {{
1316
* id: string,
@@ -532,6 +535,17 @@ async function isUserBlocked(users) {
532535
}
533536
}
534537

538+
function isMessageEditableOrDeletable(chatId, messageId) {
539+
const chat = chats[chatId];
540+
if (!chat || !chat.messages || !chat.messages[messageId]) {
541+
return false; // Message doesn't exist
542+
}
543+
544+
const message = chat.messages[messageId];
545+
const timeSinceCreated = Date.now() - new Date(message.time).getTime();
546+
return timeSinceCreated <= FIFTEEN_MINUTES; // Check if within 15 minutes
547+
}
548+
535549
module.exports = {
536550
init,
537551
createChat,
@@ -552,5 +566,6 @@ module.exports = {
552566
delActiveUser,
553567
seenMessage,
554568
blockUser,
555-
isUserBlocked
569+
isUserBlocked,
570+
isMessageEditableOrDeletable
556571
};

0 commit comments

Comments
 (0)