diff --git a/packages/react/src/hooks/useSetExclusiveState.js b/packages/react/src/hooks/useSetExclusiveState.js
index 9a59fdb41..df4ebc2a6 100644
--- a/packages/react/src/hooks/useSetExclusiveState.js
+++ b/packages/react/src/hooks/useSetExclusiveState.js
@@ -10,6 +10,7 @@ import {
useStarredMessageStore,
useFileStore,
useSidebarStore,
+ useKeyboardShortcutStore,
} from '../store';
const useSetExclusiveState = () => {
@@ -31,6 +32,9 @@ const useSetExclusiveState = () => {
const setShowChannelinfo = useChannelStore(
(state) => state.setShowChannelinfo
);
+ const setShowKeyboardShortcuts = useKeyboardShortcutStore(
+ (state) => state.setShowKeyboardShortcuts
+ );
const stateSetters = useMemo(
() => [
setShowStarred,
@@ -42,12 +46,14 @@ const useSetExclusiveState = () => {
setShowAllFiles,
setShowMentions,
setShowCurrentUserInfo,
+ setShowKeyboardShortcuts,
],
[
setShowAllFiles,
setShowAllThreads,
setShowChannelinfo,
setShowCurrentUserInfo,
+ setShowKeyboardShortcuts,
setShowMembers,
setShowMentions,
setShowPinned,
diff --git a/packages/react/src/store/index.js b/packages/react/src/store/index.js
index bddd0bd1d..9ea6f6e47 100644
--- a/packages/react/src/store/index.js
+++ b/packages/react/src/store/index.js
@@ -11,3 +11,4 @@ export { default as useMentionsStore } from './mentionsStore';
export { default as usePinnedMessageStore } from './pinnedMessageStore';
export { default as useStarredMessageStore } from './starredMessageStore';
export { default as useSidebarStore } from './sidebarStore';
+export { default as useKeyboardShortcutStore } from './keyboardShortcutStore';
diff --git a/packages/react/src/store/keyboardShortcutStore.js b/packages/react/src/store/keyboardShortcutStore.js
new file mode 100644
index 000000000..aeea56e4a
--- /dev/null
+++ b/packages/react/src/store/keyboardShortcutStore.js
@@ -0,0 +1,9 @@
+import { create } from 'zustand';
+
+const useKeyboardShortcutStore = create((set) => ({
+ showKeyboardShortcuts: false,
+ setShowKeyboardShortcuts: (showKeyboardShortcuts) =>
+ set(() => ({ showKeyboardShortcuts })),
+}));
+
+export default useKeyboardShortcutStore;
diff --git a/packages/react/src/views/ChatHeader/ChatHeader.js b/packages/react/src/views/ChatHeader/ChatHeader.js
index 0986104ae..073f4a6a9 100644
--- a/packages/react/src/views/ChatHeader/ChatHeader.js
+++ b/packages/react/src/views/ChatHeader/ChatHeader.js
@@ -24,6 +24,7 @@ import {
useStarredMessageStore,
useFileStore,
useSidebarStore,
+ useKeyboardShortcutStore,
} from '../../store';
import { DynamicHeader } from '../DynamicHeader';
import useFetchChatData from '../../hooks/useFetchChatData';
@@ -50,6 +51,7 @@ const ChatHeader = ({
'members',
'search',
'rInfo',
+ 'keyboard',
'logout',
],
},
@@ -123,6 +125,10 @@ const ChatHeader = ({
const host = RCInstance.getHost();
return `${host}/avatar/${channelname}`;
};
+ const setShowKeyboardShortcuts = useKeyboardShortcutStore(
+ (state) => state.setShowKeyboardShortcuts
+ );
+
const handleGoBack = async () => {
if (isUserAuthenticated) {
getMessagesAndRoles();
@@ -300,6 +306,13 @@ const ChatHeader = ({
iconName: 'info',
visible: isUserAuthenticated,
},
+ keyboard: {
+ label: 'Keyboard Shortcuts',
+ id: 'keyboard',
+ onClick: () => setExclusiveState(setShowKeyboardShortcuts),
+ iconName: 'key',
+ visible: true,
+ },
logout: {
label: 'Logout',
id: 'logout',
@@ -324,6 +337,7 @@ const ChatHeader = ({
setShowAllFiles,
setShowSearch,
setShowChannelinfo,
+ setShowKeyboardShortcuts,
]
);
diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js
index e753b689a..43d98c6a1 100644
--- a/packages/react/src/views/ChatInput/ChatInput.js
+++ b/packages/react/src/views/ChatInput/ChatInput.js
@@ -19,7 +19,9 @@ import {
useLoginStore,
useChannelStore,
useMemberStore,
+ useSearchMessageStore,
} from '../../store';
+import useSetExclusiveState from '../../hooks/useSetExclusiveState';
import ChatInputFormattingToolbar from './ChatInputFormattingToolbar';
import useAttachmentWindowStore from '../../store/attachmentwindow';
import MembersList from '../Mentions/MembersList';
@@ -127,6 +129,9 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => {
const userInfo = { _id: userId, username, name };
+ const setShowSearch = useSearchMessageStore((state) => state.setShowSearch);
+ const setExclusiveState = useSetExclusiveState();
+
const dispatchToastMessage = useToastBarDispatch();
const showCommands = useShowCommands(
commands,
@@ -449,6 +454,26 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => {
formatSelection(messageRef, '*{{text}}*');
break;
}
+ case (e.ctrlKey || e.metaKey) && e.code === 'KeyK':
+ e.preventDefault();
+ setExclusiveState(setShowSearch);
+ break;
+ case e.code === 'ArrowUp' &&
+ !e.shiftKey &&
+ !e.ctrlKey &&
+ !e.metaKey &&
+ !e.altKey: {
+ const { value } = messageRef.current;
+ if (!value || value.trim() === '') {
+ const { messages } = useMessageStore.getState();
+ const lastOwnMsg = messages.find((m) => m.u?.username === username);
+ if (lastOwnMsg) {
+ e.preventDefault();
+ setEditMessage(lastOwnMsg);
+ }
+ }
+ break;
+ }
case (e.ctrlKey || e.metaKey || e.shiftKey) && e.code === 'Enter':
e.preventDefault();
handleNewLine(e);
diff --git a/packages/react/src/views/ChatLayout/ChatLayout.js b/packages/react/src/views/ChatLayout/ChatLayout.js
index f3b4262ac..beeeb379a 100644
--- a/packages/react/src/views/ChatLayout/ChatLayout.js
+++ b/packages/react/src/views/ChatLayout/ChatLayout.js
@@ -12,6 +12,7 @@ import {
useThreadsMessageStore,
useMemberStore,
useSidebarStore,
+ useKeyboardShortcutStore,
} from '../../store';
import RoomMembers from '../RoomMembers/RoomMember';
@@ -22,6 +23,7 @@ import PinnedMessages from '../MessageAggregators/PinnedMessages';
import SearchMessages from '../MessageAggregators/SearchMessages';
import FileGallery from '../MessageAggregators/FileGallery';
import Roominfo from '../RoomInformation/RoomInformation';
+import KeyboardShortcuts from '../KeyboardShortcuts/KeyboardShortcuts';
import UserInformation from '../UserInformation/UserInformation';
import ChatBody from '../ChatBody/ChatBody';
import ChatInput from '../ChatInput/ChatInput';
@@ -61,6 +63,9 @@ const ChatLayout = () => {
const showCurrentUserInfo = useUserStore(
(state) => state.showCurrentUserInfo
);
+ const showKeyboardShortcuts = useKeyboardShortcutStore(
+ (state) => state.showKeyboardShortcuts
+ );
const attachmentWindowOpen = useAttachmentWindowStore(
(state) => state.attachmentWindowOpen
);
@@ -134,6 +139,7 @@ const ChatLayout = () => {
{showPinned && }
{showStarred && }
{showCurrentUserInfo && }
+ {showKeyboardShortcuts && }
{uiKitContextualBarOpen && (
({
+ list: css`
+ display: flex;
+ flex-direction: column;
+ padding: 0.75rem;
+ gap: 0.25rem;
+ `,
+ row: css`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.5rem 0.5rem;
+ border-bottom: 1px solid ${theme.colors.border};
+ gap: 0.75rem;
+ `,
+ action: css`
+ font-size: 0.875rem;
+ color: ${theme.colors.foreground};
+ flex: 1;
+ `,
+ keys: css`
+ font-size: 0.8125rem;
+ font-family: monospace;
+ color: ${theme.colors.secondaryForeground};
+ background: ${theme.colors.background};
+ border: 1px solid ${theme.colors.border};
+ border-radius: 4px;
+ padding: 0.2rem 0.5rem;
+ white-space: nowrap;
+ `,
+});
+
+const KeyboardShortcuts = () => {
+ const { theme } = useTheme();
+ const styles = getStyles(theme);
+ const setExclusiveState = useSetExclusiveState();
+
+ return (
+ setExclusiveState(null)}
+ >
+
+ {shortcuts.map((shortcut) => (
+
+ {shortcut.action}
+ {shortcut.keys}
+
+ ))}
+
+
+ );
+};
+
+export default KeyboardShortcuts;