Polish: plain unfound word-search chips + no signed-out flash on refresh
- Word Search: unfound words were tinted (accent-soft background) like found ones, so the remaining words were hard to spot as the board filled. Unfound chips are now plain (transparent + a light outline); found words keep their grid colour. Easy to see what's left. - Auth: a refresh briefly flashed the signed-out header until /api/auth/me returned. Now the last-known user is cached and hydrated immediately, so the signed-in UI paints at once; the session is still revalidated every load (a stale/expired one corrects within a beat) and the cache is cleared on logout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,22 @@
|
||||
import { SvelteSet } from 'svelte/reactivity';
|
||||
import { getJSON, postJSON, delJSON } from './api.js';
|
||||
|
||||
export const auth = $state({ user: null, ready: false });
|
||||
// Cache the last-known user so a refresh paints the signed-in UI immediately
|
||||
// instead of flashing "signed out" for the /api/auth/me round-trip. The session
|
||||
// is still revalidated on every load (see refresh) — a stale/expired one just
|
||||
// corrects within a beat instead of greeting you logged-out every time.
|
||||
const AUTH_CACHE = 'goodnews:auth_user';
|
||||
function _loadUser() {
|
||||
try { return JSON.parse(localStorage.getItem(AUTH_CACHE) || 'null'); } catch { return null; }
|
||||
}
|
||||
function _saveUser(u) {
|
||||
try {
|
||||
if (u) localStorage.setItem(AUTH_CACHE, JSON.stringify(u));
|
||||
else localStorage.removeItem(AUTH_CACHE);
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
export const auth = $state({ user: _loadUser(), ready: false });
|
||||
export const savedIds = new SvelteSet(); // reactive set of saved article ids
|
||||
export const followKeys = new SvelteSet(); // reactive set of "kind:value" follows
|
||||
|
||||
@@ -16,6 +31,7 @@ export async function refresh() {
|
||||
auth.user = null;
|
||||
} finally {
|
||||
auth.ready = true;
|
||||
_saveUser(auth.user);
|
||||
}
|
||||
if (auth.user) { await loadSaved(); await loadFollows(); }
|
||||
else { savedIds.clear(); followKeys.clear(); }
|
||||
@@ -99,6 +115,7 @@ export async function logout() {
|
||||
// e.g. after delete-account or sign-out-everywhere).
|
||||
export function clearLocal() {
|
||||
auth.user = null;
|
||||
_saveUser(null);
|
||||
savedIds.clear();
|
||||
followKeys.clear();
|
||||
}
|
||||
|
||||
@@ -221,8 +221,12 @@
|
||||
.plabel { text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.62rem; font-family: var(--label);
|
||||
color: var(--muted); text-align: center; margin: 0 0 10px; }
|
||||
.words { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; padding: 0; margin: 0; }
|
||||
/* Unfound words are plain (transparent + outline) so it's easy to see what's
|
||||
left as the board fills; found words get their grid colour via inline style. */
|
||||
.words li { font-family: var(--label); font-size: 0.82rem; letter-spacing: 0.04em; color: var(--ink);
|
||||
padding: 4px 11px; border-radius: 999px; background: var(--accent-soft); transition: background 0.2s ease; }
|
||||
padding: 4px 11px; border-radius: 999px; background: transparent;
|
||||
border: 1px solid var(--line); transition: background 0.2s ease, border-color 0.2s ease; }
|
||||
.words li.got { border-color: transparent; }
|
||||
.hint { text-align: center; color: var(--muted); font-size: 0.84rem; margin: 0; }
|
||||
.result { text-align: center; }
|
||||
.rmark { font-family: var(--serif); font-style: italic; color: var(--accent-deep); font-size: 1.2rem; margin: 0 0 12px; }
|
||||
|
||||
Reference in New Issue
Block a user