fix(core): resolve 68 compiler errors and stabilize Svelte 5 reactivity
- Fixed 'Captured initial value' warnings in 65+ components by implementing proper sync effects with 'untrack' and derived states. - Hardened Event Settings JSON editors using a temporary string-buffer pattern to safely decouple object-based data from CodeMirror's string requirements. - Resolved strict TypeScript mismatches across core routes (Accounts, Sites, etc.) and improved property indexing safety in views. - Patched Flowbite-Svelte Drawer transitions for Svelte 5 compatibility using prop spreading. - Added comprehensive safety comments to high-risk reactivity blocks. - Synchronized 'ae_types.ts' with V3 backend models.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
let log_lvl: number = 0;
|
||||
|
||||
// *** Import Svelte specific
|
||||
// import { tick } from 'svelte';
|
||||
import { untrack } from 'svelte';
|
||||
import { goto, invalidateAll } from '$app/navigation';
|
||||
|
||||
import '../app.css';
|
||||
@@ -61,55 +61,60 @@
|
||||
|
||||
let { data, children }: Props = $props();
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(`ae_root +layout.svelte data:`, data);
|
||||
}
|
||||
let ae_acct = $derived(data[$slct.account_id]);
|
||||
|
||||
// Quickly save the data passed from the parent(s) to the Svelte stores, localStorage, and other. This should catch anything that is a child of this layout.svelte file.
|
||||
$slct.account_id = data.account_id;
|
||||
if (log_lvl) {
|
||||
console.log(`*ae_root +layout.svelte* $slct.account_id = ${$slct.account_id}`);
|
||||
}
|
||||
let ae_acct = data[$slct.account_id];
|
||||
|
||||
if (ae_acct) {
|
||||
$ae_api = {
|
||||
...$ae_api,
|
||||
...(ae_acct.api || {})
|
||||
};
|
||||
$effect(() => {
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$ae_api = `, $ae_api);
|
||||
console.log(`ae_root +layout.svelte data:`, data);
|
||||
}
|
||||
|
||||
// FORCE UPDATE: If the incoming data is a valid site (not a fallback ghost),
|
||||
// we must ensure the ae_loc store is updated regardless of what's in localStorage.
|
||||
if (ae_acct.loc?.account_id && ae_acct.loc.account_id !== 'ghost') {
|
||||
$ae_loc = {
|
||||
...$ae_loc,
|
||||
...(ae_acct.loc || {})
|
||||
// Quickly save the data passed from the parent(s) to the Svelte stores, localStorage, and other. This should catch anything that is a child of this layout.svelte file.
|
||||
$slct.account_id = data.account_id;
|
||||
if (log_lvl) {
|
||||
console.log(`*ae_root +layout.svelte* $slct.account_id = ${$slct.account_id}`);
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (ae_acct) {
|
||||
$ae_api = {
|
||||
...$ae_api,
|
||||
...(ae_acct.api || {})
|
||||
};
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$ae_api = `, $ae_api);
|
||||
}
|
||||
|
||||
// FORCE UPDATE: If the incoming data is a valid site (not a fallback ghost),
|
||||
// we must ensure the ae_loc store is updated regardless of what's in localStorage.
|
||||
if (ae_acct.loc?.account_id && ae_acct.loc.account_id !== 'ghost') {
|
||||
$ae_loc = {
|
||||
...$ae_loc,
|
||||
...(ae_acct.loc || {})
|
||||
};
|
||||
} else {
|
||||
// If it IS a ghost, we still update it to show the correct fallback message
|
||||
$ae_loc = {
|
||||
...$ae_loc,
|
||||
...(ae_acct.loc || {})
|
||||
};
|
||||
}
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$ae_loc = `, $ae_loc);
|
||||
}
|
||||
|
||||
$slct = {
|
||||
...$slct,
|
||||
...(ae_acct.slct || {})
|
||||
};
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$slct = `, $slct);
|
||||
}
|
||||
} else {
|
||||
// If it IS a ghost, we still update it to show the correct fallback message
|
||||
$ae_loc = {
|
||||
...$ae_loc,
|
||||
...(ae_acct.loc || {})
|
||||
};
|
||||
console.warn('ae_root +layout.svelte: ae_acct not found for account_id:', $slct.account_id);
|
||||
}
|
||||
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$ae_loc = `, $ae_loc);
|
||||
}
|
||||
|
||||
$slct = {
|
||||
...$slct,
|
||||
...(ae_acct.slct || {})
|
||||
};
|
||||
if (log_lvl > 1) {
|
||||
console.log(`$slct = `, $slct);
|
||||
}
|
||||
} else {
|
||||
console.warn('ae_root +layout.svelte: ae_acct not found for account_id:', $slct.account_id);
|
||||
}
|
||||
});
|
||||
|
||||
let flag_clear_idb: boolean = $state(false);
|
||||
let flag_clear_local: boolean = $state(false);
|
||||
@@ -373,21 +378,26 @@
|
||||
}
|
||||
// END: Expired Cache Check:
|
||||
|
||||
// $effect(() => {
|
||||
if (browser && flag_clear_idb) {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Clear IDB...`);
|
||||
}
|
||||
flag_clear_idb = false;
|
||||
$ae_loc.last_cache_refresh = Date.now();
|
||||
$effect(() => {
|
||||
// WARNING: This effect manages destructive system state (clearing DBs).
|
||||
// It MUST use untrack to ensure the reload logic doesn't trigger itself.
|
||||
if (browser && flag_clear_idb) {
|
||||
untrack(() => {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Clear IDB...`);
|
||||
}
|
||||
flag_clear_idb = false;
|
||||
$ae_loc.last_cache_refresh = Date.now();
|
||||
|
||||
clear_idb();
|
||||
clear_idb();
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: IDB cleared. Reload!`);
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: IDB cleared. Reload!`);
|
||||
}
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
// BEGIN: Access Checks:
|
||||
// Updated 2024-11-21
|
||||
@@ -458,59 +468,62 @@
|
||||
// cerberus
|
||||
}
|
||||
|
||||
// $effect(() => {
|
||||
if (browser && flag_reload) {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Reloading page after other flags checked...`);
|
||||
$effect(() => {
|
||||
if (browser && flag_reload) {
|
||||
untrack(() => {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Reloading page after other flags checked...`);
|
||||
}
|
||||
|
||||
// // Clear Indexed DB as well
|
||||
// if (flag_clear_idb) {
|
||||
// if (log_lvl) {
|
||||
// console.log(`ROOT: Clearing IndexedDB databases...`);
|
||||
// }
|
||||
|
||||
// clear_idb();
|
||||
// }
|
||||
|
||||
// Clear localStorage and sessionStorage
|
||||
if (flag_clear_local) {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Clearing localStorage...`);
|
||||
}
|
||||
|
||||
clear_local();
|
||||
}
|
||||
if (flag_clear_sess) {
|
||||
if (log_lvl) {
|
||||
console.log('ROOT: Clearing sessionStorage...');
|
||||
}
|
||||
|
||||
clear_sess();
|
||||
}
|
||||
// tick();
|
||||
|
||||
// try {
|
||||
// goto(data.route.id, {replaceState: true, invalidateAll: true});
|
||||
// } catch (e) {
|
||||
// console.log('Error going to root page:', e);
|
||||
// goto('/', {replaceState: true, invalidateAll: true});
|
||||
// }
|
||||
|
||||
// This does not seem to work fast enough or something?
|
||||
// goto('/', {replaceState: true, invalidateAll: true});
|
||||
|
||||
// The page does usually seem to reload correctly?
|
||||
// window.location.reload(true); // true only works with Firefox
|
||||
// window.location.reload({forceGet: true});
|
||||
|
||||
// location.reload();
|
||||
// tick();
|
||||
|
||||
invalidateAll();
|
||||
|
||||
// alert('Local and Session Storage cleared and Indexed DBs deleted. You will probably want to refresh the page.');
|
||||
});
|
||||
}
|
||||
|
||||
// // Clear Indexed DB as well
|
||||
// if (flag_clear_idb) {
|
||||
// if (log_lvl) {
|
||||
// console.log(`ROOT: Clearing IndexedDB databases...`);
|
||||
// }
|
||||
|
||||
// clear_idb();
|
||||
// }
|
||||
|
||||
// Clear localStorage and sessionStorage
|
||||
if (flag_clear_local) {
|
||||
if (log_lvl) {
|
||||
console.log(`ROOT: Clearing localStorage...`);
|
||||
}
|
||||
|
||||
clear_local();
|
||||
}
|
||||
if (flag_clear_sess) {
|
||||
if (log_lvl) {
|
||||
console.log('ROOT: Clearing sessionStorage...');
|
||||
}
|
||||
|
||||
clear_sess();
|
||||
}
|
||||
// tick();
|
||||
|
||||
// try {
|
||||
// goto(data.route.id, {replaceState: true, invalidateAll: true});
|
||||
// } catch (e) {
|
||||
// console.log('Error going to root page:', e);
|
||||
// goto('/', {replaceState: true, invalidateAll: true});
|
||||
// }
|
||||
|
||||
// This does not seem to work fast enough or something?
|
||||
// goto('/', {replaceState: true, invalidateAll: true});
|
||||
|
||||
// The page does usually seem to reload correctly?
|
||||
// window.location.reload(true); // true only works with Firefox
|
||||
// window.location.reload({forceGet: true});
|
||||
|
||||
// location.reload();
|
||||
// tick();
|
||||
|
||||
invalidateAll();
|
||||
|
||||
// alert('Local and Session Storage cleared and Indexed DBs deleted. You will probably want to refresh the page.');
|
||||
}
|
||||
});
|
||||
|
||||
function clear_idb() {
|
||||
indexedDB.deleteDatabase('ae_archives_db'); // Archives module
|
||||
@@ -543,115 +556,119 @@
|
||||
sessionStorage.clear();
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
// save_ds_to_local(ae_acct.ds);
|
||||
let ae_ds = ae_acct.ds;
|
||||
if (log_lvl) {
|
||||
console.log(`ae_ds__ data:`, ae_ds);
|
||||
}
|
||||
for (let [key, value] of Object.entries(ae_ds)) {
|
||||
console.log(`ae_ds__ key: ${key}, value:`, value);
|
||||
localStorage.setItem(`ae_ds__${key}`, JSON.stringify(value));
|
||||
}
|
||||
|
||||
// This is how the download and upload progress is tracked.
|
||||
window.addEventListener('message', function (event) {
|
||||
$effect(() => {
|
||||
if (browser) {
|
||||
// save_ds_to_local(ae_acct.ds);
|
||||
let ae_ds = ae_acct.ds;
|
||||
if (log_lvl) {
|
||||
console.log('Message received in root +layout.svelte:', event);
|
||||
console.log(`ae_ds__ data:`, ae_ds);
|
||||
}
|
||||
if (ae_ds) {
|
||||
for (let [key, value] of Object.entries(ae_ds)) {
|
||||
console.log(`ae_ds__ key: ${key}, value:`, value);
|
||||
localStorage.setItem(`ae_ds__${key}`, JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (event.data.type == 'api_download_blob') {
|
||||
// This is how the download and upload progress is tracked.
|
||||
window.addEventListener('message', function (event) {
|
||||
if (log_lvl) {
|
||||
console.log('Download blob (file) message received:', event.data);
|
||||
console.log('Message received in root +layout.svelte:', event);
|
||||
}
|
||||
|
||||
let task_id = event.data.task_id;
|
||||
if (event.data.type == 'api_download_blob') {
|
||||
if (log_lvl) {
|
||||
console.log('Download blob (file) message received:', event.data);
|
||||
}
|
||||
|
||||
$ae_sess.api_download_kv[task_id] = {
|
||||
status: event.data.status,
|
||||
task_id: task_id,
|
||||
endpoint: event.data.endpoint,
|
||||
filename: event.data.filename,
|
||||
size_total: event.data.size_total,
|
||||
size_loaded: event.data.size_loaded,
|
||||
percent_completed: event.data.percent_completed
|
||||
};
|
||||
} else if (event.data.type == 'api_post_json_form') {
|
||||
if (log_lvl) {
|
||||
console.log('Post JSON form message received:', event.data);
|
||||
let task_id = event.data.task_id;
|
||||
|
||||
$ae_sess.api_download_kv[task_id] = {
|
||||
status: event.data.status,
|
||||
task_id: task_id,
|
||||
endpoint: event.data.endpoint,
|
||||
filename: event.data.filename,
|
||||
size_total: event.data.size_total,
|
||||
size_loaded: event.data.size_loaded,
|
||||
percent_completed: event.data.percent_completed
|
||||
};
|
||||
} else if (event.data.type == 'api_post_json_form') {
|
||||
if (log_lvl) {
|
||||
console.log('Post JSON form message received:', event.data);
|
||||
}
|
||||
|
||||
let task_id = event.data.task_id;
|
||||
|
||||
$ae_sess.api_upload_kv[task_id] = {
|
||||
status: event.data.status,
|
||||
task_id: task_id,
|
||||
endpoint: event.data.endpoint,
|
||||
filename: event.data.filename,
|
||||
size_total: event.data.size_total,
|
||||
size_loaded: event.data.size_loaded,
|
||||
percent_completed: event.data.percent_completed,
|
||||
progress: event.data.progress,
|
||||
rate: event.data.rate
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
let task_id = event.data.task_id;
|
||||
let iframe = data.url.searchParams.get('iframe');
|
||||
if (iframe == 'true') {
|
||||
console.log('Use iframe layout!');
|
||||
$ae_loc.iframe = true;
|
||||
|
||||
$ae_sess.api_upload_kv[task_id] = {
|
||||
status: event.data.status,
|
||||
task_id: task_id,
|
||||
endpoint: event.data.endpoint,
|
||||
filename: event.data.filename,
|
||||
size_total: event.data.size_total,
|
||||
size_loaded: event.data.size_loaded,
|
||||
percent_completed: event.data.percent_completed,
|
||||
progress: event.data.progress,
|
||||
rate: event.data.rate
|
||||
};
|
||||
document.getElementsByTagName('html')[0].classList.add('iframe');
|
||||
// document.getElementsByTagName('html')[0].classList.remove('dark');
|
||||
// document.getElementsByTagName('html')[0].classList.remove('light');
|
||||
|
||||
$ae_loc.app_cfg.show_element__access_type = false;
|
||||
$ae_loc.app_cfg.show_element__cfg = false;
|
||||
} else if (iframe == 'false') {
|
||||
$ae_loc.iframe = false;
|
||||
|
||||
document.getElementsByTagName('html')[0].classList.remove('iframe');
|
||||
// document.getElementsByTagName('html')[0].classList.add('dark');
|
||||
// document.getElementsByTagName('html')[0].classList.add('light');
|
||||
}
|
||||
});
|
||||
|
||||
let iframe = data.url.searchParams.get('iframe');
|
||||
if (iframe == 'true') {
|
||||
console.log('Use iframe layout!');
|
||||
$ae_loc.iframe = true;
|
||||
|
||||
document.getElementsByTagName('html')[0].classList.add('iframe');
|
||||
// document.getElementsByTagName('html')[0].classList.remove('dark');
|
||||
// document.getElementsByTagName('html')[0].classList.remove('light');
|
||||
|
||||
$ae_loc.app_cfg.show_element__access_type = false;
|
||||
$ae_loc.app_cfg.show_element__cfg = false;
|
||||
} else if (iframe == 'false') {
|
||||
$ae_loc.iframe = false;
|
||||
|
||||
document.getElementsByTagName('html')[0].classList.remove('iframe');
|
||||
// document.getElementsByTagName('html')[0].classList.add('dark');
|
||||
// document.getElementsByTagName('html')[0].classList.add('light');
|
||||
}
|
||||
|
||||
if (!$ae_loc.iframe && $ae_loc.trusted_access) {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = true;
|
||||
} else if ($ae_loc.iframe && $ae_loc.manager_access) {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = true;
|
||||
} else {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = false;
|
||||
}
|
||||
|
||||
// This is mainly for Precon CHOW
|
||||
if (data.url.searchParams.get('event_id')) {
|
||||
$events_slct.event_id = data.url.searchParams.get('event_id');
|
||||
$events_loc.event_id = data.url.searchParams.get('event_id');
|
||||
}
|
||||
|
||||
if (data.url.searchParams.get('sponsorship_cfg_id')) {
|
||||
$slct.sponsorship_cfg_id = data.url.searchParams.get('sponsorship_cfg_id');
|
||||
$ae_loc.mod.sponsorships.cfg_id = data.url.searchParams.get('sponsorship_cfg_id');
|
||||
}
|
||||
|
||||
// *** Electron Native Mode Detection ***
|
||||
// Explicitly set is_native if the bridge is detected, ensuring reactivity for all child components
|
||||
// @ts-ignore
|
||||
if (window.native_app || window.aetherNative) {
|
||||
if (!$ae_loc.is_native) {
|
||||
console.log('ELECTRON: Native environment detected via window bridge.');
|
||||
$ae_loc.is_native = true;
|
||||
if (!$ae_loc.iframe && $ae_loc.trusted_access) {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = true;
|
||||
} else if ($ae_loc.iframe && $ae_loc.manager_access) {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = true;
|
||||
} else {
|
||||
$ae_loc.app_cfg.show_element__access_type = true;
|
||||
$ae_loc.app_cfg.show_element__cfg = false;
|
||||
}
|
||||
// Ensure launcher mode is set to native if we're in the bridge
|
||||
if ($events_loc?.launcher && $events_loc.launcher.app_mode !== 'native') {
|
||||
$events_loc.launcher.app_mode = 'native';
|
||||
|
||||
// This is mainly for Precon CHOW
|
||||
if (data.url.searchParams.get('event_id')) {
|
||||
$events_slct.event_id = data.url.searchParams.get('event_id');
|
||||
$events_loc.event_id = data.url.searchParams.get('event_id');
|
||||
}
|
||||
|
||||
if (data.url.searchParams.get('sponsorship_cfg_id')) {
|
||||
$slct.sponsorship_cfg_id = data.url.searchParams.get('sponsorship_cfg_id');
|
||||
$ae_loc.mod.sponsorships.cfg_id = data.url.searchParams.get('sponsorship_cfg_id');
|
||||
}
|
||||
|
||||
// *** Electron Native Mode Detection ***
|
||||
// Explicitly set is_native if the bridge is detected, ensuring reactivity for all child components
|
||||
// @ts-ignore
|
||||
if (window.native_app || window.aetherNative) {
|
||||
if (!$ae_loc.is_native) {
|
||||
console.log('ELECTRON: Native environment detected via window bridge.');
|
||||
$ae_loc.is_native = true;
|
||||
}
|
||||
// Ensure launcher mode is set to native if we're in the bridge
|
||||
if ($events_loc?.launcher && $events_loc.launcher.app_mode !== 'native') {
|
||||
$events_loc.launcher.app_mode = 'native';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// We want to loop through all of the data store (ds) key value pairs and set them to localStorage
|
||||
// $: if (ae_acct.ds) {
|
||||
|
||||
Reference in New Issue
Block a user