From abe09a9476f711fa3ff049cbbf5220f1d37bb5ff Mon Sep 17 00:00:00 2001 From: Wroud Date: Fri, 19 Nov 2021 20:20:29 +0300 Subject: [PATCH] fix: CB-1439 keybinding --- webapp/package.json | 2 +- webapp/packages/core-app/src/Body.tsx | 27 +++++++---- .../Bindings/KEY_BINDING_OPEN_IN_TAB.ts | 3 +- .../src/Action/KeyBinding/IKeyBinding.ts | 1 + .../src/Action/KeyBinding/createKeyBinding.ts | 1 + .../core-view/src/View/CaptureView.tsx | 48 ++++++++++--------- webapp/yarn.lock | 17 ++++--- 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index 7902481a55..43ba721f92 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -45,7 +45,7 @@ "preact-ssr-prepass": "^1.2.0", "react": "^17.0.2", "react-dom": "^17.0.2", - "react-hotkeys": "^2.0.0", + "react-hotkeys-hook": "^3.4.4", "reakit": "^1.3.10", "reflect-metadata": "^0.1.13", "reshadow": "^0.0.1-alpha.80", diff --git a/webapp/packages/core-app/src/Body.tsx b/webapp/packages/core-app/src/Body.tsx index 40060855b4..99538a26e0 100644 --- a/webapp/packages/core-app/src/Body.tsx +++ b/webapp/packages/core-app/src/Body.tsx @@ -16,19 +16,26 @@ import { DialogsPortal } from '@cloudbeaver/core-dialogs'; import { Notifications } from '@cloudbeaver/core-notifications'; import { PermissionsResource } from '@cloudbeaver/core-root'; import { ScreenService } from '@cloudbeaver/core-routing'; -import { useStyles } from '@cloudbeaver/core-theming'; +import { composes, useStyles } from '@cloudbeaver/core-theming'; import { useAppVersion } from './useAppVersion'; -const bodyStyles = css` - theme { - height: 100vh; - display: flex; - padding: 0 !important; /* fix additional padding with modal reakit menu */ - flex-direction: column; - overflow: hidden; - } -`; +const bodyStyles = composes( + css` + theme { + composes: theme-background-surface theme-text-on-surface from global + } + `, + css` + theme { + height: 100vh; + display: flex; + padding: 0 !important; /* fix additional padding with modal reakit menu */ + flex-direction: column; + overflow: hidden; + } + ` +); export const Body = observer(function Body() { useAppLoadingScreen(); diff --git a/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_OPEN_IN_TAB.ts b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_OPEN_IN_TAB.ts index 90aa64f09e..3ee9f85ceb 100644 --- a/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_OPEN_IN_TAB.ts +++ b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_OPEN_IN_TAB.ts @@ -11,5 +11,6 @@ import { createKeyBinding } from '../createKeyBinding'; export const KEY_BINDING_OPEN_IN_TAB = createKeyBinding({ id: 'open-in-tab', label: 'ui_rename', - keys: 'Alt+t', + keys: 'alt+t', + preventDefault: true, }); diff --git a/webapp/packages/core-view/src/Action/KeyBinding/IKeyBinding.ts b/webapp/packages/core-view/src/Action/KeyBinding/IKeyBinding.ts index 972bc57642..0963cee744 100644 --- a/webapp/packages/core-view/src/Action/KeyBinding/IKeyBinding.ts +++ b/webapp/packages/core-view/src/Action/KeyBinding/IKeyBinding.ts @@ -9,5 +9,6 @@ export interface IKeyBinding { id: string; label: string; + preventDefault?: boolean; keys: string | string[]; } diff --git a/webapp/packages/core-view/src/Action/KeyBinding/createKeyBinding.ts b/webapp/packages/core-view/src/Action/KeyBinding/createKeyBinding.ts index ec8a89fbf0..b5b0b432a0 100644 --- a/webapp/packages/core-view/src/Action/KeyBinding/createKeyBinding.ts +++ b/webapp/packages/core-view/src/Action/KeyBinding/createKeyBinding.ts @@ -11,6 +11,7 @@ import type { IKeyBinding } from './IKeyBinding'; interface IKeyBindingOptions { id: string; label: string; + preventDefault?: boolean; keys: string | string[]; } diff --git a/webapp/packages/core-view/src/View/CaptureView.tsx b/webapp/packages/core-view/src/View/CaptureView.tsx index 41873230e1..0f29588032 100644 --- a/webapp/packages/core-view/src/View/CaptureView.tsx +++ b/webapp/packages/core-view/src/View/CaptureView.tsx @@ -7,7 +7,7 @@ */ import { observer } from 'mobx-react-lite'; -import { HotKeys, configure } from 'react-hotkeys'; +import { useHotkeys } from 'react-hotkeys-hook'; import styled, { css } from 'reshadow'; import { getComputed, useFocus } from '@cloudbeaver/core-blocks'; @@ -20,10 +20,6 @@ import type { IView } from './IView'; import { useActiveView } from './useActiveView'; import { useViewContext } from './useViewContext'; -configure({ - ignoreTags: [], -}); - const styles = css` div { outline: none; @@ -48,31 +44,39 @@ export const CaptureView = observer(function CaptureView({ const actionItems = getComputed(() => ( view.actions .map(action => actionService.getAction(viewContext, action)) + .filter(action => action?.binding && !action.isDisabled()) .filter(Boolean) as IActionItem[] )); - const keyMap = actionItems.reduce((map, item) => ({ - ...map, - [item.binding!.id]: item.binding?.binding.keys, - }), {}); + const keys = actionItems + .map(item => item.binding?.binding.keys) + .flat() + .join(','); - const handlers = actionItems.reduce((map, item) => ({ - ...map, - [item.binding!.id]: () => item.activate(true), - }), {}); + useHotkeys(keys, (event, handler) => { + if (!ref.current?.contains(document.activeElement)) { + return; + } + + const action = actionItems.find(action => ( + action.binding?.binding.keys === handler.key + || action.binding?.binding.keys.includes(handler.key) + )); + + if (action?.binding?.binding.preventDefault) { + event.preventDefault(); + } + + action?.activate(true); + }, { + enableOnTags: ['INPUT', 'SELECT', 'TEXTAREA'], + }); return styled(styles)( - +
{children} - +
); }); diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 683837b7a4..22011f6148 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -7329,6 +7329,11 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" +hotkeys-js@3.8.7: + version "3.8.7" + resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.8.7.tgz#c16cab978b53d7242f860ca3932e976b92399981" + integrity sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg== + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -11107,7 +11112,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -11272,12 +11277,12 @@ react-fast-compare@^3.0.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-hotkeys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-hotkeys/-/react-hotkeys-2.0.0.tgz#a7719c7340cbba888b0e9184f806a9ec0ac2c53f" - integrity sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q== +react-hotkeys-hook@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-3.4.4.tgz#52ba5d8ef5e47cc2e776c70a9036d518e0993d51" + integrity sha512-vaORq07rWgmuF3owWRhgFV/3VL8/l2q9lz0WyVEddJnWTtKW+AOgU5YgYKuwN6h6h7bCcLG3MFsJIjCrM/5DvQ== dependencies: - prop-types "^15.6.1" + hotkeys-js "3.8.7" react-is@^16.8.1: version "16.13.1"