241 lines
7.2 KiB
TypeScript
241 lines
7.2 KiB
TypeScript
import React, { useEffect } from "react";
|
|
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
|
import { usePlayerStore, useToggleStore } from "../../store/useUIToggleStore";
|
|
import {
|
|
useActiveSubTool,
|
|
useActiveTool,
|
|
useAddAction,
|
|
useDeleteTool,
|
|
useSaveVersion,
|
|
useSelectedWallItem,
|
|
useShortcutStore,
|
|
useToggleView,
|
|
useToolMode,
|
|
useViewSceneStore,
|
|
} from "../../store/builder/store";
|
|
import useCameraModeStore, {
|
|
usePlayButtonStore,
|
|
} from "../../store/usePlayButtonStore";
|
|
import { detectModifierKeys } from "./detectModifierKeys";
|
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
|
import { useLogger } from "../../components/ui/log/LoggerContext";
|
|
|
|
const KeyPressListener: React.FC = () => {
|
|
const { activeModule, setActiveModule } = useModuleStore();
|
|
const { setActiveSubTool } = useActiveSubTool();
|
|
const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
|
|
const { setToggleThreeD } = useThreeDStore();
|
|
const { setToolMode } = useToolMode();
|
|
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
|
const { toggleView, setToggleView } = useToggleView();
|
|
const { setDeleteTool } = useDeleteTool();
|
|
const { setAddAction } = useAddAction();
|
|
const { setSelectedWallItem } = useSelectedWallItem();
|
|
const { setActiveTool } = useActiveTool();
|
|
const { clearSelectedZone } = useSelectedZoneStore();
|
|
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
|
const { setWalkMode } = useCameraModeStore();
|
|
const { setIsVersionSaved } = useSaveVersion();
|
|
const { isLogListVisible, setIsLogListVisible } = useLogger();
|
|
const { hidePlayer, setHidePlayer } = usePlayerStore();
|
|
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
|
|
|
const isTextInput = (element: Element | null): boolean =>
|
|
element instanceof HTMLInputElement ||
|
|
element instanceof HTMLTextAreaElement ||
|
|
element?.getAttribute("contenteditable") === "true";
|
|
|
|
const handleModuleSwitch = (keyCombination: string) => {
|
|
const modules: Record<string, string> = {
|
|
"1": "builder",
|
|
"2": "simulation",
|
|
"3": "visualization",
|
|
"4": "market",
|
|
};
|
|
const module = modules[keyCombination];
|
|
if (module && !toggleView) {
|
|
console.log("hi");
|
|
setActiveTool("cursor");
|
|
setActiveSubTool("cursor");
|
|
if (module === "market") setToggleUI(false, false);
|
|
setActiveModule(module);
|
|
}
|
|
};
|
|
|
|
const handlePrimaryTools = (key: string) => {
|
|
const toolMap: Record<string, string> = {
|
|
V: "cursor",
|
|
X: "delete",
|
|
H: "free-hand",
|
|
};
|
|
const tool = toolMap[key];
|
|
if (tool) {
|
|
setActiveTool(tool);
|
|
setActiveSubTool(tool);
|
|
}
|
|
};
|
|
|
|
const handleBuilderShortcuts = (key: string) => {
|
|
if (activeModule !== "builder" || isPlaying) return;
|
|
|
|
if (key === "TAB") {
|
|
const toggleTo2D = toggleView;
|
|
setToggleView(!toggleTo2D);
|
|
setToggleThreeD(toggleTo2D);
|
|
setToggleUI(toggleTo2D, toggleTo2D);
|
|
if (toggleTo2D) {
|
|
setSelectedWallItem(null);
|
|
setDeleteTool(false);
|
|
setAddAction(null);
|
|
}
|
|
setActiveTool("cursor");
|
|
setActiveSubTool("cursor");
|
|
return;
|
|
}
|
|
|
|
// These should only apply in 2D view
|
|
const twoDToolConfigs: Record<string, { tool: string; mode: string }> = {
|
|
Q: { tool: "draw-wall", mode: "Wall" },
|
|
"6": { tool: "draw-wall", mode: "Wall" },
|
|
R: { tool: "draw-aisle", mode: "Aisle" },
|
|
"7": { tool: "draw-aisle", mode: "Aisle" },
|
|
E: { tool: "draw-zone", mode: "Zone" },
|
|
"8": { tool: "draw-zone", mode: "Zone" },
|
|
T: { tool: "draw-floor", mode: "Floor" },
|
|
"9": { tool: "draw-floor", mode: "Floor" },
|
|
};
|
|
|
|
const config = twoDToolConfigs[key];
|
|
if (toggleView && config) {
|
|
setActiveTool(config.tool);
|
|
setToolMode(config.mode);
|
|
}
|
|
|
|
// Measurement tool should work in both 2D and 3D
|
|
if (key === "M") {
|
|
setActiveTool("measure");
|
|
setToolMode("MeasurementScale");
|
|
}
|
|
};
|
|
|
|
const handleSidebarShortcuts = (key: string) => {
|
|
if (activeModule === "market") return;
|
|
|
|
const updateLocalStorage = (left: boolean, right: boolean) => {
|
|
localStorage.setItem("navBarUiLeft", JSON.stringify(left));
|
|
localStorage.setItem("navBarUiRight", JSON.stringify(right));
|
|
};
|
|
|
|
switch (key) {
|
|
case "Ctrl+\\":
|
|
if (toggleUILeft === toggleUIRight) {
|
|
const newState = !toggleUILeft;
|
|
setToggleUI(newState, newState);
|
|
updateLocalStorage(newState, newState);
|
|
} else {
|
|
setToggleUI(true, true);
|
|
updateLocalStorage(true, true);
|
|
}
|
|
break;
|
|
|
|
case "Ctrl+]":
|
|
setToggleUI(toggleUILeft, !toggleUIRight);
|
|
updateLocalStorage(toggleUILeft, !toggleUIRight);
|
|
break;
|
|
|
|
case "Ctrl+[":
|
|
setToggleUI(!toggleUILeft, toggleUIRight);
|
|
updateLocalStorage(!toggleUILeft, toggleUIRight);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
const handleKeyPress = (event: KeyboardEvent) => {
|
|
console.log(
|
|
"isTextInput(document.activeElement): ",
|
|
isTextInput(document.activeElement)
|
|
);
|
|
if (isTextInput(document.activeElement)) return;
|
|
|
|
const keyCombination = detectModifierKeys(event);
|
|
if (
|
|
!keyCombination ||
|
|
["F5", "F11", "F12"].includes(event.key) ||
|
|
keyCombination === "Ctrl+R"
|
|
)
|
|
return;
|
|
console.log("keyCombination: ", keyCombination);
|
|
|
|
event.preventDefault();
|
|
|
|
// Shortcuts specific for sidebar visibility toggle and others specific to sidebar if added
|
|
handleSidebarShortcuts(keyCombination);
|
|
// Active module selection (builder, simulation, etc.)
|
|
handleModuleSwitch(keyCombination);
|
|
// Common editing tools: cursor | delete | free-hand
|
|
handlePrimaryTools(keyCombination);
|
|
// Shortcuts specific to the builder module (e.g., drawing and measurement tools)
|
|
handleBuilderShortcuts(keyCombination);
|
|
|
|
// Shortcut to enter play mode
|
|
if (keyCombination === "Ctrl+P" && !toggleView) {
|
|
setIsPlaying(true);
|
|
}
|
|
|
|
if (keyCombination === "L") {
|
|
setIsLogListVisible(!isLogListVisible);
|
|
}
|
|
|
|
if (keyCombination === "H") {
|
|
setHidePlayer(!hidePlayer);
|
|
}
|
|
|
|
if (keyCombination === "ESCAPE") {
|
|
setWalkMode(false);
|
|
setActiveTool("cursor");
|
|
setActiveSubTool("cursor");
|
|
setIsPlaying(false);
|
|
clearSelectedZone();
|
|
setShowShortcuts(false);
|
|
setIsVersionSaved(false);
|
|
setIsLogListVisible(false);
|
|
}
|
|
|
|
if (keyCombination === "Ctrl+Shift+?") {
|
|
setShowShortcuts(!showShortcuts);
|
|
}
|
|
if (keyCombination === "U") {
|
|
console.log("viewSceneLabels: ", viewSceneLabels);
|
|
setViewSceneLabels((prev) => !prev);
|
|
}
|
|
// Placeholder for future implementation
|
|
if (
|
|
["Ctrl+Z", "Ctrl+Y", "Ctrl+Shift+Z", "Ctrl+F"].includes(keyCombination)
|
|
) {
|
|
// Implement undo/redo/help/find/shortcuts
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
window.addEventListener("keydown", handleKeyPress);
|
|
return () => window.removeEventListener("keydown", handleKeyPress);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [
|
|
activeModule,
|
|
toggleUIRight,
|
|
toggleUILeft,
|
|
toggleView,
|
|
showShortcuts,
|
|
isPlaying,
|
|
isLogListVisible,
|
|
hidePlayer,
|
|
]);
|
|
|
|
return null;
|
|
};
|
|
|
|
export default KeyPressListener;
|