From c0e3739c08a80e63e5652fdf3d67943bbd931b2e Mon Sep 17 00:00:00 2001 From: Kyle Florence Date: Fri, 8 May 2026 14:33:01 -0700 Subject: [PATCH 1/4] Track puzzle status on play puzzle list. Fixes #123 --- package.json | 2 +- src/components/game.js | 4 ++++ src/index.html | 1 + src/puzzles/index.js | 35 ++++++++++++++++++++++++----------- src/styles.css | 18 ++++++++++++++++-- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 530c8b8..76c4820 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "beaming", "author": "Kyle Florence", "description": "A browser-based puzzle game that involves directing beams through a hexagonal grid.", - "version": "0.4.1", + "version": "0.4.2", "license": "CC BY-NC 4.0", "main": "src/electron/main.js", "type": "module", diff --git a/src/components/game.js b/src/components/game.js index 1b13e6b..726e506 100644 --- a/src/components/game.js +++ b/src/components/game.js @@ -23,6 +23,7 @@ const elements = Object.freeze({ editPuzzles: document.getElementById('edit-puzzles'), play: document.getElementById('title-play'), playLoad: document.getElementById('play-custom-load'), + playProfile: document.getElementById('play-profile'), playPuzzles: document.getElementById('play-puzzles'), quit: document.getElementById('title-quit'), screen: document.getElementById('screen'), @@ -37,6 +38,8 @@ export class Game { #eventListeners = new EventListeners({ context: this }) constructor () { + elements.playProfile.textContent = Storage.Profile.get().name + this.puzzle = new Puzzle() this.editor = new Editor(this.puzzle) @@ -177,6 +180,7 @@ export class Game { async #onProfileUpdate (event) { this.#teardown() Storage.Profiles.set(event.detail.id) + elements.playProfile.textContent = Storage.Profile.get().name Game.updatePuzzles() } diff --git a/src/index.html b/src/index.html index 34a8843..44ef70d 100644 --- a/src/index.html +++ b/src/index.html @@ -110,6 +110,7 @@

Play

Puzzles

Load a puzzle by tapping on its name in the list below. Puzzles which are greyed out have not been unlocked yet.

+

Using profile: default (you can change this on the settings screen)

diff --git a/src/puzzles/index.js b/src/puzzles/index.js index fba17b3..76e89e4 100644 --- a/src/puzzles/index.js +++ b/src/puzzles/index.js @@ -33,13 +33,15 @@ export class Puzzles { return } + const custom = !Puzzles.has(id) const selected = id === currentId + const solved = state?.getSolution() !== undefined const li = document.createElement('li') li.classList.add('puzzle') - li.classList.toggle('custom', !Puzzles.has(id)) + li.classList.toggle('custom', custom) li.classList.toggle('selected', selected) - li.classList.toggle('solved', state?.getSolution() !== undefined) + li.classList.toggle('solved', solved) li.classList.toggle('unlocked', Puzzles.isUnlocked(id, context)) li.dataset.id = id @@ -51,28 +53,39 @@ export class Puzzles { div.classList.add('wrapper') li.append(div) - const span = document.createElement('span') - span.classList.add('flex-left', 'title') + const left = document.createElement('span') + left.classList.add('flex-left', 'title') const title = Puzzles.titles[id] ?? state.getTitle() ?? id const idParts = id.split('-') - span.textContent = title === id ? title : `${idParts.length ? idParts[idParts.length - 1] : id}: ${title}` + left.textContent = title === id ? title : `${idParts.length ? idParts[idParts.length - 1] : id}: ${title}` if (selected) { const cont = document.createElement('span') cont.classList.add('continue') cont.textContent = '(Continue)' - span.append(cont) + left.append(cont) } - div.append(span) + div.append(left) - if (!Puzzles.has(id)) { - const i = document.createElement('i') - i.classList.add('flex-right', 'ph-bold', 'ph-trash', 'remove') - div.append(i) + const right = document.createElement('span') + right.classList.add('flex-right') + + if (custom) { + const remove = document.createElement('i') + remove.classList.add('ph-bold', 'ph-trash', 'remove') + remove.title = 'Remove from list' + right.append(remove) } + const status = document.createElement('i') + status.classList.add('ph-bold', solved ? 'ph-check-circle' : 'ph-circle', 'status') + status.title = solved ? 'Solved!' : 'Unsolved' + right.append(status) + + div.append(right) + if (context === State.ContextKeys.Play && puzzle.layout?.imports?.length) { const ul = document.createElement('ul') ul.classList.add('imports') diff --git a/src/styles.css b/src/styles.css index 976dd9c..f604921 100644 --- a/src/styles.css +++ b/src/styles.css @@ -623,8 +623,19 @@ dialog ul { padding: 0.5em; width: 100%; } + + #play-profile-wrapper { + border-top: 1px solid #ddd; + margin-top: 1em; + padding-top: 1em; + } +} + +#play-profile { + font-weight: bold; } + #play-custom-configuration-error { background-color: #dc3545; border: 1px #dc3545 solid; @@ -799,7 +810,6 @@ dialog ul { overflow: hidden; } - .puzzles { border: 1px solid #aaa; border-radius: 0.5em; @@ -853,7 +863,7 @@ dialog ul { } &.unlocked > .wrapper .title, - .remove { + .remove{ color: #333; cursor: pointer; } @@ -863,6 +873,10 @@ dialog ul { margin-left: 0.5em; } + &.unlocked > .wrapper .status { + color: #333; + } + .title { display: block; margin-left: 0.5em; From aa7934498fa6d5ff8e24beb910bce5e9a39ebe90 Mon Sep 17 00:00:00 2001 From: Kyle Florence Date: Fri, 8 May 2026 14:34:26 -0700 Subject: [PATCH 2/4] npm audit fix --- package-lock.json | 125 +++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index a8c3342..a1ea7f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "beaming", - "version": "0.3.7", + "version": "0.4.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "beaming", - "version": "0.3.7", + "version": "0.4.2", "license": "CC BY-NC 4.0", "dependencies": { "@fontsource-variable/noto-sans-mono": "^5.2.10", @@ -3098,6 +3098,32 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/optimizer-htmlnano/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@parcel/optimizer-htmlnano/node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/@parcel/optimizer-htmlnano/node_modules/htmlnano": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.1.5.tgz", @@ -3146,6 +3172,41 @@ } } }, + "node_modules/@parcel/optimizer-htmlnano/node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/@parcel/optimizer-htmlnano/node_modules/svgo": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, "node_modules/@parcel/optimizer-image": { "version": "2.16.4", "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.16.4.tgz", @@ -3676,9 +3737,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3700,9 +3758,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3724,9 +3779,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3748,9 +3800,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6023,11 +6072,10 @@ } }, "node_modules/basic-ftp": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz", - "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -9118,9 +9166,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -9130,8 +9178,7 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ], - "license": "BSD-3-Clause" + ] }, "node_modules/fastq": { "version": "1.18.0", @@ -10302,15 +10349,10 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "devOptional": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -10956,13 +10998,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "devOptional": true, - "license": "MIT" - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -14882,13 +14917,12 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", "devOptional": true, - "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -14976,8 +15010,9 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "devOptional": true, - "license": "BSD-3-Clause" + "dev": true, + "license": "BSD-3-Clause", + "optional": true }, "node_modules/ssri": { "version": "9.0.1", From 7df9c9789aff5eb9e7e90ad8152829b10572bd2a Mon Sep 17 00:00:00 2001 From: Kyle Florence Date: Fri, 8 May 2026 14:40:19 -0700 Subject: [PATCH 3/4] Fix not getting profile if no ID is set --- src/components/storage.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/storage.js b/src/components/storage.js index 2cca67f..9e6e27a 100644 --- a/src/components/storage.js +++ b/src/components/storage.js @@ -67,15 +67,12 @@ export class Storage { this.name = name } - static get () { - const id = Storage.Profile.getId() - if (id !== null) { - return Storage.Profiles.get(id) - } + static get (id) { + return Storage.Profiles.get(id ?? Storage.Profile.getId()) } static getId () { - return localStorage.getItem(getKey(Storage.Prefix, Storage.Keys.Profile)) + return localStorage.getItem(getKey(Storage.Prefix, Storage.Keys.Profile)) ?? Storage.ProfilesByName.Default.id } } From 16531902c792bbd8fa26c963f472334a9cffabeb Mon Sep 17 00:00:00 2001 From: Kyle Florence Date: Fri, 8 May 2026 14:45:31 -0700 Subject: [PATCH 4/4] Fix missing space --- src/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles.css b/src/styles.css index f604921..f94aee2 100644 --- a/src/styles.css +++ b/src/styles.css @@ -863,7 +863,7 @@ dialog ul { } &.unlocked > .wrapper .title, - .remove{ + .remove { color: #333; cursor: pointer; }