Add alt drag duplicate shortcut for tokens, notes and selection
This commit is contained in:
parent
27bcc127bc
commit
d6d8ee2f11
@ -40,6 +40,7 @@ import {
|
||||
SelectionItemsChangeEventHandler,
|
||||
SelectionItemsRemoveEventHandler,
|
||||
SelectionItemsCreateEventHandler,
|
||||
TokensStateCreateHandler,
|
||||
} from "../../types/Events";
|
||||
|
||||
import useMapTokens from "../../hooks/useMapTokens";
|
||||
@ -53,6 +54,7 @@ type MapProps = {
|
||||
mapActions: MapActions;
|
||||
onMapTokenStateChange: TokenStateChangeEventHandler;
|
||||
onMapTokenStateRemove: TokenStateRemoveHandler;
|
||||
onMapTokensStateCreate: TokensStateCreateHandler;
|
||||
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
||||
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
|
||||
onSelectionItemsCreate: SelectionItemsCreateEventHandler;
|
||||
@ -75,6 +77,7 @@ function Map({
|
||||
mapActions,
|
||||
onMapTokenStateChange,
|
||||
onMapTokenStateRemove,
|
||||
onMapTokensStateCreate,
|
||||
onSelectionItemsChange,
|
||||
onSelectionItemsRemove,
|
||||
onSelectionItemsCreate,
|
||||
@ -142,6 +145,7 @@ function Map({
|
||||
mapState,
|
||||
onMapTokenStateChange,
|
||||
onMapTokenStateRemove,
|
||||
onMapTokensStateCreate,
|
||||
selectedToolId
|
||||
);
|
||||
|
||||
|
@ -1,11 +1,15 @@
|
||||
import Konva from "konva";
|
||||
import { KonvaEventObject } from "konva/lib/Node";
|
||||
import { useState } from "react";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import Note from "../components/konva/Note";
|
||||
import NoteDragOverlay from "../components/note/NoteDragOverlay";
|
||||
import NoteMenu from "../components/note/NoteMenu";
|
||||
import NoteTool from "../components/tools/NoteTool";
|
||||
import { useBlur, useKeyboard } from "../contexts/KeyboardContext";
|
||||
import { useUserId } from "../contexts/UserIdContext";
|
||||
import shortcuts from "../shortcuts";
|
||||
import {
|
||||
NoteChangeEventHandler,
|
||||
NoteCreateEventHander,
|
||||
@ -47,6 +51,12 @@ function useMapNotes(
|
||||
}
|
||||
|
||||
function handleNoteDragStart(_: KonvaEventObject<DragEvent>, noteId: string) {
|
||||
if (duplicateNote) {
|
||||
const note = mapState?.notes[noteId];
|
||||
if (note) {
|
||||
onNoteCreate([{ ...note, id: uuid() }]);
|
||||
}
|
||||
}
|
||||
setNoteDraggingOptions({ dragging: true, noteId });
|
||||
}
|
||||
|
||||
@ -60,6 +70,26 @@ function useMapNotes(
|
||||
setNoteDraggingOptions(undefined);
|
||||
}
|
||||
|
||||
const [duplicateNote, setDuplicateNote] = useState(false);
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateNote(true);
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateNote(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
setDuplicateNote(false);
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
useBlur(handleBlur);
|
||||
|
||||
const notes = (
|
||||
<NoteTool
|
||||
map={map}
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import SelectionDragOverlay from "../components/selection/SelectionDragOverlay";
|
||||
import SelectionMenu from "../components/selection/SelectionMenu";
|
||||
import SelectTool from "../components/tools/SelectTool";
|
||||
import { useBlur, useKeyboard } from "../contexts/KeyboardContext";
|
||||
import { useUserId } from "../contexts/UserIdContext";
|
||||
import shortcuts from "../shortcuts";
|
||||
import {
|
||||
SelectionItemsChangeEventHandler,
|
||||
SelectionItemsCreateEventHandler,
|
||||
@ -10,8 +14,10 @@ import {
|
||||
} from "../types/Events";
|
||||
import { Map, MapToolId } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
import { Note } from "../types/Note";
|
||||
import { Selection } from "../types/Select";
|
||||
import { SelectToolSettings } from "../types/Select";
|
||||
import { TokenState } from "../types/TokenState";
|
||||
|
||||
function useMapSelection(
|
||||
map: Map | null,
|
||||
@ -66,6 +72,24 @@ function useMapSelection(
|
||||
}, [map]);
|
||||
|
||||
function handleSelectionDragStart() {
|
||||
if (duplicateSelection && selection) {
|
||||
const tokenStates: TokenState[] = [];
|
||||
const notes: Note[] = [];
|
||||
for (let item of selection.items) {
|
||||
if (item.type === "token") {
|
||||
const token = mapState?.tokens[item.id];
|
||||
if (token && !token.locked) {
|
||||
tokenStates.push({ ...token, id: uuid() });
|
||||
}
|
||||
} else {
|
||||
const note = mapState?.notes[item.id];
|
||||
if (note && !note.locked) {
|
||||
notes.push({ ...note, id: uuid() });
|
||||
}
|
||||
}
|
||||
}
|
||||
onSelectionItemsCreate(tokenStates, notes);
|
||||
}
|
||||
setIsSelectionDragging(true);
|
||||
}
|
||||
|
||||
@ -81,6 +105,26 @@ function useMapSelection(
|
||||
onSelectionItemsRemove(tokenStateIds, noteIds);
|
||||
}
|
||||
|
||||
const [duplicateSelection, setDuplicateSelection] = useState(false);
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateSelection(true);
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateSelection(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
setDuplicateSelection(false);
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
useBlur(handleBlur);
|
||||
|
||||
const selectionTool = map ? (
|
||||
<SelectTool
|
||||
active={active}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Group } from "react-konva";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import { Map, MapToolId } from "../types/Map";
|
||||
import { MapState } from "../types/MapState";
|
||||
@ -11,6 +12,7 @@ import { TokenState } from "../types/TokenState";
|
||||
import {
|
||||
TokenStateRemoveHandler,
|
||||
TokenStateChangeEventHandler,
|
||||
TokensStateCreateHandler,
|
||||
} from "../types/Events";
|
||||
import { useState } from "react";
|
||||
import Konva from "konva";
|
||||
@ -19,12 +21,15 @@ import { KonvaEventObject } from "konva/lib/Node";
|
||||
import TokenMenu from "../components/token/TokenMenu";
|
||||
import TokenDragOverlay from "../components/token/TokenDragOverlay";
|
||||
import { useUserId } from "../contexts/UserIdContext";
|
||||
import { useBlur, useKeyboard } from "../contexts/KeyboardContext";
|
||||
import shortcuts from "../shortcuts";
|
||||
|
||||
function useMapTokens(
|
||||
map: Map | null,
|
||||
mapState: MapState | null,
|
||||
onTokenStateChange: TokenStateChangeEventHandler,
|
||||
onTokenStateRemove: TokenStateRemoveHandler,
|
||||
onTokensStateCreate: TokensStateCreateHandler,
|
||||
selectedToolId: MapToolId
|
||||
) {
|
||||
const userId = useUserId();
|
||||
@ -57,6 +62,12 @@ function useMapTokens(
|
||||
_: KonvaEventObject<DragEvent>,
|
||||
tokenStateId: string
|
||||
) {
|
||||
if (duplicateToken) {
|
||||
const state = mapState?.tokens[tokenStateId];
|
||||
if (state) {
|
||||
onTokensStateCreate([{ ...state, id: uuid() }]);
|
||||
}
|
||||
}
|
||||
setTokenDraggingOptions({
|
||||
dragging: true,
|
||||
tokenStateId,
|
||||
@ -76,6 +87,26 @@ function useMapTokens(
|
||||
setTokenDraggingOptions(undefined);
|
||||
}
|
||||
|
||||
const [duplicateToken, setDuplicateToken] = useState(false);
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateToken(true);
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp(event: KeyboardEvent) {
|
||||
if (shortcuts.duplicate(event)) {
|
||||
setDuplicateToken(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
setDuplicateToken(false);
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
useBlur(handleBlur);
|
||||
|
||||
function tokenFromTokenState(tokenState: TokenState) {
|
||||
return (
|
||||
map && (
|
||||
|
@ -417,6 +417,7 @@ function NetworkedMapAndTokens({ session }: { session: Session }) {
|
||||
mapActions={mapActions}
|
||||
onMapTokenStateChange={handleMapTokenStateChange}
|
||||
onMapTokenStateRemove={handleMapTokenStateRemove}
|
||||
onMapTokensStateCreate={handleMapTokensStateCreate}
|
||||
onSelectionItemsChange={handleSelectionItemsChange}
|
||||
onSelectionItemsRemove={handleSelectionItemsRemove}
|
||||
onSelectionItemsCreate={handleSelectionItemsCreate}
|
||||
|
@ -104,6 +104,7 @@ const shortcuts: Record<string, Shortcut> = {
|
||||
paste,
|
||||
delete: ({ key }) => key === "Backspace" || key === "Delete",
|
||||
disableSnapping: ({ key }) => key === "Control" || key === "Meta",
|
||||
duplicate: ({ key }) => key === "Alt",
|
||||
};
|
||||
|
||||
export default shortcuts;
|
||||
|
Loading…
Reference in New Issue
Block a user