Skip to content

Commit 9fcf68c

Browse files
Copilotmikebarkmin
andcommitted
Refactor touch support to use @neodrag/react library
Co-authored-by: mikebarkmin <2592379+mikebarkmin@users.noreply.github.com>
1 parent b3ab91a commit 9fcf68c

4 files changed

Lines changed: 69 additions & 73 deletions

File tree

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@codemirror/state": "^6.5.0",
1717
"@codemirror/view": "^6.36.2",
1818
"@lezer/common": "^1.2.3",
19+
"@neodrag/react": "^2.3.1",
1920
"@uiw/codemirror-extensions-langs": "^4.23.0",
2021
"@uiw/react-codemirror": "^4.23.0",
2122
"@xyflow/react": "^12.3.6",

src/MemoryView.tsx

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ export const MemoryView = () => {
108108
const [reactFlowInstance, setReactFlowInstance] =
109109
useState<ReactFlowInstance<CustomNodeType, CustomEdgeType> | null>(null);
110110
const connectingNode = useRef<OnConnectStartParams | null>(null);
111-
const [placementMode, setPlacementMode] = useState<string | null>(null);
112111

113112
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
114113
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
@@ -450,34 +449,23 @@ export const MemoryView = () => {
450449
}
451450
};
452451

453-
const onPaneClick = useCallback(
454-
(event: any) => {
455-
if (!placementMode || !reactFlowInstance) return;
452+
const onNodeDrop = useCallback(
453+
(nodeType: string, offsetX: number, offsetY: number) => {
454+
if (!reactFlowInstance) return;
456455

457456
const position = reactFlowInstance.screenToFlowPosition({
458-
x: event.clientX,
459-
y: event.clientY,
457+
x: offsetX,
458+
y: offsetY,
460459
});
461-
462-
createNodeAtPosition(placementMode, position);
463-
setPlacementMode(null);
460+
461+
createNodeAtPosition(nodeType, position);
464462
},
465-
[placementMode, reactFlowInstance, lastMethodCall]
463+
[reactFlowInstance, lastMethodCall]
466464
);
467465

468-
const onTouchItemSelect = useCallback((nodeType: string) => {
469-
setPlacementMode(nodeType);
470-
}, []);
471-
472466
return (
473467
<div className="memory-view">
474-
{!memory.options.hideSidebar && <Sidebar memory={memory} onTouchItemSelect={onTouchItemSelect} />}
475-
{placementMode && (
476-
<div className="placement-mode-indicator">
477-
Tap on canvas to place: {placementMode === "method-call" ? "Method Call" : placementMode === "variable" ? "Global Variable" : `new ${placementMode}`}
478-
<button onClick={() => setPlacementMode(null)} className="cancel-placement">Cancel</button>
479-
</div>
480-
)}
468+
{!memory.options.hideSidebar && <Sidebar memory={memory} onNodeDrop={onNodeDrop} />}
481469
<ReactFlowProvider>
482470
<ReactFlow
483471
className="memory"
@@ -538,7 +526,6 @@ export const MemoryView = () => {
538526
onInit={setReactFlowInstance}
539527
onDrop={onDrop}
540528
onDragOver={onDragOver}
541-
onPaneClick={placementMode ? onPaneClick : undefined}
542529
onNodesChange={onNodesChange}
543530
onEdgesChange={onEdgesChange}
544531
proOptions={{

src/Sidebar.tsx

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,75 @@
11
import { Memory } from "./memory";
2-
import { useEffect, useState } from "react";
2+
import { useDraggable } from "@neodrag/react";
3+
import { useRef } from "react";
4+
5+
interface DraggableNodeProps {
6+
className: string;
7+
children: React.ReactNode;
8+
nodeType: string;
9+
onDrop: (nodeType: string, offsetX: number, offsetY: number) => void;
10+
}
11+
12+
function DraggableNode({ className, children, nodeType, onDrop }: DraggableNodeProps) {
13+
const draggableRef = useRef<HTMLDivElement>(null);
14+
15+
useDraggable(draggableRef, {
16+
onDragEnd: (data) => {
17+
onDrop(nodeType, data.offsetX, data.offsetY);
18+
},
19+
});
20+
21+
return (
22+
<div ref={draggableRef} className={className} style={{ cursor: 'grab' }}>
23+
{children}
24+
</div>
25+
);
26+
}
327

428
export const Sidebar = ({
529
memory,
6-
onTouchItemSelect,
30+
onNodeDrop,
731
}: {
832
memory: Memory;
9-
onTouchItemSelect?: (nodeType: string) => void;
33+
onNodeDrop: (nodeType: string, offsetX: number, offsetY: number) => void;
1034
}) => {
11-
const [isTouchDevice, setIsTouchDevice] = useState(false);
12-
13-
useEffect(() => {
14-
// Detect touch device
15-
const checkTouch = () => {
16-
setIsTouchDevice(
17-
"ontouchstart" in window ||
18-
navigator.maxTouchPoints > 0 ||
19-
(navigator as any).msMaxTouchPoints > 0
20-
);
21-
};
22-
checkTouch();
23-
}, []);
24-
25-
const onDragStart = (event: any, nodeType: string) => {
26-
event.dataTransfer.setData("application/java-memory-playground", nodeType);
27-
event.dataTransfer.effectAllowed = "move";
28-
};
29-
30-
const onTouchStart = (nodeType: string) => {
31-
if (onTouchItemSelect) {
32-
onTouchItemSelect(nodeType);
33-
}
34-
};
35-
36-
const getItemProps = (nodeType: string) => {
37-
if (isTouchDevice) {
38-
return {
39-
onTouchStart: (e: any) => {
40-
e.preventDefault();
41-
onTouchStart(nodeType);
42-
},
43-
};
44-
}
45-
return {
46-
onDragStart: (e: any) => onDragStart(e, nodeType),
47-
draggable: true,
48-
};
49-
};
50-
5135
return (
5236
<div className="sidebar">
5337
{Object.entries(memory.klasses).map(([name]) => (
54-
<div key={name} className="sidebar-class" {...getItemProps(name)}>
38+
<DraggableNode
39+
key={name}
40+
className="sidebar-class"
41+
nodeType={name}
42+
onDrop={onNodeDrop}
43+
>
5544
new {name}
56-
</div>
45+
</DraggableNode>
5746
))}
5847
{!memory.options.hideNewArray && (
59-
<div className="sidebar-class" {...getItemProps("Array")}>
48+
<DraggableNode
49+
className="sidebar-class"
50+
nodeType="Array"
51+
onDrop={onNodeDrop}
52+
>
6053
new Array
61-
</div>
54+
</DraggableNode>
6255
)}
6356
{!memory.options.hideDeclareGlobalVariable && (
64-
<div className="sidebar-variable" {...getItemProps("variable")}>
57+
<DraggableNode
58+
className="sidebar-variable"
59+
nodeType="variable"
60+
onDrop={onNodeDrop}
61+
>
6562
Declare Global Variable
66-
</div>
63+
</DraggableNode>
6764
)}
6865
{!memory.options.hideCallMethod && (
69-
<div className="sidebar-method-call" {...getItemProps("method-call")}>
66+
<DraggableNode
67+
className="sidebar-method-call"
68+
nodeType="method-call"
69+
onDrop={onNodeDrop}
70+
>
7071
Call Method
71-
</div>
72+
</DraggableNode>
7273
)}
7374
</div>
7475
);

0 commit comments

Comments
 (0)