Remove goto cmds from msg input also fix #81
authorAjay Bura <ajbura@gmail.com>
Sun, 12 Dec 2021 06:01:52 +0000 (11:31 +0530)
committerAjay Bura <ajbura@gmail.com>
Sun, 12 Dec 2021 06:01:52 +0000 (11:31 +0530)
Signed-off-by: Ajay Bura <ajbura@gmail.com>
src/app/molecules/following-members/FollowingMembers.jsx [new file with mode: 0644]
src/app/molecules/following-members/FollowingMembers.scss [new file with mode: 0644]
src/app/molecules/message/TimelineChange.jsx
src/app/organisms/room/RoomViewCmdBar.jsx
src/app/organisms/room/RoomViewCmdBar.scss
src/app/organisms/room/RoomViewInput.jsx

diff --git a/src/app/molecules/following-members/FollowingMembers.jsx b/src/app/molecules/following-members/FollowingMembers.jsx
new file mode 100644 (file)
index 0000000..6529653
--- /dev/null
@@ -0,0 +1,59 @@
+/* eslint-disable react/prop-types */
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import './FollowingMembers.scss';
+
+import initMatrix from '../../../client/initMatrix';
+import cons from '../../../client/state/cons';
+import { openReadReceipts } from '../../../client/action/navigation';
+
+import Text from '../../atoms/text/Text';
+import RawIcon from '../../atoms/system-icons/RawIcon';
+import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
+
+import { getUsersActionJsx } from '../../organisms/room/common';
+
+function FollowingMembers({ roomTimeline }) {
+  const [followingMembers, setFollowingMembers] = useState([]);
+  const { roomId } = roomTimeline;
+  const mx = initMatrix.matrixClient;
+  const { roomsInput } = initMatrix;
+  const myUserId = mx.getUserId();
+
+  const handleOnMessageSent = () => setFollowingMembers([]);
+
+  useEffect(() => {
+    const updateFollowingMembers = () => {
+      setFollowingMembers(roomTimeline.getLiveReaders());
+    };
+    updateFollowingMembers();
+    roomTimeline.on(cons.events.roomTimeline.LIVE_RECEIPT, updateFollowingMembers);
+    roomsInput.on(cons.events.roomsInput.MESSAGE_SENT, handleOnMessageSent);
+    return () => {
+      roomTimeline.removeListener(cons.events.roomTimeline.LIVE_RECEIPT, updateFollowingMembers);
+      roomsInput.removeListener(cons.events.roomsInput.MESSAGE_SENT, handleOnMessageSent);
+    };
+  }, [roomTimeline]);
+
+  const filteredM = followingMembers.filter((userId) => userId !== myUserId);
+
+  return filteredM.length !== 0 && (
+    <button
+      className="following-members"
+      onClick={() => openReadReceipts(roomId, followingMembers)}
+      type="button"
+    >
+      <RawIcon
+        size="extra-small"
+        src={TickMarkIC}
+      />
+      <Text variant="b2">{getUsersActionJsx(roomId, filteredM, 'following the conversation.')}</Text>
+    </button>
+  );
+}
+
+FollowingMembers.propTypes = {
+  roomTimeline: PropTypes.shape({}).isRequired,
+};
+
+export default FollowingMembers;
diff --git a/src/app/molecules/following-members/FollowingMembers.scss b/src/app/molecules/following-members/FollowingMembers.scss
new file mode 100644 (file)
index 0000000..42885bf
--- /dev/null
@@ -0,0 +1,32 @@
+
+.following-members {
+  width: 100%;
+  padding: 0 var(--sp-normal);
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  cursor: pointer;
+  
+  & .ic-raw {
+    min-width: var(--ic-extra-small);
+    opacity: 0.4;
+    margin: 0 var(--sp-extra-tight);
+  }
+  & .text {
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    color: var(--tc-surface-low);
+    b {
+      color: var(--tc-surface-normal);
+    }
+  }
+
+  &:hover,
+  &:focus {
+    background-color: var(--bg-surface-hover);
+  }
+  &:active {
+    background-color: var(--bg-surface-active);
+  }
+}
\ No newline at end of file
index 2ef28c116a9b2a58c0678da2fe817163337a9af1..5ad33d31b3c7a0e6e1fe0fe8b525dd50631fbba3 100644 (file)
@@ -10,7 +10,6 @@ import LeaveArraowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
 import InviteArraowIC from '../../../../public/res/ic/outlined/invite-arrow.svg';
 import InviteCancelArraowIC from '../../../../public/res/ic/outlined/invite-cancel-arrow.svg';
 import UserIC from '../../../../public/res/ic/outlined/user.svg';
-import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
 
 function TimelineChange({
   variant, content, time, onClick,
@@ -33,9 +32,6 @@ function TimelineChange({
     case 'avatar':
       iconSrc = UserIC;
       break;
-    case 'follow':
-      iconSrc = TickMarkIC;
-      break;
     default:
       iconSrc = JoinArraowIC;
       break;
@@ -67,7 +63,6 @@ TimelineChange.propTypes = {
   variant: PropTypes.oneOf([
     'join', 'leave', 'invite',
     'invite-cancel', 'avatar', 'other',
-    'follow',
   ]),
   content: PropTypes.oneOfType([
     PropTypes.string,
index 34c0701419ffa6466cc9af3895f05d6d9d4cfebd..e4a3e6341ef1d55443e212fdafe9622ab2d69593 100644 (file)
@@ -6,31 +6,19 @@ import parse from 'html-react-parser';
 import twemoji from 'twemoji';
 
 import initMatrix from '../../../client/initMatrix';
-import cons from '../../../client/state/cons';
 import { toggleMarkdown } from '../../../client/action/settings';
 import * as roomActions from '../../../client/action/room';
 import {
-  selectTab,
-  selectRoom,
   openCreateRoom,
   openPublicRooms,
   openInviteUser,
-  openReadReceipts,
 } from '../../../client/action/navigation';
 import { emojis } from '../emoji-board/emoji';
 import AsyncSearch from '../../../util/AsyncSearch';
 
 import Text from '../../atoms/text/Text';
-import Button from '../../atoms/button/Button';
-import IconButton from '../../atoms/button/IconButton';
-import ContextMenu, { MenuHeader } from '../../atoms/context-menu/ContextMenu';
 import ScrollView from '../../atoms/scroll/ScrollView';
-import SettingTile from '../../molecules/setting-tile/SettingTile';
-import TimelineChange from '../../molecules/message/TimelineChange';
-
-import CmdIC from '../../../../public/res/ic/outlined/cmd.svg';
-
-import { getUsersActionJsx } from './common';
+import FollowingMembers from '../../molecules/following-members/FollowingMembers';
 
 const commands = [{
   name: 'markdown',
@@ -61,121 +49,6 @@ const commands = [{
   exe: (roomId, searchTerm) => openInviteUser(roomId, searchTerm),
 }];
 
-function CmdHelp() {
-  return (
-    <ContextMenu
-      placement="top"
-      content={(
-        <>
-          <MenuHeader>General command</MenuHeader>
-          <Text variant="b2">/command_name</Text>
-          <MenuHeader>Go-to commands</MenuHeader>
-          <Text variant="b2">{'>*space_name'}</Text>
-          <Text variant="b2">{'>#room_name'}</Text>
-          <Text variant="b2">{'>@people_name'}</Text>
-          <MenuHeader>Autofill commands</MenuHeader>
-          <Text variant="b2">:emoji_name</Text>
-          <Text variant="b2">@name</Text>
-        </>
-      )}
-      render={(toggleMenu) => (
-        <IconButton
-          src={CmdIC}
-          size="extra-small"
-          onClick={toggleMenu}
-          tooltip="Commands"
-        />
-      )}
-    />
-  );
-}
-
-function ViewCmd() {
-  function renderAllCmds() {
-    return commands.map((command) => (
-      <SettingTile
-        key={command.name}
-        title={command.name}
-        content={(<Text variant="b3">{command.description}</Text>)}
-      />
-    ));
-  }
-  return (
-    <ContextMenu
-      maxWidth={250}
-      placement="top"
-      content={(
-        <>
-          <MenuHeader>General commands</MenuHeader>
-          {renderAllCmds()}
-        </>
-      )}
-      render={(toggleMenu) => (
-        <span>
-          <Button onClick={toggleMenu}><span className="text text-b3">View all</span></Button>
-        </span>
-      )}
-    />
-  );
-}
-
-function FollowingMembers({ roomId, roomTimeline, viewEvent }) {
-  const [followingMembers, setFollowingMembers] = useState([]);
-  const mx = initMatrix.matrixClient;
-  const myUserId = mx.getUserId();
-
-  const handleOnMessageSent = () => setFollowingMembers([]);
-
-  useEffect(() => {
-    const updateFollowingMembers = () => {
-      setFollowingMembers(roomTimeline.getLiveReaders());
-    };
-    updateFollowingMembers();
-    roomTimeline.on(cons.events.roomTimeline.LIVE_RECEIPT, updateFollowingMembers);
-    viewEvent.on('message_sent', handleOnMessageSent);
-    return () => {
-      roomTimeline.removeListener(cons.events.roomTimeline.LIVE_RECEIPT, updateFollowingMembers);
-      viewEvent.removeListener('message_sent', handleOnMessageSent);
-    };
-  }, [roomTimeline]);
-
-  const filteredM = followingMembers.filter((userId) => userId !== myUserId);
-  return filteredM.length !== 0 && (
-    <TimelineChange
-      variant="follow"
-      content={getUsersActionJsx(roomId, filteredM, 'following the conversation.')}
-      time=""
-      onClick={() => openReadReceipts(roomId, followingMembers)}
-    />
-  );
-}
-
-FollowingMembers.propTypes = {
-  roomId: PropTypes.string.isRequired,
-  roomTimeline: PropTypes.shape({}).isRequired,
-  viewEvent: PropTypes.shape({}).isRequired,
-};
-
-function getCmdActivationMessage(prefix) {
-  function genMessage(prime, secondary) {
-    return (
-      <>
-        <span>{prime}</span>
-        <span>{secondary}</span>
-      </>
-    );
-  }
-  const cmd = {
-    '/': () => genMessage('General command mode activated. ', 'Type command name for suggestions.'),
-    '>*': () => genMessage('Go-to command mode activated. ', 'Type space name for suggestions.'),
-    '>#': () => genMessage('Go-to command mode activated. ', 'Type room name for suggestions.'),
-    '>@': () => genMessage('Go-to command mode activated. ', 'Type people name for suggestions.'),
-    ':': () => genMessage('Emoji autofill command mode activated. ', 'Type emoji shortcut for suggestions.'),
-    '@': () => genMessage('Name autofill command mode activated. ', 'Type name for suggestions.'),
-  };
-  return cmd[prefix]?.();
-}
-
 function CmdItem({ onClick, children }) {
   return (
     <button className="cmd-item" onClick={onClick} type="button">
@@ -188,8 +61,8 @@ CmdItem.propTypes = {
   children: PropTypes.node.isRequired,
 };
 
-function getCmdSuggestions({ prefix, option, suggestions }, fireCmd) {
-  function getGenCmdSuggestions(cmdPrefix, cmds) {
+function renderSuggestions({ prefix, option, suggestions }, fireCmd) {
+  function renderCmdSuggestions(cmdPrefix, cmds) {
     const cmdOptString = (typeof option === 'string') ? `/${option}` : '/?';
     return cmds.map((cmd) => (
       <CmdItem
@@ -207,23 +80,7 @@ function getCmdSuggestions({ prefix, option, suggestions }, fireCmd) {
     ));
   }
 
-  function getRoomsSuggestion(cmdPrefix, rooms) {
-    return rooms.map((room) => (
-      <CmdItem
-        key={room.roomId}
-        onClick={() => {
-          fireCmd({
-            prefix: cmdPrefix,
-            result: room,
-          });
-        }}
-      >
-        <Text variant="b2">{room.name}</Text>
-      </CmdItem>
-    ));
-  }
-
-  function getEmojiSuggestion(emPrefix, emos) {
+  function renderEmojiSuggestion(emPrefix, emos) {
     return emos.map((emoji) => (
       <CmdItem
         key={emoji.hexcode}
@@ -248,7 +105,7 @@ function getCmdSuggestions({ prefix, option, suggestions }, fireCmd) {
     ));
   }
 
-  function getNameSuggestion(namePrefix, members) {
+  function renderNameSuggestion(namePrefix, members) {
     return members.map((member) => (
       <CmdItem
         key={member.userId}
@@ -265,12 +122,9 @@ function getCmdSuggestions({ prefix, option, suggestions }, fireCmd) {
   }
 
   const cmd = {
-    '/': (cmds) => getGenCmdSuggestions(prefix, cmds),
-    '>*': (spaces) => getRoomsSuggestion(prefix, spaces),
-    '>#': (rooms) => getRoomsSuggestion(prefix, rooms),
-    '>@': (peoples) => getRoomsSuggestion(prefix, peoples),
-    ':': (emos) => getEmojiSuggestion(prefix, emos),
-    '@': (members) => getNameSuggestion(prefix, members),
+    '/': (cmds) => renderCmdSuggestions(prefix, cmds),
+    ':': (emos) => renderEmojiSuggestion(prefix, emos),
+    '@': (members) => renderNameSuggestion(prefix, members),
   };
   return cmd[prefix]?.(suggestions);
 }
@@ -319,29 +173,28 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
     asyncSearch.search(searchTerm);
   }
   function activateCmd(prefix) {
-    setCmd({ prefix });
     cmdPrefix = prefix;
+    cmdPrefix = undefined;
 
-    const { roomList, matrixClient } = initMatrix;
-    function getRooms(roomIds) {
-      return roomIds.map((rId) => {
-        const room = matrixClient.getRoom(rId);
-        return {
-          name: room.name,
-          roomId: room.roomId,
-        };
-      });
-    }
+    const mx = initMatrix.matrixClient;
     const setupSearch = {
-      '/': () => asyncSearch.setup(commands, { keys: ['name'], isContain: true }),
-      '>*': () => asyncSearch.setup(getRooms([...roomList.spaces]), { keys: ['name'], limit: 20 }),
-      '>#': () => asyncSearch.setup(getRooms([...roomList.rooms]), { keys: ['name'], limit: 20 }),
-      '>@': () => asyncSearch.setup(getRooms([...roomList.directs]), { keys: ['name'], limit: 20 }),
-      ':': () => asyncSearch.setup(emojis, { keys: ['shortcode'], isContain: true, limit: 20 }),
-      '@': () => asyncSearch.setup(matrixClient.getRoom(roomId).getJoinedMembers().map((member) => ({
-        name: member.name,
-        userId: member.userId.slice(1),
-      })), { keys: ['name', 'userId'], limit: 20 }),
+      '/': () => {
+        asyncSearch.setup(commands, { keys: ['name'], isContain: true });
+        setCmd({ prefix, suggestions: commands });
+      },
+      ':': () => {
+        asyncSearch.setup(emojis, { keys: ['shortcode'], isContain: true, limit: 20 });
+        setCmd({ prefix, suggestions: emojis.slice(26, 46) });
+      },
+      '@': () => {
+        const members = mx.getRoom(roomId).getJoinedMembers().map((member) => ({
+          name: member.name,
+          userId: member.userId.slice(1),
+        }));
+        asyncSearch.setup(members, { keys: ['name', 'userId'], limit: 20 });
+        const endIndex = members.length > 20 ? 20 : members.length;
+        setCmd({ prefix, suggestions: members.slice(0, endIndex) });
+      },
     };
     setupSearch[prefix]?.();
   }
@@ -351,11 +204,6 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
     cmdPrefix = undefined;
   }
   function fireCmd(myCmd) {
-    if (myCmd.prefix.match(/^>[*#@]$/)) {
-      if (cmd.prefix === '>*') selectTab(myCmd.result.roomId);
-      else selectRoom(myCmd.result.roomId);
-      viewEvent.emit('cmd_fired');
-    }
     if (myCmd.prefix === '/') {
       myCmd.result.exe(roomId, myCmd.option);
       viewEvent.emit('cmd_fired');
@@ -421,15 +269,11 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
     };
   }, [cmd]);
 
-  if (typeof cmd?.error === 'string') {
+  const isError = typeof cmd?.error === 'string';
+  if (cmd === null || isError) {
     return (
       <div className="cmd-bar">
-        <div className="cmd-bar__info">
-          <div className="cmd-bar__info-indicator--error" />
-        </div>
-        <div className="cmd-bar__content">
-          <Text className="cmd-bar__content-error" variant="b2">{cmd.error}</Text>
-        </div>
+        <FollowingMembers roomTimeline={roomTimeline} />
       </div>
     );
   }
@@ -437,27 +281,14 @@ function RoomViewCmdBar({ roomId, roomTimeline, viewEvent }) {
   return (
     <div className="cmd-bar">
       <div className="cmd-bar__info">
-        {cmd === null && <CmdHelp />}
-        {cmd !== null && typeof cmd.suggestions === 'undefined' && <div className="cmd-bar__info-indicator" /> }
-        {cmd !== null && typeof cmd.suggestions !== 'undefined' && <Text variant="b3">TAB</Text>}
+        <Text variant="b3">TAB</Text>
       </div>
       <div className="cmd-bar__content">
-        {cmd === null && (
-          <FollowingMembers
-            roomId={roomId}
-            roomTimeline={roomTimeline}
-            viewEvent={viewEvent}
-          />
-        )}
-        {cmd !== null && typeof cmd.suggestions === 'undefined' && <Text className="cmd-bar__content-help" variant="b2">{getCmdActivationMessage(cmd.prefix)}</Text>}
-        {cmd !== null && typeof cmd.suggestions !== 'undefined' && (
-          <ScrollView horizontal vertical={false} invisible>
-            <div className="cmd-bar__content__suggestions">{getCmdSuggestions(cmd, fireCmd)}</div>
-          </ScrollView>
-        )}
-      </div>
-      <div className="cmd-bar__more">
-        {cmd !== null && cmd.prefix === '/' && <ViewCmd />}
+        <ScrollView horizontal vertical={false} invisible>
+          <div className="cmd-bar__content-suggestions">
+            { renderSuggestions(cmd, fireCmd) }
+          </div>
+        </ScrollView>
       </div>
     </div>
   );
index dc8a98122c063d4246e7147c68aa19ad14979076..dd459062a763759cff3bd602631f2c521eabe0cf 100644 (file)
 
   &__info {
     display: flex;
-    width: calc(2 * var(--sp-extra-loose));
-    padding-left: var(--sp-ultra-tight);
+    width: 40px;
+    margin: 0 10px 0 14px;
     [dir=rtl] & {
-      padding-left: 0;
-      padding-right: var(--sp-ultra-tight);
+      margin: 0 14px 0 10px;
     }
-
     & > * {
       margin: auto;
     }
-
-    & .ic-btn-surface {
-      padding: 0;
-      & .ic-raw {
-        background-color: var(--tc-surface-low);
-      }
-    }
-    & .context-menu .text-b2 {
-      margin: var(--sp-extra-tight) var(--sp-tight);
-    }
-
-    &-indicator,
-    &-indicator--error {
-      width: 8px;
-      height: 8px;
-      border-radius: 50%;
-      background-color: var(--bg-positive);
-    }
-    &-indicator--error {
-      background-color: var(--bg-danger);
-    }
   }
 
   &__content {
     flex: 1;
     display: flex;
 
-    &-help,
-    &-error {
-      @extend .overflow-ellipsis;
-      align-self: center;
-      span {
-        color: var(--tc-surface-low);
-        &:first-child {
-          color: var(--tc-surface-normal)
-        }
-      }
-    }
-    &-error {
-      color: var(--bg-danger);
-    }
-    &__suggestions {
-      display: flex;
+    &-suggestions {
       height: 100%;
       white-space: nowrap;
-    }
-  }
-  &__more {
-    display: flex;
-    & button {
-      min-width: 0;
-      height: 100%;
-      margin: 0 var(--sp-normal);
-      padding: 0 var(--sp-extra-tight);
-      box-shadow: none;
-      border-radius: var(--bo-radius) var(--bo-radius) 0 0;
-      & .text {
-        color: var(--tc-surface-normal);
-      }
-    }
-    & .setting-tile {
-      margin: var(--sp-tight);
-    }
-  }
-
-  & .timeline-change {
-    width: 100%;
-    justify-content: flex-end;
-    padding: var(--sp-ultra-tight) var(--sp-normal);
-    border-radius: var(--bo-radius) var(--bo-radius) 0 0;
+      display: flex;
+      align-items: center;
 
-    &__content {
-      margin: 0;
-      flex: unset;
       & > .text {
         @extend .overflow-ellipsis;
-        & b {
-          color: var(--tc-surface-normal);
-        }
       }
     }
   }
index dd4f0d85d7f3f88f048f026ab3a16177a0cecd64..a262fee57d8a4ebb7515eb5c1d3a523ec851eaa5 100644 (file)
@@ -30,7 +30,7 @@ import MarkdownIC from '../../../../public/res/ic/outlined/markdown.svg';
 import FileIC from '../../../../public/res/ic/outlined/file.svg';
 import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
 
-const CMD_REGEX = /(^\/|^>[#*@]|:|@)(\S*)$/;
+const CMD_REGEX = /(^\/|:|@)(\S*)$/;
 let isTyping = false;
 let isCmdActivated = false;
 let cmdCursorPos = null;
@@ -45,8 +45,6 @@ function RoomViewInput({
   const inputBaseRef = useRef(null);
   const uploadInputRef = useRef(null);
   const uploadProgressRef = useRef(null);
-  const rightOptionsRef = useRef(null);
-  const escBtnRef = useRef(null);
 
   const TYPING_TIMEOUT = 5000;
   const mx = initMatrix.matrixClient;
@@ -90,30 +88,11 @@ function RoomViewInput({
     uploadInputRef.current.value = null;
   }
 
-  function rightOptionsA11Y(A11Y) {
-    const rightOptions = rightOptionsRef.current.children;
-    for (let index = 0; index < rightOptions.length; index += 1) {
-      rightOptions[index].disabled = !A11Y;
-    }
-  }
-
   function activateCmd(prefix) {
     isCmdActivated = true;
-    requestAnimationFrame(() => {
-      inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-positive)';
-      escBtnRef.current.style.display = 'block';
-    });
-    rightOptionsA11Y(false);
     viewEvent.emit('cmd_activate', prefix);
   }
   function deactivateCmd() {
-    if (inputBaseRef.current !== null) {
-      requestAnimationFrame(() => {
-        inputBaseRef.current.style.boxShadow = 'var(--bs-surface-border)';
-        escBtnRef.current.style.display = 'none';
-      });
-      rightOptionsA11Y(true);
-    }
     isCmdActivated = false;
     cmdCursorPos = null;
   }
@@ -121,11 +100,6 @@ function RoomViewInput({
     deactivateCmd();
     viewEvent.emit('cmd_deactivate');
   }
-  function errorCmd() {
-    requestAnimationFrame(() => {
-      inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-danger)';
-    });
-  }
   function setCursorPosition(pos) {
     setTimeout(() => {
       textAreaRef.current.focus();
@@ -163,7 +137,6 @@ function RoomViewInput({
     roomsInput.on(cons.events.roomsInput.UPLOAD_PROGRESS_CHANGES, uploadingProgress);
     roomsInput.on(cons.events.roomsInput.ATTACHMENT_CANCELED, clearAttachment);
     roomsInput.on(cons.events.roomsInput.FILE_UPLOADED, clearAttachment);
-    viewEvent.on('cmd_error', errorCmd);
     viewEvent.on('cmd_fired', firedCmd);
     navigation.on(cons.events.navigation.REPLY_TO_CLICKED, setUpReply);
     if (textAreaRef?.current !== null) {
@@ -177,7 +150,6 @@ function RoomViewInput({
       roomsInput.removeListener(cons.events.roomsInput.UPLOAD_PROGRESS_CHANGES, uploadingProgress);
       roomsInput.removeListener(cons.events.roomsInput.ATTACHMENT_CANCELED, clearAttachment);
       roomsInput.removeListener(cons.events.roomsInput.FILE_UPLOADED, clearAttachment);
-      viewEvent.removeListener('cmd_error', errorCmd);
       viewEvent.removeListener('cmd_fired', firedCmd);
       navigation.removeListener(cons.events.navigation.REPLY_TO_CLICKED, setUpReply);
       if (isCmdActivated) deactivateCmd();
@@ -193,7 +165,7 @@ function RoomViewInput({
     };
   }, [roomId]);
 
-  async function sendMessage() {
+  const sendMessage = async () => {
     const msgBody = textAreaRef.current.value;
     if (roomsInput.isSending(roomId)) return;
     if (msgBody.trim() === '' && attachment === null) return;
@@ -214,7 +186,7 @@ function RoomViewInput({
     viewEvent.emit('message_sent');
     textAreaRef.current.style.height = 'unset';
     if (replyTo !== null) setReplyTo(null);
-  }
+  };
 
   function processTyping(msg) {
     const isEmptyMsg = msg === '';
@@ -259,19 +231,16 @@ function RoomViewInput({
       return;
     }
     if (!isCmdActivated) activateCmd(cmdPrefix);
-    requestAnimationFrame(() => {
-      inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-caution)';
-    });
     viewEvent.emit('cmd_process', cmdPrefix, cmdSlug);
   }
 
-  function handleMsgTyping(e) {
+  const handleMsgTyping = (e) => {
     const msg = e.target.value;
     recognizeCmd(e.target.value);
     if (!isCmdActivated) processTyping(msg);
-  }
+  };
 
-  function handleKeyDown(e) {
+  const handleKeyDown = (e) => {
     if (e.keyCode === 13 && e.shiftKey === false) {
       e.preventDefault();
 
@@ -279,13 +248,9 @@ function RoomViewInput({
         viewEvent.emit('cmd_exe');
       } else sendMessage();
     }
-    if (e.keyCode === 27 && isCmdActivated) {
-      deactivateCmdAndEmit();
-      e.preventDefault();
-    }
-  }
+  };
 
-  function handlePaste(e) {
+  const handlePaste = (e) => {
     if (e.clipboardData === false) {
       return;
     }
@@ -309,19 +274,19 @@ function RoomViewInput({
         }
       }
     }
-  }
+  };
 
   function addEmoji(emoji) {
     textAreaRef.current.value += emoji.unicode;
     textAreaRef.current.focus();
   }
 
-  function handleUploadClick() {
+  const handleUploadClick = () => {
     if (attachment === null) uploadInputRef.current.click();
     else {
       roomsInput.cancelAttachment(roomId);
     }
-  }
+  };
   function uploadFileChange(e) {
     const file = e.target.files.item(0);
     setAttachment(file);
@@ -356,9 +321,8 @@ function RoomViewInput({
             </Text>
           </ScrollView>
           {isMarkdown && <RawIcon size="extra-small" src={MarkdownIC} />}
-          <button ref={escBtnRef} tabIndex="-1" onClick={deactivateCmdAndEmit} className="btn-cmd-esc" type="button"><Text variant="b3">ESC</Text></button>
         </div>
-        <div ref={rightOptionsRef} className="room-input__option-container">
+        <div className="room-input__option-container">
           <IconButton
             onClick={(e) => {
               const cords = getEventCords(e);