mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 14:30:29 +03:00 
			
		
		
		
	Make hotkeys work again (#1819)
This commit is contained in:
		
							parent
							
								
									c52c4f7d32
								
							
						
					
					
						commit
						c4abe39375
					
				
					 40 changed files with 182 additions and 39 deletions
				
			
		| 
						 | 
				
			
			@ -26,6 +26,7 @@ import * as css from './PdfViewer.css';
 | 
			
		|||
import { AsyncStatus } from '../../hooks/useAsyncCallback';
 | 
			
		||||
import { useZoom } from '../../hooks/useZoom';
 | 
			
		||||
import { createPage, usePdfDocumentLoader, usePdfJSLoader } from '../../plugins/pdfjs-dist';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export type PdfViewerProps = {
 | 
			
		||||
  name: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -201,6 +202,7 @@ export const PdfViewer = as<'div', PdfViewerProps>(
 | 
			
		|||
                      initialFocus: false,
 | 
			
		||||
                      onDeactivate: () => setJumpAnchor(undefined),
 | 
			
		||||
                      clickOutsideDeactivates: true,
 | 
			
		||||
                      escapeDeactivates: stopPropagation,
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <Menu variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ import {
 | 
			
		|||
  IconButton,
 | 
			
		||||
} from 'folds';
 | 
			
		||||
import FocusTrap from 'focus-trap-react';
 | 
			
		||||
import { stopPropagation } from '../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export type UIAFlowOverlayProps = {
 | 
			
		||||
  currentStep: number;
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +29,7 @@ export function UIAFlowOverlay({
 | 
			
		|||
}: UIAFlowOverlayProps) {
 | 
			
		||||
  return (
 | 
			
		||||
    <Overlay open backdrop={<OverlayBackdrop />}>
 | 
			
		||||
      <FocusTrap focusTrapOptions={{ initialFocus: false }}>
 | 
			
		||||
      <FocusTrap focusTrapOptions={{ initialFocus: false, escapeDeactivates: stopPropagation }}>
 | 
			
		||||
        <Box style={{ height: '100%' }} direction="Column" grow="Yes" gap="400">
 | 
			
		||||
          <Box grow="Yes" direction="Column" alignItems="Center" justifyContent="Center">
 | 
			
		||||
            {children}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ import {
 | 
			
		|||
 | 
			
		||||
import { CustomEditor, useEditor } from './Editor';
 | 
			
		||||
import { Toolbar } from './Toolbar';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export function EditorPreview() {
 | 
			
		||||
  const [open, setOpen] = useState(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,7 @@ export function EditorPreview() {
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              onDeactivate: () => setOpen(false),
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Modal size="500">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ import { isMacOS } from '../../utils/user-agent';
 | 
			
		|||
import { KeySymbol } from '../../utils/key-symbol';
 | 
			
		||||
import { useSetting } from '../../state/hooks/settings';
 | 
			
		||||
import { settingsAtom } from '../../state/settings';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
function BtnTooltip({ text, shortCode }: { text: string; shortCode?: string }) {
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -151,6 +152,7 @@ export function HeadingBlockButton() {
 | 
			
		|||
            isKeyForward: (evt: KeyboardEvent) =>
 | 
			
		||||
              evt.key === 'ArrowDown' || evt.key === 'ArrowRight',
 | 
			
		||||
            isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp' || evt.key === 'ArrowLeft',
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu style={{ padding: config.space.S100 }}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import { isKeyHotkey } from 'is-hotkey';
 | 
			
		|||
import { Header, Menu, Scroll, config } from 'folds';
 | 
			
		||||
 | 
			
		||||
import * as css from './AutocompleteMenu.css';
 | 
			
		||||
import { preventScrollWithArrowKey } from '../../../utils/keyboard';
 | 
			
		||||
import { preventScrollWithArrowKey, stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type AutocompleteMenuProps = {
 | 
			
		||||
  requestClose: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ export function AutocompleteMenu({ headerContent, requestClose, children }: Auto
 | 
			
		|||
            allowOutsideClick: true,
 | 
			
		||||
            isKeyForward: (evt: KeyboardEvent) => isKeyHotkey('arrowdown', evt),
 | 
			
		||||
            isKeyBackward: (evt: KeyboardEvent) => isKeyHotkey('arrowup', evt),
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu className={css.AutocompleteMenu}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ import * as css from './EmojiBoard.css';
 | 
			
		|||
import { EmojiGroupId, IEmoji, IEmojiGroup, emojiGroups, emojis } from '../../plugins/emoji';
 | 
			
		||||
import { IEmojiGroupLabels, useEmojiGroupLabels } from './useEmojiGroupLabels';
 | 
			
		||||
import { IEmojiGroupIcons, useEmojiGroupIcons } from './useEmojiGroupIcons';
 | 
			
		||||
import { preventScrollWithArrowKey } from '../../utils/keyboard';
 | 
			
		||||
import { preventScrollWithArrowKey, stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
import { useRelevantImagePacks } from '../../hooks/useImagePacks';
 | 
			
		||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
 | 
			
		||||
import { useRecentEmoji } from '../../hooks/useRecentEmoji';
 | 
			
		||||
| 
						 | 
				
			
			@ -775,6 +775,7 @@ export function EmojiBoard({
 | 
			
		|||
          !editableActiveElement() && isKeyHotkey(['arrowdown', 'arrowright'], evt),
 | 
			
		||||
        isKeyBackward: (evt: KeyboardEvent) =>
 | 
			
		||||
          !editableActiveElement() && isKeyHotkey(['arrowup', 'arrowleft'], evt),
 | 
			
		||||
        escapeDeactivates: stopPropagation,
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <EmojiBoardLayout
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ import {
 | 
			
		|||
import { MatrixError } from 'matrix-js-sdk';
 | 
			
		||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
 | 
			
		||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type LeaveRoomPromptProps = {
 | 
			
		||||
  roomId: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,7 @@ export function LeaveRoomPrompt({ roomId, onDone, onCancel }: LeaveRoomPromptPro
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: onCancel,
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ import {
 | 
			
		|||
import { MatrixError } from 'matrix-js-sdk';
 | 
			
		||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
 | 
			
		||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type LeaveSpacePromptProps = {
 | 
			
		||||
  roomId: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +53,7 @@ export function LeaveSpacePrompt({ roomId, onDone, onCancel }: LeaveSpacePromptP
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: onCancel,
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ import {
 | 
			
		|||
  mimeTypeToExt,
 | 
			
		||||
} from '../../../utils/mimeTypes';
 | 
			
		||||
import * as css from './style.css';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
const renderErrorButton = (retry: () => void, text: string) => (
 | 
			
		||||
  <TooltipProvider
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +102,7 @@ export function ReadTextFile({ body, mimeType, url, encInfo, renderViewer }: Rea
 | 
			
		|||
                initialFocus: false,
 | 
			
		||||
                onDeactivate: () => setTextViewer(false),
 | 
			
		||||
                clickOutsideDeactivates: true,
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <Modal
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +186,7 @@ export function ReadPdfFile({ body, mimeType, url, encInfo, renderViewer }: Read
 | 
			
		|||
                initialFocus: false,
 | 
			
		||||
                onDeactivate: () => setPdfViewer(false),
 | 
			
		||||
                clickOutsideDeactivates: true,
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <Modal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ import { getFileSrcUrl } from './util';
 | 
			
		|||
import * as css from './style.css';
 | 
			
		||||
import { bytesToSize } from '../../../utils/common';
 | 
			
		||||
import { FALLBACK_MIMETYPE } from '../../../utils/mimeTypes';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type RenderViewerProps = {
 | 
			
		||||
  src: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +109,7 @@ export const ImageContent = as<'div', ImageContentProps>(
 | 
			
		|||
                  initialFocus: false,
 | 
			
		||||
                  onDeactivate: () => setViewer(false),
 | 
			
		||||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <Modal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ import { nameInitials } from '../../utils/common';
 | 
			
		|||
import { millify } from '../../plugins/millify';
 | 
			
		||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
 | 
			
		||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
 | 
			
		||||
import { onEnterOrSpace } from '../../utils/keyboard';
 | 
			
		||||
import { onEnterOrSpace, stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
import { RoomType, StateEvent } from '../../../types/matrix/room';
 | 
			
		||||
import { useJoinedRoomId } from '../../hooks/useJoinedRoomId';
 | 
			
		||||
import { useElementSizeObserver } from '../../hooks/useElementSizeObserver';
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +107,7 @@ function ErrorDialog({
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              onDeactivate: closeError,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			@ -236,6 +237,7 @@ export const RoomCard = as<'div', RoomCardProps>(
 | 
			
		|||
                  initialFocus: false,
 | 
			
		||||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  onDeactivate: closeTopic,
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                {renderTopicViewer(roomName, roomTopic, closeTopic)}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
 | 
			
		|||
import { UseStateProvider } from '../../components/UseStateProvider';
 | 
			
		||||
import { LeaveSpacePrompt } from '../../components/leave-space-prompt';
 | 
			
		||||
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type HierarchyItemWithParent = HierarchyItem & {
 | 
			
		||||
  parentId: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -227,6 +228,7 @@ export function HierarchyItemMenu({
 | 
			
		|||
                clickOutsideDeactivates: true,
 | 
			
		||||
                isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <Menu style={{ maxWidth: toRem(150), width: '100vw' }}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ import { openInviteUser, openSpaceSettings } from '../../../client/action/naviga
 | 
			
		|||
import { IPowerLevels, usePowerLevelsAPI } from '../../hooks/usePowerLevels';
 | 
			
		||||
import { UseStateProvider } from '../../components/UseStateProvider';
 | 
			
		||||
import { LeaveSpacePrompt } from '../../components/leave-space-prompt';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type LobbyMenuProps = {
 | 
			
		||||
  roomId: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -197,6 +198,7 @@ export function LobbyHeader({ showProfile, powerLevels }: LobbyHeaderProps) {
 | 
			
		|||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <LobbyMenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ import { UseStateProvider } from '../../components/UseStateProvider';
 | 
			
		|||
import { RoomTopicViewer } from '../../components/room-topic-viewer';
 | 
			
		||||
import * as css from './LobbyHero.css';
 | 
			
		||||
import { PageHero } from '../../components/page';
 | 
			
		||||
import { onEnterOrSpace } from '../../utils/keyboard';
 | 
			
		||||
import { onEnterOrSpace, stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export function LobbyHero() {
 | 
			
		||||
  const mx = useMatrixClient();
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ export function LobbyHero() {
 | 
			
		|||
                        initialFocus: false,
 | 
			
		||||
                        clickOutsideDeactivates: true,
 | 
			
		||||
                        onDeactivate: () => setViewTopic(false),
 | 
			
		||||
                        escapeDeactivates: stopPropagation,
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <RoomTopicViewer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ import {
 | 
			
		|||
} from '../../components/RoomSummaryLoader';
 | 
			
		||||
import { UseStateProvider } from '../../components/UseStateProvider';
 | 
			
		||||
import { RoomTopicViewer } from '../../components/room-topic-viewer';
 | 
			
		||||
import { onEnterOrSpace } from '../../utils/keyboard';
 | 
			
		||||
import { onEnterOrSpace, stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
import { Membership, RoomType } from '../../../types/matrix/room';
 | 
			
		||||
import * as css from './RoomItem.css';
 | 
			
		||||
import * as styleCss from './style.css';
 | 
			
		||||
| 
						 | 
				
			
			@ -264,6 +264,7 @@ function RoomProfile({
 | 
			
		|||
                          initialFocus: false,
 | 
			
		||||
                          clickOutsideDeactivates: true,
 | 
			
		||||
                          onDeactivate: () => setView(false),
 | 
			
		||||
                          escapeDeactivates: stopPropagation,
 | 
			
		||||
                        }}
 | 
			
		||||
                      >
 | 
			
		||||
                        <RoomTopicViewer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ import * as styleCss from './style.css';
 | 
			
		|||
import { ErrorCode } from '../../cs-errorcode';
 | 
			
		||||
import { useDraggableItem } from './DnD';
 | 
			
		||||
import { openCreateRoom, openSpaceAddExisting } from '../../../client/action/navigation';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
function SpaceProfileLoading() {
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -277,6 +278,7 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
 | 
			
		|||
            clickOutsideDeactivates: true,
 | 
			
		||||
            isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
            isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu style={{ padding: config.space.S100 }}>
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +340,7 @@ function AddSpaceButton({ item }: { item: HierarchyItem }) {
 | 
			
		|||
            clickOutsideDeactivates: true,
 | 
			
		||||
            isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
            isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu style={{ padding: config.space.S100 }}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ import {
 | 
			
		|||
} from '../../hooks/useAsyncSearch';
 | 
			
		||||
import { DebounceOptions, useDebounce } from '../../hooks/useDebounce';
 | 
			
		||||
import { VirtualTile } from '../../components/virtualizer';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type OrderButtonProps = {
 | 
			
		||||
  order?: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +67,7 @@ function OrderButton({ order, onChange }: OrderButtonProps) {
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: () => setMenuAnchor(undefined),
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			@ -202,6 +204,7 @@ function SelectRoomButton({ roomList, selectedRooms, onChange }: SelectRoomButto
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: () => setMenuAnchor(undefined),
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu variant="Surface" style={{ width: toRem(250) }}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
 | 
			
		|||
import { useClientConfig } from '../../hooks/useClientConfig';
 | 
			
		||||
import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers';
 | 
			
		||||
import { TypingIndicator } from '../../components/typing-indicator';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type RoomNavItemMenuProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,6 +270,7 @@ export function RoomNavItem({
 | 
			
		|||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <RoomNavItemMenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,7 @@ import { millify } from '../../plugins/millify';
 | 
			
		|||
import { ScrollTopContainer } from '../../components/scroll-top-container';
 | 
			
		||||
import { UserAvatar } from '../../components/user-avatar';
 | 
			
		||||
import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export const MembershipFilters = {
 | 
			
		||||
  filterJoined: (m: RoomMember) => m.membership === Membership.Join,
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +301,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
 | 
			
		|||
                            clickOutsideDeactivates: true,
 | 
			
		||||
                            isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                            isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                            escapeDeactivates: stopPropagation,
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          <Menu style={{ padding: config.space.S100 }}>
 | 
			
		||||
| 
						 | 
				
			
			@ -358,6 +360,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
 | 
			
		|||
                            clickOutsideDeactivates: true,
 | 
			
		||||
                            isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                            isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                            escapeDeactivates: stopPropagation,
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          <Menu style={{ padding: config.space.S100 }}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
import { Box, Line } from 'folds';
 | 
			
		||||
import { useParams } from 'react-router-dom';
 | 
			
		||||
import { isKeyHotkey } from 'is-hotkey';
 | 
			
		||||
import { RoomView } from './RoomView';
 | 
			
		||||
import { MembersDrawer } from './MembersDrawer';
 | 
			
		||||
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +9,8 @@ import { useSetting } from '../../state/hooks/settings';
 | 
			
		|||
import { settingsAtom } from '../../state/settings';
 | 
			
		||||
import { PowerLevelsContextProvider, usePowerLevels } from '../../hooks/usePowerLevels';
 | 
			
		||||
import { useRoom } from '../../hooks/useRoom';
 | 
			
		||||
import { useKeyDown } from '../../hooks/useKeyDown';
 | 
			
		||||
import { markAsRead } from '../../../client/action/notifications';
 | 
			
		||||
 | 
			
		||||
export function Room() {
 | 
			
		||||
  const { eventId } = useParams();
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +20,18 @@ export function Room() {
 | 
			
		|||
  const screenSize = useScreenSizeContext();
 | 
			
		||||
  const powerLevels = usePowerLevels(room);
 | 
			
		||||
 | 
			
		||||
  useKeyDown(
 | 
			
		||||
    window,
 | 
			
		||||
    useCallback(
 | 
			
		||||
      (evt) => {
 | 
			
		||||
        if (isKeyHotkey('escape', evt)) {
 | 
			
		||||
          markAsRead(room.roomId);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      [room.roomId]
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <PowerLevelsContextProvider value={powerLevels}>
 | 
			
		||||
      <Box grow="Yes">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
import React, { useRef } from 'react';
 | 
			
		||||
import React, { useCallback, useRef } from 'react';
 | 
			
		||||
import { Box, Text, config } from 'folds';
 | 
			
		||||
import { EventType, Room } from 'matrix-js-sdk';
 | 
			
		||||
 | 
			
		||||
import { ReactEditor } from 'slate-react';
 | 
			
		||||
import { isKeyHotkey } from 'is-hotkey';
 | 
			
		||||
import { useStateEvent } from '../../hooks/useStateEvent';
 | 
			
		||||
import { StateEvent } from '../../../types/matrix/room';
 | 
			
		||||
import { usePowerLevelsAPI, usePowerLevelsContext } from '../../hooks/usePowerLevels';
 | 
			
		||||
| 
						 | 
				
			
			@ -15,10 +16,42 @@ import { RoomInput } from './RoomInput';
 | 
			
		|||
import { RoomViewFollowing } from './RoomViewFollowing';
 | 
			
		||||
import { Page } from '../../components/page';
 | 
			
		||||
import { RoomViewHeader } from './RoomViewHeader';
 | 
			
		||||
import { useKeyDown } from '../../hooks/useKeyDown';
 | 
			
		||||
import { editableActiveElement } from '../../utils/dom';
 | 
			
		||||
import navigation from '../../../client/state/navigation';
 | 
			
		||||
 | 
			
		||||
const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
 | 
			
		||||
  const { code } = evt;
 | 
			
		||||
  console.log(code);
 | 
			
		||||
  if (evt.metaKey || evt.altKey || evt.ctrlKey) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  // do not focus on F keys
 | 
			
		||||
  if (/^F\d+$/.test(code)) return false;
 | 
			
		||||
 | 
			
		||||
  // do not focus on numlock/scroll lock
 | 
			
		||||
  if (
 | 
			
		||||
    code.startsWith('OS') ||
 | 
			
		||||
    code.startsWith('Meta') ||
 | 
			
		||||
    code.startsWith('Shift') ||
 | 
			
		||||
    code.startsWith('Alt') ||
 | 
			
		||||
    code.startsWith('Control') ||
 | 
			
		||||
    code.startsWith('Arrow') ||
 | 
			
		||||
    code === 'Tab' ||
 | 
			
		||||
    code === 'Space' ||
 | 
			
		||||
    code === 'Enter' ||
 | 
			
		||||
    code === 'NumLock' ||
 | 
			
		||||
    code === 'ScrollLock'
 | 
			
		||||
  ) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
 | 
			
		||||
  const roomInputRef = useRef(null);
 | 
			
		||||
  const roomViewRef = useRef(null);
 | 
			
		||||
  const roomInputRef = useRef<HTMLDivElement>(null);
 | 
			
		||||
  const roomViewRef = useRef<HTMLDivElement>(null);
 | 
			
		||||
 | 
			
		||||
  const { roomId } = room;
 | 
			
		||||
  const editor = useEditor();
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +66,25 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
 | 
			
		|||
    ? canSendEvent(EventType.RoomMessage, getPowerLevel(myUserId))
 | 
			
		||||
    : false;
 | 
			
		||||
 | 
			
		||||
  useKeyDown(
 | 
			
		||||
    window,
 | 
			
		||||
    useCallback(
 | 
			
		||||
      (evt) => {
 | 
			
		||||
        if (editableActiveElement()) return;
 | 
			
		||||
        if (
 | 
			
		||||
          document.body.lastElementChild?.className !== 'ReactModalPortal' ||
 | 
			
		||||
          navigation.isRawModalVisible
 | 
			
		||||
        ) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (shouldFocusMessageField(evt) || isKeyHotkey('mod+v')) {
 | 
			
		||||
          ReactEditor.focus(editor);
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      [editor]
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Page ref={roomViewRef}>
 | 
			
		||||
      <RoomViewHeader />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import { useMatrixClient } from '../../hooks/useMatrixClient';
 | 
			
		|||
import { useRoomLatestRenderedEvent } from '../../hooks/useRoomLatestRenderedEvent';
 | 
			
		||||
import { useRoomEventReaders } from '../../hooks/useRoomEventReaders';
 | 
			
		||||
import { EventReaders } from '../../components/event-readers';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export type RoomViewFollowingProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,7 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>(
 | 
			
		|||
                  initialFocus: false,
 | 
			
		||||
                  onDeactivate: () => setOpen(false),
 | 
			
		||||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <Modal variant="Surface" size="300">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,7 @@ import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMet
 | 
			
		|||
import { mDirectAtom } from '../../state/mDirectList';
 | 
			
		||||
import { useClientConfig } from '../../hooks/useClientConfig';
 | 
			
		||||
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type RoomMenuProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +241,7 @@ export function RoomViewHeader() {
 | 
			
		|||
                            initialFocus: false,
 | 
			
		||||
                            clickOutsideDeactivates: true,
 | 
			
		||||
                            onDeactivate: () => setViewTopic(false),
 | 
			
		||||
                            escapeDeactivates: stopPropagation,
 | 
			
		||||
                          }}
 | 
			
		||||
                        >
 | 
			
		||||
                          <RoomTopicViewer
 | 
			
		||||
| 
						 | 
				
			
			@ -331,6 +333,7 @@ export function RoomViewHeader() {
 | 
			
		|||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <RoomMenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,6 +74,7 @@ import {
 | 
			
		|||
} from '../../../pages/pathUtils';
 | 
			
		||||
import { copyToClipboard } from '../../../utils/dom';
 | 
			
		||||
import { useClientConfig } from '../../../hooks/useClientConfig';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export type ReactionHandler = (keyOrMxc: string, shortcode: string) => void;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +149,7 @@ export const MessageAllReactionItem = as<
 | 
			
		|||
              returnFocusOnDeactivate: false,
 | 
			
		||||
              onDeactivate: () => handleClose(),
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Modal variant="Surface" size="300">
 | 
			
		||||
| 
						 | 
				
			
			@ -201,6 +203,7 @@ export const MessageReadReceiptItem = as<
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              onDeactivate: handleClose,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Modal variant="Surface" size="300">
 | 
			
		||||
| 
						 | 
				
			
			@ -278,6 +281,7 @@ export const MessageSourceCodeItem = as<
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              onDeactivate: handleClose,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Modal variant="Surface" size="500">
 | 
			
		||||
| 
						 | 
				
			
			@ -401,6 +405,7 @@ export const MessageDeleteItem = as<
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              onDeactivate: handleClose,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			@ -530,6 +535,7 @@ export const MessageReportItem = as<
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              onDeactivate: handleClose,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			@ -875,6 +881,7 @@ export const Message = as<'div', MessageProps>(
 | 
			
		|||
                        clickOutsideDeactivates: true,
 | 
			
		||||
                        isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                        isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                        escapeDeactivates: stopPropagation,
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <Menu>
 | 
			
		||||
| 
						 | 
				
			
			@ -1089,6 +1096,7 @@ export const Event = as<'div', EventProps>(
 | 
			
		|||
                        clickOutsideDeactivates: true,
 | 
			
		||||
                        isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                        isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                        escapeDeactivates: stopPropagation,
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <Menu {...props} ref={ref}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ import { Reaction, ReactionTooltipMsg } from '../../../components/message';
 | 
			
		|||
import { useRelations } from '../../../hooks/useRelations';
 | 
			
		||||
import * as css from './styles.css';
 | 
			
		||||
import { ReactionViewer } from '../reaction-viewer';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export type ReactionsProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -105,6 +106,7 @@ export const Reactions = as<'div', ReactionsProps>(
 | 
			
		|||
                  returnFocusOnDeactivate: false,
 | 
			
		||||
                  onDeactivate: () => setViewer(false),
 | 
			
		||||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <Modal variant="Surface" size="300">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import React, { useState, useEffect, useRef } from 'react';
 | 
			
		||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
 | 
			
		||||
import { useAtomValue } from 'jotai';
 | 
			
		||||
import './Search.scss';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,8 @@ import { roomToUnreadAtom } from '../../state/room/roomToUnread';
 | 
			
		|||
import { roomToParentsAtom } from '../../state/room/roomToParents';
 | 
			
		||||
import { allRoomsAtom } from '../../state/room-list/roomList';
 | 
			
		||||
import { mDirectAtom } from '../../state/mDirectList';
 | 
			
		||||
import { useKeyDown } from '../../hooks/useKeyDown';
 | 
			
		||||
import { openSearch } from '../../../client/action/navigation';
 | 
			
		||||
 | 
			
		||||
function useVisiblityToggle(setResult) {
 | 
			
		||||
  const [isOpen, setIsOpen] = useState(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +51,27 @@ function useVisiblityToggle(setResult) {
 | 
			
		|||
    }
 | 
			
		||||
  }, [isOpen]);
 | 
			
		||||
 | 
			
		||||
  useKeyDown(
 | 
			
		||||
    window,
 | 
			
		||||
    useCallback((event) => {
 | 
			
		||||
      // Ctrl/Cmd +
 | 
			
		||||
      if (event.ctrlKey || event.metaKey) {
 | 
			
		||||
        // open search modal
 | 
			
		||||
        if (event.key === 'k') {
 | 
			
		||||
          event.preventDefault();
 | 
			
		||||
          // means some menu or modal window is open
 | 
			
		||||
          if (
 | 
			
		||||
            document.body.lastChild.className !== 'ReactModalPortal' ||
 | 
			
		||||
            navigation.isRawModalVisible
 | 
			
		||||
          ) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          openSearch();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }, [])
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const requestClose = () => setIsOpen(false);
 | 
			
		||||
 | 
			
		||||
  return [isOpen, requestClose];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import {
 | 
			
		|||
import FocusTrap from 'focus-trap-react';
 | 
			
		||||
 | 
			
		||||
import { useDebounce } from '../../hooks/useDebounce';
 | 
			
		||||
import { stopPropagation } from '../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export function ServerPicker({
 | 
			
		||||
  server,
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +104,7 @@ export function ServerPicker({
 | 
			
		|||
                  clickOutsideDeactivates: true,
 | 
			
		||||
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                  escapeDeactivates: stopPropagation,
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <Menu>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ import {
 | 
			
		|||
import { PasswordInput } from '../../../components/password-input/PasswordInput';
 | 
			
		||||
import { FieldError } from '../FiledError';
 | 
			
		||||
import { getResetPasswordPath } from '../../pathUtils';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
function UsernameHint({ server }: { server: string }) {
 | 
			
		||||
  const [anchor, setAnchor] = useState<RectCords>();
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +55,7 @@ function UsernameHint({ server }: { server: string }) {
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: () => setAnchor(undefined),
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
import { Box, Spinner, Text } from 'folds';
 | 
			
		||||
import React, { ReactNode, useEffect, useState } from 'react';
 | 
			
		||||
import initMatrix from '../../../client/initMatrix';
 | 
			
		||||
import { initHotkeys } from '../../../client/event/hotkeys';
 | 
			
		||||
import { getSecret } from '../../../client/state/auth';
 | 
			
		||||
import { SplashScreen } from '../../components/splash-screen';
 | 
			
		||||
import { CapabilitiesAndMediaConfigLoader } from '../../components/CapabilitiesAndMediaConfigLoader';
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +46,6 @@ export function ClientRoot({ children }: ClientRootProps) {
 | 
			
		|||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const handleStart = () => {
 | 
			
		||||
      initHotkeys();
 | 
			
		||||
      setLoading(false);
 | 
			
		||||
    };
 | 
			
		||||
    initMatrix.once('init_loading_finished', handleStart);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@ import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page
 | 
			
		|||
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
 | 
			
		||||
import { useRoomsUnread } from '../../../state/hooks/unread';
 | 
			
		||||
import { markAsRead } from '../../../../client/action/notifications';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type DirectMenuProps = {
 | 
			
		||||
  requestClose: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +119,7 @@ function DirectHeader() {
 | 
			
		|||
              clickOutsideDeactivates: true,
 | 
			
		||||
              isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
              isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <DirectMenu requestClose={() => setMenuAnchor(undefined)} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ import { getMxIdServer } from '../../../utils/matrix';
 | 
			
		|||
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
 | 
			
		||||
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
 | 
			
		||||
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
export function AddServer() {
 | 
			
		||||
  const mx = useMatrixClient();
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +81,7 @@ export function AddServer() {
 | 
			
		|||
              initialFocus: false,
 | 
			
		||||
              clickOutsideDeactivates: true,
 | 
			
		||||
              onDeactivate: () => setDialog(false),
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Dialog variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,7 @@ import * as css from './style.css';
 | 
			
		|||
import { allRoomsAtom } from '../../../state/room-list/roomList';
 | 
			
		||||
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
 | 
			
		||||
import { getMxIdServer } from '../../../utils/matrix';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
const useServerSearchParams = (searchParams: URLSearchParams): ExploreServerPathSearchParams =>
 | 
			
		||||
  useMemo(
 | 
			
		||||
| 
						 | 
				
			
			@ -182,6 +183,7 @@ function ThirdPartyProtocolsSelector({
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: () => setMenuAnchor(undefined),
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			@ -277,6 +279,7 @@ function LimitButton({ limit, onLimitChange }: LimitButtonProps) {
 | 
			
		|||
            initialFocus: false,
 | 
			
		||||
            onDeactivate: () => setMenuAnchor(undefined),
 | 
			
		||||
            clickOutsideDeactivates: true,
 | 
			
		||||
            escapeDeactivates: stopPropagation,
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu variant="Surface">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,7 @@ import { PageNav, PageNavHeader, PageNavContent } from '../../../components/page
 | 
			
		|||
import { useRoomsUnread } from '../../../state/hooks/unread';
 | 
			
		||||
import { markAsRead } from '../../../../client/action/notifications';
 | 
			
		||||
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type HomeMenuProps = {
 | 
			
		||||
  requestClose: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +122,7 @@ function HomeHeader() {
 | 
			
		|||
              clickOutsideDeactivates: true,
 | 
			
		||||
              isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
              isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
              escapeDeactivates: stopPropagation,
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <HomeMenu requestClose={() => setMenuAnchor(undefined)} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ import { RoomAvatar } from '../../../components/room-avatar';
 | 
			
		|||
import { addRoomIdToMDirect, getMxIdLocalPart, guessDmRoomUserId } from '../../../utils/matrix';
 | 
			
		||||
import { Time } from '../../../components/message';
 | 
			
		||||
import { useElementSizeObserver } from '../../../hooks/useElementSizeObserver';
 | 
			
		||||
import { onEnterOrSpace } from '../../../utils/keyboard';
 | 
			
		||||
import { onEnterOrSpace, stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
import { RoomTopicViewer } from '../../../components/room-topic-viewer';
 | 
			
		||||
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
 | 
			
		||||
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
 | 
			
		||||
| 
						 | 
				
			
			@ -140,6 +140,7 @@ function InviteCard({ room, userId, direct, compact, onNavigate }: InviteCardPro
 | 
			
		|||
                      initialFocus: false,
 | 
			
		||||
                      clickOutsideDeactivates: true,
 | 
			
		||||
                      onDeactivate: closeTopic,
 | 
			
		||||
                      escapeDeactivates: stopPropagation,
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    <RoomTopicViewer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
 | 
			
		|||
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
 | 
			
		||||
import { useDirectRooms } from '../direct/useDirectRooms';
 | 
			
		||||
import { markAsRead } from '../../../../client/action/notifications';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type DirectMenuProps = {
 | 
			
		||||
  requestClose: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,6 +121,7 @@ export function DirectTab() {
 | 
			
		|||
                clickOutsideDeactivates: true,
 | 
			
		||||
                isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <DirectMenu requestClose={() => setMenuAnchor(undefined)} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
 | 
			
		|||
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
 | 
			
		||||
import { useHomeRooms } from '../home/useHomeRooms';
 | 
			
		||||
import { markAsRead } from '../../../../client/action/notifications';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type HomeMenuProps = {
 | 
			
		||||
  requestClose: () => void;
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +123,7 @@ export function HomeTab() {
 | 
			
		|||
                clickOutsideDeactivates: true,
 | 
			
		||||
                isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <HomeMenu requestClose={() => setMenuAnchor(undefined)} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,6 +90,7 @@ import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
 | 
			
		|||
import { markAsRead } from '../../../../client/action/notifications';
 | 
			
		||||
import { copyToClipboard } from '../../../utils/dom';
 | 
			
		||||
import { openInviteUser, openSpaceSettings } from '../../../../client/action/navigation';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type SpaceMenuProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -463,6 +464,7 @@ function SpaceTab({
 | 
			
		|||
                    clickOutsideDeactivates: true,
 | 
			
		||||
                    isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                    isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                    escapeDeactivates: stopPropagation,
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  <SpaceMenu
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,6 +73,7 @@ import { useClientConfig } from '../../../hooks/useClientConfig';
 | 
			
		|||
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
 | 
			
		||||
import { useStateEvent } from '../../../hooks/useStateEvent';
 | 
			
		||||
import { StateEvent } from '../../../../types/matrix/room';
 | 
			
		||||
import { stopPropagation } from '../../../utils/keyboard';
 | 
			
		||||
 | 
			
		||||
type SpaceMenuProps = {
 | 
			
		||||
  room: Room;
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +249,7 @@ function SpaceHeader() {
 | 
			
		|||
                clickOutsideDeactivates: true,
 | 
			
		||||
                isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
 | 
			
		||||
                isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
 | 
			
		||||
                escapeDeactivates: stopPropagation,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <SpaceMenu room={space} requestClose={() => setMenuAnchor(undefined)} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,3 +30,8 @@ export const onEnterOrSpace = (callback: () => void) => (evt: KeyboardEventLike)
 | 
			
		|||
    callback();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const stopPropagation = (evt: KeyboardEvent): boolean => {
 | 
			
		||||
  evt.stopPropagation();
 | 
			
		||||
  return true;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
import { openSearch } from '../action/navigation';
 | 
			
		||||
import navigation from '../state/navigation';
 | 
			
		||||
 | 
			
		||||
function listenKeyboard(event) {
 | 
			
		||||
  // Ctrl/Cmd +
 | 
			
		||||
  if (event.ctrlKey || event.metaKey) {
 | 
			
		||||
    // open search modal
 | 
			
		||||
    if (event.key === 'k') {
 | 
			
		||||
      event.preventDefault();
 | 
			
		||||
      if (navigation.isRawModalVisible) return;
 | 
			
		||||
      openSearch();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initHotkeys() {
 | 
			
		||||
  document.body.addEventListener('keydown', listenKeyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function removeHotkeys() {
 | 
			
		||||
  document.body.removeEventListener('keydown', listenKeyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { initHotkeys, removeHotkeys };
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue