Optimized patch

main
Boris Sekachev 6 years ago
parent ba97952801
commit bed93e2a6e

@ -33,6 +33,7 @@ interface StateToProps {
labels: any[]; labels: any[];
jobInstance: any; jobInstance: any;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
} }
interface DispatchToProps { interface DispatchToProps {
@ -59,6 +60,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
}, },
shortcuts: { shortcuts: {
keyMap, keyMap,
normalizedKeyMap,
}, },
} = state; } = state;
@ -69,6 +71,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
activatedAttributeID, activatedAttributeID,
states, states,
keyMap, keyMap,
normalizedKeyMap,
}; };
} }
@ -93,6 +96,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
updateAnnotations, updateAnnotations,
activateObject, activateObject,
keyMap, keyMap,
normalizedKeyMap,
} = props; } = props;
const [labelAttrMap, setLabelAttrMap] = useState( const [labelAttrMap, setLabelAttrMap] = useState(
@ -226,7 +230,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
occluded={activeObjectState.occluded} occluded={activeObjectState.occluded}
objectsCount={states.length} objectsCount={states.length}
currentIndex={states.indexOf(activeObjectState)} currentIndex={states.indexOf(activeObjectState)}
keyMap={keyMap} normalizedKeyMap={normalizedKeyMap}
nextObject={nextObject} nextObject={nextObject}
/> />
<ObjectBasicsEditor <ObjectBasicsEditor
@ -254,7 +258,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
currentIndex={activeObjectState.label.attributes currentIndex={activeObjectState.label.attributes
.indexOf(activeAttribute)} .indexOf(activeAttribute)}
attributesCount={activeObjectState.label.attributes.length} attributesCount={activeObjectState.label.attributes.length}
keyMap={keyMap} normalizedKeyMap={normalizedKeyMap}
nextAttribute={nextAttribute} nextAttribute={nextAttribute}
/> />
<AttributeEditor <AttributeEditor

@ -3,19 +3,16 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import Icon from 'antd/lib/icon'; import Icon from 'antd/lib/icon';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import { formatShortcuts } from 'utils/shortcuts';
interface Props { interface Props {
currentAttribute: string; currentAttribute: string;
currentIndex: number; currentIndex: number;
attributesCount: number; attributesCount: number;
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
nextAttribute(step: number): void; nextAttribute(step: number): void;
} }
@ -25,13 +22,13 @@ function AttributeSwitcher(props: Props): JSX.Element {
currentIndex, currentIndex,
attributesCount, attributesCount,
nextAttribute, nextAttribute,
keyMap, normalizedKeyMap,
} = props; } = props;
const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`; const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`;
return ( return (
<div className='attribute-annotation-sidebar-switcher'> <div className='attribute-annotation-sidebar-switcher'>
<Tooltip title={`Previous attribute ${formatShortcuts(keyMap.PREVIOUS_ATTRIBUTE)}`}> <Tooltip title={`Previous attribute ${normalizedKeyMap.PREVIOUS_ATTRIBUTE}`}>
<Button disabled={attributesCount <= 1} onClick={() => nextAttribute(-1)}> <Button disabled={attributesCount <= 1} onClick={() => nextAttribute(-1)}>
<Icon type='left' /> <Icon type='left' />
</Button> </Button>
@ -40,7 +37,7 @@ function AttributeSwitcher(props: Props): JSX.Element {
<Text className='cvat-text'>{currentAttribute}</Text> <Text className='cvat-text'>{currentAttribute}</Text>
<Text strong>{` [${currentIndex + 1}/${attributesCount}]`}</Text> <Text strong>{` [${currentIndex + 1}/${attributesCount}]`}</Text>
</Tooltip> </Tooltip>
<Tooltip title={`Next attribute ${formatShortcuts(keyMap.NEXT_ATTRIBUTE)}`}> <Tooltip title={`Next attribute ${normalizedKeyMap.NEXT_ATTRIBUTE}`}>
<Button disabled={attributesCount <= 1} onClick={() => nextAttribute(1)}> <Button disabled={attributesCount <= 1} onClick={() => nextAttribute(1)}>
<Icon type='right' /> <Icon type='right' />
</Button> </Button>

@ -3,21 +3,18 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import Icon from 'antd/lib/icon'; import Icon from 'antd/lib/icon';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import { formatShortcuts } from 'utils/shortcuts';
interface Props { interface Props {
currentLabel: string; currentLabel: string;
clientID: number; clientID: number;
occluded: boolean; occluded: boolean;
objectsCount: number; objectsCount: number;
currentIndex: number; currentIndex: number;
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
nextObject(step: number): void; nextObject(step: number): void;
} }
@ -28,14 +25,14 @@ function ObjectSwitcher(props: Props): JSX.Element {
objectsCount, objectsCount,
currentIndex, currentIndex,
nextObject, nextObject,
keyMap, normalizedKeyMap,
} = props; } = props;
const title = `${currentLabel} ${clientID} [${currentIndex + 1}/${objectsCount}]`; const title = `${currentLabel} ${clientID} [${currentIndex + 1}/${objectsCount}]`;
return ( return (
<div className='attribute-annotation-sidebar-switcher'> <div className='attribute-annotation-sidebar-switcher'>
<Tooltip title={`Previous object ${formatShortcuts(keyMap.PREVIOUS_OBJECT)}`}> <Tooltip title={`Previous object ${normalizedKeyMap.PREVIOUS_OBJECT}`}>
<Button disabled={objectsCount <= 1} onClick={() => nextObject(-1)}> <Button disabled={objectsCount <= 1} onClick={() => nextObject(-1)}>
<Icon type='left' /> <Icon type='left' />
</Button> </Button>
@ -45,7 +42,7 @@ function ObjectSwitcher(props: Props): JSX.Element {
<Text className='cvat-text'>{` ${clientID} `}</Text> <Text className='cvat-text'>{` ${clientID} `}</Text>
<Text strong>{`[${currentIndex + 1}/${objectsCount}]`}</Text> <Text strong>{`[${currentIndex + 1}/${objectsCount}]`}</Text>
</Tooltip> </Tooltip>
<Tooltip title={`Next object ${formatShortcuts(keyMap.NEXT_OBJECT)}`}> <Tooltip title={`Next object ${normalizedKeyMap.NEXT_OBJECT}`}>
<Button disabled={objectsCount <= 1} onClick={() => nextObject(1)}> <Button disabled={objectsCount <= 1} onClick={() => nextObject(1)}>
<Icon type='right' /> <Icon type='right' />
</Button> </Button>

@ -8,7 +8,6 @@ import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces'; import { ActiveControl, Rotation } from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas'; import { Canvas } from 'cvat-canvas';
import { formatShortcuts } from 'utils/shortcuts';
import RotateControl from './rotate-control'; import RotateControl from './rotate-control';
import CursorControl from './cursor-control'; import CursorControl from './cursor-control';
@ -28,6 +27,7 @@ interface Props {
canvasInstance: Canvas; canvasInstance: Canvas;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
mergeObjects(enabled: boolean): void; mergeObjects(enabled: boolean): void;
groupObjects(enabled: boolean): void; groupObjects(enabled: boolean): void;
@ -50,6 +50,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
repeatDrawShape, repeatDrawShape,
pasteShape, pasteShape,
resetGroup, resetGroup,
normalizedKeyMap,
keyMap, keyMap,
} = props; } = props;
@ -142,14 +143,14 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
> >
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<CursorControl <CursorControl
cursorShortkey={formatShortcuts(keyMap.CANCEL)} cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance} canvasInstance={canvasInstance}
activeControl={activeControl} activeControl={activeControl}
/> />
<MoveControl canvasInstance={canvasInstance} activeControl={activeControl} /> <MoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
<RotateControl <RotateControl
anticlockwiseShortcut={formatShortcuts(keyMap.ANTICLOCKWISE_ROTATION)} anticlockwiseShortcut={normalizedKeyMap.ANTICLOCKWISE_ROTATION}
clockwiseShortcut={formatShortcuts(keyMap.CLOCKWISE_ROTATION)} clockwiseShortcut={normalizedKeyMap.CLOCKWISE_ROTATION}
rotateFrame={rotateFrame} rotateFrame={rotateFrame}
/> />
@ -185,14 +186,14 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
<hr /> <hr />
<MergeControl <MergeControl
switchMergeShortcut={formatShortcuts(keyMap.SWITCH_MERGE_MODE)} switchMergeShortcut={normalizedKeyMap.SWITCH_MERGE_MODE}
canvasInstance={canvasInstance} canvasInstance={canvasInstance}
activeControl={activeControl} activeControl={activeControl}
mergeObjects={mergeObjects} mergeObjects={mergeObjects}
/> />
<GroupControl <GroupControl
switchGroupShortcut={formatShortcuts(keyMap.SWITCH_GROUP_MODE)} switchGroupShortcut={normalizedKeyMap.SWITCH_GROUP_MODE}
resetGroupShortcut={formatShortcuts(keyMap.RESET_GROUP)} resetGroupShortcut={normalizedKeyMap.RESET_GROUP}
canvasInstance={canvasInstance} canvasInstance={canvasInstance}
activeControl={activeControl} activeControl={activeControl}
groupObjects={groupObjects} groupObjects={groupObjects}

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import Icon from 'antd/lib/icon'; import Icon from 'antd/lib/icon';
import Select from 'antd/lib/select'; import Select from 'antd/lib/select';
@ -34,7 +33,6 @@ import {
import { ObjectType, ShapeType } from 'reducers/interfaces'; import { ObjectType, ShapeType } from 'reducers/interfaces';
import { clamp } from 'utils/math'; import { clamp } from 'utils/math';
import { formatShortcuts } from 'utils/shortcuts';
function ItemMenu( function ItemMenu(
serverID: number | undefined, serverID: number | undefined,
@ -675,7 +673,7 @@ function ItemAttributesComponent(props: ItemAttributesComponentProps): JSX.Eleme
const ItemAttributes = React.memo(ItemAttributesComponent, attrAreTheSame); const ItemAttributes = React.memo(ItemAttributesComponent, attrAreTheSame);
interface Props { interface Props {
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
activated: boolean; activated: boolean;
objectType: ObjectType; objectType: ObjectType;
shapeType: ShapeType; shapeType: ShapeType;
@ -742,7 +740,7 @@ function objectItemsAreEqual(prevProps: Props, nextProps: Props): boolean {
&& nextProps.collapsed === prevProps.collapsed && nextProps.collapsed === prevProps.collapsed
&& nextProps.labels === prevProps.labels && nextProps.labels === prevProps.labels
&& nextProps.attributes === prevProps.attributes && nextProps.attributes === prevProps.attributes
&& nextProps.keyMap === prevProps.keyMap && nextProps.normalizedKeyMap === prevProps.normalizedKeyMap
&& nextProps.navigateFirstKeyframe === prevProps.navigateFirstKeyframe && nextProps.navigateFirstKeyframe === prevProps.navigateFirstKeyframe
&& nextProps.navigatePrevKeyframe === prevProps.navigatePrevKeyframe && nextProps.navigatePrevKeyframe === prevProps.navigatePrevKeyframe
&& nextProps.navigateNextKeyframe === prevProps.navigateNextKeyframe && nextProps.navigateNextKeyframe === prevProps.navigateNextKeyframe
@ -771,7 +769,7 @@ function ObjectItemComponent(props: Props): JSX.Element {
attributes, attributes,
labels, labels,
collapsed, collapsed,
keyMap, normalizedKeyMap,
navigateFirstKeyframe, navigateFirstKeyframe,
navigatePrevKeyframe, navigatePrevKeyframe,
navigateNextKeyframe, navigateNextKeyframe,
@ -839,12 +837,12 @@ function ObjectItemComponent(props: Props): JSX.Element {
objectType={objectType} objectType={objectType}
type={type} type={type}
locked={locked} locked={locked}
copyShortcut={formatShortcuts(keyMap.COPY_SHAPE)} copyShortcut={normalizedKeyMap.COPY_SHAPE}
pasteShortcut={formatShortcuts(keyMap.PASTE_SHAPE)} pasteShortcut={normalizedKeyMap.PASTE_SHAPE}
propagateShortcut={formatShortcuts(keyMap.PROPAGATE_OBJECT)} propagateShortcut={normalizedKeyMap.PROPAGATE_OBJECT}
toBackgroundShortcut={formatShortcuts(keyMap.TO_BACKGROUND)} toBackgroundShortcut={normalizedKeyMap.TO_BACKGROUND}
toForegroundShortcut={formatShortcuts(keyMap.TO_FOREGROUND)} toForegroundShortcut={normalizedKeyMap.TO_FOREGROUND}
removeShortcut={formatShortcuts(keyMap.DELETE_OBJECT)} removeShortcut={normalizedKeyMap.DELETE_OBJECT}
changeLabel={changeLabel} changeLabel={changeLabel}
copy={copy} copy={copy}
remove={remove} remove={remove}
@ -862,13 +860,13 @@ function ObjectItemComponent(props: Props): JSX.Element {
pinned={pinned} pinned={pinned}
hidden={hidden} hidden={hidden}
keyframe={keyframe} keyframe={keyframe}
switchOccludedShortcut={formatShortcuts(keyMap.SWITCH_OCCLUDED)} switchOccludedShortcut={normalizedKeyMap.SWITCH_OCCLUDED}
switchOutsideShortcut={formatShortcuts(keyMap.SWITCH_OUTSIDE)} switchOutsideShortcut={normalizedKeyMap.SWITCH_OUTSIDE}
switchLockShortcut={formatShortcuts(keyMap.SWITCH_LOCK)} switchLockShortcut={normalizedKeyMap.SWITCH_LOCK}
switchHiddenShortcut={formatShortcuts(keyMap.SWITCH_HIDDEN)} switchHiddenShortcut={normalizedKeyMap.SWITCH_HIDDEN}
switchKeyFrameShortcut={formatShortcuts(keyMap.SWITCH_KEYFRAME)} switchKeyFrameShortcut={normalizedKeyMap.SWITCH_KEYFRAME}
nextKeyFrameShortcut={formatShortcuts(keyMap.NEXT_KEY_FRAME)} nextKeyFrameShortcut={normalizedKeyMap.NEXT_KEY_FRAME}
prevKeyFrameShortcut={formatShortcuts(keyMap.PREV_KEY_FRAME)} prevKeyFrameShortcut={normalizedKeyMap.PREV_KEY_FRAME}
navigateFirstKeyframe={navigateFirstKeyframe} navigateFirstKeyframe={navigateFirstKeyframe}
navigatePrevKeyframe={navigatePrevKeyframe} navigatePrevKeyframe={navigatePrevKeyframe}
navigateNextKeyframe={navigateNextKeyframe} navigateNextKeyframe={navigateNextKeyframe}

@ -23,6 +23,7 @@ interface StateToProps {
rotateAll: boolean; rotateAll: boolean;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
} }
interface DispatchToProps { interface DispatchToProps {
@ -50,6 +51,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
}, },
shortcuts: { shortcuts: {
keyMap, keyMap,
normalizedKeyMap,
}, },
} = state; } = state;
@ -57,6 +59,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
rotateAll, rotateAll,
canvasInstance, canvasInstance,
activeControl, activeControl,
normalizedKeyMap,
keyMap, keyMap,
}; };
} }

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { RadioChangeEvent } from 'antd/lib/radio'; import { RadioChangeEvent } from 'antd/lib/radio';
@ -11,7 +10,6 @@ import { CombinedState, ShapeType, ObjectType } from 'reducers/interfaces';
import { rememberObject } from 'actions/annotation-actions'; import { rememberObject } from 'actions/annotation-actions';
import { Canvas, RectDrawingMethod } from 'cvat-canvas'; import { Canvas, RectDrawingMethod } from 'cvat-canvas';
import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import { formatShortcuts } from 'utils/shortcuts';
interface OwnProps { interface OwnProps {
shapeType: ShapeType; shapeType: ShapeType;
@ -28,7 +26,7 @@ interface DispatchToProps {
} }
interface StateToProps { interface StateToProps {
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas; canvasInstance: Canvas;
shapeType: ShapeType; shapeType: ShapeType;
labels: any[]; labels: any[];
@ -59,7 +57,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
}, },
}, },
shortcuts: { shortcuts: {
keyMap, normalizedKeyMap,
}, },
} = state; } = state;
@ -67,7 +65,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
...own, ...own,
canvasInstance, canvasInstance,
labels, labels,
keyMap, normalizedKeyMap,
}; };
} }
@ -164,7 +162,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
} = this.state; } = this.state;
const { const {
keyMap, normalizedKeyMap,
labels, labels,
shapeType, shapeType,
} = this.props; } = this.props;
@ -177,7 +175,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
selectedLabeID={selectedLabelID} selectedLabeID={selectedLabelID}
numberOfPoints={numberOfPoints} numberOfPoints={numberOfPoints}
rectDrawingMethod={rectDrawingMethod} rectDrawingMethod={rectDrawingMethod}
repeatShapeShortcut={formatShortcuts(keyMap.SWITCH_DRAW_MODE)} repeatShapeShortcut={normalizedKeyMap.SWITCH_DRAW_MODE}
onChangeLabel={this.onChangeLabel} onChangeLabel={this.onChangeLabel}
onChangePoints={this.onChangePoints} onChangePoints={this.onChangePoints}
onChangeRectDrawingMethod={this.onChangeRectDrawingMethod} onChangeRectDrawingMethod={this.onChangeRectDrawingMethod}

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { CombinedState, ObjectType } from 'reducers/interfaces'; import { CombinedState, ObjectType } from 'reducers/interfaces';
@ -11,7 +10,6 @@ import { createAnnotationsAsync, rememberObject } from 'actions/annotation-actio
import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover'; import SetupTagPopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover';
import { Canvas } from 'cvat-canvas'; import { Canvas } from 'cvat-canvas';
import { formatShortcuts } from 'utils/shortcuts';
import getCore from 'cvat-core'; import getCore from 'cvat-core';
const cvat = getCore(); const cvat = getCore();
@ -21,7 +19,7 @@ interface DispatchToProps {
} }
interface StateToProps { interface StateToProps {
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas; canvasInstance: Canvas;
jobInstance: any; jobInstance: any;
labels: any[]; labels: any[];
@ -56,7 +54,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
}, },
}, },
shortcuts: { shortcuts: {
keyMap, normalizedKeyMap,
}, },
} = state; } = state;
@ -65,7 +63,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
jobInstance, jobInstance,
labels, labels,
frame, frame,
keyMap, normalizedKeyMap,
}; };
} }
@ -118,13 +116,13 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
public render(): JSX.Element { public render(): JSX.Element {
const { selectedLabelID } = this.state; const { selectedLabelID } = this.state;
const { keyMap, labels } = this.props; const { normalizedKeyMap, labels } = this.props;
return ( return (
<SetupTagPopoverComponent <SetupTagPopoverComponent
labels={labels} labels={labels}
selectedLabeID={selectedLabelID} selectedLabeID={selectedLabelID}
repeatShapeShortcut={formatShortcuts(keyMap.SWITCH_DRAW_MODE)} repeatShapeShortcut={normalizedKeyMap.SWITCH_DRAW_MODE}
onChangeLabel={this.onChangeLabel} onChangeLabel={this.onChangeLabel}
onSetup={this.onSetup} onSetup={this.onSetup}
/> />

@ -5,7 +5,6 @@
import React from 'react'; import React from 'react';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { LogType } from 'cvat-logger'; import { LogType } from 'cvat-logger';
import { ActiveControl, CombinedState, ColorBy } from 'reducers/interfaces'; import { ActiveControl, CombinedState, ColorBy } from 'reducers/interfaces';
@ -44,7 +43,7 @@ interface StateToProps {
activeControl: ActiveControl; activeControl: ActiveControl;
minZLayer: number; minZLayer: number;
maxZLayer: number; maxZLayer: number;
keyMap: Record<string, ExtendedKeyMapOptions>; normalizedKeyMap: Record<string, string>;
} }
interface DispatchToProps { interface DispatchToProps {
@ -94,7 +93,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
}, },
}, },
shortcuts: { shortcuts: {
keyMap, normalizedKeyMap,
}, },
} = state; } = state;
@ -119,7 +118,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
activated: activatedStateID === own.clientID, activated: activatedStateID === own.clientID,
minZLayer, minZLayer,
maxZLayer, maxZLayer,
keyMap, normalizedKeyMap,
}; };
} }
@ -442,7 +441,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
activated, activated,
colorBy, colorBy,
colors, colors,
keyMap, normalizedKeyMap,
} = this.props; } = this.props;
const { const {
@ -484,7 +483,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
color={stateColor} color={stateColor}
colors={colors} colors={colors}
attributes={attributes} attributes={attributes}
keyMap={keyMap} normalizedKeyMap={normalizedKeyMap}
labels={labels} labels={labels}
collapsed={collapsed} collapsed={collapsed}
navigateFirstKeyframe={ navigateFirstKeyframe={

@ -6,7 +6,6 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys';
import { formatShortcuts } from 'utils/shortcuts';
import ObjectsListComponent from 'components/annotation-page/standard-workspace/objects-side-bar/objects-list'; import ObjectsListComponent from 'components/annotation-page/standard-workspace/objects-side-bar/objects-list';
import { import {
updateAnnotationsAsync, updateAnnotationsAsync,
@ -32,6 +31,7 @@ interface StateToProps {
maxZLayer: number; maxZLayer: number;
annotationsFiltersHistory: string[]; annotationsFiltersHistory: string[];
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
} }
interface DispatchToProps { interface DispatchToProps {
@ -69,6 +69,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
}, },
shortcuts: { shortcuts: {
keyMap, keyMap,
normalizedKeyMap,
}, },
} = state; } = state;
@ -102,6 +103,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
maxZLayer, maxZLayer,
annotationsFiltersHistory, annotationsFiltersHistory,
keyMap, keyMap,
normalizedKeyMap,
}; };
} }
@ -251,6 +253,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
maxZLayer, maxZLayer,
minZLayer, minZLayer,
keyMap, keyMap,
normalizedKeyMap,
} = this.props; } = this.props;
const { const {
sortedStatesID, sortedStatesID,
@ -410,8 +413,8 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
{...this.props} {...this.props}
statesOrdering={statesOrdering} statesOrdering={statesOrdering}
sortedStatesID={sortedStatesID} sortedStatesID={sortedStatesID}
switchHiddenAllShortcut={formatShortcuts(keyMap.SWITCH_ALL_HIDDEN)} switchHiddenAllShortcut={normalizedKeyMap.SWITCH_ALL_HIDDEN}
switchLockAllShortcut={formatShortcuts(keyMap.SWITCH_ALL_LOCK)} switchLockAllShortcut={normalizedKeyMap.SWITCH_ALL_LOCK}
changeStatesOrdering={this.onChangeStatesOrdering} changeStatesOrdering={this.onChangeStatesOrdering}
lockAllStates={this.onLockAllStates} lockAllStates={this.onLockAllStates}
unlockAllStates={this.onUnlockAllStates} unlockAllStates={this.onUnlockAllStates}

@ -26,7 +26,6 @@ import {
import AnnotationTopBarComponent from 'components/annotation-page/top-bar/top-bar'; import AnnotationTopBarComponent from 'components/annotation-page/top-bar/top-bar';
import { CombinedState, FrameSpeed, Workspace } from 'reducers/interfaces'; import { CombinedState, FrameSpeed, Workspace } from 'reducers/interfaces';
import { formatShortcuts } from 'utils/shortcuts';
interface StateToProps { interface StateToProps {
jobInstance: any; jobInstance: any;
@ -45,6 +44,7 @@ interface StateToProps {
autoSaveInterval: number; autoSaveInterval: number;
workspace: Workspace; workspace: Workspace;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
} }
interface DispatchToProps { interface DispatchToProps {
@ -96,6 +96,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
}, },
shortcuts: { shortcuts: {
keyMap, keyMap,
normalizedKeyMap,
}, },
} = state; } = state;
@ -116,6 +117,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
autoSaveInterval, autoSaveInterval,
workspace, workspace,
keyMap, keyMap,
normalizedKeyMap,
}; };
} }
@ -469,6 +471,7 @@ class AnnotationTopBarContainer extends React.PureComponent<Props> {
searchAnnotations, searchAnnotations,
changeWorkspace, changeWorkspace,
keyMap, keyMap,
normalizedKeyMap,
} = this.props; } = this.props;
const preventDefault = (event: KeyboardEvent | undefined): void => { const preventDefault = (event: KeyboardEvent | undefined): void => {
@ -584,15 +587,15 @@ class AnnotationTopBarContainer extends React.PureComponent<Props> {
inputFrameRef={this.inputFrameRef} inputFrameRef={this.inputFrameRef}
undoAction={undoAction} undoAction={undoAction}
redoAction={redoAction} redoAction={redoAction}
saveShortcut={formatShortcuts(keyMap.SAVE_JOB)} saveShortcut={normalizedKeyMap.SAVE_JOB}
undoShortcut={formatShortcuts(keyMap.UNDO)} undoShortcut={normalizedKeyMap.UNDO}
redoShortcut={formatShortcuts(keyMap.REDO)} redoShortcut={normalizedKeyMap.REDO}
playPauseShortcut={formatShortcuts(keyMap.PLAY_PAUSE)} playPauseShortcut={normalizedKeyMap.PLAY_PAUSE}
nextFrameShortcut={formatShortcuts(keyMap.NEXT_FRAME)} nextFrameShortcut={normalizedKeyMap.NEXT_FRAME}
previousFrameShortcut={formatShortcuts(keyMap.PREV_FRAME)} previousFrameShortcut={normalizedKeyMap.PREV_FRAME}
forwardShortcut={formatShortcuts(keyMap.FORWARD_FRAME)} forwardShortcut={normalizedKeyMap.FORWARD_FRAME}
backwardShortcut={formatShortcuts(keyMap.BACKWARD_FRAME)} backwardShortcut={normalizedKeyMap.BACKWARD_FRAME}
focusFrameInputShortcut={formatShortcuts(keyMap.FOCUS_INPUT_FRAME)} focusFrameInputShortcut={normalizedKeyMap.FOCUS_INPUT_FRAME}
onUndoClick={this.undo} onUndoClick={this.undo}
onRedoClick={this.redo} onRedoClick={this.redo}
/> />

@ -8,7 +8,6 @@ import getCore from 'cvat-core';
import HeaderComponent from 'components/header/header'; import HeaderComponent from 'components/header/header';
import { SupportedPlugins, CombinedState } from 'reducers/interfaces'; import { SupportedPlugins, CombinedState } from 'reducers/interfaces';
import { logoutAsync } from 'actions/auth-actions'; import { logoutAsync } from 'actions/auth-actions';
import { formatShortcuts } from 'utils/shortcuts';
const core = getCore(); const core = getCore();
@ -49,7 +48,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
packageVersion, packageVersion,
}, },
shortcuts: { shortcuts: {
keyMap, normalizedKeyMap,
}, },
} = state; } = state;
@ -67,7 +66,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
coreVersion: packageVersion.core, coreVersion: packageVersion.core,
canvasVersion: packageVersion.canvas, canvasVersion: packageVersion.canvas,
uiVersion: packageVersion.ui, uiVersion: packageVersion.ui,
switchSettingsShortcut: formatShortcuts(keyMap.OPEN_SETTINGS), switchSettingsShortcut: normalizedKeyMap.OPEN_SETTINGS,
}; };
} }

@ -445,6 +445,7 @@ export interface SettingsState {
export interface ShortcutsState { export interface ShortcutsState {
visibleShortcutsHelp: boolean; visibleShortcutsHelp: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: Record<string, ExtendedKeyMapOptions>;
normalizedKeyMap: Record<string, string>;
} }
export interface CombinedState { export interface CombinedState {

@ -9,304 +9,323 @@ import { AuthActions, AuthActionTypes } from 'actions/auth-actions';
import { ShortcutsActions, ShortcutsActionsTypes } from 'actions/shortcuts-actions'; import { ShortcutsActions, ShortcutsActionsTypes } from 'actions/shortcuts-actions';
import { ShortcutsState } from './interfaces'; import { ShortcutsState } from './interfaces';
function formatShortcuts(shortcuts: ExtendedKeyMapOptions): string {
const list: string[] = shortcuts.sequences as string[];
return `[${list.map((shortcut: string): string => {
let keys = shortcut.split('+');
keys = keys.map((key: string): string => `${key ? key[0].toUpperCase() : key}${key.slice(1)}`);
keys = keys.join('+').split(/\s/g);
keys = keys.map((key: string): string => `${key ? key[0].toUpperCase() : key}${key.slice(1)}`);
return keys.join(' ');
}).join(', ')}]`;
}
const defaultState: ShortcutsState = { const defaultKeyMap = {
visibleShortcutsHelp: false, SWITCH_SHORTCUTS: {
keyMap: { name: 'Show shortcuts',
SWITCH_SHORTCUTS: { description: 'Open/hide the list of available shortcuts',
name: 'Show shortcuts', sequences: ['f1'],
description: 'Open/hide the list of available shortcuts', action: 'keydown',
sequences: ['f1'], },
action: 'keydown', OPEN_SETTINGS: {
}, name: 'Open settings',
OPEN_SETTINGS: { description: 'Go to the settings page or go back',
name: 'Open settings', sequences: ['f2'],
description: 'Go to the settings page or go back', action: 'keydown',
sequences: ['f2'], },
action: 'keydown',
}, SWITCH_ALL_LOCK: {
name: 'Lock/unlock all objects',
description: 'Change locked state for all objects in the side bar',
sequences: ['t+l'],
action: 'keydown',
},
SWITCH_LOCK: {
name: 'Lock/unlock an object',
description: 'Change locked state for an active object',
sequences: ['l'],
action: 'keydown',
},
SWITCH_ALL_HIDDEN: {
name: 'Hide/show all objects',
description: 'Change hidden state for objects in the side bar',
sequences: ['t+h'],
action: 'keydown',
},
SWITCH_HIDDEN: {
name: 'Hide/show an object',
description: 'Change hidden state for an active object',
sequences: ['h'],
action: 'keydown',
},
SWITCH_OCCLUDED: {
name: 'Switch occluded',
description: 'Change occluded property for an active object',
sequences: ['q', '/'],
action: 'keydown',
},
SWITCH_KEYFRAME: {
name: 'Switch keyframe',
description: 'Change keyframe property for an active track',
sequences: ['k'],
action: 'keydown',
},
SWITCH_OUTSIDE: {
name: 'Switch outside',
description: 'Change outside property for an active track',
sequences: ['o'],
action: 'keydown',
},
DELETE_OBJECT: {
name: 'Delete object',
description: 'Delete an active object. Use shift to force delete of locked objects',
sequences: ['del', 'shift+del'],
action: 'keydown',
},
TO_BACKGROUND: {
name: 'To background',
description: 'Put an active object "farther" from the user (decrease z axis value)',
sequences: ['-', '_'],
action: 'keydown',
},
TO_FOREGROUND: {
name: 'To foreground',
description: 'Put an active object "closer" to the user (increase z axis value)',
sequences: ['+', '='],
action: 'keydown',
},
COPY_SHAPE: {
name: 'Copy shape',
description: 'Copy shape to CVAT internal clipboard',
sequences: ['ctrl+c'],
action: 'keydown',
},
PROPAGATE_OBJECT: {
name: 'Propagate object',
description: 'Make a copy of the object on the following frames',
sequences: ['ctrl+b'],
action: 'keydown',
},
NEXT_KEY_FRAME: {
name: 'Next keyframe',
description: 'Go to the next keyframe of an active track',
sequences: ['r'],
action: 'keydown',
},
PREV_KEY_FRAME: {
name: 'Previous keyframe',
description: 'Go to the previous keyframe of an active track',
sequences: ['e'],
action: 'keydown',
},
SWITCH_ALL_LOCK: { NEXT_ATTRIBUTE: {
name: 'Lock/unlock all objects', name: 'Next attribute',
description: 'Change locked state for all objects in the side bar', description: 'Go to the next attribute',
sequences: ['t+l'], sequences: ['ArrowDown'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_LOCK: { PREVIOUS_ATTRIBUTE: {
name: 'Lock/unlock an object', name: 'Previous attribute',
description: 'Change locked state for an active object', description: 'Go to the previous attribute',
sequences: ['l'], sequences: ['ArrowUp'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_ALL_HIDDEN: { NEXT_OBJECT: {
name: 'Hide/show all objects', name: 'Next object',
description: 'Change hidden state for objects in the side bar', description: 'Go to the next object',
sequences: ['t+h'], sequences: ['Tab'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_HIDDEN: { PREVIOUS_OBJECT: {
name: 'Hide/show an object', name: 'Previous object',
description: 'Change hidden state for an active object', description: 'Go to the previous object',
sequences: ['h'], sequences: ['Shift+Tab'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_OCCLUDED: {
name: 'Switch occluded',
description: 'Change occluded property for an active object',
sequences: ['q', '/'],
action: 'keydown',
},
SWITCH_KEYFRAME: {
name: 'Switch keyframe',
description: 'Change keyframe property for an active track',
sequences: ['k'],
action: 'keydown',
},
SWITCH_OUTSIDE: {
name: 'Switch outside',
description: 'Change outside property for an active track',
sequences: ['o'],
action: 'keydown',
},
DELETE_OBJECT: {
name: 'Delete object',
description: 'Delete an active object. Use shift to force delete of locked objects',
sequences: ['del', 'shift+del'],
action: 'keydown',
},
TO_BACKGROUND: {
name: 'To background',
description: 'Put an active object "farther" from the user (decrease z axis value)',
sequences: ['-', '_'],
action: 'keydown',
},
TO_FOREGROUND: {
name: 'To foreground',
description: 'Put an active object "closer" to the user (increase z axis value)',
sequences: ['+', '='],
action: 'keydown',
},
COPY_SHAPE: {
name: 'Copy shape',
description: 'Copy shape to CVAT internal clipboard',
sequences: ['ctrl+c'],
action: 'keydown',
},
PROPAGATE_OBJECT: {
name: 'Propagate object',
description: 'Make a copy of the object on the following frames',
sequences: ['ctrl+b'],
action: 'keydown',
},
NEXT_KEY_FRAME: {
name: 'Next keyframe',
description: 'Go to the next keyframe of an active track',
sequences: ['r'],
action: 'keydown',
},
PREV_KEY_FRAME: {
name: 'Previous keyframe',
description: 'Go to the previous keyframe of an active track',
sequences: ['e'],
action: 'keydown',
},
NEXT_ATTRIBUTE: { INCREASE_BRIGHTNESS: {
name: 'Next attribute', name: 'Brightness+',
description: 'Go to the next attribute', description: 'Increase brightness level for the image',
sequences: ['ArrowDown'], sequences: ['shift+b+='],
action: 'keydown', action: 'keypress',
}, },
PREVIOUS_ATTRIBUTE: { DECREASE_BRIGHTNESS: {
name: 'Previous attribute', name: 'Brightness-',
description: 'Go to the previous attribute', description: 'Decrease brightness level for the image',
sequences: ['ArrowUp'], sequences: ['shift+b+-'],
action: 'keydown', action: 'keydown',
}, },
NEXT_OBJECT: { INCREASE_CONTRAST: {
name: 'Next object', name: 'Contrast+',
description: 'Go to the next object', description: 'Increase contrast level for the image',
sequences: ['Tab'], sequences: ['shift+c+='],
action: 'keydown', action: 'keydown',
}, },
PREVIOUS_OBJECT: { DECREASE_CONTRAST: {
name: 'Previous object', name: 'Contrast-',
description: 'Go to the previous object', description: 'Decrease contrast level for the image',
sequences: ['Shift+Tab'], sequences: ['shift+c+-'],
action: 'keydown', action: 'keydown',
}, },
INCREASE_SATURATION: {
name: 'Saturation+',
description: 'Increase saturation level for the image',
sequences: ['shift+s+='],
action: 'keydown',
},
DECREASE_SATURATION: {
name: 'Saturation-',
description: 'Increase contrast level for the image',
sequences: ['shift+s+-'],
action: 'keydown',
},
INCREASE_GRID_OPACITY: {
name: 'Grid opacity+',
description: 'Make the grid more visible',
sequences: ['shift+g+='],
action: 'keydown',
},
DECREASE_GRID_OPACITY: {
name: 'Grid opacity-',
description: 'Make the grid less visible',
sequences: ['shift+g+-'],
action: 'keydown',
},
CHANGE_GRID_COLOR: {
name: 'Grid color',
description: 'Set another color for the image grid',
sequences: ['shift+g+enter'],
action: 'keydown',
},
INCREASE_BRIGHTNESS: { PASTE_SHAPE: {
name: 'Brightness+', name: 'Paste shape',
description: 'Increase brightness level for the image', description: 'Paste a shape from internal CVAT clipboard',
sequences: ['shift+b+='], sequences: ['ctrl+v'],
action: 'keypress', action: 'keydown',
}, },
DECREASE_BRIGHTNESS: { SWITCH_DRAW_MODE: {
name: 'Brightness-', name: 'Draw mode',
description: 'Decrease brightness level for the image', description: 'Repeat the latest procedure of drawing with the same parameters',
sequences: ['shift+b+-'], sequences: ['n'],
action: 'keydown', action: 'keydown',
}, },
INCREASE_CONTRAST: { SWITCH_MERGE_MODE: {
name: 'Contrast+', name: 'Merge mode',
description: 'Increase contrast level for the image', description: 'Activate or deactivate mode to merging shapes',
sequences: ['shift+c+='], sequences: ['m'],
action: 'keydown', action: 'keydown',
}, },
DECREASE_CONTRAST: { SWITCH_GROUP_MODE: {
name: 'Contrast-', name: 'Group mode',
description: 'Decrease contrast level for the image', description: 'Activate or deactivate mode to grouping shapes',
sequences: ['shift+c+-'], sequences: ['g'],
action: 'keydown', action: 'keydown',
}, },
INCREASE_SATURATION: { RESET_GROUP: {
name: 'Saturation+', name: 'Reset group',
description: 'Increase saturation level for the image', description: 'Reset group for selected shapes (in group mode)',
sequences: ['shift+s+='], sequences: ['shift+g'],
action: 'keydown', action: 'keyup',
}, },
DECREASE_SATURATION: { CANCEL: {
name: 'Saturation-', name: 'Cancel',
description: 'Increase contrast level for the image', description: 'Cancel any active canvas mode',
sequences: ['shift+s+-'], sequences: ['esc'],
action: 'keydown', action: 'keydown',
}, },
INCREASE_GRID_OPACITY: { CLOCKWISE_ROTATION: {
name: 'Grid opacity+', name: 'Rotate clockwise',
description: 'Make the grid more visible', description: 'Change image angle (add 90 degrees)',
sequences: ['shift+g+='], sequences: ['ctrl+r'],
action: 'keydown', action: 'keydown',
}, },
DECREASE_GRID_OPACITY: { ANTICLOCKWISE_ROTATION: {
name: 'Grid opacity-', name: 'Rotate anticlockwise',
description: 'Make the grid less visible', description: 'Change image angle (substract 90 degrees)',
sequences: ['shift+g+-'], sequences: ['ctrl+shift+r'],
action: 'keydown', action: 'keydown',
}, },
CHANGE_GRID_COLOR: {
name: 'Grid color',
description: 'Set another color for the image grid',
sequences: ['shift+g+enter'],
action: 'keydown',
},
PASTE_SHAPE: { SAVE_JOB: {
name: 'Paste shape', name: 'Save the job',
description: 'Paste a shape from internal CVAT clipboard', description: 'Send all changes of annotations to the server',
sequences: ['ctrl+v'], sequences: ['ctrl+s'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_DRAW_MODE: { UNDO: {
name: 'Draw mode', name: 'Undo action',
description: 'Repeat the latest procedure of drawing with the same parameters', description: 'Cancel the latest action related with objects',
sequences: ['n'], sequences: ['ctrl+z'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_MERGE_MODE: { REDO: {
name: 'Merge mode', name: 'Redo action',
description: 'Activate or deactivate mode to merging shapes', description: 'Cancel undo action',
sequences: ['m'], sequences: ['ctrl+shift+z', 'ctrl+y'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_GROUP_MODE: { NEXT_FRAME: {
name: 'Group mode', name: 'Next frame',
description: 'Activate or deactivate mode to grouping shapes', description: 'Go to the next frame',
sequences: ['g'], sequences: ['f'],
action: 'keydown', action: 'keydown',
}, },
RESET_GROUP: { PREV_FRAME: {
name: 'Reset group', name: 'Previous frame',
description: 'Reset group for selected shapes (in group mode)', description: 'Go to the previous frame',
sequences: ['shift+g'], sequences: ['d'],
action: 'keyup', action: 'keydown',
}, },
CANCEL: { FORWARD_FRAME: {
name: 'Cancel', name: 'Forward frame',
description: 'Cancel any active canvas mode', description: 'Go forward with a step',
sequences: ['esc'], sequences: ['v'],
action: 'keydown', action: 'keydown',
}, },
CLOCKWISE_ROTATION: { BACKWARD_FRAME: {
name: 'Rotate clockwise', name: 'Backward frame',
description: 'Change image angle (add 90 degrees)', description: 'Go backward with a step',
sequences: ['ctrl+r'], sequences: ['c'],
action: 'keydown', action: 'keydown',
}, },
ANTICLOCKWISE_ROTATION: { SEARCH_FORWARD: {
name: 'Rotate anticlockwise', name: 'Search forward',
description: 'Change image angle (substract 90 degrees)', description: 'Search the next frame that satisfies to the filters',
sequences: ['ctrl+shift+r'], sequences: ['right'],
action: 'keydown', action: 'keydown',
}, },
SEARCH_BACKWARD: {
name: 'Search backward',
description: 'Search the previous frame that satisfies to the filters',
sequences: ['left'],
action: 'keydown',
},
PLAY_PAUSE: {
name: 'Play/pause',
description: 'Start/stop automatic changing frames',
sequences: ['space'],
action: 'keydown',
},
FOCUS_INPUT_FRAME: {
name: 'Focus input frame',
description: 'Focus on the element to change the current frame',
sequences: ['`', '~'],
action: 'keydown',
},
} as any as Record<string, ExtendedKeyMapOptions>;
SAVE_JOB: {
name: 'Save the job', const defaultState: ShortcutsState = {
description: 'Send all changes of annotations to the server', visibleShortcutsHelp: false,
sequences: ['ctrl+s'], keyMap: defaultKeyMap,
action: 'keydown', normalizedKeyMap: Object.keys(defaultKeyMap)
}, .reduce((acc: Record<string, string>, key: string) => {
UNDO: { const normalized = formatShortcuts(defaultKeyMap[key]);
name: 'Undo action', acc[key] = normalized;
description: 'Cancel the latest action related with objects', return acc;
sequences: ['ctrl+z'], }, {}),
action: 'keydown',
},
REDO: {
name: 'Redo action',
description: 'Cancel undo action',
sequences: ['ctrl+shift+z', 'ctrl+y'],
action: 'keydown',
},
NEXT_FRAME: {
name: 'Next frame',
description: 'Go to the next frame',
sequences: ['f'],
action: 'keydown',
},
PREV_FRAME: {
name: 'Previous frame',
description: 'Go to the previous frame',
sequences: ['d'],
action: 'keydown',
},
FORWARD_FRAME: {
name: 'Forward frame',
description: 'Go forward with a step',
sequences: ['v'],
action: 'keydown',
},
BACKWARD_FRAME: {
name: 'Backward frame',
description: 'Go backward with a step',
sequences: ['c'],
action: 'keydown',
},
SEARCH_FORWARD: {
name: 'Search forward',
description: 'Search the next frame that satisfies to the filters',
sequences: ['right'],
action: 'keydown',
},
SEARCH_BACKWARD: {
name: 'Search backward',
description: 'Search the previous frame that satisfies to the filters',
sequences: ['left'],
action: 'keydown',
},
PLAY_PAUSE: {
name: 'Play/pause',
description: 'Start/stop automatic changing frames',
sequences: ['space'],
action: 'keydown',
},
FOCUS_INPUT_FRAME: {
name: 'Focus input frame',
description: 'Focus on the element to change the current frame',
sequences: ['`', '~'],
action: 'keydown',
},
} as any as Record<string, ExtendedKeyMapOptions>,
}; };
export default ( export default (

@ -1,17 +0,0 @@
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
/* eslint-disable-next-line import/prefer-default-export */
export function formatShortcuts(shortcuts: ExtendedKeyMapOptions): string {
const list: string[] = shortcuts.sequences as string[];
return `[${list.map((shortcut: string): string => {
let keys = shortcut.split('+');
keys = keys.map((key: string): string => `${key ? key[0].toUpperCase() : key}${key.slice(1)}`);
keys = keys.join('+').split(/\s/g);
keys = keys.map((key: string): string => `${key ? key[0].toUpperCase() : key}${key.slice(1)}`);
return keys.join(' ');
}).join(', ')}]`;
}
Loading…
Cancel
Save