Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/react/src/hooks/useSetExclusiveState.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
useStarredMessageStore,
useFileStore,
useSidebarStore,
useKeyboardShortcutStore,
} from '../store';

const useSetExclusiveState = () => {
Expand All @@ -31,6 +32,9 @@ const useSetExclusiveState = () => {
const setShowChannelinfo = useChannelStore(
(state) => state.setShowChannelinfo
);
const setShowKeyboardShortcuts = useKeyboardShortcutStore(
(state) => state.setShowKeyboardShortcuts
);
const stateSetters = useMemo(
() => [
setShowStarred,
Expand All @@ -42,12 +46,14 @@ const useSetExclusiveState = () => {
setShowAllFiles,
setShowMentions,
setShowCurrentUserInfo,
setShowKeyboardShortcuts,
],
[
setShowAllFiles,
setShowAllThreads,
setShowChannelinfo,
setShowCurrentUserInfo,
setShowKeyboardShortcuts,
setShowMembers,
setShowMentions,
setShowPinned,
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
9 changes: 9 additions & 0 deletions packages/react/src/store/keyboardShortcutStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { create } from 'zustand';

const useKeyboardShortcutStore = create((set) => ({
showKeyboardShortcuts: false,
setShowKeyboardShortcuts: (showKeyboardShortcuts) =>
set(() => ({ showKeyboardShortcuts })),
}));

export default useKeyboardShortcutStore;
14 changes: 14 additions & 0 deletions packages/react/src/views/ChatHeader/ChatHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
useStarredMessageStore,
useFileStore,
useSidebarStore,
useKeyboardShortcutStore,
} from '../../store';
import { DynamicHeader } from '../DynamicHeader';
import useFetchChatData from '../../hooks/useFetchChatData';
Expand All @@ -50,6 +51,7 @@ const ChatHeader = ({
'members',
'search',
'rInfo',
'keyboard',
'logout',
],
},
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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',
Expand All @@ -324,6 +337,7 @@ const ChatHeader = ({
setShowAllFiles,
setShowSearch,
setShowChannelinfo,
setShowKeyboardShortcuts,
]
);

Expand Down
25 changes: 25 additions & 0 deletions packages/react/src/views/ChatInput/ChatInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/views/ChatLayout/ChatLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
useThreadsMessageStore,
useMemberStore,
useSidebarStore,
useKeyboardShortcutStore,
} from '../../store';

import RoomMembers from '../RoomMembers/RoomMember';
Expand All @@ -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';
Expand Down Expand Up @@ -61,6 +63,9 @@ const ChatLayout = () => {
const showCurrentUserInfo = useUserStore(
(state) => state.showCurrentUserInfo
);
const showKeyboardShortcuts = useKeyboardShortcutStore(
(state) => state.showKeyboardShortcuts
);
const attachmentWindowOpen = useAttachmentWindowStore(
(state) => state.attachmentWindowOpen
);
Expand Down Expand Up @@ -134,6 +139,7 @@ const ChatLayout = () => {
{showPinned && <PinnedMessages />}
{showStarred && <StarredMessages />}
{showCurrentUserInfo && <UserInformation />}
{showKeyboardShortcuts && <KeyboardShortcuts />}
{uiKitContextualBarOpen && (
<UiKitContextualBar
key={Math.random()}
Expand Down
106 changes: 106 additions & 0 deletions packages/react/src/views/KeyboardShortcuts/KeyboardShortcuts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from 'react';
import { css } from '@emotion/react';
import { Box, Sidebar, useTheme } from '@embeddedchat/ui-elements';
import useSetExclusiveState from '../../hooks/useSetExclusiveState';

const isMac =
typeof navigator !== 'undefined' &&
/Mac/.test(navigator.userAgentData?.platform || navigator.platform);
const mod = isMac ? '⌘' : 'Ctrl';
const alt = isMac ? '⌥' : 'Alt';

const shortcuts = [
{
action: 'Open Channel / User search',
keys: `${mod} + K`,
},
{
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} + ←`,
},
{
action: 'Move to the beginning of the message',
keys: `${mod} / ${alt} + ↑`,
},
{
action: 'Move to the end of the message',
keys: `${mod} / ${alt} + →`,
},
{
action: 'Move to the end of the message',
keys: `${mod} / ${alt} + ↓`,
},
{
action: 'New line in message compose input',
keys: 'Shift + Enter',
},
];

const getStyles = (theme) => ({
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 (
<Sidebar
title="Keyboard Shortcuts"
iconName="key"
onClose={() => setExclusiveState(null)}
>
<Box css={styles.list}>
{shortcuts.map((shortcut) => (
<Box key={`${shortcut.action}-${shortcut.keys}`} css={styles.row}>
<span css={styles.action}>{shortcut.action}</span>
<span css={styles.keys}>{shortcut.keys}</span>
</Box>
))}
</Box>
</Sidebar>
);
};

export default KeyboardShortcuts;