diff --git a/bun.lock b/bun.lock index 6a3c5b8..bc7cda3 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "dependencies": { "@prisma/adapter-pg": "^6.19.0", "@prisma/client": "^6.19.0", + "valibot": "^1.1.0", }, "devDependencies": { "@eslint/compat": "^1.4.0", @@ -766,6 +767,8 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "valibot": ["valibot@1.1.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-Nk8lX30Qhu+9txPYTwM0cFlWLdPFsFr6LblzqIySfbZph9+BFsAHsNvHOymEviUepeIW6KFHzpX8TKhbptBXXw=="], + "vite": ["vite@7.1.9", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="], "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], diff --git a/package.json b/package.json index 2462d83..cf22fb3 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ }, "dependencies": { "@prisma/adapter-pg": "^6.19.0", - "@prisma/client": "^6.19.0" + "@prisma/client": "^6.19.0", + "valibot": "^1.1.0" } } diff --git a/prisma/migrations/20251109055509_add_board_name/migration.sql b/prisma/migrations/20251109055509_add_board_name/migration.sql new file mode 100644 index 0000000..5ec5c34 --- /dev/null +++ b/prisma/migrations/20251109055509_add_board_name/migration.sql @@ -0,0 +1,9 @@ +-- CreateTable +CREATE TABLE "BoardState" ( + "id" SERIAL NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "boardData" JSONB NOT NULL, + "boardName" TEXT NOT NULL, + + CONSTRAINT "BoardState_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 961ea04..ff842dc 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -19,4 +19,5 @@ model BoardState { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) boardData Json + boardName String } diff --git a/src/iframe/life-game.html b/src/iframe/life-game.html index 9608c87..f9c5624 100644 --- a/src/iframe/life-game.html +++ b/src/iframe/life-game.html @@ -13,10 +13,6 @@ " >
- - - - diff --git a/src/iframe/life-game.js b/src/iframe/life-game.js index 1250aec..54fd2ce 100644 --- a/src/iframe/life-game.js +++ b/src/iframe/life-game.js @@ -25,9 +25,6 @@ function isNextAlive(around, self) { return false; } -const saveButton = document.getElementById("saveButton"); -const loadButton = document.getElementById("loadButton"); - //Boardの初期化 let board = Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => false)); const table = document.getElementById("game-board"); @@ -131,10 +128,6 @@ on.pause = () => { clearInterval(timerId); }; -on.load_board = (boardTemplate) => { - board = boardTemplate; -}; - on.resize = (newBoardSize) => { boardSize = newBoardSize; }; @@ -191,18 +184,12 @@ on.stateupdate = () => { on.sizechange(boardSize); -saveButton.onclick = async () => { +on.save_board = async () => { window.parent.postMessage({ type: "save_board", data: board }, "*"); }; -loadButton.onclick = async () => { - window.parent.postMessage({ type: "request:load_board" }, "*"); -}; - -on.load_board = (loadedBoard) => { - console.log("on.load_board"); - board = loadedBoard; +on.apply_board = (newBoard) => { + board = newBoard; renderBoard(); generationChange(0); - stop(); }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 574deed..0ba797b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -33,6 +33,10 @@ let generationFigure = $state(0); let sizeInputValue = $state(20); + type SaveState = { saving: false } | { saving: true; boardData: boolean[][] }; + let saveState: SaveState = $state({ saving: false }); + let boardNameInput = $state(""); + onMount(() => { const handleMessage = (event: MessageEvent) => { if (event.data.type === "patternError") { @@ -60,23 +64,12 @@ onMount(() => { const handler = async (event: MessageEvent) => { - console.log("handler call"); const data = event.data as | { type: "unknown event" } - | { type: "save_board"; data: boolean[][] } - | { type: "request:load_board" }; + | { type: "save_board"; data: boolean[][] }; if (data.type === "save_board") { - console.log("board saved!"); - await saveBoard(data.data); - return; - } - - if (data.type === "request:load_board") { - console.log("loaded board"); - const board = await loadBoard(); - if (board) { - sendEvent("load_board", board); - } + saveState = { saving: true, boardData: data.data }; + boardNameInput = ""; return; } }; @@ -84,6 +77,25 @@ window.addEventListener("message", handler); return () => window.removeEventListener("message", handler); }); + + async function handleSave() { + if (!saveState.saving) return; + + const name = boardNameInput.trim() === "" ? "Unnamed Board" : boardNameInput.trim(); + + await saveBoard({ board: saveState.boardData, name: name }); + + saveState = { saving: false }; + boardNameInput = ""; + } + + async function handleLoad() { + const board = await loadBoard(); + if (board) { + sendEvent("apply_board", board); + } + return; + } + + +