diff --git a/documentation/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md b/documentation/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md new file mode 100644 index 00000000..5dae7beb --- /dev/null +++ b/documentation/PROJECT_LAUNCHER_CONFIG_OVERHAUL.md @@ -0,0 +1,37 @@ +# Project: Launcher Configuration UI/UX Overhaul + +**Status:** IN-PROGRESS +**Goal:** Create a standardized, responsive, and categorized configuration interface for the AE Events Launcher. + +## 1. Objectives +- **Standardization**: Use consistent naming (`snake_case`), styling, and layout across all config pieces. +- **Flexibility**: Support mobile, tablet, and high-res Macbook displays using responsive widths. +- **Intelligent Collapsing**: Implement a 3-way state logic: `collapsed`, `auto_collapse`, `pinned`. +- **Contextual Fields**: Hide technical/editable fields unless `$ae_loc.edit_mode` is enabled. + +## 2. 3-Way State Logic +- **`collapsed`**: Section content is hidden. +- **`auto`**: Section is expanded by default, but closes if another "auto" section is opened. +- **`pinned`**: Section is expanded and *ignores* the auto-collapse signals from other sections. + +## 3. Component Architecture +- **`Launcher_Cfg`**: The main container with Tabbed Navigation (System, Sync, General). +- **`Launcher_Cfg_Section`**: Shared wrapper component providing the header, 3-way toggle, and responsive container. +- **Sub-components**: Individual sections (Health, Native OS, Timers, etc.) refactored to use the shared wrapper. + +## 4. Feature Matrix & `edit_mode` +| Component | Always Visible (Read-Only) | Edit Mode Only (Write/Technical) | +| :--- | :--- | :--- | +| **Health** | Heartbeat Status, RAM/CPU Gauges | Raw Metadata JSON, Hostname, IPs | +| **Native OS** | Folder Open Buttons, Recording Toggle | Manual Terminal CMD, Reset Wallpaper | +| **Sync** | Sync Stats (Total/Cached) | Millisecond Timers, Hash Prefix Length | +| **Updates** | Current Version, Check Button | Update Path/URL inputs | + +## 5. Progress Tracker +- [ ] Migrate `events_loc.launcher` visibility flags to 3-way states. +- [ ] Implement `Launcher_Cfg_Section` wrapper component. +- [ ] Refactor `Launcher_Cfg_Health`. +- [ ] Refactor `Launcher_Cfg_Native_OS`. +- [ ] Refactor `Launcher_Cfg_Sync_Timers`. +- [ ] Refactor `Launcher_Cfg_Updates`. +- [ ] Final UI/UX Polish. diff --git a/src/lib/stores/ae_events_stores.ts b/src/lib/stores/ae_events_stores.ts index 58e9009b..7f2291e3 100644 --- a/src/lib/stores/ae_events_stores.ts +++ b/src/lib/stores/ae_events_stores.ts @@ -152,6 +152,17 @@ const events_local_data_struct: key_val = { show_section__controller: false, + // 3-Way Section States (V5 Overhaul) + // Values: 'collapsed' | 'auto' | 'pinned' + section_state__health: 'auto', + section_state__native_os: 'collapsed', + section_state__sync_timers: 'collapsed', + section_state__updates: 'collapsed', + section_state__controller: 'auto', + section_state__screen_saver: 'collapsed', + section_state__app_modes: 'collapsed', + section_state__local_actions: 'collapsed', + datetime_format: 'datetime_12_long', time_format: 'time_12_short', time_hours: 12, // 12 or 24 diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_app_modes.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_app_modes.svelte index d66d9904..2506dfb2 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_app_modes.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_app_modes.svelte @@ -1,229 +1,104 @@ -
-

+ +
+ + +
+ +
+ + + +
+
+ + +
+ +
+ + + + +
+
+ + -

-
-
- {#if !$events_loc.launcher.app_mode || $events_loc.launcher.app_mode != 'default'} - - {/if} - {#if $events_loc.launcher.app_mode != 'native'} - - {/if} - {#if $events_loc.launcher.app_mode != 'onsite'} - - {/if} -
- -
- {#if $events_loc.launcher.hide__launcher_menu} - - {/if} - {#if !$events_loc.launcher.hide__launcher_header} - - {/if} - {#if $events_loc.launcher.hide__launcher_header} - - {/if} - - {#if !$events_loc.launcher.hide__launcher_footer} - - {/if} - {#if $events_loc.launcher.hide__launcher_footer} - - {/if} - - {#if !$events_loc.launcher.hide__launcher_menu} - - {/if} - {#if !$events_loc.launcher.hide__session_datetimes} - - {/if} - {#if $events_loc.launcher.hide__session_datetimes} - - {/if} - - - - {#if !$events_loc.launcher.hide__ws_element} - - {/if} - {#if $events_loc.launcher.hide__ws_element} - - {/if} - - {#if !$events_loc.launcher.hide__modal_header_title} - - {/if} - {#if $events_loc.launcher.hide__modal_header_title} - - {/if} -
+ + {#if $ae_loc.edit_mode} +
+ +
+ + +
+
+ {/if}
-
+ diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_controller.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_controller.svelte index 3f6c1abb..485c9567 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_controller.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_controller.svelte @@ -1,69 +1,54 @@ -
-

- -

+ -
-
+ +
+
-
- { - $events_sess.launcher.controller_unlock_group_code = - !$events_sess.launcher.controller_unlock_group_code; - - if ($events_loc.launcher.ws_connect) { - $events_sess.launcher.trigger__ws_disconnect = true; - } - }} - readonly={!$events_sess.launcher.controller_unlock_group_code} - /> + +
- {#if $events_loc.launcher.ws_connect} - - {/if} +
+ + + {#if $ae_loc.edit_mode} +
+ +
+ $events_sess.launcher.controller_unlock_group_code = true} + /> + +
+

Double-click input to unlock editing. Changing code triggers reconnect.

+
+ {/if}
-
+ diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_health.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_health.svelte index 5b175451..535cb25f 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_health.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_health.svelte @@ -1,6 +1,12 @@ -{#if $ae_loc.is_native} -
-

- -

- -
- -
- - -
-
- CPU Architecture: {$ae_loc.native_device?.meta_json?.arch || '...'} - Load: Healthy -
-
-
-
-
- - -
-
- Memory (RAM) - {ram_usage_pct}% Used -
-
-
-
-
- Free: {$ae_loc.native_device?.meta_json?.free_mem || '...'} / {$ae_loc.native_device?.meta_json?.total_mem || '...'} -
-
+ + + +
+ + +
+
+ CPU Architecture: {$ae_loc.native_device?.meta_json?.arch || '...'} + Load: Healthy
- - -
-
- Last Heartbeat - - {$events_sess.launcher.heartbeat_info.last_timestamp || 'Pending...'} - -
- -
- Local File Cache - - {$events_sess.launcher.sync_stats.cached} / {$events_sess.launcher.sync_stats.total} - -
- - {#if $events_sess.launcher.sync_stats.currently_syncing} -
-
- -
- Syncing File... - {$events_sess.launcher.sync_stats.currently_syncing} -
-
-
- {/if} -
- - -
-
- Hostname: - {$ae_loc.native_device.info_hostname || '...'} -
-
- IP Addresses: - {$ae_loc.native_device.info_ip_list || '...'} -
+
+
-
-{/if} + + +
+
+ Memory (RAM) + {ram_usage_pct}% Used +
+
+
+
+
+ Free: {$ae_loc.native_device?.meta_json?.free_mem || '...'} / {$ae_loc.native_device?.meta_json?.total_mem || '...'} +
+
+ + + +
+
+ Last Heartbeat + + {$events_sess.launcher.heartbeat_info.last_timestamp || 'Pending...'} + +
+ +
+ Local File Cache + + {$events_sess.launcher.sync_stats.cached} / {$events_sess.launcher.sync_stats.total} + +
+ + {#if $events_sess.launcher.sync_stats.currently_syncing} +
+
+ +
+ Syncing File... + {$events_sess.launcher.sync_stats.currently_syncing} +
+
+
+ {/if} +
+ + + {#if $ae_loc.edit_mode} +
+
+ Hostname: + {$ae_loc.native_device.info_hostname || '...'} +
+
+ IP Addresses: + {$ae_loc.native_device.info_ip_list || '...'} +
+
+ +
+                    {JSON.stringify($ae_loc.native_device, null, 2)}
+                
+
+
+ {/if} + diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_local_actions.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_local_actions.svelte index c1001668..e2f331f5 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_local_actions.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_local_actions.svelte @@ -1,117 +1,109 @@ -
-

- -

- -
-
+
+ + +
+ - - The action happens when the option is selected + + * Destructive actions require browser confirmation.
-
+ +
-
API: {$ae_api.base_url}
+ + {#if $ae_loc.edit_mode} +
+ +
+ Endpoint: {$ae_api.base_url}
+ Account: {$ae_loc.account_id} +
+
+ {/if}
-
+ diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_native_os.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_native_os.svelte index 4ca03a71..b7b97d10 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_native_os.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_native_os.svelte @@ -2,6 +2,12 @@ import { ae_loc, ae_api, ae_sess } from '$lib/stores/ae_stores'; import { events_loc, events_sess } from '$lib/stores/ae_events_stores'; import * as native from '$lib/electron/electron_relay'; + import Launcher_Cfg_Section from './launcher_cfg_section.svelte'; + + interface Props { + on_expand?: () => void; + } + let { on_expand }: Props = $props(); let test_cmd_result = $state(''); let remote_app: 'powerpoint' | 'keynote' = $state('powerpoint'); @@ -34,202 +40,154 @@ let show_power_confirm = $state<{ action: string, label: string } | null>(null); -{#if $ae_loc.is_native} -
-

- -

+ + + + + -
- {#if system_status} -
- {system_status} + +
+
+ + +
+ +
+ + + + +
+ {#if remote_status} +
{remote_status}
+ {/if} +
+ + + {#if $ae_loc.edit_mode} +
+
+
+ +
+ + +
- {/if} - - -
- -
- - - - +
+ +
+ + +
- -
- -
- - - - - -
-
- - -
- -
- - -
-
- - -
-
- - -
- -
- - - - -
- {#if remote_status} -
{remote_status}
- {/if} -
- - -
+
+ >Run
- {#if test_cmd_result} -
-
{test_cmd_result}
- -
+
{test_cmd_result}
{/if}
-
-{/if} + {/if} + {#if show_power_confirm}
-
+

Confirm System Action

Are you sure you want to {show_power_confirm.action} this host machine? - This will terminate the native application and any active presentations.

@@ -247,5 +205,3 @@
{/if} - - diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_screen_saver.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_screen_saver.svelte index 5b1f9dd5..185fdc50 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_screen_saver.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_screen_saver.svelte @@ -1,65 +1,75 @@ -
-

- -

+ +
+ + + {#if $ae_loc.edit_mode} +
+ +
+
+ Idle Wait + +
+
+ Cycle Check + +
+
+ Image Rotation + +
+
+
+ {:else} + +
+
+ Active Idle Timeout: + {($events_loc.launcher.idle_timer / 60000).toFixed(1)} minutes +
+

+ The screen saver automatically rotates digital posters when no activity is detected for the specified time. +

+
+ {/if} -
- - - - - +
+

+ Applies to "Poster" session types only +

+
-
+ diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_section.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_section.svelte new file mode 100644 index 00000000..7d0f5387 --- /dev/null +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_section.svelte @@ -0,0 +1,102 @@ + + +
+ + + +
+
+ +
+ {title} + {#if description && !is_open} + {description} + {/if} +
+
+ +
+ + + + + +
+
+ + + {#if is_open} +
+ {#if $ae_loc.edit_mode} +
+ + Technical Mode + + {#if state === 'pinned'} + Pinned + {/if} +
+ {/if} + +
+ {@render children?.()} +
+
+ {/if} +
diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_sync_timers.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_sync_timers.svelte index 50d5de11..44681f72 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_sync_timers.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_sync_timers.svelte @@ -1,85 +1,104 @@ -{#if $ae_loc.is_native} -
-

- -

+ + + {#if $ae_loc.native_device} +
+ + + {#if $ae_loc.edit_mode} +
+ +
+
+ Event Data + +
+
+ Device Config + +
+
+ Room/Location + +
+
+ Session Loop + +
+
+
-
- {#if $ae_loc.native_device} - - - - - -
- * Prefix: {($ae_loc.native_device.hash_prefix_length || 2)} chars. Reload required. +
+ +
+ Hash Prefix Length + +
+

* Prefix change requires a full app reload to take effect.

{:else} -
No device config hydrated.
+ +
+
+ Event Sync: + {($ae_loc.native_device.check_event_loop_period / 1000).toFixed(1)}s +
+
+ Room Monitor: + {($ae_loc.native_device.check_event_location_loop_period / 1000).toFixed(1)}s +
+
+ Prefix Sharding: + {$ae_loc.native_device.hash_prefix_length || 2} chars +
+
+
+

Enable Edit Mode to adjust polling intervals.

+
{/if}
-
-{/if} + {:else} +
+ Device configuration not loaded. +
+ {/if} + diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_template.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_template.svelte new file mode 100644 index 00000000..de8ec88a --- /dev/null +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_template.svelte @@ -0,0 +1,203 @@ + + + + + {#if action_status} +
+ {action_status} +
+ {/if} + + +
+ + + +
+ + +
+ + +
+ + +
+
+ + +
+ + +
+
+ Engine Health + Stable +
+ + +
+
+ Processing Load + 45% +
+
+
+
+
+
+ + +
+ + + {#if $ae_loc.edit_mode} +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ +
+ Threshold (ms) + +
+
+ + +
+ +
+[LOG] System Initialized
+[INFO] Store synced with IndexedDB
+[DEBUG] active_tab: template
+[WARN] Latency detected in sync loop
+                
+
+
+ {/if} +
+ + +{#if show_confirm} +
+
+

Confirm Action

+

+ Are you sure you want to perform this test operation? This demonstrate the standard confirmation pattern. +

+
+ + +
+
+
+{/if} diff --git a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_updates.svelte b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_updates.svelte index bcdb8893..14c43f7c 100644 --- a/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_updates.svelte +++ b/src/routes/events/[event_id]/(launcher)/cfg_components/launcher_cfg_updates.svelte @@ -2,6 +2,12 @@ import { ae_loc, ae_api, ae_sess } from '$lib/stores/ae_stores'; import { events_loc, events_sess } from '$lib/stores/ae_events_stores'; import * as native from '$lib/electron/electron_relay'; + import Launcher_Cfg_Section from './launcher_cfg_section.svelte'; + + interface Props { + on_expand?: () => void; + } + let { on_expand }: Props = $props(); let update_source: 'url' | 'file' = $state('file'); let update_path = $state('~/OSIT/Speaker Ready System/Admin Share/Custom Applications/osit_binaries/'); @@ -24,7 +30,7 @@ if (res.success) { download_result = res; - update_status = 'Update located/downloaded. ready to install.'; + update_status = 'Update located/downloaded. Ready to install.'; } else { update_status = `Failed: ${res.error}`; } @@ -37,42 +43,23 @@ async function handle_install() { update_status = 'Initiating installation...'; - // Note: Real installation logic in the Electron app will likely - // terminate the process or restart it. alert('Installation logic is OS-specific. This will typically swap the application bundle and restart.'); } -{#if $ae_loc.is_native} -
-

- -

- -
-
+ + +
+ + + {#if $ae_loc.edit_mode} +
@@ -89,45 +76,46 @@ {:else} {/if} - - - - {#if update_status} -
- {update_status} -
- {/if} - - {#if download_result} - - {/if}
-
-
-{/if} + {/if} + + + + + {#if update_status} +
+ {update_status} +
+ {/if} + + {#if download_result} + + {/if} +
+ diff --git a/src/routes/events/[event_id]/(launcher)/launcher/+layout.svelte b/src/routes/events/[event_id]/(launcher)/launcher/+layout.svelte index cc8dd790..ce847b6b 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher/+layout.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher/+layout.svelte @@ -1228,11 +1228,11 @@
{ + if (key.startsWith('section_state__') && key !== `section_state__${current_key}`) { + if (launcher[key] === 'auto') { + launcher[key] = 'collapsed'; + } + } + }); + $events_loc.launcher = launcher; // Trigger store update + }
{#if $ae_loc.is_native} - - - + handle_section_expand('health')} /> + handle_section_expand('native_os')} /> + handle_section_expand('updates')} /> {:else}
Native OS features are only available when running in the Aether Desktop app. @@ -105,16 +122,16 @@ {#if active_tab === 'sync'}
- + handle_section_expand('sync_timers')} />
{/if} {#if active_tab === 'general'}
- - - - + handle_section_expand('controller')} /> + handle_section_expand('app_modes')} /> + handle_section_expand('screen_saver')} /> + handle_section_expand('local_actions')} />
{/if}