Changes
diff --git a/scripts/lib.js b/scripts/lib.js
index 4e4850e..9a5e957 100644
--- a/scripts/lib.js
+++ b/scripts/lib.js
@@ -2,9 +2,39 @@ const h = preact.h;
const CELL_SIZE = 32;
const GRID_SIZE_X = 21;
const GRID_SIZE_Y = 21;
+const FLOOR_COUNT = 15;
const ASSET_SVG_PROPS = {"width": CELL_SIZE, "height": CELL_SIZE,
"version": "1.1"};
const ASSET_WHITE_BG = h("rect", {"x": 0, "y": 0, "width": CELL_SIZE,
"height": CELL_SIZE, "fill": "white",
"stroke-width": 0 });
+
+// Bytes is a Uint8Array
+async function compressBytes(bytes)
+{
+ let blob = new Blob([bytes]);
+ const ds = new CompressionStream("deflate");
+ const compressed = blob.stream().pipeThrough(ds);
+ let compressed_blob = await new Response(compressed).blob();
+ const reader = new FileReader();
+ return new Promise((resolve, _) => {
+ reader.onloadend = (event) => {
+ const result = event.target.result;
+ resolve(result.replace(/^data:.+;base64,/, '')
+ .replaceAll("/", "-").replaceAll("+", "_"));
+ }
+ reader.readAsDataURL(compressed_blob);
+ });
+}
+
+// Decompress into Uint8Array
+function decompressBytes(s)
+{
+ const decoded = window.atob(s.replaceAll("_", "+").replaceAll("-", "/"));
+ const decoded_array = Uint8Array.from(decoded, c => c.charCodeAt(0));
+ let blob = new Blob([decoded_array]);
+ const cs = new DecompressionStream("deflate");
+ const decompressed = blob.stream().pipeThrough(cs);
+ return new Response(decompressed).bytes();
+}
diff --git a/scripts/main.js b/scripts/main.js
index 01301a1..7347f37 100644
--- a/scripts/main.js
+++ b/scripts/main.js
@@ -3,8 +3,15 @@ const DEFAULT_APP_STATE = {
plan: new Array(GRID_SIZE_X * GRID_SIZE_Y).fill(0),
// mouse_state can be “normal”, or “dnd”.
mouse_state: "normal",
+ plan_code: "",
};
+async function serializePlan(app_state)
+{
+ let rest = new Array(GRID_SIZE_X * GRID_SIZE_Y * (FLOOR_COUNT - 1)).fill(0);
+ return compressBytes(Uint8Array.from(app_state.plan.concat(rest)));
+}
+
function genGrid(x_count, y_count, cell_size)
{
let lines = [];
@@ -62,7 +69,6 @@ function PlanGridView({content, mouse_state})
}
let hilight_box = null;
- console.debug(mouse_coord);
if(mouse_coord !== null && mouse_state != "dnd")
{
@@ -130,7 +136,13 @@ function App({initial_state})
let new_state = structuredClone(state);
new_state.plan[cell_index] = asset_index;
new_state.mouse_state = "normal";
- setState(new_state);
+ serializePlan(new_state).then((s) => {
+ new_state.plan_code = s;
+ setState(new_state);
+ const url = new URL(location);
+ url.searchParams.set("plan", s);
+ window.history.pushState({}, "", url);
+ });
}
function onClickSaveImg()
@@ -157,13 +169,37 @@ function App({initial_state})
}
return h("div", {},
+ h("h2", {}, `Floor ${state.floor}`),
h(AssetsView, {on_drag_begin: onDragAssetBegin,
on_drag_end: onDragAssetEnd}),
h(PlanView, {plan: state.plan, mouse_state: state.mouse_state}),
h("div", {},
h("a", {"href": "javascript:void(0);", onclick: onClickSaveImg},
- "Open Image!")));
+ "Open Image!")),
+ h("div", {},
+ h("textarea", {readonly: true}, state.plan_code)),
+ );
}
-preact.render(h(App, {initial_state: DEFAULT_APP_STATE}),
- document.getElementById("Plan"));
+function render(app_state)
+{
+ preact.render(h(App, {initial_state: app_state}),
+ document.getElementById("Plan"));
+}
+
+const paramsString = window.location.search;
+const searchParams = new URLSearchParams(paramsString);
+const encoded_plan = searchParams.get("plan");
+if(encoded_plan === null)
+{
+ render(DEFAULT_APP_STATE);
+}
+else
+{
+ decompressBytes(encoded_plan).then(a => {
+ let state = structuredClone(DEFAULT_APP_STATE);
+ state.plan = Array.from(a.subarray(0, GRID_SIZE_X * GRID_SIZE_Y));
+ state.plan_code = encoded_plan;
+ render(state);
+ });
+}