BareGit

Fix asset drop clientx issue.

On Windows Firefox, the clientX property of the dragend event is
unreliable. Use the drop event.
Author: MetroWind <chris.corsair@gmail.com>
Date: Sun Aug 31 22:08:18 2025 -0700
Commit: bdbac00d7935a0c52a0f5198d56d00a4b033c8a2

Changes

diff --git a/scripts/main.js b/scripts/main.js
index 8f3bbee..d6b6787 100644
--- a/scripts/main.js
+++ b/scripts/main.js
@@ -4,15 +4,13 @@ const DEFAULT_APP_STATE = {
         new Array(GRID_SIZE_X * GRID_SIZE_Y).fill(0)),
     // mouse_state can be “normal”, or “dnd”.
     mouse_state: "normal",
+    dragged_asset_index: null,
     plan_code: "",
 };
 
 async function serializePlan(app_state)
 {
-    let rest = new Array(GRID_SIZE_X * GRID_SIZE_Y * (FLOOR_COUNT - 1)).fill(0);
-    let concated_plans =
-        app_state.plan.reduce((big, floor_plan) => big.concat(floor_plan), []);
-    return compressBytes(Uint8Array.from(concated_plans));
+    return compressBytes(Uint8Array.from(app_state.plan.flat()));
 }
 
 function genGrid(x_count, y_count, cell_size)
@@ -58,7 +56,7 @@ function AssetsView({on_drag_begin, on_drag_end})
     return h("div", {}, views);
 }
 
-function PlanGridView({content, mouse_state})
+function PlanGridView({content, mouse_state, on_drop_asset})
 {
     const [mouse_coord, setMouseCoord] = preactHooks.useState(null);
 
@@ -109,6 +107,7 @@ ${cell_y * (CELL_SIZE + 1) + 1})`}, bg, TILES[idx].inner_svg);
     let img_height = GRID_SIZE_Y * (CELL_SIZE + 1) + 1;
     return h("svg", {"width": img_width, "height": img_height,
                      "version": "1.1", "ondragover": onDragOver,
+                     "ondrop": on_drop_asset,
                      "id": "Grid", "ondragleave": onDragLeave,},
              h("rect", {x: 0, y: 0, width: img_width, height: img_height,
                         fill: "#c0c0c0", "stroke-width": 0}),
@@ -116,11 +115,12 @@ ${cell_y * (CELL_SIZE + 1) + 1})`}, bg, TILES[idx].inner_svg);
              hilight_box);
 }
 
-function PlanView({plan, mouse_state})
+function PlanView({plan, mouse_state, on_drop_asset})
 {
     return h("div", {"id": "PlanView"},
              h("div", {"id": "EntryIndicator"}, "⬇️"),
-             h(PlanGridView, {content: plan, mouse_state: mouse_state}));
+             h(PlanGridView, {content: plan, mouse_state: mouse_state,
+                              on_drop_asset: on_drop_asset}));
 }
 
 // on_floor_change takes one argument, which is the 0-based floor number.
@@ -137,28 +137,31 @@ function App({initial_state})
 {
     const [state, setState] = preactHooks.useState(initial_state);
 
+    // This event is targeted at the dragged asset.
     function onDragAssetBegin(e)
     {
         let new_state = structuredClone(state);
         new_state.mouse_state = "dnd";
+        new_state.dragged_asset_index =
+            parseInt(e.target.getAttribute("data-asset-index"));
         setState(new_state);
     }
-    function onDragAssetEnd(e)
+
+    // This event is targeted at the grid.
+    function onDropAssetOnGrid(e)
     {
         if(e.dragEffect === "none") return;
         let grid = document.getElementById("Grid");
         let b = grid.getBoundingClientRect();
         let x = e.clientX - b.left;
         let y = e.clientY - b.top;
-        if(x < 0 || y < 0 || x > b.width || y > b.height) return;
         let cell_x = Math.floor(x / (CELL_SIZE + 1));
         let cell_y = Math.floor(y / (CELL_SIZE + 1));
         let cell_index = cell_y * GRID_SIZE_X + cell_x;
-        let asset_index = parseInt(e.target.getAttribute("data-asset-index"));
-
         let new_state = structuredClone(state);
-        new_state.plan[new_state.floor][cell_index] = asset_index;
+        new_state.plan[new_state.floor][cell_index] = state.dragged_asset_index;
         new_state.mouse_state = "normal";
+        new_state.dragged_asset_index = null;
         serializePlan(new_state).then((s) => {
             new_state.plan_code = s;
             setState(new_state);
@@ -206,10 +209,10 @@ function App({initial_state})
                                    on_floor_change: onFloorChange}),
                  h("div", {"class": "LabeledPanel"},
                    h("h2", {}, "Rooms"),
-                   h(AssetsView, {on_drag_begin: onDragAssetBegin,
-                                  on_drag_end: onDragAssetEnd}))),
+                   h(AssetsView, {on_drag_begin: onDragAssetBegin,}))),
                h(PlanView, {plan: state.plan[state.floor],
-                            mouse_state: state.mouse_state})),
+                            mouse_state: state.mouse_state,
+                            on_drop_asset: onDropAssetOnGrid,})),
              h("hr", {}),
              h("div", {},
                h("textarea", {readonly: true}, state.plan_code)),