2025-04-10 17:46:11 +05:30
// Importing React and useEffect from React library
import React , { useEffect } from "react" ;
2025-04-10 17:52:30 +05:30
// Importing the necessary hooks and types from the application's state management stores
2025-04-10 17:46:11 +05:30
import useModuleStore , { useThreeDStore } from "../../store/useModuleStore" ;
import useToggleStore from "../../store/useUIToggleStore" ;
2025-04-10 17:52:30 +05:30
import {
useActiveSubTool ,
useActiveTool ,
useAddAction ,
useDeleteTool ,
useSelectedWallItem ,
useToggleView ,
useToolMode ,
} from "../../store/store" ;
2025-04-10 17:46:11 +05:30
import { usePlayButtonStore } from "../../store/usePlayButtonStore" ;
2025-04-10 17:52:30 +05:30
// Utility function to detect modifier keys (Ctrl, Alt, Shift) and key combinations
import { detectModifierKeys } from "./detectModifierKeys" ;
2025-04-10 17:46:11 +05:30
2025-04-10 17:52:30 +05:30
// KeyPressListener component to handle global keyboard shortcuts
const KeyPressListener : React.FC = ( ) = > {
// Accessing state and actions from different stores
const { activeModule , setActiveModule } = useModuleStore ( ) ; // Module management (e.g., builder, simulation, visualization)
const { setActiveSubTool } = useActiveSubTool ( ) ; // Sub-tool management
const { toggleUI , setToggleUI } = useToggleStore ( ) ; // UI visibility toggle
const { setToggleThreeD } = useThreeDStore ( ) ; // 3D view toggle
const { setToolMode } = useToolMode ( ) ; // Tool mode management
const { setIsPlaying } = usePlayButtonStore ( ) ; // Play button state management
// Wall and tool-related actions
const { toggleView , setToggleView } = useToggleView ( ) ; // 2D/3D toggle state
const { setDeleteTool } = useDeleteTool ( ) ; // Delete tool action
const { setAddAction } = useAddAction ( ) ; // Add action management
const { setSelectedWallItem } = useSelectedWallItem ( ) ; // Selected wall item management
const { setActiveTool } = useActiveTool ( ) ; // Active tool management
// useEffect to manage global keyboard shortcuts
2025-04-10 17:46:11 +05:30
useEffect ( ( ) = > {
// Function to handle keydown events
const handleKeyPress = ( event : KeyboardEvent ) = > {
2025-04-10 17:52:30 +05:30
// Identify the currently focused element
2025-04-10 17:46:11 +05:30
const activeElement = document . activeElement ;
2025-04-10 17:52:30 +05:30
// Check if the user is typing in an input field, textarea, or contenteditable element
const isTyping =
activeElement instanceof HTMLInputElement ||
activeElement instanceof HTMLTextAreaElement ||
( activeElement && activeElement . getAttribute ( "contenteditable" ) === "true" ) ;
2025-04-10 17:46:11 +05:30
if ( isTyping ) {
2025-04-10 17:52:30 +05:30
return ; // Skip shortcut handling while typing
2025-04-10 17:46:11 +05:30
}
2025-04-10 17:52:30 +05:30
// Detect the combination of keys pressed
2025-04-10 17:46:11 +05:30
const keyCombination = detectModifierKeys ( event ) ;
2025-04-10 17:52:30 +05:30
// Allow browser default behavior for specific keys (e.g., F5 for refresh)
2025-04-10 17:46:11 +05:30
if ( [ "F5" , "F11" , "F12" ] . includes ( event . key ) || keyCombination === "Ctrl+R" ) {
return ;
}
2025-04-10 17:52:30 +05:30
// Prevent the default browser action for other handled key presses
2025-04-10 17:46:11 +05:30
event . preventDefault ( ) ;
if ( keyCombination ) {
2025-04-10 17:52:30 +05:30
// Switch between different modules (e.g., builder, simulation)
2025-04-10 17:46:11 +05:30
if ( keyCombination === "1" && ! toggleView ) {
setActiveTool ( "cursor" ) ;
setActiveSubTool ( "cursor" ) ;
setActiveModule ( "builder" ) ;
}
if ( keyCombination === "2" && ! toggleView ) {
setActiveTool ( "cursor" ) ;
setActiveSubTool ( "cursor" ) ;
setActiveModule ( "simulation" ) ;
}
if ( keyCombination === "3" && ! toggleView ) {
setActiveTool ( "cursor" ) ;
setActiveSubTool ( "cursor" ) ;
setActiveModule ( "visualization" ) ;
}
if ( keyCombination === "4" && ! toggleView ) {
setActiveTool ( "cursor" ) ;
setActiveSubTool ( "cursor" ) ;
setToggleUI ( false ) ;
setActiveModule ( "market" ) ;
}
2025-04-10 17:52:30 +05:30
// Toggle UI visibility
2025-04-10 17:46:11 +05:30
if ( keyCombination === "Ctrl+." && activeModule !== "market" ) {
setToggleUI ( ! toggleUI ) ;
}
2025-04-10 17:52:30 +05:30
// Tool selection shortcuts
2025-04-10 17:46:11 +05:30
if ( keyCombination === "V" ) {
setActiveTool ( "cursor" ) ;
setActiveSubTool ( "cursor" ) ;
}
if ( keyCombination === "X" ) {
setActiveTool ( "delete" ) ;
setActiveSubTool ( "delete" ) ;
}
if ( keyCombination === "H" ) {
setActiveTool ( "free-hand" ) ;
setActiveSubTool ( "free-hand" ) ;
}
2025-04-10 17:52:30 +05:30
// Toggle play mode
2025-04-10 17:46:11 +05:30
if ( keyCombination === "Ctrl+P" && ! toggleView ) {
setIsPlaying ( true ) ;
}
2025-04-10 17:52:30 +05:30
// Builder-specific shortcuts
2025-04-10 17:46:11 +05:30
if ( activeModule === "builder" ) {
if ( keyCombination === "TAB" ) {
2025-04-10 17:52:30 +05:30
// Switch between 2D and 3D views
2025-04-10 17:46:11 +05:30
if ( toggleView ) {
setToggleView ( false ) ;
setToggleThreeD ( true ) ;
setActiveTool ( "cursor" ) ;
} else {
setSelectedWallItem ( null ) ;
setDeleteTool ( false ) ;
setAddAction ( null ) ;
setToggleView ( true ) ;
setToggleThreeD ( false ) ;
setActiveTool ( "cursor" ) ;
}
}
2025-04-10 17:52:30 +05:30
// Wall-related tools
2025-04-10 17:46:11 +05:30
if ( toggleView ) {
if ( keyCombination === "Q" || keyCombination === "6" ) {
setActiveTool ( "draw-wall" ) ;
setToolMode ( "Wall" ) ;
}
if ( keyCombination === "R" || keyCombination === "7" ) {
setActiveTool ( "draw-aisle" ) ;
setToolMode ( "Aisle" ) ;
}
if ( keyCombination === "E" || keyCombination === "8" ) {
setActiveTool ( "draw-zone" ) ;
setToolMode ( "Zone" ) ;
}
if ( keyCombination === "T" || keyCombination === "9" ) {
setActiveTool ( "draw-floor" ) ;
setToolMode ( "Floor" ) ;
}
}
2025-04-10 17:52:30 +05:30
// Measurement tool
2025-04-10 17:46:11 +05:30
if ( keyCombination === "M" ) {
setActiveTool ( "measure" ) ;
setToolMode ( "MeasurementScale" ) ;
}
}
2025-04-10 17:52:30 +05:30
// Undo and redo actions
2025-04-10 17:46:11 +05:30
if ( keyCombination === "Ctrl+Z" ) {
2025-04-10 17:52:30 +05:30
// Handle undo action
2025-04-10 17:46:11 +05:30
}
if ( keyCombination === "Ctrl+Y" || keyCombination === "Ctrl+Shift+Z" ) {
2025-04-10 17:52:30 +05:30
// Handle redo action
}
// Helper actions
if ( keyCombination === "Ctrl+H" ) {
// Open help
}
if ( keyCombination === "Ctrl+F" ) {
// Open find functionality
}
if ( keyCombination === "Ctrl+?" ) {
// Show shortcuts info
2025-04-10 17:46:11 +05:30
}
2025-04-10 17:52:30 +05:30
// Reset to cursor tool and stop play mode
2025-04-10 17:46:11 +05:30
if ( keyCombination === "ESCAPE" ) {
setActiveTool ( "cursor" ) ;
setIsPlaying ( false ) ;
}
}
} ;
2025-04-10 17:52:30 +05:30
// Add keydown event listener
2025-04-10 17:46:11 +05:30
window . addEventListener ( "keydown" , handleKeyPress ) ;
2025-04-10 17:52:30 +05:30
// Cleanup function to remove the event listener
2025-04-10 17:46:11 +05:30
return ( ) = > {
window . removeEventListener ( "keydown" , handleKeyPress ) ;
} ;
2025-04-29 13:42:24 +05:30
} , [ activeModule , setActiveModule , setActiveSubTool , setActiveTool , setAddAction , setDeleteTool , setIsPlaying , setSelectedWallItem , setToggleThreeD , setToggleUI , setToggleView , setToolMode , toggleUI , toggleView ] ) ; // Dependencies to reapply effect if these values change
2025-04-10 17:46:11 +05:30
2025-04-10 17:52:30 +05:30
return null ; // This component does not render any UI
2025-04-10 17:46:11 +05:30
} ;
export default KeyPressListener ;