|
|
|
|
@@ -124,6 +124,7 @@ let timer__session: any = $state(null);
|
|
|
|
|
let timer__presentation: any = $state(null);
|
|
|
|
|
let timer__presenter: any = $state(null);
|
|
|
|
|
let timer__file_sync: any = $state(null);
|
|
|
|
|
let timer__file_list: any = $state(null);
|
|
|
|
|
|
|
|
|
|
let is_syncing = false;
|
|
|
|
|
let show_monitor = $state(false);
|
|
|
|
|
@@ -196,6 +197,15 @@ onMount(async () => {
|
|
|
|
|
// 3. Native File Sync Loop (Dexie -> Disk)
|
|
|
|
|
timer__file_sync = setInterval(() => run_sync_cycle(), loop_info.file_sync);
|
|
|
|
|
|
|
|
|
|
// 4. File List Refresh Loop (API -> Dexie, prunes deleted/hidden session files)
|
|
|
|
|
// WHY: The presenter/session refresh loops don't fetch file lists, so deleted or
|
|
|
|
|
// hidden files can stay in Dexie on the Launcher machine indefinitely (until IDB is
|
|
|
|
|
// manually cleared). This loop calls load_ae_obj_li__event_file for the selected
|
|
|
|
|
// session, which triggers the stale-record pruning in _refresh_file_li_background.
|
|
|
|
|
// 60s matches the session/location loops; presenter files are pruned via inc_file_li
|
|
|
|
|
// in refresh_presenter_data which runs every 120s.
|
|
|
|
|
timer__file_list = setInterval(() => refresh_current_session_files(), 60000);
|
|
|
|
|
|
|
|
|
|
// Immediate first run for metadata
|
|
|
|
|
refresh_event_data();
|
|
|
|
|
run_device_heartbeat();
|
|
|
|
|
@@ -211,6 +221,7 @@ onMount(async () => {
|
|
|
|
|
setTimeout(() => refresh_session_data(), 1000);
|
|
|
|
|
setTimeout(() => refresh_presentation_data(), 3000);
|
|
|
|
|
setTimeout(() => refresh_presenter_data(), 5000);
|
|
|
|
|
setTimeout(() => refresh_current_session_files(), 7000);
|
|
|
|
|
|
|
|
|
|
// Clean up stale .tmp files (interrupted downloads) on startup.
|
|
|
|
|
// Age threshold is user-configurable (cfg → General → Cache Maintenance), default 24h.
|
|
|
|
|
@@ -235,6 +246,7 @@ onDestroy(() => {
|
|
|
|
|
if (timer__presentation) clearInterval(timer__presentation);
|
|
|
|
|
if (timer__presenter) clearInterval(timer__presenter);
|
|
|
|
|
if (timer__file_sync) clearInterval(timer__file_sync);
|
|
|
|
|
if (timer__file_list) clearInterval(timer__file_list);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// WHY: refresh_location_config() runs on a 60s timer. Without this effect,
|
|
|
|
|
@@ -248,6 +260,15 @@ $effect(() => {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// WHY: fires refresh_current_session_files() immediately when the operator switches
|
|
|
|
|
// sessions so deleted/hidden files are pruned without waiting for the 60s timer.
|
|
|
|
|
$effect(() => {
|
|
|
|
|
const session_id = $events_slct.event_session_id;
|
|
|
|
|
if (session_id) {
|
|
|
|
|
refresh_current_session_files();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Force Sync Trigger: fetches ALL child metadata for ALL sessions in the room.
|
|
|
|
|
// WHY: by default, the launcher only warms presentation/presenter caches for the
|
|
|
|
|
// *selected* session to save bandwidth. Onsite operators use this trigger to
|
|
|
|
|
@@ -341,6 +362,7 @@ async function refresh_presenter_data() {
|
|
|
|
|
api_cfg: $ae_api,
|
|
|
|
|
for_obj_type: 'event_session',
|
|
|
|
|
for_obj_id: session_id,
|
|
|
|
|
inc_file_li: true, // WHY: triggers pruning of deleted/hidden presenter files in Dexie
|
|
|
|
|
try_cache: true,
|
|
|
|
|
log_lvl: 0
|
|
|
|
|
});
|
|
|
|
|
@@ -600,6 +622,29 @@ async function refresh_location_config() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Session File List Refresh
|
|
|
|
|
* Fetches the file list for the SELECTED session and prunes stale/deleted/hidden records.
|
|
|
|
|
* WHY: The regular session/presenter refresh loops don't fetch file lists, so deleted or
|
|
|
|
|
* hidden files persist in the Launcher's Dexie indefinitely. This runs on a 60s timer
|
|
|
|
|
* and also fires immediately when the selected session changes. Presenter-level files are
|
|
|
|
|
* handled separately via inc_file_li=true in refresh_presenter_data (120s timer).
|
|
|
|
|
*/
|
|
|
|
|
async function refresh_current_session_files() {
|
|
|
|
|
if ($events_loc.launcher.sync_paused) return;
|
|
|
|
|
const session_id = $events_slct.event_session_id;
|
|
|
|
|
if (!session_id) return;
|
|
|
|
|
try {
|
|
|
|
|
await events_func.load_ae_obj_li__event_file({
|
|
|
|
|
api_cfg: $ae_api,
|
|
|
|
|
for_obj_type: 'event_session',
|
|
|
|
|
for_obj_id: session_id,
|
|
|
|
|
try_cache: true,
|
|
|
|
|
log_lvl: 0
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force Location Sync
|
|
|
|
|
* Fetches ALL sessions and their children (presentations, presenters, files)
|
|
|
|
|
|