|
9 | 9 | import { CodeManager } from "$lib/models/CodeManager.svelte"; |
10 | 10 | import BoardModals from "$lib/components/BoardModals.svelte"; |
11 | 11 | import CodeModals from "$lib/components/CodeModals.svelte"; |
| 12 | + import { toast } from "$lib/models/ToastStore.svelte"; |
12 | 13 | import CodeMirror from "svelte-codemirror-editor"; |
13 | 14 | import { javascript } from "@codemirror/lang-javascript"; |
14 | 15 | import { oneDark } from "@codemirror/theme-one-dark"; |
|
32 | 33 | const boardManager = new BoardManager(); |
33 | 34 | const codeManager = new CodeManager(); |
34 | 35 |
|
| 36 | + let disabledTemplates: { [key: string]: boolean } = $derived.by(() => { |
| 37 | + const newDisabledState: { [key: string]: boolean } = {}; |
| 38 | + for (const key in patterns) { |
| 39 | + const patternName = key as keyof typeof patterns; |
| 40 | + const patternData = patterns[patternName]; |
| 41 | + newDisabledState[patternName] = sizeValue < (patternData.minBoardSize || 0); |
| 42 | + } |
| 43 | + return newDisabledState; |
| 44 | + }); |
| 45 | +
|
35 | 46 | let timer: "running" | "stopped" = $state("stopped"); |
36 | 47 | let intervalMs = $state(1000); |
37 | 48 | $effect(() => { |
|
45 | 56 | type OngoingEvent = |
46 | 57 | | "play" |
47 | 58 | | "pause" |
48 | | - | "state_update" |
49 | 59 | | "board_reset" |
50 | 60 | | "board_randomize" |
51 | 61 | | "place_template" |
|
69 | 79 | break; |
70 | 80 | } |
71 | 81 | case "Size shortage": { |
72 | | - alert( |
| 82 | + toast.show( |
73 | 83 | isJapanese |
74 | 84 | ? "盤面からはみ出してしまうため、キャンセルしました" |
75 | 85 | : "This action was canceled because it would have extended beyond the board.", |
| 86 | + "error", |
76 | 87 | ); |
77 | 88 | break; |
78 | 89 | } |
|
101 | 112 | async function onBoardSelect(id: number) { |
102 | 113 | const board = await boardManager.load(id, isJapanese); |
103 | 114 | if (board) { |
104 | | - sizeValue = board.length; |
105 | 115 | sendEvent("apply_board", board); |
106 | 116 | } |
107 | 117 | } |
|
169 | 179 | <div class="bg-base-200 shadow-lg p-4 h-48 w-full overflow-x-auto"> |
170 | 180 | <div class="flex gap-4"> |
171 | 181 | {#each Object.keys(patterns) as (keyof typeof patterns)[] as patternName (patternName)} |
172 | | - <div class="text-center flex-shrink-0"> |
| 182 | + <div |
| 183 | + class="text-center flex-shrink-0" |
| 184 | + style:opacity={disabledTemplates[patternName] ? 0.3 : 1} |
| 185 | + > |
173 | 186 | <p class="font-bold mb-2"> |
174 | 187 | {isJapanese ? patterns[patternName].names.ja : patterns[patternName].names.en} |
175 | 188 | </p> |
176 | 189 | <button |
177 | 190 | class="btn overflow-hidden p-0 w-24 h-24" |
178 | 191 | onclick={() => { |
179 | | - sendEvent("request_sync"); |
180 | | - |
181 | | - const patternData = patterns[patternName]; |
182 | | - const patternShape = patternData.shape; |
183 | | - |
184 | | - if (sizeValue < (patternData.minBoardSize || 0)) { |
185 | | - if (isJapanese) { |
186 | | - alert( |
187 | | - `このパターンには ${patternData.minBoardSize}x${patternData.minBoardSize} 以上の盤面が必要です`, |
188 | | - ); |
189 | | - } else { |
190 | | - alert( |
191 | | - `This pattern requires a board size of at least ${patternData.minBoardSize}x${patternData.minBoardSize}.`, |
192 | | - ); |
193 | | - } |
194 | | - |
| 192 | + if (disabledTemplates[patternName]) { |
| 193 | + toast.show( |
| 194 | + isJapanese |
| 195 | + ? `このパターンには ${patterns[patternName].minBoardSize}x${patterns[patternName].minBoardSize} 以上の盤面が必要です` |
| 196 | + : `This pattern requires a board size of at least ${patterns[patternName].minBoardSize}x${patterns[patternName].minBoardSize}.`, |
| 197 | + "error", |
| 198 | + ); |
195 | 199 | return; |
196 | 200 | } |
| 201 | + const patternData = patterns[patternName]; |
| 202 | + const patternShape = patternData.shape; |
197 | 203 | bottomDrawerOpen = false; |
198 | 204 | sendEvent("place_template", patternShape); |
199 | 205 | }} |
|
253 | 259 | class="w-[80%] h-[90%] rounded-lg mx-auto my-5 bg-white shadow-lg" |
254 | 260 | onload={() => { |
255 | 261 | setTimeout(() => { |
256 | | - sendEvent("state_update"); |
| 262 | + sendEvent("request_sync"); |
257 | 263 | console.log("generationFigure onload:", generationFigure); |
258 | 264 | }, 50); |
259 | 265 | }} |
|
283 | 289 | <!-- Left Section --> |
284 | 290 | <div class="flex items-center"> |
285 | 291 | <button |
286 | | - class="btn rounded-none h-12 justify-start" |
| 292 | + class="btn rounded-none h-12 justify-start w-30" |
287 | 293 | onclick={() => (bottomDrawerOpen = !bottomDrawerOpen)} |
288 | 294 | > |
289 | 295 | {#if bottomDrawerOpen} |
|
295 | 301 | {/if} |
296 | 302 | </button> |
297 | 303 |
|
298 | | - <div class="font-bold text-black ml-4"> |
299 | | - {isJapanese ? "第" + generationFigure + "世代" : "Generation:" + generationFigure} |
| 304 | + <div class="font-bold text-black ml-4 w-25"> |
| 305 | + {isJapanese ? "世代数:" + generationFigure : "Generation:" + generationFigure} |
300 | 306 | </div> |
301 | 307 | </div> |
302 | 308 |
|
|
329 | 335 | <img class="size-6" src={icons.accelerate} alt="accelerate" /> |
330 | 336 | </button> |
331 | 337 |
|
332 | | - <div class="font-bold text-black ml-2"> |
| 338 | + <div class="font-bold text-black ml-2 w-25"> |
333 | 339 | {isJapanese ? "現在の速度" : "Current speed"}: x{1000 / intervalMs} |
334 | 340 | </div> |
335 | 341 |
|
336 | 342 | <div class="w-px bg-gray-400 h-6 mx-4"></div> |
337 | 343 | <!-- Separator --> |
338 | 344 |
|
339 | | - <button class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)]"> |
340 | | - <img class="size-6" src={icons.LeftArrow} alt="Left Arrow" /> |
341 | | - </button> |
342 | | - |
343 | 345 | <button |
344 | 346 | class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)] swap" |
345 | 347 | onclick={() => { |
|
357 | 359 | <img class="size-6 swap-on" src={icons.Pause} alt="Pause" /> |
358 | 360 | <img class="size-6 swap-off" src={icons.Play} alt="Play" /> |
359 | 361 | </button> |
360 | | - |
361 | | - <button class="btn btn-ghost btn-circle hover:bg-[rgb(220,220,220)]"> |
362 | | - <img class="size-6" src={icons.RightArrow} alt="Right Arrow" /> |
363 | | - </button> |
364 | 362 | </div> |
365 | 363 |
|
366 | 364 | <!-- Right Section --> |
|
418 | 416 | <!-- Separator --> |
419 | 417 | <div class="font-bold text-black">{isJapanese ? "コード" : "Code"}:</div> |
420 | 418 | <button |
421 | | - class="btn btn-ghost hover:bg-[rgb(220,220,220)] text-black" |
| 419 | + class={[ |
| 420 | + "btn text-black", |
| 421 | + editingCode === appliedCode ? "btn-ghost hover:bg-[rgb(220,220,220)]" : "btn-success", |
| 422 | + ]} |
422 | 423 | onclick={() => { |
423 | 424 | appliedCode = editingCode; |
424 | 425 | isProgress = false; |
|
0 commit comments