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:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user