From 19a89085a4c9a773a7b88437d7cd79c3e7131cfd Mon Sep 17 00:00:00 2001 From: MayAsteroidea <58619976+zasx77771@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:35:23 +0800 Subject: [PATCH] The title / login screen has a settings button: it opens the in-match settings dialog (local preferences only) (#183) One gear button in the title connection row opens the existing SettingsModal; it reads and writes the same local preferences and touches no server state. Contributed by @zasx77771. --- public/css/devices.css | 2 +- public/js/screens/title.js | 7 +++++++ test/client-static.test.js | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/public/css/devices.css b/public/css/devices.css index 9c0396b4..746e4ddc 100644 --- a/public/css/devices.css +++ b/public/css/devices.css @@ -103,7 +103,7 @@ html:not(.sp-in-match) .toast-host { margin-top: var(--sa-t); } .fsbtn { display: grid; place-items: center; padding: 0; background: rgba(8, 11, 10, .85); border: 1px solid var(--line-2); color: var(--text-lo); transition: color var(--t-fast), border-color var(--t-fast); } .fsbtn .icon { width: .26rem; height: .26rem; } .fsbtn:hover, .fsbtn[aria-pressed="true"] { color: var(--mint-400); border-color: var(--mint-700); } -.title-fs { width: .4rem; height: .4rem; margin-left: .06rem; } +.title-fs, .title-settings { width: .4rem; height: .4rem; margin-left: .06rem; } /* standalone / fullscreen: the browser bars are gone, nothing to reserve */ .sp-standalone .rotate-hint__micro::after { content: ' · PWA'; } diff --git a/public/js/screens/title.js b/public/js/screens/title.js index 2b745756..9d1e15dc 100644 --- a/public/js/screens/title.js +++ b/public/js/screens/title.js @@ -17,6 +17,8 @@ import { net, identity } from '../net.js'; import { store, useStore, shallowEqual } from '../store.js'; import { data, useData } from '../data.js'; import { FullscreenButton, detectFeatures } from '../ui/device.js'; +import { GIcon } from '../ui/gameComponents.js'; +import { SettingsModal } from '../ui/settings.js'; // Same character classes as server/net.js sanitizeName (control, zero-width, bidi, BOM), so a name // the client accepts is never rejected by the server's hello validation. @@ -183,6 +185,7 @@ export function TitleScreen() { const conn = useStore((s) => s.connection, shallowEqual); const pendingJoin = useStore((s) => s.ui.pendingJoin); const [name, setName] = useState(() => store.get().me.name || identity.loadName() || ''); + const [settingsOpen, setSettingsOpen] = useState(false); const assetsSettled = useData('assets'); const assets = data.get('assets'); const backdrop = findUiAsset(assets, BACKDROP_KEYS); @@ -258,11 +261,15 @@ export function TitleScreen() { ${STATUS_TEXT[conn.status] || conn.status} ${conn.status === 'online' ? html`<${PingPill} ms=${conn.ping} />` : null} <${GuideButton} class="title-guide" /> + <${FullscreenButton} class="title-fs" /> + <${SettingsModal} open=${settingsOpen} onClose=${() => setSettingsOpen(false)} /> +