Refactor shortcuts into a central file and fix issue with caps lock

This commit is contained in:
Mitchell McCaffrey 2021-03-25 16:31:06 +11:00
parent c77db06bce
commit ad68aa7226
9 changed files with 190 additions and 85 deletions

View File

@ -42,6 +42,8 @@ import SubtractShapeAction from "../../actions/SubtractShapeAction";
import useSetting from "../../hooks/useSetting";
import shortcuts from "../../shortcuts";
function MapFog({
map,
shapes,
@ -402,16 +404,20 @@ function MapFog({
}, [toolSettings, drawingShape, onShapesCut, onShapesAdd, shapes]);
// Add keyboard shortcuts
function handleKeyDown({ key }) {
if (key === "Enter" && toolSettings.type === "polygon" && drawingShape) {
function handleKeyDown(event) {
if (
shortcuts.fogFinishPolygon(event) &&
toolSettings.type === "polygon" &&
drawingShape
) {
finishDrawingPolygon();
}
if (key === "Escape" && drawingShape) {
if (shortcuts.fogCancelPolygon(event) && drawingShape) {
setDrawingShape(null);
}
// Remove last point from polygon shape if delete pressed
if (
(key === "Backspace" || key === "Delete") &&
shortcuts.delete(event) &&
drawingShape &&
toolSettings.type === "polygon"
) {

View File

@ -11,6 +11,8 @@ import { useKeyboard } from "../../contexts/KeyboardContext";
import Vector2 from "../../helpers/Vector2";
import shortcuts from "../../shortcuts";
function MapGridEditor({ map, onGridChange }) {
const stageScale = useDebouncedStageScale();
const mapWidth = useMapWidth();
@ -166,20 +168,19 @@ function MapGridEditor({ map, onGridChange }) {
}
function handleKeyDown(event) {
const { key, shiftKey } = event;
const nudgeAmount = shiftKey ? 2 : 0.5;
if (key === "ArrowUp") {
const nudgeAmount = event.shiftKey ? 2 : 0.5;
if (shortcuts.gridNudgeUp(event)) {
// Stop arrow up/down scrolling if overflowing
event.preventDefault();
nudgeGrid({ x: 0, y: -1 }, nudgeAmount);
}
if (key === "ArrowLeft") {
if (shortcuts.gridNudgeLeft(event)) {
nudgeGrid({ x: -1, y: 0 }, nudgeAmount);
}
if (key === "ArrowRight") {
if (shortcuts.gridNudgeRight(event)) {
nudgeGrid({ x: 1, y: 0 }, nudgeAmount);
}
if (key === "ArrowDown") {
if (shortcuts.gridNudgeDown(event)) {
event.preventDefault();
nudgeGrid({ x: 0, y: 1 }, nudgeAmount);
}

View File

@ -17,6 +17,8 @@ import { useMapStage } from "../../contexts/MapStageContext";
import { GridProvider } from "../../contexts/GridContext";
import { useKeyboard } from "../../contexts/KeyboardContext";
import shortcuts from "../../shortcuts";
function MapInteraction({
map,
mapState,
@ -111,12 +113,12 @@ function MapInteraction({
function handleKeyDown(event) {
// Change to move tool when pressing space
if (event.key === " " && selectedToolId === "move") {
if (shortcuts.move(event) && selectedToolId === "move") {
// Stop active state on move icon from being selected
event.preventDefault();
}
if (
event.key === " " &&
shortcuts.move(event) &&
selectedToolId !== "move" &&
!disabledControls.includes("move")
) {
@ -126,28 +128,28 @@ function MapInteraction({
}
// Basic keyboard shortcuts
if (event.key === "w" && !disabledControls.includes("move")) {
if (shortcuts.moveTool(event) && !disabledControls.includes("move")) {
onSelectedToolChange("move");
}
if (event.key === "d" && !disabledControls.includes("drawing")) {
if (shortcuts.drawingTool(event) && !disabledControls.includes("drawing")) {
onSelectedToolChange("drawing");
}
if (event.key === "f" && !disabledControls.includes("fog")) {
if (shortcuts.fogTool(event) && !disabledControls.includes("fog")) {
onSelectedToolChange("fog");
}
if (event.key === "m" && !disabledControls.includes("measure")) {
if (shortcuts.measureTool(event) && !disabledControls.includes("measure")) {
onSelectedToolChange("measure");
}
if (event.key === "q" && !disabledControls.includes("pointer")) {
if (shortcuts.pointerTool(event) && !disabledControls.includes("pointer")) {
onSelectedToolChange("pointer");
}
if (event.key === "n" && !disabledControls.includes("note")) {
if (shortcuts.noteTool(event) && !disabledControls.includes("note")) {
onSelectedToolChange("note");
}
}
function handleKeyUp(event) {
if (event.key === " " && selectedToolId === "move") {
if (shortcuts.move(event) && selectedToolId === "move") {
onSelectedToolChange(previousSelectedToolRef.current);
}
}

View File

@ -24,6 +24,8 @@ import Divider from "../../Divider";
import { useKeyboard } from "../../../contexts/KeyboardContext";
import shortcuts from "../../../shortcuts";
function DrawingToolSettings({
settings,
onSettingChange,
@ -31,36 +33,26 @@ function DrawingToolSettings({
disabledActions,
}) {
// Keyboard shotcuts
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
if (key === "b") {
function handleKeyDown(event) {
if (shortcuts.drawBrush(event)) {
onSettingChange({ type: "brush" });
} else if (key === "p") {
} else if (shortcuts.drawPaint(event)) {
onSettingChange({ type: "paint" });
} else if (key === "l") {
} else if (shortcuts.drawLine(event)) {
onSettingChange({ type: "line" });
} else if (key === "r") {
} else if (shortcuts.drawRect(event)) {
onSettingChange({ type: "rectangle" });
} else if (key === "c") {
} else if (shortcuts.drawCircle(event)) {
onSettingChange({ type: "circle" });
} else if (key === "t") {
} else if (shortcuts.drawTriangle(event)) {
onSettingChange({ type: "triangle" });
} else if (key === "e") {
} else if (shortcuts.drawErase(event)) {
onSettingChange({ type: "erase" });
} else if (key === "o") {
} else if (shortcuts.drawBlend(event)) {
onSettingChange({ useBlending: !settings.useBlending });
} else if (
(key === "z" || key === "Z") &&
(ctrlKey || metaKey) &&
shiftKey &&
!disabledActions.includes("redo")
) {
} else if (shortcuts.redo(event) && !disabledActions.includes("redo")) {
onToolAction("mapRedo");
} else if (
key === "z" &&
(ctrlKey || metaKey) &&
!shiftKey &&
!disabledActions.includes("undo")
) {
} else if (shortcuts.undo(event) && !disabledActions.includes("undo")) {
onToolAction("mapUndo");
}
}

View File

@ -22,6 +22,8 @@ import Divider from "../../Divider";
import { useKeyboard } from "../../../contexts/KeyboardContext";
import shortcuts from "../../../shortcuts";
function BrushToolSettings({
settings,
onSettingChange,
@ -29,36 +31,26 @@ function BrushToolSettings({
disabledActions,
}) {
// Keyboard shortcuts
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
if (key === "p") {
function handleKeyDown(event) {
if (shortcuts.fogPolygon(event)) {
onSettingChange({ type: "polygon" });
} else if (key === "b") {
} else if (shortcuts.fogBrush(event)) {
onSettingChange({ type: "brush" });
} else if (key === "t") {
} else if (shortcuts.fogToggle(event)) {
onSettingChange({ type: "toggle" });
} else if (key === "e") {
} else if (shortcuts.fogErase(event)) {
onSettingChange({ type: "remove" });
} else if (key === "l") {
} else if (shortcuts.fogLayer(event)) {
onSettingChange({ multilayer: !settings.multilayer });
} else if (key === "f") {
} else if (shortcuts.fogPreview(event)) {
onSettingChange({ preview: !settings.preview });
} else if (key === "c") {
} else if (shortcuts.fogCut(event)) {
onSettingChange({ useFogCut: !settings.useFogCut });
} else if (key === "r") {
} else if (shortcuts.fogRectangle(event)) {
onSettingChange({ type: "rectangle" });
} else if (
(key === "z" || key === "Z") &&
(ctrlKey || metaKey) &&
shiftKey &&
!disabledActions.includes("redo")
) {
} else if (shortcuts.redo(event) && !disabledActions.includes("redo")) {
onToolAction("fogRedo");
} else if (
key === "z" &&
(ctrlKey || metaKey) &&
!shiftKey &&
!disabledActions.includes("undo")
) {
} else if (shortcuts.undo(event) && !disabledActions.includes("undo")) {
onToolAction("fogUndo");
}
}

View File

@ -4,6 +4,8 @@ import normalizeWheel from "normalize-wheel";
import { useKeyboard, useBlur } from "../contexts/KeyboardContext";
import shortcuts from "../shortcuts";
const wheelZoomSpeed = -1;
const touchZoomSpeed = 0.005;
const minZoom = 0.1;
@ -184,18 +186,14 @@ function useStageInteraction(
}
);
function handleKeyDown({ key, ctrlKey, metaKey }) {
function handleKeyDown(event) {
// TODO: Find better way to detect whether keyboard event should fire.
// This one fires on all open stages
if (preventInteraction) {
return;
}
if (
(key === "=" || key === "+" || key === "-" || key === "_") &&
!ctrlKey &&
!metaKey
) {
const pixelY = key === "=" || key === "+" ? -100 : 100;
if (shortcuts.stageZoomIn(event) || shortcuts.stageZoomOut(event)) {
const pixelY = shortcuts.stageZoomIn(event) ? -100 : 100;
const newScale = Math.min(
Math.max(
stageScale +
@ -219,13 +217,13 @@ function useStageInteraction(
onStageScaleChange(newScale);
}
if (key === "Shift") {
if (shortcuts.stagePrecisionZoom(event)) {
setZoomSpeed(0.25);
}
}
function handleKeyUp({ key }) {
if (key === "Shift") {
function handleKeyUp(event) {
if (shortcuts.stagePrecisionZoom(event)) {
setZoomSpeed(1);
}
}

View File

@ -28,6 +28,8 @@ import { useMapData } from "../contexts/MapDataContext";
import { useAuth } from "../contexts/AuthContext";
import { useKeyboard, useBlur } from "../contexts/KeyboardContext";
import shortcuts from "../shortcuts";
const defaultMapProps = {
showGrid: false,
snapToGrid: true,
@ -345,17 +347,17 @@ function SelectMapModal({
/**
* Shortcuts
*/
function handleKeyDown({ key }) {
function handleKeyDown(event) {
if (!isOpen) {
return;
}
if (key === "Shift") {
if (shortcuts.selectRange(event)) {
setSelectMode("range");
}
if (key === "Control" || key === "Meta") {
if (shortcuts.selectMultiple(event)) {
setSelectMode("multiple");
}
if (key === "Backspace" || key === "Delete") {
if (shortcuts.delete(event)) {
// Selected maps and none are default
if (
selectedMapIds.length > 0 &&
@ -370,14 +372,14 @@ function SelectMapModal({
}
}
function handleKeyUp({ key }) {
function handleKeyUp(event) {
if (!isOpen) {
return;
}
if (key === "Shift" && selectMode === "range") {
if (shortcuts.selectRange(event) && selectMode === "range") {
setSelectMode("single");
}
if ((key === "Control" || key === "Meta") && selectMode === "multiple") {
if (shortcuts.selectMultiple(event) && selectMode === "multiple") {
setSelectMode("single");
}
}

View File

@ -22,6 +22,8 @@ import { useTokenData } from "../contexts/TokenDataContext";
import { useAuth } from "../contexts/AuthContext";
import { useKeyboard, useBlur } from "../contexts/KeyboardContext";
import shortcuts from "../shortcuts";
function SelectTokensModal({ isOpen, onRequestClose }) {
const { userId } = useAuth();
const {
@ -186,17 +188,17 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
/**
* Shortcuts
*/
function handleKeyDown({ key }) {
function handleKeyDown(event) {
if (!isOpen) {
return;
}
if (key === "Shift") {
if (shortcuts.selectRange(event)) {
setSelectMode("range");
}
if (key === "Control" || key === "Meta") {
if (shortcuts.selectMultiple(event)) {
setSelectMode("multiple");
}
if (key === "Backspace" || key === "Delete") {
if (shortcuts.delete(event)) {
// Selected tokens and none are default
if (
selectedTokenIds.length > 0 &&
@ -210,14 +212,14 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
}
}
function handleKeyUp({ key }) {
function handleKeyUp(event) {
if (!isOpen) {
return;
}
if (key === "Shift" && selectMode === "range") {
if (shortcuts.selectRange(event) && selectMode === "range") {
setSelectMode("single");
}
if ((key === "Control" || key === "Meta") && selectMode === "multiple") {
if (shortcuts.selectMultiple(event) && selectMode === "multiple") {
setSelectMode("single");
}
}

110
src/shortcuts.js Normal file
View File

@ -0,0 +1,110 @@
/**
* @param {KeyboardEvent} event
* @returns {boolean}
*/
function hasModifier(event) {
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
}
/**
* Key press without any modifiers and ignoring capitals
* @param {KeyboardEvent} event
* @param {string} key
* @returns {boolean}
*/
function singleKey(event, key) {
return (
!hasModifier(event) &&
(event.key === key || event.key === key.toUpperCase())
);
}
/**
* @param {Keyboard} event
*/
function undo(event) {
const { key, ctrlKey, metaKey, shiftKey } = event;
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && !shiftKey;
}
/**
* @param {Keyboard} event
*/
function redo(event) {
const { key, ctrlKey, metaKey, shiftKey } = event;
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && shiftKey;
}
/**
* @param {Keyboard} event
*/
function zoomIn(event) {
const { key, ctrlKey, metaKey } = event;
return (key === "=" || key === "+") && !ctrlKey && !metaKey;
}
/**
* @param {Keyboard} event
*/
function zoomOut(event) {
const { key, ctrlKey, metaKey } = event;
return (key === "-" || key === "_") && !ctrlKey && !metaKey;
}
/**
* @callback shortcut
* @param {KeyboardEvent} event
* @returns {boolean}
*/
/**
* @type {Object.<string, shortcut>}
*/
const shortcuts = {
// Tools
move: (event) => singleKey(event, " "),
moveTool: (event) => singleKey(event, "w"),
drawingTool: (event) => singleKey(event, "d"),
fogTool: (event) => singleKey(event, "f"),
measureTool: (event) => singleKey(event, "m"),
pointerTool: (event) => singleKey(event, "q"),
noteTool: (event) => singleKey(event, "n"),
// Map editor
gridNudgeUp: ({ key }) => key === "ArrowUp",
gridNudgeLeft: ({ key }) => key === "ArrowLeft",
gridNudgeRight: ({ key }) => key === "ArrowRight",
gridNudgeDown: ({ key }) => key === "ArrowDown",
// Drawing tool
drawBrush: (event) => singleKey(event, "b"),
drawPaint: (event) => singleKey(event, "p"),
drawLine: (event) => singleKey(event, "l"),
drawRect: (event) => singleKey(event, "r"),
drawCircle: (event) => singleKey(event, "c"),
drawTriangle: (event) => singleKey(event, "t"),
drawErase: (event) => singleKey(event, "e"),
drawBlend: (event) => singleKey(event, "o"),
// Fog tool
fogPolygon: (event) => singleKey(event, "p"),
fogRectangle: (event) => singleKey(event, "r"),
fogBrush: (event) => singleKey(event, "b"),
fogToggle: (event) => singleKey(event, "t"),
fogErase: (event) => singleKey(event, "e"),
fogLayer: (event) => singleKey(event, "l"),
fogPreview: (event) => singleKey(event, "f"),
fogCut: (event) => singleKey(event, "c"),
fogFinishPolygon: ({ key }) => key === "Enter",
fogCancelPolygon: ({ key }) => key === "Escape",
// Stage interaction
stageZoomIn: zoomIn,
stageZoomOut: zoomOut,
stagePrecisionZoom: ({ key }) => key === "Shift",
// Select
selectRange: ({ key }) => key === "Shift",
selectMultiple: ({ key }) => key === "Control" || key === "Meta",
// Common
undo,
redo,
delete: ({ key }) => key === "Backspace" || key === "Delete",
};
export default shortcuts;