refactor: consolidate obscure_email and browser reset into shared utilities
- Remove 6 local copies of obscure_email(); all now use ae_util.obscure_email() (badges list, badge review, badge print, presenter list, presenter detail, session view) - badge review page: add missing ae_util import - e_app_sys_bar: replace inline IDB/storage clear implementations with core_func.clear_idb() and core_func.clear_all_storage(); adds known-names fallback the inline version lacked - fix-sw page: replace 110-line inline nuke with core_func.clear_all_storage(log_callback); step-by-step logging and countdown UI preserved via BrowserResetLogFn callback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ import {
|
|||||||
User
|
User
|
||||||
} from '@lucide/svelte';
|
} from '@lucide/svelte';
|
||||||
import { ae_loc, ae_sess } from '$lib/stores/ae_stores';
|
import { ae_loc, ae_sess } from '$lib/stores/ae_stores';
|
||||||
|
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||||
|
|
||||||
import Element_access_type from '$lib/app_components/e_app_access_type.svelte';
|
import Element_access_type from '$lib/app_components/e_app_access_type.svelte';
|
||||||
import Element_sign_in_out from '$lib/app_components/e_app_sign_in_out.svelte';
|
import Element_sign_in_out from '$lib/app_components/e_app_sign_in_out.svelte';
|
||||||
@@ -91,18 +92,11 @@ async function handle_clear_idb_only() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
const db_list = await indexedDB.databases();
|
await core_func.clear_idb();
|
||||||
console.log('[clear_idb] IDB databases found:', db_list.map((d) => d.name));
|
|
||||||
for (const db of db_list) {
|
|
||||||
if (db.name) indexedDB.deleteDatabase(db.name);
|
|
||||||
}
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Dev: full reset — SW + Cache Storage + IDB + localStorage/sessionStorage ──
|
// ── Dev: full reset — SW + Cache Storage + IDB + localStorage/sessionStorage ──
|
||||||
// SW and Cache Storage MUST be cleared here. Clearing IDB/localStorage alone leaves
|
|
||||||
// the SW serving old JS bundles from its own Cache Storage on the next reload,
|
|
||||||
// which means the user stays stuck on old code. Order: SW → cache → IDB → storage.
|
|
||||||
async function handle_clear_storage_and_idb() {
|
async function handle_clear_storage_and_idb() {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
@@ -110,21 +104,7 @@ async function handle_clear_storage_and_idb() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
await core_func.clear_all_storage();
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
||||||
for (const reg of registrations) await reg.unregister();
|
|
||||||
}
|
|
||||||
const cache_keys = await caches.keys();
|
|
||||||
for (const key of cache_keys) await caches.delete(key);
|
|
||||||
|
|
||||||
const db_list = await indexedDB.databases();
|
|
||||||
console.log('[clear_all] IDB databases found:', db_list.map((d) => d.name));
|
|
||||||
for (const db of db_list) {
|
|
||||||
if (db.name) indexedDB.deleteDatabase(db.name);
|
|
||||||
}
|
|
||||||
localStorage.clear();
|
|
||||||
sessionStorage.clear();
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,12 +76,6 @@ function build_review_url(): string {
|
|||||||
return `/events/${$lq__event_badge_obj?.event_id}/badges/${$lq__event_badge_obj?.event_badge_id}/review`;
|
return `/events/${$lq__event_badge_obj?.event_id}/badges/${$lq__event_badge_obj?.event_badge_id}/review`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
return `${email.slice(0, Math.min(3, at))}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: replace alert with actual email API call when available
|
// TODO: replace alert with actual email API call when available
|
||||||
function send_review_email() {
|
function send_review_email() {
|
||||||
@@ -92,7 +86,7 @@ function send_review_email() {
|
|||||||
`${badge?.given_name ?? ''} ${badge?.family_name ?? ''}`.trim();
|
`${badge?.given_name ?? ''} ${badge?.family_name ?? ''}`.trim();
|
||||||
const email = is_trusted
|
const email = is_trusted
|
||||||
? (badge?.email ?? '(no email on file)')
|
? (badge?.email ?? '(no email on file)')
|
||||||
: obscure_email(badge?.email);
|
: ae_util.obscure_email(badge?.email);
|
||||||
const event_name = EVENTS_MODULE_TITLE;
|
const event_name = EVENTS_MODULE_TITLE;
|
||||||
alert(
|
alert(
|
||||||
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { untrack } from 'svelte';
|
|||||||
import { liveQuery } from 'dexie';
|
import { liveQuery } from 'dexie';
|
||||||
|
|
||||||
import { ae_loc } from '$lib/stores/ae_stores';
|
import { ae_loc } from '$lib/stores/ae_stores';
|
||||||
|
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||||
import { db_events } from '$lib/ae_events/db_events';
|
import { db_events } from '$lib/ae_events/db_events';
|
||||||
import { EVENTS_MODULE_TITLE } from '$lib/stores/ae_events_stores';
|
import { EVENTS_MODULE_TITLE } from '$lib/stores/ae_events_stores';
|
||||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||||
@@ -158,12 +159,6 @@ async function copy_review_link() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
return `${email.slice(0, Math.min(3, at))}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: replace alert with actual email API call when available
|
// TODO: replace alert with actual email API call when available
|
||||||
function send_review_email() {
|
function send_review_email() {
|
||||||
@@ -174,7 +169,7 @@ function send_review_email() {
|
|||||||
`${badge?.given_name ?? ''} ${badge?.family_name ?? ''}`.trim();
|
`${badge?.given_name ?? ''} ${badge?.family_name ?? ''}`.trim();
|
||||||
const email = is_trusted
|
const email = is_trusted
|
||||||
? (badge?.email ?? '(no email on file)')
|
? (badge?.email ?? '(no email on file)')
|
||||||
: obscure_email(badge?.email);
|
: ae_util.obscure_email(badge?.email);
|
||||||
const event_name = EVENTS_MODULE_TITLE;
|
const event_name = EVENTS_MODULE_TITLE;
|
||||||
alert(
|
alert(
|
||||||
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
||||||
|
|||||||
@@ -52,17 +52,6 @@ let is_manager = $derived($ae_loc.manager_access === true);
|
|||||||
let is_public = $derived($ae_loc.public_access === true); // public passcode or higher — may print first prints
|
let is_public = $derived($ae_loc.public_access === true); // public passcode or higher — may print first prints
|
||||||
let is_edit_mode = $derived($ae_loc.edit_mode === true);
|
let is_edit_mode = $derived($ae_loc.edit_mode === true);
|
||||||
|
|
||||||
/**
|
|
||||||
* Obscures an email address for display to non-trusted users.
|
|
||||||
* e.g. john.doe@example.com → joh***@example.com
|
|
||||||
*/
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
const visible = email.slice(0, Math.min(3, at));
|
|
||||||
return `${visible}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function build_review_url(event_badge_obj: any): string {
|
function build_review_url(event_badge_obj: any): string {
|
||||||
// TODO: append ?passcode=... when person_passcode is added to the event_badge schema
|
// TODO: append ?passcode=... when person_passcode is added to the event_badge schema
|
||||||
@@ -96,7 +85,7 @@ function do_send_review_email(event_badge_obj: any) {
|
|||||||
`${event_badge_obj?.given_name ?? ''} ${event_badge_obj?.family_name ?? ''}`.trim();
|
`${event_badge_obj?.given_name ?? ''} ${event_badge_obj?.family_name ?? ''}`.trim();
|
||||||
const email = is_trusted
|
const email = is_trusted
|
||||||
? (event_badge_obj?.email ?? '(no email on file)')
|
? (event_badge_obj?.email ?? '(no email on file)')
|
||||||
: obscure_email(event_badge_obj?.email);
|
: ae_util.obscure_email(event_badge_obj?.email);
|
||||||
const event_name = EVENTS_MODULE_TITLE;
|
const event_name = EVENTS_MODULE_TITLE;
|
||||||
alert(
|
alert(
|
||||||
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
`PLACEHOLDER: An email will be sent to ${name} at ${email}. Use that link to review your ${event_name} badge.`
|
||||||
@@ -243,7 +232,7 @@ let visible_badge_obj_li = $derived(
|
|||||||
>
|
>
|
||||||
{is_trusted
|
{is_trusted
|
||||||
? event_badge_obj.email
|
? event_badge_obj.email
|
||||||
: obscure_email(event_badge_obj.email)}
|
: ae_util.obscure_email(event_badge_obj.email)}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -315,7 +304,7 @@ let visible_badge_obj_li = $derived(
|
|||||||
">
|
">
|
||||||
{is_trusted
|
{is_trusted
|
||||||
? event_badge_obj.email
|
? event_badge_obj.email
|
||||||
: obscure_email(event_badge_obj.email)}
|
: ae_util.obscure_email(event_badge_obj.email)}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -185,12 +185,6 @@ let presenter_sign_in_url = $derived((() => {
|
|||||||
|
|
||||||
// *** Functions and Logic
|
// *** Functions and Logic
|
||||||
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
return `${email.slice(0, Math.min(3, at))}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -335,7 +329,7 @@ function obscure_email(email: string | null | undefined): string {
|
|||||||
}
|
}
|
||||||
const display_email = $ae_loc.trusted_access
|
const display_email = $ae_loc.trusted_access
|
||||||
? use_email
|
? use_email
|
||||||
: obscure_email(use_email);
|
: ae_util.obscure_email(use_email);
|
||||||
if (!confirm(`This will send the sign in email to ${display_email}`)) {
|
if (!confirm(`This will send the sign in email to ${display_email}`)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -366,7 +360,7 @@ function obscure_email(email: string | null | undefined): string {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 m-0.25 border"
|
class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 m-0.25 border"
|
||||||
title="Email the access link to {$lq__event_presenter_obj?.full_name ?? 'presenter'} ({$ae_loc.trusted_access ? ($lq__event_presenter_obj?.person_primary_email ?? $lq__event_presenter_obj?.email ?? 'no email on file') : obscure_email($lq__event_presenter_obj?.person_primary_email ?? $lq__event_presenter_obj?.email)})">
|
title="Email the access link to {$lq__event_presenter_obj?.full_name ?? 'presenter'} ({$ae_loc.trusted_access ? ($lq__event_presenter_obj?.person_primary_email ?? $lq__event_presenter_obj?.email ?? 'no email on file') : ae_util.obscure_email($lq__event_presenter_obj?.person_primary_email ?? $lq__event_presenter_obj?.email)})">
|
||||||
<Mail size="1em" class="" />
|
<Mail size="1em" class="" />
|
||||||
<Link size="1em" class="" />
|
<Link size="1em" class="" />
|
||||||
Email Access Link
|
Email Access Link
|
||||||
|
|||||||
@@ -68,12 +68,6 @@ let ae_tmp: key_val = $state({});
|
|||||||
|
|
||||||
// *** Functions and Logic
|
// *** Functions and Logic
|
||||||
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
return `${email.slice(0, Math.min(3, at))}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="float-right flex flex-row items-center">
|
<div class="float-right flex flex-row items-center">
|
||||||
@@ -210,7 +204,7 @@ function obscure_email(email: string | null | undefined): string {
|
|||||||
}
|
}
|
||||||
const display_email = $ae_loc.trusted_access
|
const display_email = $ae_loc.trusted_access
|
||||||
? use_email
|
? use_email
|
||||||
: obscure_email(use_email);
|
: ae_util.obscure_email(use_email);
|
||||||
if (!confirm(`This will send the access link email to ${event_presenter_obj.full_name ?? 'this presenter'} (${display_email})?`)) {
|
if (!confirm(`This will send the access link email to ${event_presenter_obj.full_name ?? 'this presenter'} (${display_email})?`)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -241,7 +235,7 @@ function obscure_email(email: string | null | undefined): string {
|
|||||||
}}
|
}}
|
||||||
class="btn preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 my-0.5 border transition-all hover:transition-all"
|
class="btn preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 my-0.5 border transition-all hover:transition-all"
|
||||||
class:btn-sm={display_mode != 'default'}
|
class:btn-sm={display_mode != 'default'}
|
||||||
title="Email the access link to {event_presenter_obj.full_name ?? 'presenter'} ({$ae_loc.trusted_access ? (event_presenter_obj.person_primary_email ?? event_presenter_obj.email ?? 'no email on file') : obscure_email(event_presenter_obj.person_primary_email ?? event_presenter_obj.email)})">
|
title="Email the access link to {event_presenter_obj.full_name ?? 'presenter'} ({$ae_loc.trusted_access ? (event_presenter_obj.person_primary_email ?? event_presenter_obj.email ?? 'no email on file') : ae_util.obscure_email(event_presenter_obj.person_primary_email ?? event_presenter_obj.email)})">
|
||||||
<Mail size="1em" class="mr-1" />
|
<Mail size="1em" class="mr-1" />
|
||||||
Email Access Link
|
Email Access Link
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -191,19 +191,13 @@ $effect(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function obscure_email(email: string | null | undefined): string {
|
|
||||||
if (!email) return '';
|
|
||||||
const at = email.indexOf('@');
|
|
||||||
if (at < 0) return email;
|
|
||||||
return `${email.slice(0, Math.min(3, at))}***${email.slice(at)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function send_poc_email_link() {
|
async function send_poc_email_link() {
|
||||||
const sess = $lq__event_session_obj;
|
const sess = $lq__event_session_obj;
|
||||||
if (!sess?.poc_person_primary_email) return;
|
if (!sess?.poc_person_primary_email) return;
|
||||||
const display_email = $ae_loc.trusted_access
|
const display_email = $ae_loc.trusted_access
|
||||||
? sess.poc_person_primary_email
|
? sess.poc_person_primary_email
|
||||||
: obscure_email(sess.poc_person_primary_email);
|
: ae_util.obscure_email(sess.poc_person_primary_email);
|
||||||
if (!confirm(`Send sign-in link to ${sess.poc_person_full_name} (${display_email})?`)) return;
|
if (!confirm(`Send sign-in link to ${sess.poc_person_full_name} (${display_email})?`)) return;
|
||||||
poc_email_status = 'sending';
|
poc_email_status = 'sending';
|
||||||
try {
|
try {
|
||||||
@@ -498,7 +492,7 @@ async function send_poc_email_link() {
|
|||||||
type="button"
|
type="button"
|
||||||
disabled={poc_email_status === 'sending'}
|
disabled={poc_email_status === 'sending'}
|
||||||
onclick={send_poc_email_link}
|
onclick={send_poc_email_link}
|
||||||
title="Email the sign-in link to {pres_mgmt_loc.current.label__session_poc_name}: {$lq__event_session_obj?.poc_person_full_name} ({$ae_loc.trusted_access ? $lq__event_session_obj?.poc_person_primary_email : obscure_email($lq__event_session_obj?.poc_person_primary_email)})"
|
title="Email the sign-in link to {pres_mgmt_loc.current.label__session_poc_name}: {$lq__event_session_obj?.poc_person_full_name} ({$ae_loc.trusted_access ? $lq__event_session_obj?.poc_person_primary_email : ae_util.obscure_email($lq__event_session_obj?.poc_person_primary_email)})"
|
||||||
class="btn btn-sm preset-outlined-secondary-300-700 transition-all duration-200"
|
class="btn btn-sm preset-outlined-secondary-300-700 transition-all duration-200"
|
||||||
class:preset-tonal-secondary={poc_email_status === 'idle'}
|
class:preset-tonal-secondary={poc_email_status === 'idle'}
|
||||||
class:preset-tonal-warning={poc_email_status === 'sending'}
|
class:preset-tonal-warning={poc_email_status === 'sending'}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { RefreshCw } from '@lucide/svelte';
|
import { RefreshCw } from '@lucide/svelte';
|
||||||
|
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||||
|
|
||||||
let status: string[] = $state([]);
|
let status: string[] = $state([]);
|
||||||
let done = $state(false);
|
let done = $state(false);
|
||||||
@@ -14,122 +15,12 @@ function log(msg: string) {
|
|||||||
console.log(`[FIX-SW] ${msg}`);
|
console.log(`[FIX-SW] ${msg}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_ok(msg: string) {
|
|
||||||
log(`✓ ${msg}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_warn(msg: string) {
|
|
||||||
log(`⚠ ${msg}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function nuke_everything() {
|
async function nuke_everything() {
|
||||||
log('Starting full storage reset...');
|
await core_func.clear_all_storage((msg, level) => {
|
||||||
|
if (level === 'error') has_error = true;
|
||||||
// 1. Unregister all service workers
|
const prefix = level === 'ok' ? '✓ ' : level === 'warn' ? '⚠ ' : '';
|
||||||
if ('serviceWorker' in navigator) {
|
log(prefix + msg);
|
||||||
try {
|
|
||||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
||||||
if (registrations.length === 0) {
|
|
||||||
log_warn('No active service worker registrations found.');
|
|
||||||
} else {
|
|
||||||
log(`Found ${registrations.length} service worker registration(s).`);
|
|
||||||
for (const reg of registrations) {
|
|
||||||
const ok = await reg.unregister();
|
|
||||||
log_ok(`Unregistered SW at scope: ${reg.scope} (success: ${ok})`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
has_error = true;
|
|
||||||
log(`ERROR unregistering service workers: ${err.message}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log_warn('Service Workers not supported in this browser.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Clear all Cache Storage caches
|
|
||||||
try {
|
|
||||||
const cache_keys = await caches.keys();
|
|
||||||
if (cache_keys.length === 0) {
|
|
||||||
log_warn('No Cache Storage entries found.');
|
|
||||||
} else {
|
|
||||||
for (const key of cache_keys) {
|
|
||||||
await caches.delete(key);
|
|
||||||
log_ok(`Cleared cache: ${key}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
has_error = true;
|
|
||||||
log(`ERROR clearing Cache Storage: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Clear all IndexedDB databases
|
|
||||||
try {
|
|
||||||
if ('databases' in indexedDB) {
|
|
||||||
const db_list = await indexedDB.databases();
|
|
||||||
if (db_list.length === 0) {
|
|
||||||
log_warn('No IndexedDB databases found.');
|
|
||||||
} else {
|
|
||||||
for (const db_info of db_list) {
|
|
||||||
if (!db_info.name) continue;
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
const req = indexedDB.deleteDatabase(db_info.name!);
|
|
||||||
req.onsuccess = () => {
|
|
||||||
log_ok(`Deleted IDB database: ${db_info.name}`);
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
req.onerror = () => {
|
|
||||||
log(`ERROR deleting IDB database: ${db_info.name}`);
|
|
||||||
has_error = true;
|
|
||||||
resolve(); // continue anyway
|
|
||||||
};
|
|
||||||
req.onblocked = () => {
|
|
||||||
log_warn(`IDB delete blocked (open connections): ${db_info.name} — will proceed`);
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Fallback: delete known Aether databases by name
|
|
||||||
log_warn('indexedDB.databases() not available — deleting known Aether databases by name.');
|
|
||||||
const known_dbs = [
|
|
||||||
'ae_core_db', 'ae_events_db', 'ae_journals_db',
|
|
||||||
'ae_archives_db', 'ae_posts_db', 'ae_idaa_db',
|
|
||||||
'ae_sponsorships_db', 'ae_reports_db',
|
|
||||||
];
|
|
||||||
for (const name of known_dbs) {
|
|
||||||
await new Promise<void>((resolve) => {
|
|
||||||
const req = indexedDB.deleteDatabase(name);
|
|
||||||
req.onsuccess = () => { log_ok(`Deleted IDB database: ${name}`); resolve(); };
|
|
||||||
req.onerror = () => { resolve(); }; // not present = silent
|
|
||||||
req.onblocked = () => { log_warn(`IDB delete blocked: ${name}`); resolve(); };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
has_error = true;
|
|
||||||
log(`ERROR clearing IndexedDB: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Clear localStorage
|
|
||||||
try {
|
|
||||||
const local_count = localStorage.length;
|
|
||||||
localStorage.clear();
|
|
||||||
log_ok(`Cleared localStorage (${local_count} item(s)).`);
|
|
||||||
} catch (err: any) {
|
|
||||||
has_error = true;
|
|
||||||
log(`ERROR clearing localStorage: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Clear sessionStorage
|
|
||||||
try {
|
|
||||||
const session_count = sessionStorage.length;
|
|
||||||
sessionStorage.clear();
|
|
||||||
log_ok(`Cleared sessionStorage (${session_count} item(s)).`);
|
|
||||||
} catch (err: any) {
|
|
||||||
has_error = true;
|
|
||||||
log(`ERROR clearing sessionStorage: ${err.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
log(`─── Reset complete. Reloading in ${RELOAD_DELAY_S} seconds... ───`);
|
log(`─── Reset complete. Reloading in ${RELOAD_DELAY_S} seconds... ───`);
|
||||||
done = true;
|
done = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user