From 94b55fdfd97b14b2114bc27dd3410507f61a4dae Mon Sep 17 00:00:00 2001 From: not-meet Date: Fri, 27 Feb 2026 01:52:58 +0530 Subject: [PATCH 1/2] Feat : added keyboard shortcuts in options menu --- .../react/src/hooks/useSetExclusiveState.js | 6 ++ packages/react/src/store/index.js | 1 + .../react/src/store/keyboardShortcutStore.js | 9 ++ .../react/src/views/ChatHeader/ChatHeader.js | 14 +++ .../react/src/views/ChatInput/ChatInput.js | 25 +++++ .../react/src/views/ChatLayout/ChatLayout.js | 6 ++ .../KeyboardShortcuts/KeyboardShortcuts.js | 97 +++++++++++++++++++ 7 files changed, 158 insertions(+) create mode 100644 packages/react/src/store/keyboardShortcutStore.js create mode 100644 packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js diff --git a/packages/react/src/hooks/useSetExclusiveState.js b/packages/react/src/hooks/useSetExclusiveState.js index 9a59fdb419..df4ebc2a60 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 bddd0bd1d6..9ea6f6e478 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 0000000000..aeea56e4ab --- /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 0986104ae5..073f4a6a96 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 e753b689ae..83aba15f6d 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.code === 'KeyP'): + 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 f3b4262acb..beeeb379a7 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; From dda3cc5f4fe6729ce04eda741a3f5b7e9447f6a1 Mon Sep 17 00:00:00 2001 From: not-meet Date: Tue, 3 Mar 2026 15:02:31 +0530 Subject: [PATCH 2/2] fix: added bold and italic in keyboard shortcut model and fixed print screen bug --- packages/react/src/views/ChatInput/ChatInput.js | 2 +- .../src/views/KeyboardShortcuts/KeyboardShortcuts.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js index 83aba15f6d..43d98c6a1d 100644 --- a/packages/react/src/views/ChatInput/ChatInput.js +++ b/packages/react/src/views/ChatInput/ChatInput.js @@ -454,7 +454,7 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => { formatSelection(messageRef, '*{{text}}*'); break; } - case (e.ctrlKey || e.metaKey) && (e.code === 'KeyK' || e.code === 'KeyP'): + case (e.ctrlKey || e.metaKey) && e.code === 'KeyK': e.preventDefault(); setExclusiveState(setShowSearch); break; diff --git a/packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js b/packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js index f1fd46d831..ba7f68f40a 100644 --- a/packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js +++ b/packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js @@ -4,7 +4,8 @@ import { Box, Sidebar, useTheme } from '@embeddedchat/ui-elements'; import useSetExclusiveState from '../../hooks/useSetExclusiveState'; const isMac = - typeof navigator !== 'undefined' && /Mac/.test(navigator.platform); + typeof navigator !== 'undefined' && + /Mac/.test(navigator.userAgentData?.platform || navigator.platform); const mod = isMac ? '⌘' : 'Ctrl'; const alt = isMac ? '⌥' : 'Alt'; @@ -17,6 +18,14 @@ const shortcuts = [ action: 'Edit previous message', keys: '↑ (Up Arrow)', }, + { + action: 'Bold message', + keys: `${mod} + B`, + }, + { + action: 'Italic message', + keys: `${mod} + I`, + }, { action: 'Move to the beginning of the message', keys: `${mod} / ${alt} + ←`,