diff --git a/src/lib/ae_events/ae_events__event.ts b/src/lib/ae_events/ae_events__event.ts index 186e89fa..857e1142 100644 --- a/src/lib/ae_events/ae_events__event.ts +++ b/src/lib/ae_events/ae_events__event.ts @@ -10,6 +10,7 @@ import { load_ae_obj_li__event_device } from './ae_events__event_device'; import { load_ae_obj_li__event_location } from './ae_events__event_location'; import { load_ae_obj_li__event_session } from './ae_events__event_session'; import { load_ae_obj_li__event_badge_template } from '$lib/ae_events/ae_events__event_badge_template'; +import { load_ae_obj_li__event_file } from '$lib/ae_events/ae_events__event_file'; const ae_promises: key_val = {}; diff --git a/src/lib/ae_events/ae_events__event_location.ts b/src/lib/ae_events/ae_events__event_location.ts index c05025ba..1c999230 100644 --- a/src/lib/ae_events/ae_events__event_location.ts +++ b/src/lib/ae_events/ae_events__event_location.ts @@ -4,6 +4,7 @@ import { api } from '$lib/api/api'; import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie'; import { db_events } from '$lib/ae_events/db_events'; import type { ae_EventLocation } from '$lib/types/ae_types'; +import { load_ae_obj_li__event_file } from '$lib/ae_events/ae_events__event_file'; const ae_promises: key_val = {}; @@ -12,12 +13,18 @@ export async function load_ae_obj_id__event_location({ api_cfg, event_location_id, view = 'default', + inc_file_li = false, + inc_session_li = false, + inc_all_file_li = false, try_cache = true, log_lvl = 0 }: { api_cfg: any; event_location_id: string; view?: string; + inc_file_li?: boolean; + inc_session_li?: boolean; + inc_all_file_li?: boolean; try_cache?: boolean; log_lvl?: number; }): Promise { @@ -58,7 +65,11 @@ export async function load_ae_obj_id__event_location({ } } - return ae_promises.load__event_location_obj || null; + if (!ae_promises?.load__event_location_obj) { + return null; + } + + return await _handle_nested_loads(ae_promises.load__event_location_obj, { api_cfg, inc_file_li, log_lvl }); } // Updated 2026-01-20 to V3 @@ -66,6 +77,7 @@ export async function load_ae_obj_li__event_location({ api_cfg, for_obj_type = 'event', for_obj_id, + inc_file_li = false, enabled = 'enabled', hidden = 'not_hidden', limit = 100, @@ -82,6 +94,7 @@ export async function load_ae_obj_li__event_location({ api_cfg: any; for_obj_type?: string; for_obj_id: string; + inc_file_li?: boolean; enabled?: 'enabled' | 'all' | 'not_enabled'; hidden?: 'hidden' | 'all' | 'not_hidden'; limit?: number; @@ -136,9 +149,35 @@ export async function load_ae_obj_li__event_location({ } } + if (ae_promises.load__event_location_obj_li) { + for (const location of ae_promises.load__event_location_obj_li) { + await _handle_nested_loads(location, { api_cfg, inc_file_li, log_lvl }); + } + } + return ae_promises.load__event_location_obj_li || []; } +/** + * Handle nested data loads for a single location object. + */ +async function _handle_nested_loads(location_obj: any, { api_cfg, inc_file_li, log_lvl }: any) { + const current_location_id = location_obj.event_location_id_random || location_obj.event_location_id || location_obj.id; + + if (inc_file_li) { + location_obj.event_file_li = await load_ae_obj_li__event_file({ + api_cfg, + for_obj_type: 'event_location', + for_obj_id: current_location_id, + enabled: 'all', + limit: 25, + log_lvl + }); + } + + return location_obj; +} + // Updated 2026-01-20 to V3 export async function create_ae_obj__event_location({ api_cfg, diff --git a/src/lib/electron/electron_relay.ts b/src/lib/electron/electron_relay.ts index 6da0bd12..70749a57 100644 --- a/src/lib/electron/electron_relay.ts +++ b/src/lib/electron/electron_relay.ts @@ -1,123 +1,76 @@ /** - * Aether Electron Relay (V3) - * Maps legacy launcher commands to the modern Aether Native Bridge. + * Aether Native Bridge Relay (TypeScript) + * Standardizes communication between SvelteKit and the Electron Main process. */ -const log_lvl = 1; +// Handle the standardized aetherNative bridge +const native = (typeof window !== 'undefined') ? (window as any).aetherNative : null; -/** - * Returns the native bridge if available. - */ -function getBridge() { - if (typeof window !== 'undefined' && (window as any).aetherNative) { - return (window as any).aetherNative; - } - return null; +export async function get_device_config(): Promise { + if (!native) return null; + return await native.get_device_config(); } -/** - * Open a local directory in the OS File Manager. - */ -export async function open_folder(path: string) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - - if (log_lvl) console.log(`Relay: Opening folder: ${path}`); - return await bridge.openFolder(path); +// --- File Operations --- + +export async function check_hash_file_cache({ cache_root, hash }: { cache_root: string; hash: string }): Promise { + if (!native) return false; + // Uses the specific bridge method instead of generic invoke + return await native.check_cache({ cache_root, hash }); } -/** - * Launch a file using the OS default application. - */ -export async function launch_file(path: string) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - - if (log_lvl) console.log(`Relay: Launching file: ${path}`); - return await bridge.launchFile(path); +export async function download_to_cache({ + url, + cache_root, + hash, + api_key, + account_id +}: { + url: string; + cache_root: string; + hash: string; + api_key: string; + account_id: string; +}): Promise<{ success: boolean; path?: string; error?: string }> { + if (!native) return { success: false, error: 'Native bridge not available' }; + return await native.download_to_cache({ url, cache_root, hash, api_key, account_id }); } -/** - * Legacy compatibility alias for launch_file. - */ -export const open_local_file_v2 = async ({ file_path, filename }: { file_path: string, filename: string }) => { - return launch_file(`${file_path}/${filename}`); -}; - -/** - * Run a shell command. - */ -export async function run_cmd({ cmd, return_stdout = true }: { cmd: string, return_stdout?: boolean }) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - - if (log_lvl) console.log(`Relay: Running command: ${cmd}`); - const result = await bridge.runCommand(cmd); - - if (return_stdout) return result.stdout; - return result.success; +export async function launch_from_cache({ + cache_root, + hash, + temp_root, + filename +}: { + cache_root: string; + hash: string; + temp_root: string; + filename: string; +}): Promise<{ success: boolean; error?: string }> { + if (!native) return { success: false, error: 'Native bridge not available' }; + return await native.launch_from_cache({ cache_root, hash, temp_root, filename }); } -/** - * Legacy compatibility alias for run_cmd. - */ -export const run_cmd_sync = run_cmd; +// --- OS Operations --- -/** - * Kill specific processes by name. - */ -export async function kill_processes({ process_name_li = [] }: { process_name_li: string[] }) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - - for (const name of process_name_li) { - if (log_lvl) console.log(`Relay: Killing process: ${name}`); - await bridge.runCommand(`pkill -f "${name}"`); - } - return true; +export async function open_folder(path: string): Promise { + if (!native) return; + return await native.open_folder(path); } -/** - * Check if a file hash exists in the local cache. - */ -export async function check_hash_file_cache({ cacheRoot, hash }: { cacheRoot: string, hash: string }) { - const bridge = getBridge(); - if (!bridge) return false; - return await bridge.checkCache({ cacheRoot, hash }); +export async function run_cmd({ cmd, return_stdout = false }: { cmd: string; return_stdout?: boolean }): Promise { + if (!native) return false; + return await native.run_command({ cmd, return_stdout }); } -/** - * Download a file to the local cache. - */ -export async function download_to_cache({ url, cacheRoot, hash, apiKey }: { url: string, cacheRoot: string, hash: string, apiKey: string }) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - return await bridge.downloadToCache({ url, cacheRoot, hash, apiKey }); +export async function run_cmd_sync({ cmd, return_stdout = false }: { cmd: string; return_stdout?: boolean }): Promise { + if (!native) return false; + // Legacy mapping to the same command handler + return await native.run_command({ cmd, return_stdout }); } -/** - * Launch a file from the local cache (copies to temp first). - */ -export async function launch_from_cache({ cacheRoot, hash, tempRoot, filename }: { cacheRoot: string, hash: string, tempRoot: string, filename: string }) { - const bridge = getBridge(); - if (!bridge) return { success: false, error: 'Native bridge not found' }; - return await bridge.launchFromCache({ cacheRoot, hash, tempRoot, filename }); -} - -/** - * Get system/device info. - */ -export async function get_device_info() { - const bridge = getBridge(); - if (!bridge) return null; - return await bridge.getDeviceConfig(); -} - -/** - * Placeholder for legacy AppleScript execution. - */ -export async function run_osascript({ cmd }: { cmd: string }) { - const bridge = getBridge(); - if (!bridge) return null; - return await bridge.runCommand(`osascript -e '${cmd}'`); -} \ No newline at end of file +// --- Compatibility Aliases (Legacy) --- +export const open_local_file_v2 = launch_from_cache; +export const get_device_info = get_device_config; +export const run_osascript = async ({ cmd }: { cmd: string }) => await run_cmd({ cmd: `osascript -e '${cmd}'` }); +export const kill_processes = async ({ process_name }: { process_name: string }) => await run_cmd({ cmd: `pkill -f '${process_name}'` }); diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index f3c64a09..f1b581af 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -128,7 +128,7 @@ export async function load({ fetch, params, parent, route, url }) { is_native = true; if (log_lvl) console.log('ROOT LOAD: Detected Aether Native Bridge. Requesting device config...'); try { - const native_device_config = await (window as any).aetherNative.getDeviceConfig(); + const native_device_config = await (window as any).aetherNative.get_device_config(); if (native_device_config) { if (log_lvl) console.log('ROOT LOAD: Native device config received:', native_device_config); // Map native device config to the expected result structure diff --git a/src/routes/events/[event_id]/(launcher)/+layout.svelte b/src/routes/events/[event_id]/(launcher)/+layout.svelte new file mode 100644 index 00000000..df860770 --- /dev/null +++ b/src/routes/events/[event_id]/(launcher)/+layout.svelte @@ -0,0 +1,21 @@ + + + + + + +{@render children?.()} diff --git a/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.svelte b/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.svelte index f2e12221..f230a13b 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.svelte @@ -184,7 +184,8 @@ // console.log('GET DEVICE INFO!!! GET DEVICE INFO!!! GET DEVICE INFO!!!'); - let get_device_info_promise = get_device_info({ event_device_id: event_device_id }); + // Using standardized relay method + let get_device_info_promise = get_device_info(); get_device_info_promise.then(function (result) { // console.log('GOT DEVICE INFO!!! GOT DEVICE INFO!!! GOT DEVICE INFO!!!'); console.log(get_device_info_promise); diff --git a/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.ts b/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.ts index 72d50749..097467e6 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.ts +++ b/src/routes/events/[event_id]/(launcher)/launcher/[event_location_id]/+page.ts @@ -51,7 +51,7 @@ export async function load({ params, parent, url }) { for_obj_type: 'event_location', for_obj_id: event_location_id, inc_file_li: true, // Only include files directly under the session? - inc_all_file_li: false, // Also include files under presentations and presenters as well? + inc_all_file_li: true, // Also include files under presentations and presenters as well? inc_presentation_li: true, inc_presenter_li: true, enabled: 'enabled', diff --git a/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte b/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte index 64f90305..4277bfaa 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte @@ -1,126 +1,149 @@ {#if currently_syncing && log_lvl} -
- - Pre-Caching: {currently_syncing} +
+
+ +
+ Syncing Room Files... + {currently_syncing} + Room Status: {sync_stats.cached}/{sync_stats.total} Ready +
+
-{/if} +{/if} \ No newline at end of file diff --git a/src/routes/events/[event_id]/(launcher)/launcher_file_cont.svelte b/src/routes/events/[event_id]/(launcher)/launcher_file_cont.svelte index fb2fab76..0927470e 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher_file_cont.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher_file_cont.svelte @@ -90,30 +90,33 @@ // 1. NATIVE MODE (Electron) if ($ae_loc.is_native && $events_loc.launcher.app_mode === 'native') { - const cacheRoot = $ae_loc.local_file_cache_path; - const tempRoot = $ae_loc.host_file_temp_path; + const cache_root = $ae_loc.local_file_cache_path; + const temp_root = $ae_loc.host_file_temp_path; open_file_clicked = true; open_file_status = 'checking_cache'; open_file_status_message = 'Checking local cache...'; - const exists = await native.check_hash_file_cache({ cacheRoot, hash: event_file_obj.hash_sha256 }); + const exists = await native.check_hash_file_cache({ cache_root, hash: event_file_obj.hash_sha256 }); if (!exists) { open_file_status = 'downloading_file'; open_file_status_message = 'Downloading file to cache...'; - const url = `${$ae_api.base_url}/v3/crud/hosted_file/${event_file_obj.hosted_file_id}/download`; - const dlResult = await native.download_to_cache({ + // Use the PROVEN endpoint path from api.ts that is known to work in Default Mode. + const url = `${$ae_api.base_url}/hosted_file/${event_file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(event_file_obj.filename)}`; + + const dl_result = await native.download_to_cache({ url, - cacheRoot, + cache_root, hash: event_file_obj.hash_sha256, - apiKey: $ae_api.api_secret_key + api_key: $ae_api.api_secret_key, + account_id: $ae_api.account_id }); - if (!dlResult.success) { + if (!dl_result.success) { open_file_status = 'error'; - open_file_status_message = `Download failed: ${dlResult.error}`; + open_file_status_message = `Download failed: ${dl_result.error}`; setTimeout(() => open_file_clicked = false, 5000); return; } @@ -122,16 +125,16 @@ open_file_status = 'opening_file'; open_file_status_message = 'Opening Application'; - const launchResult = await native.launch_from_cache({ - cacheRoot, + const launch_result = await native.launch_from_cache({ + cache_root, hash: event_file_obj.hash_sha256, - tempRoot, + temp_root, filename: event_file_obj.filename }); - if (!launchResult.success) { + if (!launch_result.success) { open_file_status = 'error'; - open_file_status_message = `Failed to open: ${launchResult.error}`; + open_file_status_message = `Failed to open: ${launch_result.error}`; } setTimeout(() => open_file_clicked = false, 5000); diff --git a/src/routes/events/[event_id]/+layout.ts b/src/routes/events/[event_id]/+layout.ts index 3ffef18a..c371c5f7 100644 --- a/src/routes/events/[event_id]/+layout.ts +++ b/src/routes/events/[event_id]/+layout.ts @@ -46,7 +46,7 @@ export async function load({ params, parent, url }) { const load_event_obj: ae_Event | null = await events_func.load_ae_obj_id__event({ api_cfg: ae_acct.api, event_id: event_id, - // inc_file_li: true, + inc_file_li: true, // inc_device_li: true, inc_location_li: true, inc_session_li: true,