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>;
|
||||
syncRef: React.MutableRefObject<SyncHandle | null>;
|
||||
inboxZoneRef: React.MutableRefObject<InboxZone | null>;
|
||||
canvasContainerRef: React.RefObject<HTMLDivElement | null>;
|
||||
onCanvasChange: (changedIds?: string[]) => void;
|
||||
showToast: (msg: string) => void;
|
||||
setOnlineUsers: React.Dispatch<React.SetStateAction<OnlineUser[]>>;
|
||||
@@ -53,7 +54,7 @@ interface CanvasSetupDeps {
|
||||
export function useCanvasSetup(deps: CanvasSetupDeps) {
|
||||
const {
|
||||
boardData, resolvedBoardId, user, isPublicView,
|
||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef,
|
||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef, canvasContainerRef,
|
||||
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
||||
} = deps;
|
||||
|
||||
@@ -252,21 +253,11 @@ export function useCanvasSetup(deps: CanvasSetupDeps) {
|
||||
|
||||
// Setup drag/drop and paste
|
||||
if (!isPublicView || user) {
|
||||
const canvasElements = document.querySelectorAll('canvas');
|
||||
let domContainer: HTMLElement | null = null;
|
||||
for (const c of canvasElements) {
|
||||
if (c.parentElement && c.width > 100) {
|
||||
domContainer = c.parentElement;
|
||||
break;
|
||||
const dropTarget = canvasContainerRef.current;
|
||||
if (dropTarget) {
|
||||
dropCleanupRef.current = setupDragDrop(dropTarget, viewport, scene, resolvedBoardId, onCanvasChange);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
const toolCleanupRef = useRef<(() => void) | null>(null);
|
||||
const inboxZoneRef = useRef<InboxZone | null>(null);
|
||||
const clipboardRef = useRef<SceneItem[]>([]);
|
||||
const canvasContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// UI state
|
||||
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)
|
||||
useCanvasSetup({
|
||||
boardData, resolvedBoardId, user, isPublicView,
|
||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef,
|
||||
canvasRef, selectionRef, undoRef, syncRef, inboxZoneRef, canvasContainerRef,
|
||||
onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
|
||||
});
|
||||
|
||||
@@ -473,7 +474,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
/>}
|
||||
|
||||
{/* 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 */}
|
||||
{showGrid && (() => {
|
||||
const scale = canvasTransform[0] || 1;
|
||||
|
||||
Reference in New Issue
Block a user