diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 6d01efb..d62c1ff 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -18,7 +18,7 @@ net.connect(); net.startGamePolling(); - let name = $state(""); + let name = $state(prefs.wizardName); let joinCode = $state(""); let claimPhrase = $state(""); let showHelp = $state(false); @@ -953,6 +953,15 @@ /** The preferences slip (client-side taste, saved on this device). */ let prefsOpen = $state(false); + + // In a lobby before the deal: claim the preferred color when it is free + // and this seat has not chosen. One quiet attempt per availability change. + $effect(() => { + if (view || !net.roomId || !net.you || prefs.color == null) return; + if (net.roomColors[net.you] !== undefined) return; + const takenBy = Object.entries(net.roomColors).find(([, v]) => v === prefs.color)?.[0]; + if (takenBy === undefined) net.pickColor(prefs.color); + }); function setPref(k: K, v: (typeof prefs)[K]) { prefs[k] = v; savePrefs(); @@ -1220,6 +1229,21 @@ onchange={(e) => setPref("flourishes", e.currentTarget.checked)} /> Spell flourishes (the animated effects) + +
+ Preferred color + {#each [0, 1, 2, 3, 4, 5] as c (c)} + + {/each} +
Saved on this device. Rules are never affected.
@@ -1450,12 +1474,12 @@
- or join one -
@@ -2452,6 +2476,16 @@ color: #43331f; } .pref-note { font-size: 0.72rem; color: #8a7a5e; margin-top: 0.6rem; } + .pref-name { max-width: 11rem; } + .pref-swatch { + width: 1.3rem; + height: 1.3rem; + border-radius: 50%; + border: 2px solid #43331f; + cursor: pointer; + opacity: 0.55; + } + .pref-swatch.current { opacity: 1; outline: 2px solid #d8b23a; outline-offset: 1px; } .slip.council { background: #ece4f1; border-color: #7a6f9a; } .council-head { font-weight: 700; diff --git a/packages/web/src/prefs.svelte.ts b/packages/web/src/prefs.svelte.ts index df37988..400c8e1 100644 --- a/packages/web/src/prefs.svelte.ts +++ b/packages/web/src/prefs.svelte.ts @@ -10,12 +10,16 @@ export interface Prefs { autoGrab: boolean; /** Spell flourishes (the animated effects layer). */ flourishes: boolean; + /** Pre-filled wizard name for creating and joining games. */ + wizardName: string; + /** Preferred wizard color (0-5), claimed in lobbies when free. */ + color: number | null; } const KEY = "wizwar-prefs"; function load(): Prefs { - const fallback: Prefs = { art: "photo", autoGrab: false, flourishes: true }; + const fallback: Prefs = { art: "photo", autoGrab: false, flourishes: true, wizardName: "", color: null }; try { const raw = localStorage.getItem(KEY); if (!raw) return fallback; @@ -24,6 +28,8 @@ function load(): Prefs { art: p.art === "drawn" ? "drawn" : "photo", autoGrab: p.autoGrab === true, flourishes: p.flourishes !== false, + wizardName: typeof p.wizardName === "string" ? p.wizardName.slice(0, 20) : "", + color: typeof p.color === "number" && p.color >= 0 && p.color <= 5 ? p.color : null, }; } catch { return fallback;