fix(refboard): place multi-dropped images side-by-side instead of overlapping

Images dropped together are now laid out horizontally with a 20px gap,
using each image's actual rendered width to calculate the next position.
This commit is contained in:
Hiren Kangad
2026-03-10 04:01:29 +05:30
parent e9509ef7b0
commit cfd17c4c2e
+12 -10
View File
@@ -29,6 +29,7 @@ function removePlaceholder(viewport: Viewport, g: Graphics) {
/* Handle upload response (image or video) */ /* Handle upload response (image or video) */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
/** Returns the placed width so callers can offset subsequent items. */
function handleUploadResult( function handleUploadResult(
res: any, res: any,
viewport: Viewport, viewport: Viewport,
@@ -36,7 +37,7 @@ function handleUploadResult(
x: number, x: number,
y: number, y: number,
onChange: OnChange, onChange: OnChange,
) { ): number {
const imgData = res.data.image || res.data; const imgData = res.data.image || res.data;
const mediaType: string = imgData.media_type || 'image'; const mediaType: string = imgData.media_type || 'image';
const assetKey: string | undefined = imgData.asset_key; const assetKey: string | undefined = imgData.asset_key;
@@ -64,6 +65,7 @@ function handleUploadResult(
} }
onChange(); onChange();
return finalW;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -118,26 +120,26 @@ export function setupDragDrop(
return; return;
} }
let dropIndex = 0; const rect = container.getBoundingClientRect();
const world = viewport.toWorld(e.clientX - rect.left, e.clientY - rect.top);
const GAP = 20; // px gap between dropped images
let cursorX = world.x; // running x position for side-by-side placement
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
const file = files[i]; const file = files[i];
if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) continue; if (!file.type.startsWith('image/') && !file.type.startsWith('video/')) continue;
const rect = container.getBoundingClientRect(); const placeholder = createPlaceholder(viewport, cursorX, world.y);
const world = viewport.toWorld(e.clientX - rect.left, e.clientY - rect.top);
// Offset each subsequent file so they don't overlap
const offsetX = dropIndex * 30;
const offsetY = dropIndex * 30;
const placeholder = createPlaceholder(viewport, world.x + offsetX, world.y + offsetY);
dropIndex++;
try { try {
const res = await uploadImage(boardId, file); const res = await uploadImage(boardId, file);
removePlaceholder(viewport, placeholder); removePlaceholder(viewport, placeholder);
handleUploadResult(res, viewport, sceneManager, world.x + offsetX, world.y + offsetY, onChange); const placedWidth = handleUploadResult(res, viewport, sceneManager, cursorX, world.y, onChange);
cursorX += placedWidth + GAP;
} catch (err) { } catch (err) {
console.error('Image upload failed:', err); console.error('Image upload failed:', err);
removePlaceholder(viewport, placeholder); removePlaceholder(viewport, placeholder);
cursorX += 220; // fallback offset if upload fails
} }
} }
} }