|
9 | 9 | import { onMount } from "svelte"; |
10 | 10 | import { loadBoard, saveBoard } from "./api.ts"; |
11 | 11 |
|
12 | | - let code = $state(lifeGameJS); |
| 12 | + let editingcode = $state(lifeGameJS); |
| 13 | + let appliedCode = $state(lifeGameJS); |
13 | 14 |
|
14 | 15 | let previewDoc = $derived( |
15 | 16 | lifeGameHTML.replace( |
16 | 17 | /<script src="\.\/life-game\.js"><\/script>/, |
17 | 18 | `<script> |
18 | 19 | \n${event}\n |
19 | | - \n${lifeGameJS}\n |
| 20 | + \n${appliedCode}\n |
20 | 21 | \n${placetemplate}\n |
21 | 22 | <\/script>`, |
22 | 23 | ), |
|
25 | 26 | let showEditor = $state(true); |
26 | 27 | let preview_iframe: HTMLIFrameElement | undefined = $state(); |
27 | 28 | let isProgress = $state(false); |
28 | | - let intervalMs = 1000; |
29 | | - let drawerOpen = $state(false); |
30 | 29 | let resetModalOpen = $state(false); |
31 | 30 | let bottomDrawerOpen = $state(false); |
32 | 31 |
|
| 32 | + let intervalMs = $state(1000); |
| 33 | + let generationFigure = $state(0); |
| 34 | + let sizeInputValue = $state(20); |
| 35 | +
|
33 | 36 | onMount(() => { |
34 | | - window.addEventListener("message", (event) => { |
| 37 | + const handleMessage = (event: MessageEvent) => { |
35 | 38 | if (event.data.type === "patternError") { |
36 | 39 | alert(event.data.message); |
37 | 40 | } |
38 | | - }); |
| 41 | + if (event.data.type === "generation_change") { |
| 42 | + generationFigure = event.data.data; |
| 43 | + } |
| 44 | + if (event.data.type === "stateupdate") { |
| 45 | + generationFigure = event.data.data.generationFigure; |
| 46 | + sizeInputValue = event.data.data.boardSize; |
| 47 | + } |
| 48 | + }; |
| 49 | +
|
| 50 | + window.addEventListener("message", handleMessage); |
| 51 | +
|
| 52 | + return () => { |
| 53 | + window.removeEventListener("message", handleMessage); |
| 54 | + }; |
39 | 55 | }); |
40 | 56 |
|
41 | 57 | function sendEvent(event: string, message?: unknown) { |
|
71 | 87 | </script> |
72 | 88 |
|
73 | 89 | <div class="navbar bg-[#E0E0E0] shadow-sm"> |
74 | | - <button |
75 | | - class="btn btn-sm btn-ghost btn-circle bg-[#E0E0E0] mx-5 w-8 rounded border-none" |
76 | | - onclick={() => { |
77 | | - drawerOpen = !drawerOpen; |
78 | | - }} |
79 | | - > |
80 | | - <img src={icons.bars_3} alt="settings" /> |
81 | | - </button> |
82 | | - |
83 | | - <div class="mx-5 avatar w-8 rounded"> |
| 90 | + <div class="ml-15 avatar w-8 rounded"> |
84 | 91 | <img src={icons.utcode} alt="ut.code();_Logo" /> |
85 | 92 | </div> |
86 | 93 |
|
87 | | - <div class="font-semibold text-black text-[20px]">Life code</div> |
| 94 | + <div class="font-semibold text-black text-[20px] ml-5">Life code</div> |
88 | 95 |
|
89 | 96 | <button |
90 | 97 | class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] ml-auto" |
|
158 | 165 | </div> |
159 | 166 | </div> |
160 | 167 |
|
161 | | -<div class="flex h-screen box-border"> |
| 168 | +<div class="flex box-border h-screen" style="height: calc(100vh - 4rem - 3rem);"> |
162 | 169 | <div |
163 | 170 | class={[ |
164 | 171 | "flex overflow-hidden bg-[rgb(202,202,202)] shrink-0 transition-[flex-basis] duration-300 ease-in-out", |
|
170 | 177 | srcdoc={previewDoc} |
171 | 178 | title="Preview" |
172 | 179 | sandbox="allow-scripts" |
173 | | - class="w-[90%] h-[80%] rounded-lg m-auto shadow-lg" |
| 180 | + class="w-[80%] h-[90%] rounded-lg mx-auto my-5 shadow-lg" |
| 181 | + onload={() => { |
| 182 | + setTimeout(() => { |
| 183 | + sendEvent("stateupdate"); |
| 184 | + console.log("generationFigure onload:", generationFigure); |
| 185 | + }, 50); |
| 186 | + }} |
174 | 187 | ></iframe> |
175 | 188 | </div> |
176 | 189 |
|
|
180 | 193 | showEditor ? "basis-[40%] opacity-100" : "basis-0 opacity-0", |
181 | 194 | ]} |
182 | 195 | > |
183 | | - <textarea bind:value={code} class="w-full h-full border-none p-4 font-mono bg-black text-[#0f0]" |
| 196 | + <textarea |
| 197 | + bind:value={editingcode} |
| 198 | + class="w-full h-full border-none p-4 font-mono bg-black text-[#0f0]" |
184 | 199 | ></textarea> |
185 | 200 | </div> |
186 | 201 | </div> |
187 | 202 |
|
188 | | -<div class="bg-[#E0E0E0] shadow-sm fixed bottom-0 left-0 right-0 z-50 h-12 p-0"> |
| 203 | +<div class="bg-[#E0E0E0] shadow-sm fixed bottom-0 left-0 right-0 z-50 h-12 p-0 flex items-center"> |
189 | 204 | <button |
190 | 205 | class="btn rounded-none h-12 justify-start" |
191 | 206 | onclick={() => (bottomDrawerOpen = !bottomDrawerOpen)} |
192 | 207 | > |
193 | 208 | {bottomDrawerOpen ? "▼" : "▲ テンプレート"} |
194 | 209 | </button> |
195 | 210 |
|
| 211 | + <div class="font-bold text-black ml-10"> |
| 212 | + 第 {generationFigure} 世代 |
| 213 | + </div> |
| 214 | + |
| 215 | + <p class="ml-10 text-black">ボードのサイズ(10~100):</p> |
| 216 | + <input type="number" bind:value={sizeInputValue} class="w-10 text-black bg-white ml-2" /> |
| 217 | + |
| 218 | + <button |
| 219 | + class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black ml-2" |
| 220 | + onclick={() => { |
| 221 | + isProgress = false; |
| 222 | + if (isNaN(sizeInputValue) || sizeInputValue < 10 || sizeInputValue > 100) { |
| 223 | + alert("サイズは10から100の間で指定してください。"); |
| 224 | + return; |
| 225 | + } |
| 226 | + sendEvent("sizechange", sizeInputValue.toString()); |
| 227 | + }} |
| 228 | + > |
| 229 | + Change |
| 230 | + </button> |
| 231 | + |
196 | 232 | <div |
197 | 233 | class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap fixed left-1/2 !-translate-x-1/2 -ml-15 bottom-1" |
198 | 234 | > |
|
219 | 255 | </div> |
220 | 256 |
|
221 | 257 | <button |
222 | | - class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2" |
| 258 | + class="btn btn-ghost hover:bg-[rgb(220,220,220)] ml-100 text-black" |
| 259 | + onclick={() => { |
| 260 | + isProgress = false; |
| 261 | + sendEvent("boardreset"); |
| 262 | + }} |
| 263 | + > |
| 264 | + Reset |
| 265 | + </button> |
| 266 | + |
| 267 | + <button |
| 268 | + class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black" |
| 269 | + onclick={() => { |
| 270 | + isProgress = false; |
| 271 | + sendEvent("boardrandom"); |
| 272 | + }} |
| 273 | + > |
| 274 | + Random |
| 275 | + </button> |
| 276 | + |
| 277 | + <button |
| 278 | + class="btn btn-ghost hover:bg-[rgb(220,220,220)] ml-5 text-black" |
| 279 | + onclick={() => { |
| 280 | + appliedCode = editingcode; |
| 281 | + }} |
| 282 | + > |
| 283 | + Apply Code |
| 284 | + </button> |
| 285 | + <button |
| 286 | + class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2" |
223 | 287 | onclick={() => { |
224 | 288 | intervalMs = intervalMs / 2; |
225 | 289 | sendEvent("timer_change", intervalMs); |
|
229 | 293 | </button> |
230 | 294 |
|
231 | 295 | <button |
232 | | - class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2" |
| 296 | + class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2" |
233 | 297 | onclick={() => { |
234 | 298 | intervalMs = intervalMs * 2; |
235 | 299 | sendEvent("timer_change", intervalMs); |
|
239 | 303 | </button> |
240 | 304 |
|
241 | 305 | <button |
242 | | - class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap ml-2" |
| 306 | + class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] text-black ml-2" |
243 | 307 | onclick={() => { |
244 | 308 | intervalMs = 1000; |
245 | 309 | sendEvent("timer_change", intervalMs); |
|
0 commit comments