|
1 | 1 | <script lang="ts"> |
| 2 | + import { onMount } from "svelte"; |
| 3 | + import event from "@/iframe/event.js?raw"; |
2 | 4 | import lifeGameHTML from "@/iframe/life-game.html?raw"; |
3 | 5 | import lifeGameJS from "@/iframe/life-game.js?raw"; |
4 | | - import event from "@/iframe/event.js?raw"; |
5 | | -
|
6 | | - import * as icons from "$lib/icons/index.ts"; |
7 | 6 | import patterns from "$lib/board-templates"; |
8 | | - import { onMount } from "svelte"; |
| 7 | + import * as icons from "$lib/icons/index.ts"; |
9 | 8 | import { loadBoard, saveBoard } from "./api.ts"; |
10 | 9 |
|
11 | | - let editingcode = $state(lifeGameJS); |
| 10 | + let editingCode = $state(lifeGameJS); |
12 | 11 | let appliedCode = $state(lifeGameJS); |
13 | 12 |
|
14 | | - let previewDoc = $derived( |
15 | | - lifeGameHTML.replace( |
16 | | - /<script src="\.\/life-game\.js"><\/script>/, |
17 | | - `<script> |
18 | | - \n${event}\n |
19 | | - \n${appliedCode}\n |
20 | | - <\/script>`, |
21 | | - ), |
22 | | - ); |
| 13 | + const previewDoc = $derived(lifeGameHTML.replace('"@JAVASCRIPT@";', `${event}\n${appliedCode}`)); |
23 | 14 |
|
24 | 15 | let showEditor = $state(true); |
25 | 16 | let preview_iframe: HTMLIFrameElement | undefined = $state(); |
|
36 | 27 | let saveState: SaveState = $state({ saving: false }); |
37 | 28 | let boardNameInput = $state(""); |
38 | 29 |
|
39 | | - onMount(() => { |
40 | | - const handleMessage = (event: MessageEvent) => { |
41 | | - if (event.data.type === "generation_change") { |
42 | | - generationFigure = event.data.data; |
43 | | - } |
44 | | - if (event.data.type === "Sync") { |
45 | | - generationFigure = event.data.data.generationFigure; |
46 | | - sizeValue = event.data.data.boardSize; |
47 | | - } |
48 | | - }; |
| 30 | + type OngoingEvent = |
| 31 | + | "play" |
| 32 | + | "pause" |
| 33 | + | "state_update" |
| 34 | + | "timer_change" |
| 35 | + | "board_reset" |
| 36 | + | "board_randomize" |
| 37 | + | "place_template" |
| 38 | + | "save_board" |
| 39 | + | "apply_board" |
| 40 | + | "request_sync" |
| 41 | + // unused events |
| 42 | + | "board_resize"; |
| 43 | +
|
| 44 | + type IncomingEvent = "generation_change" | "sync" | "save_board"; |
| 45 | +
|
| 46 | + function handleMessage(event: MessageEvent<{ type: IncomingEvent; data: unknown }>) { |
| 47 | + switch (event.data.type) { |
| 48 | + case "generation_change": |
| 49 | + generationFigure = event.data.data as number; |
| 50 | + break; |
| 51 | + case "sync": |
| 52 | + const data = event.data.data as { generationFigure: number; boardSize: number }; |
| 53 | + generationFigure = data.generationFigure; |
| 54 | + sizeValue = data.boardSize; |
| 55 | + break; |
| 56 | + case "save_board": |
| 57 | + saveState = { saving: true, boardData: event.data.data as boolean[][] }; |
| 58 | + boardNameInput = ""; |
| 59 | + break; |
| 60 | + } |
| 61 | + } |
49 | 62 |
|
| 63 | + onMount(() => { |
50 | 64 | window.addEventListener("message", handleMessage); |
51 | | -
|
52 | 65 | return () => { |
53 | 66 | window.removeEventListener("message", handleMessage); |
54 | 67 | }; |
55 | 68 | }); |
56 | 69 |
|
57 | | - function sendEvent(event: string, message?: unknown) { |
| 70 | + function sendEvent(event: OngoingEvent, message?: unknown) { |
58 | 71 | preview_iframe?.contentWindow?.postMessage({ type: event, data: message }, "*"); |
59 | 72 | } |
60 | 73 |
|
61 | | - onMount(() => { |
62 | | - const handler = async (event: MessageEvent<unknown>) => { |
63 | | - const data = event.data as |
64 | | - | { type: "unknown event" } |
65 | | - | { type: "save_board"; data: boolean[][] }; |
66 | | - if (data.type === "save_board") { |
67 | | - saveState = { saving: true, boardData: data.data }; |
68 | | - boardNameInput = ""; |
69 | | - return; |
70 | | - } |
71 | | - }; |
72 | | -
|
73 | | - window.addEventListener("message", handler); |
74 | | - return () => window.removeEventListener("message", handler); |
75 | | - }); |
76 | | -
|
77 | 74 | async function handleSave() { |
78 | 75 | if (!saveState.saving) return; |
79 | 76 |
|
|
142 | 139 | <button |
143 | 140 | class="btn overflow-hidden p-0 w-24 h-24" |
144 | 141 | onclick={() => { |
145 | | - sendEvent("requestSync"); |
| 142 | + sendEvent("request_sync"); |
146 | 143 |
|
147 | 144 | const newBoard = Array.from({ length: sizeValue }, () => |
148 | 145 | Array.from({ length: sizeValue }, () => false), |
|
177 | 174 | } |
178 | 175 | } |
179 | 176 | bottomDrawerOpen = false; |
180 | | - sendEvent("placetemplate", newBoard); |
| 177 | + sendEvent("place_template", newBoard); |
181 | 178 | }} |
182 | 179 | > |
183 | 180 | <img |
|
234 | 231 | <button |
235 | 232 | class="btn btn-error" |
236 | 233 | onclick={() => { |
| 234 | + // reset code (not board) |
237 | 235 | appliedCode = lifeGameJS; |
238 | | - editingcode = lifeGameJS; |
239 | | - console.log("Reset executed"); |
| 236 | + editingCode = lifeGameJS; |
240 | 237 | resetModalOpen = false; |
241 | 238 | }}>{isJapanese ? "リセット" : "Reset"}</button |
242 | 239 | > |
|
259 | 256 | class="w-[80%] h-[90%] rounded-lg mx-auto my-5 shadow-lg" |
260 | 257 | onload={() => { |
261 | 258 | setTimeout(() => { |
262 | | - sendEvent("stateupdate"); |
| 259 | + sendEvent("state_update"); |
263 | 260 | console.log("generationFigure onload:", generationFigure); |
264 | 261 | }, 50); |
265 | 262 | }} |
|
273 | 270 | ]} |
274 | 271 | > |
275 | 272 | <textarea |
276 | | - bind:value={editingcode} |
| 273 | + bind:value={editingCode} |
277 | 274 | class="w-full h-full border-none p-4 font-mono bg-black text-[#0f0]" |
278 | 275 | ></textarea> |
279 | 276 | </div> |
|
391 | 388 | class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black" |
392 | 389 | onclick={() => { |
393 | 390 | isProgress = false; |
394 | | - sendEvent("boardreset"); |
| 391 | + sendEvent("board_reset"); |
395 | 392 | }} |
396 | 393 | > |
397 | 394 | {isJapanese ? "リセット" : "Reset"} |
|
401 | 398 | class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black" |
402 | 399 | onclick={() => { |
403 | 400 | isProgress = false; |
404 | | - sendEvent("boardrandom"); |
| 401 | + sendEvent("board_randomize"); |
405 | 402 | }} |
406 | 403 | > |
407 | 404 | {isJapanese ? "ランダム" : "Random"} |
|
413 | 410 | <button |
414 | 411 | class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black" |
415 | 412 | onclick={() => { |
416 | | - appliedCode = editingcode; |
| 413 | + appliedCode = editingCode; |
417 | 414 | }} |
418 | 415 | > |
419 | 416 | {isJapanese ? "コードを適用" : "Apply Code"} |
|
0 commit comments