fix(badges): fix stale-Dexie race in font size initialization
The old guard locked on badge ID after the first liveQuery tick. If Dexie had a cached badge without cfg_json.font_sizes, the guard fired with no sizes to apply, then blocked the SWR background refresh that delivered the real saved sizes. Result: font sizes appeared unsaved on any browser that had visited the badge before sizes were set. Fix: track the cfg_json string last applied (_font_sizes_applied_cfg) instead of just the badge ID. Re-applies whenever cfg_json changes on a background refresh, but skips if local sizes have drifted from the last apply (user is mid-adjustment — auto-save will sync shortly). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,36 +103,76 @@ function send_review_email() {
|
||||
// the values can be forwarded to both the controls and the badge render.
|
||||
//
|
||||
// Initialization order: badge cfg_json.font_sizes takes precedence (persisted per-badge),
|
||||
// falling back to null (auto) on first load. The controls panel's "Lock Sizes" button
|
||||
// saves current sizes back to cfg_json so they survive page reloads and cross-kiosk.
|
||||
// falling back to null (auto) on first load. The auto-save in the controls panel writes
|
||||
// adjusted sizes back to cfg_json so they survive page reloads and are shared cross-kiosk.
|
||||
let font_size_name: number | null = $state(null);
|
||||
let font_size_title: number | null = $state(null);
|
||||
let font_size_affiliations: number | null = $state(null);
|
||||
let font_size_location: number | null = $state(null);
|
||||
|
||||
// Track whether we've applied the saved sizes for this badge yet.
|
||||
// Prevents re-applying on every liveQuery tick after the user adjusts sizes.
|
||||
// Initialization tracking:
|
||||
// _font_sizes_loaded_for — badge ID we last initialized for; reset on navigation.
|
||||
// _font_sizes_applied_cfg — the cfg_json string we last read font_sizes from.
|
||||
// Comparing this (not just the badge ID) lets us re-apply when a SWR background
|
||||
// refresh delivers newly-saved sizes — fixing the stale-Dexie race where the first
|
||||
// liveQuery tick has a cached badge without font_sizes, locking the badge-ID guard
|
||||
// before the API refresh arrives with the real saved values.
|
||||
let _font_sizes_loaded_for: string | null = null;
|
||||
let _font_sizes_applied_cfg: string = '$unset'; // sentinel — never equals a real cfg_json value
|
||||
|
||||
$effect(() => {
|
||||
const badge = $lq__event_badge_obj;
|
||||
if (!badge?.event_badge_id) return;
|
||||
// Only apply once per badge ID — don't clobber user adjustments on background refreshes
|
||||
if (_font_sizes_loaded_for === badge.event_badge_id) return;
|
||||
_font_sizes_loaded_for = badge.event_badge_id;
|
||||
|
||||
const current_cfg: string | null = badge.cfg_json ?? null;
|
||||
|
||||
// New badge — reset everything and fall through to apply.
|
||||
if (_font_sizes_loaded_for !== badge.event_badge_id) {
|
||||
_font_sizes_loaded_for = badge.event_badge_id;
|
||||
_font_sizes_applied_cfg = '$unset';
|
||||
font_size_name = null;
|
||||
font_size_title = null;
|
||||
font_size_affiliations = null;
|
||||
font_size_location = null;
|
||||
}
|
||||
|
||||
// cfg_json hasn't changed since we last applied — nothing to do.
|
||||
if (_font_sizes_applied_cfg === current_cfg) return;
|
||||
|
||||
// cfg_json changed (SWR refresh delivered new data). Before applying, check
|
||||
// whether local sizes have drifted from what we last applied. If the user has
|
||||
// made adjustments since our last apply, the auto-save will sync them back to
|
||||
// cfg_json shortly — don't clobber their in-progress work.
|
||||
if (_font_sizes_applied_cfg !== '$unset') {
|
||||
try {
|
||||
const prev_cfg = JSON.parse(_font_sizes_applied_cfg ?? 'null') ?? {};
|
||||
const prev_fs = prev_cfg?.font_sizes ?? null;
|
||||
const user_adjusted =
|
||||
font_size_name !== (prev_fs?.name ?? null) ||
|
||||
font_size_title !== (prev_fs?.title ?? null) ||
|
||||
font_size_affiliations !== (prev_fs?.affiliations ?? null) ||
|
||||
font_size_location !== (prev_fs?.location ?? null);
|
||||
if (user_adjusted) {
|
||||
// Advance the marker so we don't re-check on the next identical cfg_json.
|
||||
_font_sizes_applied_cfg = current_cfg ?? '$unset';
|
||||
return;
|
||||
}
|
||||
} catch { /* ignore parse errors — fall through and apply */ }
|
||||
}
|
||||
|
||||
// Apply font sizes from the fresh cfg_json.
|
||||
_font_sizes_applied_cfg = current_cfg ?? '$unset';
|
||||
try {
|
||||
const cfg = typeof badge.cfg_json === 'string'
|
||||
? JSON.parse(badge.cfg_json)
|
||||
: (badge.cfg_json ?? {});
|
||||
const fs = cfg?.font_sizes;
|
||||
if (fs) {
|
||||
font_size_name = fs.name ?? null;
|
||||
font_size_title = fs.title ?? null;
|
||||
font_size_affiliations = fs.affiliations ?? null;
|
||||
font_size_location = fs.location ?? null;
|
||||
}
|
||||
font_size_name = fs?.name ?? null;
|
||||
font_size_title = fs?.title ?? null;
|
||||
font_size_affiliations = fs?.affiliations ?? null;
|
||||
font_size_location = fs?.location ?? null;
|
||||
} catch {
|
||||
// Malformed cfg_json — stay with null (auto) for all fields
|
||||
// Malformed cfg_json — stay with current values
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user