feat: load blocks from previous session
also remove annoying unsaved changes popup
This commit is contained in:
parent
7a115e751d
commit
9b0cdfdc9b
5 changed files with 62 additions and 18 deletions
|
|
@ -34,6 +34,7 @@
|
|||
"embla-carousel-react": "^8.6.0",
|
||||
"lucide-react": "^0.544.0",
|
||||
"nbtify": "^2.2.0",
|
||||
"pako": "^2.1.0",
|
||||
"pixi.js": "^8.13.2",
|
||||
"react": "^19.1.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
|
|
@ -46,6 +47,7 @@
|
|||
"@eslint/js": "^9.36.0",
|
||||
"@tailwindcss/postcss": "^4.1.14",
|
||||
"@types/node": "^24.6.1",
|
||||
"@types/pako": "^2.0.4",
|
||||
"@types/react": "^19.1.17",
|
||||
"@types/react-dom": "^19.1.11",
|
||||
"@vitejs/plugin-react": "^5.0.4",
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ importers:
|
|||
nbtify:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
pako:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
pixi.js:
|
||||
specifier: ^8.13.2
|
||||
version: 8.13.2
|
||||
|
|
@ -111,6 +114,9 @@ importers:
|
|||
'@types/node':
|
||||
specifier: ^24.6.1
|
||||
version: 24.6.1
|
||||
'@types/pako':
|
||||
specifier: ^2.0.4
|
||||
version: 2.0.4
|
||||
'@types/react':
|
||||
specifier: ^19.1.17
|
||||
version: 19.1.17
|
||||
|
|
@ -1270,6 +1276,9 @@ packages:
|
|||
'@types/node@24.6.1':
|
||||
resolution: {integrity: sha512-ljvjjs3DNXummeIaooB4cLBKg2U6SPI6Hjra/9rRIy7CpM0HpLtG9HptkMKAb4HYWy5S7HUvJEuWgr/y0U8SHw==}
|
||||
|
||||
'@types/pako@2.0.4':
|
||||
resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==}
|
||||
|
||||
'@types/react-dom@19.1.11':
|
||||
resolution: {integrity: sha512-3BKc/yGdNTYQVVw4idqHtSOcFsgGuBbMveKCOgF8wQ5QtrYOc3jDIlzg3jef04zcXFIHLelyGlj0T+BJ8+KN+w==}
|
||||
peerDependencies:
|
||||
|
|
@ -2090,6 +2099,9 @@ packages:
|
|||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
pako@2.1.0:
|
||||
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
|
||||
|
||||
parent-module@1.0.1:
|
||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -3479,6 +3491,8 @@ snapshots:
|
|||
dependencies:
|
||||
undici-types: 7.13.0
|
||||
|
||||
'@types/pako@2.0.4': {}
|
||||
|
||||
'@types/react-dom@19.1.11(@types/react@19.1.17)':
|
||||
dependencies:
|
||||
'@types/react': 19.1.17
|
||||
|
|
@ -4347,6 +4361,8 @@ snapshots:
|
|||
dependencies:
|
||||
p-limit: 3.1.0
|
||||
|
||||
pako@2.1.0: {}
|
||||
|
||||
parent-module@1.0.1:
|
||||
dependencies:
|
||||
callsites: 3.1.0
|
||||
|
|
|
|||
|
|
@ -456,18 +456,6 @@ function Canvas() {
|
|||
return () => resizeObserver.disconnect();
|
||||
}, [loading, setStageSize]);
|
||||
|
||||
// Window events handler
|
||||
useEffect(() => {
|
||||
const onBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", onBeforeUnload);
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", onBeforeUnload);
|
||||
};
|
||||
}, [onKeyDown, onKeyUp]);
|
||||
|
||||
useGesture(
|
||||
{
|
||||
onPinch: ({ offset: [d] }) => {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
SquareDashedIcon,
|
||||
Trash2Icon,
|
||||
WandIcon,
|
||||
SaveIcon,
|
||||
} from "lucide-react";
|
||||
|
||||
import { HistoryContext } from "@/context/History";
|
||||
|
|
@ -32,6 +33,7 @@ const iconMap = {
|
|||
"Magic Wand": WandIcon,
|
||||
"Move Selection": MoveIcon,
|
||||
"New Canvas": PresentationIcon,
|
||||
"Load Previous Session": SaveIcon,
|
||||
"Open Image": ImageIcon,
|
||||
"Open Schematic": FileIcon,
|
||||
"Paint Bucket": PaintBucketIcon,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import pako from "pako";
|
||||
|
||||
import { HistoryContext } from "./History";
|
||||
import welcomeBlocksData from "@/data/welcome.json";
|
||||
|
|
@ -89,14 +90,49 @@ export const CanvasProvider = ({ children }: Props) => {
|
|||
}, [canvasSize, stageSize]);
|
||||
|
||||
useEffect(() => {
|
||||
addHistory(
|
||||
"New Canvas",
|
||||
() => setBlocks(welcomeBlocksData),
|
||||
() => setBlocks([])
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// Load blocks from previous session (if any)
|
||||
const localStorageBlocks = localStorage.getItem("blocks");
|
||||
if (localStorageBlocks) {
|
||||
try {
|
||||
// Convert stored string (Base64) back to bytes
|
||||
const compressedData = Uint8Array.from(atob(localStorageBlocks), (c) => c.charCodeAt(0));
|
||||
const decompressed = pako.inflate(compressedData, { to: "string" });
|
||||
const parsedBlocks = JSON.parse(decompressed);
|
||||
|
||||
setBlocks(parsedBlocks);
|
||||
addHistory(
|
||||
"Load Previous Session",
|
||||
() => setBlocks(parsedBlocks),
|
||||
() => setBlocks(welcomeBlocksData)
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Failed to load blocks from localStorage:", err);
|
||||
localStorage.removeItem("blocks");
|
||||
}
|
||||
} else {
|
||||
// Add history entry for new canvas
|
||||
addHistory(
|
||||
"New Canvas",
|
||||
() => setBlocks(welcomeBlocksData),
|
||||
() => setBlocks([])
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Set blocks to localStorage for session persistence
|
||||
useEffect(() => {
|
||||
// If blocks are the same as the starting welcome blocks, return
|
||||
if (JSON.stringify(blocks) === JSON.stringify(welcomeBlocksData)) return;
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(JSON.stringify(blocks));
|
||||
const compressed = pako.deflate(data);
|
||||
|
||||
// Store compressed data as Base64 string
|
||||
const base64 = btoa(String.fromCharCode(...compressed));
|
||||
localStorage.setItem("blocks", base64);
|
||||
}, [blocks]);
|
||||
|
||||
return (
|
||||
<CanvasContext.Provider
|
||||
value={{
|
||||
|
|
|
|||
Loading…
Reference in a new issue