fix(refboard): drag-drop opening in new tab — use ref for drop target
The drag/drop setup was searching for a <canvas> element to find its parent, which was fragile and could fail (returning null). When it failed, document-level dragover/drop prevention was never registered, so the browser's default behavior (open file in new tab) kicked in. Fix: pass a direct ref to the outer canvas container div from Editor to useCanvasSetup. No more DOM querying for the drop target.
This commit is contained in:
@@ -40,6 +40,7 @@ interface CanvasSetupDeps {
|
|||||||
undoRef: React.MutableRefObject<UndoManager | null>;
|
undoRef: React.MutableRefObject<UndoManager | null>;
|
||||||
syncRef: React.MutableRefObject<SyncHandle | null>;
|
syncRef: React.MutableRefObject<SyncHandle | null>;
|
||||||
inboxZoneRef: React.MutableRefObject<InboxZone | null>;
|
inboxZoneRef: React.MutableRefObject<InboxZone | null>;
|
||||||
|
canvasContainerRef: React.RefObject<HTMLDivElement | null>;
|
||||||
onCanvasChange: (changedIds?: string[]) => void;
|
onCanvasChange: (changedIds?: string[]) => void;
|
||||||
showToast: (msg: string) => void;
|
showToast: (msg: string) => void;
|
||||||
setOnlineUsers: React.Dispatch<React.SetStateAction<OnlineUser[]>>;
|
setOnlineUsers: React.Dispatch<React.SetStateAction<OnlineUser[]>>;
|
||||||
@@ -53,7 +54,7 @@ interface CanvasSetupDeps {
|
|||||||
export function useCanvasSetup(deps: CanvasSetupDeps) {
|
export function useCanvasSetup(deps: CanvasSetupDeps) {
|
||||||
const {
|
const {
|
||||||
boardData, resolvedBoardId, user, isPublicView,
|
boardData, resolvedBoardId, user, isPublicView,
|
||||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef,
|
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef, canvasContainerRef,
|
||||||
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
||||||
} = deps;
|
} = deps;
|
||||||
|
|
||||||
@@ -252,21 +253,11 @@ export function useCanvasSetup(deps: CanvasSetupDeps) {
|
|||||||
|
|
||||||
// Setup drag/drop and paste
|
// Setup drag/drop and paste
|
||||||
if (!isPublicView || user) {
|
if (!isPublicView || user) {
|
||||||
const canvasElements = document.querySelectorAll('canvas');
|
const dropTarget = canvasContainerRef.current;
|
||||||
let domContainer: HTMLElement | null = null;
|
if (dropTarget) {
|
||||||
for (const c of canvasElements) {
|
dropCleanupRef.current = setupDragDrop(dropTarget, viewport, scene, resolvedBoardId, onCanvasChange);
|
||||||
if (c.parentElement && c.width > 100) {
|
|
||||||
domContainer = c.parentElement;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domContainer) {
|
|
||||||
dropCleanupRef.current = setupDragDrop(domContainer, viewport, scene, resolvedBoardId, onCanvasChange);
|
|
||||||
pasteCleanupRef.current = setupPaste(viewport, scene, resolvedBoardId, onCanvasChange);
|
|
||||||
} else {
|
|
||||||
pasteCleanupRef.current = setupPaste(viewport, scene, resolvedBoardId, onCanvasChange);
|
|
||||||
}
|
}
|
||||||
|
pasteCleanupRef.current = setupPaste(viewport, scene, resolvedBoardId, onCanvasChange);
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
|||||||
const toolCleanupRef = useRef<(() => void) | null>(null);
|
const toolCleanupRef = useRef<(() => void) | null>(null);
|
||||||
const inboxZoneRef = useRef<InboxZone | null>(null);
|
const inboxZoneRef = useRef<InboxZone | null>(null);
|
||||||
const clipboardRef = useRef<SceneItem[]>([]);
|
const clipboardRef = useRef<SceneItem[]>([]);
|
||||||
|
const canvasContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// UI state
|
// UI state
|
||||||
const [activeTool, setActiveTool] = useState<ToolType>(ToolType.SELECT);
|
const [activeTool, setActiveTool] = useState<ToolType>(ToolType.SELECT);
|
||||||
@@ -136,7 +137,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
|||||||
// Canvas setup (selection, undo, sync, socket, drag/drop, paste, inbox)
|
// Canvas setup (selection, undo, sync, socket, drag/drop, paste, inbox)
|
||||||
useCanvasSetup({
|
useCanvasSetup({
|
||||||
boardData, resolvedBoardId, user, isPublicView,
|
boardData, resolvedBoardId, user, isPublicView,
|
||||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef,
|
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef, canvasContainerRef,
|
||||||
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -473,7 +474,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
|||||||
/>}
|
/>}
|
||||||
|
|
||||||
{/* Canvas */}
|
{/* Canvas */}
|
||||||
<div style={{ flex: 1, position: 'relative', overflow: 'hidden', background: '#1e1e1e' }} onContextMenu={handleContextMenu}>
|
<div ref={canvasContainerRef} style={{ flex: 1, position: 'relative', overflow: 'hidden', background: '#1e1e1e' }} onContextMenu={handleContextMenu}>
|
||||||
{/* Dot grid — behind transparent canvas */}
|
{/* Dot grid — behind transparent canvas */}
|
||||||
{showGrid && (() => {
|
{showGrid && (() => {
|
||||||
const scale = canvasTransform[0] || 1;
|
const scale = canvasTransform[0] || 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user