Edit last message with up arrow key (#774)
authorAjay Bura <32841439+ajbura@users.noreply.github.com>
Sun, 21 Aug 2022 14:11:48 +0000 (19:41 +0530)
committerGitHub <noreply@github.com>
Sun, 21 Aug 2022 14:11:48 +0000 (19:41 +0530)
src/app/molecules/message/Message.jsx
src/app/molecules/message/Message.scss
src/app/organisms/room/RoomViewContent.jsx

index 42344d7522fe6dfef1615a15faa8d4bac547774d..7d3ee63b9166ea16bc4c91aa80955227594b4873 100644 (file)
@@ -714,9 +714,9 @@ function getEditedBody(editedMEvent) {
 }
 
 function Message({
-  mEvent, isBodyOnly, roomTimeline, focus, fullTime,
+  mEvent, isBodyOnly, roomTimeline,
+  focus, fullTime, isEdit, setEdit, cancelEdit,
 }) {
-  const [isEditing, setIsEditing] = useState(false);
   const roomId = mEvent.getRoomId();
   const { editedTimeline, reactionTimeline } = roomTimeline ?? {};
 
@@ -731,7 +731,7 @@ function Message({
   const avatarSrc = mEvent.sender?.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop') ?? null;
 
   const edit = useCallback(() => {
-    setIsEditing(true);
+    setEdit(eventId);
   }, []);
   const reply = useCallback(() => {
     replyTo(senderId, mEvent.getId(), body);
@@ -788,7 +788,7 @@ function Message({
             eventId={mEvent.replyEventId}
           />
         )}
-        {!isEditing && (
+        {!isEdit && (
           <MessageBody
             senderName={username}
             isCustomHTML={isCustomHTML}
@@ -797,22 +797,22 @@ function Message({
             isEdited={isEdited}
           />
         )}
-        {isEditing && (
+        {isEdit && (
           <MessageEdit
             body={body}
             onSave={(newBody) => {
               if (newBody !== body) {
                 initMatrix.roomsInput.sendEditedMessage(roomId, mEvent, newBody);
               }
-              setIsEditing(false);
+              cancelEdit();
             }}
-            onCancel={() => setIsEditing(false)}
+            onCancel={cancelEdit}
           />
         )}
         {haveReactions && (
           <MessageReactionGroup roomTimeline={roomTimeline} mEvent={mEvent} />
         )}
-        {roomTimeline && !isEditing && (
+        {roomTimeline && !isEdit && (
           <MessageOptions
             roomTimeline={roomTimeline}
             mEvent={mEvent}
@@ -829,6 +829,9 @@ Message.defaultProps = {
   focus: false,
   roomTimeline: null,
   fullTime: false,
+  isEdit: false,
+  setEdit: null,
+  cancelEdit: null,
 };
 Message.propTypes = {
   mEvent: PropTypes.shape({}).isRequired,
@@ -836,6 +839,9 @@ Message.propTypes = {
   roomTimeline: PropTypes.shape({}),
   focus: PropTypes.bool,
   fullTime: PropTypes.bool,
+  isEdit: PropTypes.bool,
+  setEdit: PropTypes.func,
+  cancelEdit: PropTypes.func,
 };
 
 export { Message, MessageReply, PlaceholderMessage };
index 47338d2b0c88eeb6a36d8165c575bb48a8bb7265..66d0c7ec49c0ca745522f3879e5f89cec960bc92 100644 (file)
   padding: var(--sp-extra-tight) 0;
   &-btns button {
     margin: var(--sp-tight) 0 0 0;
+    padding: var(--sp-ultra-tight) var(--sp-tight);
+    min-width: 0;
     @include dir.side(margin, 0, var(--sp-tight));
   }
 }
index 521996483e6093bf14643577d53905e5b513d3ef..745ece822e706339a7974ac702bafe0f31423554 100644 (file)
@@ -118,7 +118,15 @@ function handleOnClickCapture(e) {
   }
 }
 
-function renderEvent(roomTimeline, mEvent, prevMEvent, isFocus = false) {
+function renderEvent(
+  roomTimeline,
+  mEvent,
+  prevMEvent,
+  isFocus,
+  isEdit,
+  setEdit,
+  cancelEdit,
+) {
   const isBodyOnly = (prevMEvent !== null
     && prevMEvent.getSender() === mEvent.getSender()
     && prevMEvent.getType() !== 'm.room.member'
@@ -147,6 +155,9 @@ function renderEvent(roomTimeline, mEvent, prevMEvent, isFocus = false) {
       roomTimeline={roomTimeline}
       focus={isFocus}
       fullTime={false}
+      isEdit={isEdit}
+      setEdit={setEdit}
+      cancelEdit={cancelEdit}
     />
   );
 }
@@ -386,6 +397,8 @@ function RoomViewContent({ eventId, roomTimeline }) {
   const timelineSVRef = useRef(null);
   const timelineScrollRef = useRef(null);
   const eventLimitRef = useRef(null);
+  const [editEventId, setEditEventId] = useState(null);
+  const cancelEdit = () => setEditEventId(null);
 
   const readUptoEvtStore = useStore(roomTimeline);
   const [onLimitUpdate, forceUpdateLimit] = useForceUpdate();
@@ -470,6 +483,42 @@ function RoomViewContent({ eventId, roomTimeline }) {
     }
   }, [newEvent]);
 
+  const listenKeyboard = useCallback((event) => {
+    if (event.ctrlKey || event.altKey || event.metaKey) return;
+    if (event.key !== 'ArrowUp') return;
+    if (navigation.isRawModalVisible) return;
+
+    if (document.activeElement.id !== 'message-textarea') return;
+    if (document.activeElement.value !== '') return;
+
+    const {
+      timeline: tl, activeTimeline, liveTimeline, matrixClient: mx,
+    } = roomTimeline;
+    const limit = eventLimitRef.current;
+    if (activeTimeline !== liveTimeline) return;
+    if (tl.length > limit.length) return;
+
+    const mTypes = ['m.text'];
+    for (let i = tl.length - 1; i >= 0; i -= 1) {
+      const mE = tl[i];
+      if (
+        mE.getSender() === mx.getUserId()
+        && mE.getType() === 'm.room.message'
+        && mTypes.includes(mE.getContent()?.msgtype)
+      ) {
+        setEditEventId(mE.getId());
+        return;
+      }
+    }
+  }, [roomTimeline]);
+
+  useEffect(() => {
+    document.body.addEventListener('keydown', listenKeyboard);
+    return () => {
+      document.body.removeEventListener('keydown', listenKeyboard);
+    };
+  }, [listenKeyboard]);
+
   const handleTimelineScroll = (event) => {
     const timelineScroll = timelineScrollRef.current;
     if (!event.target) return;
@@ -535,7 +584,15 @@ function RoomViewContent({ eventId, roomTimeline }) {
       const isFocus = focusId === mEvent.getId();
       if (isFocus) jumpToItemIndex = itemCountIndex;
 
-      tl.push(renderEvent(roomTimeline, mEvent, isNewEvent ? null : prevMEvent, isFocus));
+      tl.push(renderEvent(
+        roomTimeline,
+        mEvent,
+        isNewEvent ? null : prevMEvent,
+        isFocus,
+        editEventId === mEvent.getId(),
+        setEditEventId,
+        cancelEdit,
+      ));
       itemCountIndex += 1;
     }
     if (roomTimeline.canPaginateForward() || limit.length < timeline.length) {