CB-3546 add mac specific keys property (#1744)

* CB-3546 add mac specific keys property

* CB-3546 use common and OS specific keys, add windows keys

* CB-3546 remove label, use keys for label

---------

Co-authored-by: dariamarutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
This commit is contained in:
Tatiana Fokina
2023-06-20 14:02:11 +03:00
committed by GitHub
co-authored by dariamarutkina mr-anton-t
parent 3b8620cdfe
commit 869a87fa13
23 changed files with 141 additions and 40 deletions
@@ -11,7 +11,7 @@ import { MenuItem, MenuItemCheckbox, MenuItemRadio } from 'reakit/Menu';
import styled, { use } from 'reshadow';
import { Checkbox, MenuItemElement, menuPanelStyles, Radio, useStyles } from '@cloudbeaver/core-blocks';
import type { IMenuActionItem } from '@cloudbeaver/core-view';
import { getBindingLabel, IMenuActionItem } from '@cloudbeaver/core-view';
import type { IContextMenuItemProps } from './IContextMenuItemProps';
@@ -23,6 +23,10 @@ export const MenuActionElement = observer<IMenuActionElementProps>(function Menu
const styles = useStyles(menuPanelStyles, style);
const actionInfo = item.action.actionInfo;
const loading = item.action.isLoading();
let binding;
if (item.action.binding !== null) {
binding = getBindingLabel(item.action.binding.binding);
}
function handleClick() {
onClick();
@@ -84,7 +88,7 @@ export const MenuActionElement = observer<IMenuActionElementProps>(function Menu
<MenuItemElement
label={actionInfo.label}
icon={actionInfo.icon}
binding={item.action.binding?.binding.label}
binding={binding}
tooltip={actionInfo.tooltip}
loading={loading}
style={style}
+31
View File
@@ -0,0 +1,31 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2023 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export enum OperatingSystem {
windowsOS,
macOS,
linuxOS,
unixOS,
iOS,
androidOS,
}
export function getOS(): OperatingSystem {
const operatingSystemOptions: Array<[string, OperatingSystem]> = [
['Win', OperatingSystem.windowsOS],
['like Mac', OperatingSystem.iOS],
['Mac', OperatingSystem.macOS],
['Android', OperatingSystem.androidOS],
['Linux', OperatingSystem.linuxOS],
['X11', OperatingSystem.unixOS],
];
const userAgent = window.navigator.userAgent;
const OS = operatingSystemOptions.find(([testString]) => userAgent.includes(testString))?.[1] ?? OperatingSystem.windowsOS;
return OS;
}
+1
View File
@@ -18,6 +18,7 @@ export * from './isNotNullDefined';
export * from './flat';
export * from './generateFileName';
export * from './getMIME';
export * from './getOS';
export * from './getPathName';
export * from './getPathParent';
export * from './getPathParents';
@@ -9,7 +9,6 @@ import { createKeyBinding } from '../createKeyBinding';
export const KEY_BINDING_OPEN_IN_TAB = createKeyBinding({
id: 'open-in-tab',
label: 'Alt + T',
keys: 'alt+t',
preventDefault: true,
});
@@ -9,7 +9,7 @@ import { createKeyBinding } from '../createKeyBinding';
export const KEY_BINDING_REDO = createKeyBinding({
id: 'redo',
label: 'Ctrl + Y',
keys: ['ctrl+y', 'ctrl+shift+z', 'shift+cmd+z', 'cmd+y'],
keys: ['ctrl+y', 'ctrl+shift+z'],
keysMac: ['shift+cmd+z', 'cmd+y'],
preventDefault: true,
});
@@ -9,7 +9,7 @@ import { createKeyBinding } from '../createKeyBinding';
export const KEY_BINDING_UNDO = createKeyBinding({
id: 'undo',
label: 'Ctrl + Z',
keys: ['ctrl+z', 'cmd+z'],
keys: 'ctrl+z',
keysMac: 'cmd+z',
preventDefault: true,
});
@@ -8,7 +8,8 @@
export interface IKeyBinding {
id: string;
label: string;
preventDefault?: boolean;
keys: string | string[];
keys?: string | string[];
keysWin?: string | string[];
keysMac?: string | string[];
}
@@ -9,9 +9,10 @@ import type { IKeyBinding } from './IKeyBinding';
interface IKeyBindingOptions {
id: string;
label: string;
preventDefault?: boolean;
keys: string | string[];
keys?: string | string[];
keysWin?: string | string[];
keysMac?: string | string[];
}
export function createKeyBinding(options: IKeyBindingOptions): IKeyBinding {
@@ -0,0 +1,18 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2023 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { getOSSpecificKeys } from './getCommonAndOSSpecificKeys';
import type { IKeyBinding } from './IKeyBinding';
export function getBindingLabel(binding: IKeyBinding) {
let bindingLabel = getOSSpecificKeys(binding) ?? binding.keys;
if (Array.isArray(bindingLabel)) {
bindingLabel = bindingLabel[0];
}
return bindingLabel?.replace(/\+/g, ' + ').replace(/\b\w/g, letter => letter.toUpperCase());
}
@@ -0,0 +1,45 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2023 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { getOS, OperatingSystem } from '@cloudbeaver/core-utils';
import type { IKeyBinding } from './IKeyBinding';
export function getCommonAndOSSpecificKeys(keyBinding: IKeyBinding | undefined): string[] {
if (keyBinding === undefined) {
return [];
}
const specificKeys = getOSSpecificKeys(keyBinding);
let keys: string[] = [];
if (keyBinding.keys !== undefined) {
keys = Array.isArray(keyBinding.keys) ? keyBinding.keys : [keyBinding.keys];
}
if (specificKeys !== undefined) {
if (Array.isArray(specificKeys)) {
keys.push(...specificKeys);
} else {
keys.push(specificKeys);
}
}
return keys;
}
export function getOSSpecificKeys(keyBinding: IKeyBinding): string | string[] | undefined {
const OS = getOS();
if (OS === OperatingSystem.windowsOS) {
return keyBinding.keysWin;
}
if (OS === OperatingSystem.macOS) {
return keyBinding.keysMac;
}
return undefined;
}
@@ -15,6 +15,7 @@ import { useService } from '@cloudbeaver/core-di';
import { ActionService } from '../Action/ActionService';
import type { IActionItem } from '../Action/IActionItem';
import { getCommonAndOSSpecificKeys } from '../Action/KeyBinding/getCommonAndOSSpecificKeys';
import { CaptureViewContext } from './CaptureViewContext';
import type { IView } from './IView';
import { useActiveView } from './useActiveView';
@@ -44,7 +45,7 @@ export const CaptureView = observer<React.PropsWithChildren<Props>>(function Cap
.filter(Boolean) as IActionItem[];
let keys = actionItems
.map(item => item.binding?.binding.keys)
.map(item => getCommonAndOSSpecificKeys(item.binding?.binding))
.flat()
.join(', ');
@@ -59,7 +60,10 @@ export const CaptureView = observer<React.PropsWithChildren<Props>>(function Cap
return;
}
const action = actionItems.find(action => action.binding?.binding.keys === handler.key || action.binding?.binding.keys.includes(handler.key));
const action = actionItems.find(action => {
const commonAndSpecificKeys = getCommonAndOSSpecificKeys(action.binding?.binding);
return commonAndSpecificKeys.includes(handler.key);
});
if (action?.binding?.binding.preventDefault) {
event.preventDefault();
+3
View File
@@ -26,6 +26,9 @@ export * from './Action/IAction';
export * from './Action/IActionHandler';
export * from './Action/IActionInfo';
export * from './Action/IActionItem';
export * from './Action/KeyBinding/IKeyBinding';
export * from './Action/KeyBinding/getCommonAndOSSpecificKeys';
export * from './Action/KeyBinding/getBindingLabel';
export * from './DataContext/createDataContext';
export * from './DataContext/DataContext';
export * from './DataContext/DynamicDataContext';
@@ -5,7 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { KEY_BINDING_OPEN_IN_TAB, KEY_BINDING_REDO, KEY_BINDING_UNDO } from '@cloudbeaver/core-view';
import { getCommonAndOSSpecificKeys, IKeyBinding, KEY_BINDING_OPEN_IN_TAB, KEY_BINDING_REDO, KEY_BINDING_UNDO } from '@cloudbeaver/core-view';
import { KEY_BINDING_COLLAPSE_ALL, KEY_BINDING_ENABLE_FILTER, KEY_BINDING_LINK_OBJECT } from '@cloudbeaver/plugin-navigation-tree';
import {
KEY_BINDING_SQL_EDITOR_EXECUTE,
@@ -51,57 +51,55 @@ export const DATA_VIEWER_SHORTCUTS: IShortcut[] = [
export const SQL_EDITOR_SHORTCUTS: IShortcut[] = [
{
label: 'sql_editor_shortcut_execute_statement',
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE.keys),
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE),
},
{
label: 'sql_editor_shortcut_execute_statement_new_tab',
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE_NEW.keys),
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE_NEW),
},
{
label: 'sql_editor_shortcut_execute_script',
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE_SCRIPT.keys),
code: transformKeys(KEY_BINDING_SQL_EDITOR_EXECUTE_SCRIPT),
},
{
label: 'sql_editor_shortcut_show_execution_plan',
code: transformKeys(KEY_BINDING_SQL_EDITOR_SHOW_EXECUTION_PLAN.keys),
code: transformKeys(KEY_BINDING_SQL_EDITOR_SHOW_EXECUTION_PLAN),
},
{
label: 'sql_editor_shortcut_format',
code: transformKeys(KEY_BINDING_SQL_EDITOR_FORMAT.keys),
code: transformKeys(KEY_BINDING_SQL_EDITOR_FORMAT),
},
{
label: 'sql_editor_shortcut_undo',
code: transformKeys(KEY_BINDING_UNDO.keys),
code: transformKeys(KEY_BINDING_UNDO),
},
{
label: 'sql_editor_shortcut_redo',
code: transformKeys(KEY_BINDING_REDO.keys),
code: transformKeys(KEY_BINDING_REDO),
},
{
label: 'sql_editor_shortcut_open_editor_in_new_tab',
code: transformKeys(KEY_BINDING_OPEN_IN_TAB.keys),
code: transformKeys(KEY_BINDING_OPEN_IN_TAB),
},
];
export const NAVIGATION_TREE_SHORTCUTS: IShortcut[] = [
{
label: 'navigation_tree_shortcut_enable_filter',
code: transformKeys(KEY_BINDING_ENABLE_FILTER.keys),
code: transformKeys(KEY_BINDING_ENABLE_FILTER),
},
{
label: 'app_navigationTree_action_collapse_all',
code: transformKeys(KEY_BINDING_COLLAPSE_ALL.keys),
code: transformKeys(KEY_BINDING_COLLAPSE_ALL),
},
{
label: 'app_navigationTree_action_link_with_editor',
code: transformKeys(KEY_BINDING_LINK_OBJECT.keys),
code: transformKeys(KEY_BINDING_LINK_OBJECT),
},
];
function transformKeys(keys: string | string[]): string[] {
if (!Array.isArray(keys)) {
keys = [keys];
}
function transformKeys(keyBinding: IKeyBinding): string[] {
const keys = getCommonAndOSSpecificKeys(keyBinding);
return keys.map(key => key.toLocaleUpperCase().replace(/\+/gi, ' + '));
}
@@ -7,7 +7,7 @@
*/
import styled, { css } from 'reshadow';
import { useStyles, useTranslate } from '@cloudbeaver/core-blocks';
import { useTranslate } from '@cloudbeaver/core-blocks';
import type { IShortcut } from './IShortcut';
@@ -13,6 +13,7 @@ import {
ACTION_FILTER,
ActionService,
DATA_CONTEXT_MENU,
getBindingLabel,
IAction,
IDataContextProvider,
KeyBindingService,
@@ -60,14 +61,17 @@ export class ElementsTreeToolsMenuService {
getActionInfo: (context, action) => {
switch (action) {
case ACTION_LINK_OBJECT: {
const tooltip = this.localizationService.translate('app_navigationTree_action_link_with_editor') + ` (${KEY_BINDING_LINK_OBJECT.label})`;
const bindingLabel = getBindingLabel(KEY_BINDING_LINK_OBJECT);
const tooltip =
this.localizationService.translate('app_navigationTree_action_link_with_editor') + (bindingLabel ? ` (${bindingLabel})` : '');
return {
...action.info,
tooltip,
};
}
case ACTION_COLLAPSE_ALL: {
const tooltip = this.localizationService.translate('app_navigationTree_action_collapse_all') + ` (${KEY_BINDING_COLLAPSE_ALL.label})`;
const bindingLabel = getBindingLabel(KEY_BINDING_COLLAPSE_ALL);
const tooltip = this.localizationService.translate('app_navigationTree_action_collapse_all') + (bindingLabel ? ` (${bindingLabel})` : '');
return {
...action.info,
tooltip,
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_ENABLE_FILTER = createKeyBinding({
id: 'enable-filter',
label: 'Ctrl + F',
keys: 'ctrl+f',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_COLLAPSE_ALL = createKeyBinding({
id: 'collapse-all',
label: 'Ctrl + Shift + /',
keys: 'ctrl+shift+/',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_LINK_OBJECT = createKeyBinding({
id: 'link-object',
label: 'Ctrl + Shift + ,',
keys: 'ctrl+shift+,',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_SQL_EDITOR_EXECUTE = createKeyBinding({
id: 'sql-editor-execute',
label: 'Ctrl + Enter',
keys: 'ctrl+enter',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_SQL_EDITOR_EXECUTE_NEW = createKeyBinding({
id: 'sql-editor-execute-new',
label: 'Ctrl + \\ or Shift + Ctrl + Enter',
keys: ['ctrl+\\', 'shift+ctrl+enter'],
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_SQL_EDITOR_EXECUTE_SCRIPT = createKeyBinding({
id: 'sql-editor-execute-script',
label: 'Alt + X',
keys: 'alt+x',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_SQL_EDITOR_FORMAT = createKeyBinding({
id: 'sql-editor-format',
label: 'Shift + Ctrl + F',
keys: 'shift+ctrl+f',
preventDefault: true,
});
@@ -9,7 +9,6 @@ import { createKeyBinding } from '@cloudbeaver/core-view';
export const KEY_BINDING_SQL_EDITOR_SHOW_EXECUTION_PLAN = createKeyBinding({
id: 'sql-editor-show-execution-plan',
label: 'Shift + Ctrl + E',
keys: 'shift+ctrl+e',
preventDefault: true,
});