style(launcher): Phase 3 — FA→Lucide icon migration across all launcher files

Replaces all FontAwesome <span class="fas/fab fa-*"> with Lucide Svelte
components across 20 launcher files. launcher_cfg_section.svelte icon prop
changed from FA string to AnyComponent (svelte:component for dynamic render).
Dynamic file-extension icon now uses ae_util.file_extension_icon_lucide().
Fixes class: directives on components (invalid in Svelte 5) → ternary class.
Removes title prop from Lucide components → wrapping <span title="...">.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-16 12:33:37 -04:00
parent 99df204763
commit efc0f46079
20 changed files with 184 additions and 169 deletions

View File

@@ -2,6 +2,7 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { LayoutGrid, GraduationCap, IdCard, Clock } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -54,7 +55,7 @@
<Launcher_Cfg_Section
title="Display & App Modes"
icon="fa-object-group"
icon={LayoutGrid}
bind:state={$events_loc.launcher.section_state__app_modes}
{on_expand}
description="Mode: {$events_loc.launcher.app_mode} | UI Layout"
@@ -73,7 +74,7 @@
class:preset-tonal-surface={is_poster_mode}
title="Standard oral/presentation layout — menus and headers visible"
>
<span class="fas fa-chalkboard-teacher mr-1 opacity-70"></span>
<GraduationCap size="0.85em" class="mr-1 opacity-70" />
Oral / Default
</button>
<button
@@ -84,7 +85,7 @@
class:preset-tonal-surface={!is_poster_mode}
title="Digital Poster kiosk — hides site chrome, menu, header & footer"
>
<span class="fas fa-id-badge mr-1 opacity-70"></span>
<IdCard size="0.85em" class="mr-1 opacity-70" />
Poster Kiosk
</button>
</div>
@@ -204,7 +205,7 @@
}}
class="btn btn-xs preset-tonal-surface w-full text-[10px]"
>
<span class="fas fa-clock mr-2 opacity-50"></span>
<Clock size="0.85em" class="mr-1 opacity-50" />
Clock Format:
<strong>{$events_loc.launcher.time_hours}-hour</strong>
</button>

View File

@@ -2,6 +2,7 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { Gamepad2, Plug, Unlink, Link, RefreshCw, LockOpen, Lock } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -15,7 +16,7 @@
<Launcher_Cfg_Section
title="Remote Controller"
icon="fa-gamepad"
icon={Gamepad2}
bind:state={$events_loc.launcher.section_state__controller}
{on_expand}
description="Mode: {$events_loc.launcher?.controller} | WS: {ws_connected
@@ -29,7 +30,7 @@
class="flex items-center justify-between bg-surface-500/5 p-2 rounded border border-surface-500/10"
>
<div class="flex items-center gap-2">
<span class="fas fa-plug opacity-50"></span>
<Plug size="1em" class="opacity-50" />
<span class="text-[10px] font-bold uppercase tracking-wider"
>WebSocket Link</span
>
@@ -79,9 +80,9 @@
class:preset-tonal-success={!$events_loc.launcher.ws_connect}
>
{#if $events_loc.launcher.ws_connect}
<span class="fas fa-unlink mr-2"></span> Disconnect
<Unlink size="0.85em" class="mr-1" /> Disconnect
{:else}
<span class="fas fa-link mr-2"></span> Connect Now
<Link size="0.85em" class="mr-1" /> Connect Now
{/if}
</button>
@@ -94,7 +95,7 @@
class="btn btn-sm preset-tonal-secondary hover:preset-filled-secondary-500 text-[10px] font-bold"
disabled={!ws_connected}
>
<span class="fas fa-sync-alt mr-2"></span> Group Reload
<RefreshCw size="0.85em" class="mr-1" /> Group Reload
</button>
</div>
@@ -125,12 +126,11 @@
class="btn btn-xs preset-tonal-surface"
title="Toggle Unlock"
>
<span
class="fas {$events_sess.launcher
.controller_unlock_group_code
? 'fa-lock-open text-primary-500'
: 'fa-lock'}"
></span>
{#if $events_sess.launcher.controller_unlock_group_code}
<LockOpen size="0.85em" class="text-primary-500" />
{:else}
<Lock size="0.85em" />
{/if}
</button>
</div>
<p class="text-[8px] opacity-40 italic ml-1">

View File

@@ -2,6 +2,7 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { HeartPulse, RefreshCw } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -43,7 +44,7 @@
<Launcher_Cfg_Section
title="System & Sync Health"
icon="fa-heartbeat"
icon={HeartPulse}
bind:state={$events_loc.launcher.section_state__health}
{on_expand}
description="Heartbeat: {$events_sess.launcher.heartbeat_info
@@ -132,7 +133,7 @@
class="col-span-full bg-primary-500/10 p-2 rounded border border-primary-500/20 animate-pulse mt-1"
>
<div class="flex items-center gap-2">
<span class="fas fa-sync fa-spin text-primary-500"></span>
<RefreshCw size="1em" class="animate-spin text-primary-500" />
<div class="flex flex-col truncate">
<span
class="text-[8px] uppercase font-bold text-primary-500"

View File

@@ -3,6 +3,7 @@
import { events_loc } from '$lib/stores/ae_events_stores';
import { cleanup_tmp_files } from '$lib/electron/electron_relay';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { Wrench, Eraser } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -76,7 +77,7 @@
<Launcher_Cfg_Section
title="Local Reset & Actions"
icon="fa-tools"
icon={Wrench}
bind:state={$events_loc.launcher.section_state__local_actions}
{on_expand}
description="Cache wiping and global menu toggles"
@@ -160,7 +161,7 @@
onclick={handle_cleanup_now}
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 grow"
>
<span class="fas fa-broom mr-1"></span> Clean .tmp Now
<Eraser size="0.85em" class="mr-1" /> Clean .tmp Now
</button>
</div>
{#if cleanup_status}

View File

@@ -3,6 +3,11 @@
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';
import {
Code, FlaskConical, FolderOpen, Maximize2, Monitor,
SkipBack, Play, Square, SkipForward,
Columns2, Image, RefreshCw, Power
} from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -49,7 +54,7 @@
<Launcher_Cfg_Section
title="Native OS Management"
icon="fa-laptop-code"
icon={Code}
bind:state={$events_loc.launcher.section_state__native_os}
{on_expand}
description="OS: {$ae_loc.native_device?.meta_json?.platform ||
@@ -59,7 +64,7 @@
electron_relay functions all return null when native is absent — no errors. -->
{#if $ae_loc.edit_mode && !$ae_loc.is_native}
<div class="flex items-center gap-2 px-2 py-1.5 rounded-lg bg-warning-500/10 border border-warning-500/30 mb-1">
<span class="fas fa-flask text-warning-500 text-xs"></span>
<FlaskConical size="0.75em" class="text-warning-500" />
<span class="text-[9px] text-warning-500 font-bold uppercase tracking-wide">Dev Preview — controls visible but non-functional without Electron</span>
</div>
{/if}
@@ -84,21 +89,21 @@
native.open_folder($ae_loc.local_file_cache_path)}
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
>
<span class="fas fa-folder-open mr-2 w-3"></span> Cache
<FolderOpen size="0.85em" class="mr-1 shrink-0" /> Cache
</button>
<button
type="button"
onclick={() => native.open_folder($ae_loc.host_file_temp_path)}
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
>
<span class="fas fa-folder-open mr-2 w-3"></span> Temp
<FolderOpen size="0.85em" class="mr-1 shrink-0" /> Temp
</button>
<button
type="button"
onclick={() => native.window_control({ action: 'maximize' })}
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
>
<span class="fas fa-expand mr-1"></span> Maximize
<Maximize2 size="0.85em" class="mr-1" /> Maximize
</button>
<button
type="button"
@@ -109,7 +114,7 @@
)}
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
>
<span class="fas fa-desktop mr-1"></span> Kiosk
<Monitor size="0.85em" class="mr-1" /> Kiosk
</button>
</div>
</div>
@@ -136,7 +141,7 @@
class="btn btn-sm preset-tonal-secondary"
title="Previous Slide"
>
<span class="fas fa-step-backward"></span>
<SkipBack size="1em" />
</button>
<button
type="button"
@@ -144,7 +149,7 @@
class="btn btn-sm preset-tonal-success"
title="Start/Resume Slideshow"
>
<span class="fas fa-play"></span>
<Play size="1em" />
</button>
<button
type="button"
@@ -152,7 +157,7 @@
class="btn btn-sm preset-tonal-error"
title="Stop Slideshow"
>
<span class="fas fa-stop"></span>
<Square size="1em" />
</button>
<button
type="button"
@@ -160,7 +165,7 @@
class="btn btn-sm preset-tonal-secondary"
title="Next Slide"
>
<span class="fas fa-step-forward"></span>
<SkipForward size="1em" />
</button>
</div>
{#if remote_status}
@@ -194,7 +199,7 @@
)}
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
>
<span class="fas fa-columns mr-2 w-3"></span> Extend Mode
<Columns2 size="0.85em" class="mr-1 shrink-0" /> Extend Mode
</button>
<button
type="button"
@@ -208,7 +213,7 @@
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
disabled={!$ae_loc.site_header_image_path}
>
<span class="fas fa-image mr-2 w-3"></span> Reset Wallpaper
<Image size="0.85em" class="mr-1 shrink-0" /> Reset Wallpaper
</button>
</div>
</div>
@@ -227,7 +232,7 @@
})}
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
>
<span class="fas fa-sync-alt mr-2 w-3"></span> Reboot
<RefreshCw size="0.85em" class="mr-1 shrink-0" /> Reboot
</button>
<button
type="button"
@@ -238,7 +243,7 @@
})}
class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start"
>
<span class="fas fa-power-off mr-2 w-3"></span> Shutdown
<Power size="0.85em" class="mr-1 shrink-0" /> Shutdown
</button>
</div>
</div>

View File

@@ -2,6 +2,7 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { IdCard } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -11,7 +12,7 @@
<Launcher_Cfg_Section
title="Poster Screen Saver"
icon="fa-id-badge"
icon={IdCard}
bind:state={$events_loc.launcher.section_state__screen_saver}
{on_expand}
description="Idle: {($events_loc.launcher.idle_timer / 60000).toFixed(

View File

@@ -2,10 +2,13 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc } from '$lib/stores/ae_events_stores';
import { slide } from 'svelte/transition';
import { Pin, ChevronRight, ChevronDown, Pencil } from 'lucide-svelte';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyComponent = any;
interface Props {
title: string;
icon: string;
icon: AnyComponent;
state: 'collapsed' | 'auto' | 'pinned';
description?: string;
children?: import('svelte').Snippet;
@@ -69,11 +72,13 @@
onclick={toggle_expand}
>
<div class="flex items-center gap-3">
<span
class="fas {icon} w-5 text-center opacity-70 {state === 'auto'
<svelte:component
this={icon}
size="1em"
class="w-5 text-center opacity-70 {state === 'auto'
? 'text-primary-500'
: ''} {state === 'pinned' ? 'text-warning-500' : ''}"
></span>
/>
<div class="flex flex-col">
<span
class="text-sm font-bold tracking-tight uppercase {!is_open
@@ -101,16 +106,15 @@
? 'Unpin Section'
: 'Pin Section (Stay open)'}
>
<span class="fas fa-thumbtack text-[10px]"></span>
<Pin size="0.7em" />
</button>
<!-- Collapse Icon -->
<span
class="fas transition-transform duration-300 opacity-30"
class:fa-chevron-right={!is_open}
class:fa-chevron-down={is_open}
class:rotate-180={is_open}
></span>
{#if is_open}
<ChevronDown size="1em" class="transition-transform duration-300 opacity-30" />
{:else}
<ChevronRight size="1em" class="transition-transform duration-300 opacity-30" />
{/if}
</div>
</header>
@@ -125,11 +129,11 @@
<span
class="text-[8px] uppercase font-bold tracking-widest text-primary-500/60 flex items-center gap-1"
>
<span class="fas fa-edit"></span> Technical Mode
<Pencil size="0.7em" /> Technical Mode
</span>
{#if state === 'pinned'}
<span
class="badge variant-filled-warning text-[8px] uppercase"
class="badge preset-filled-warning text-[8px] uppercase"
>Pinned</span
>
{/if}

View File

@@ -2,6 +2,7 @@
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { RefreshCw, Play, Pause } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -11,7 +12,7 @@
<Launcher_Cfg_Section
title="Sync Engine & Timers"
icon="fa-sync"
icon={RefreshCw}
bind:state={$events_loc.launcher.section_state__sync_timers}
{on_expand}
description="Prefix: {$ae_loc.native_device?.hash_prefix_length ||
@@ -31,9 +32,9 @@
class:preset-tonal-success={!$events_loc.launcher.sync_paused}
>
{#if $events_loc.launcher.sync_paused}
<span class="fas fa-play mr-1"></span> Resume
<Play size="0.85em" class="mr-1" /> Resume
{:else}
<span class="fas fa-pause mr-1"></span> Pause
<Pause size="0.85em" class="mr-1" /> Pause
{/if}
</button>
</div>

View File

@@ -7,6 +7,7 @@
import { ae_loc, ae_api, ae_sess } from '$lib/stores/ae_stores';
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
import { Boxes, Zap, Settings, RefreshCw, AlertTriangle, Trash2 } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -40,7 +41,7 @@
<Launcher_Cfg_Section
title="Template Section"
icon="fa-cubes"
icon={Boxes}
bind:state={$events_loc.launcher.section_state__template}
{on_expand}
description="Kitchen Sink Scaffold | Demo Only"
@@ -67,14 +68,14 @@
onclick={() => handle_test_action('Primary')}
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
>
<span class="fas fa-bolt mr-2 w-3 text-center"></span> Primary
<Zap size="0.85em" class="mr-1 shrink-0" /> Primary
</button>
<button
type="button"
onclick={() => handle_test_action('Secondary')}
class="btn btn-xs preset-tonal-secondary hover:preset-filled-secondary-500 justify-start"
>
<span class="fas fa-cog mr-2 w-3 text-center"></span> Secondary
<Settings size="0.85em" class="mr-1 shrink-0" /> Secondary
</button>
</div>
@@ -146,7 +147,7 @@
onclick={() => handle_test_action('Refresh')}
class="btn btn-xs preset-outlined-surface-500 w-full text-[10px]"
>
<span class="fas fa-sync mr-2" class:fa-spin={is_loading}></span>
<RefreshCw size="0.85em" class="mr-1 {is_loading ? 'animate-spin' : ''}" />
Refresh State
</button>
</div>
@@ -168,8 +169,7 @@
onclick={() => (show_confirm = true)}
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
>
<span class="fas fa-exclamation-triangle mr-2 w-3"
></span> Reset All
<AlertTriangle size="0.85em" class="mr-1 shrink-0" /> Reset All
</button>
</div>
<div class="flex flex-col gap-1">
@@ -181,7 +181,7 @@
type="button"
class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start"
>
<span class="fas fa-trash-alt mr-2 w-3"></span> Wipe Cache
<Trash2 size="0.85em" class="mr-1 shrink-0" /> Wipe Cache
</button>
</div>
</div>

View File

@@ -3,6 +3,7 @@
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';
import { CloudDownload, LoaderCircle, Search, Wand2 } from 'lucide-svelte';
interface Props {
on_expand?: () => void;
@@ -56,7 +57,7 @@
<Launcher_Cfg_Section
title="Application Updates"
icon="fa-cloud-download-alt"
icon={CloudDownload}
bind:state={$events_loc.launcher.section_state__updates}
{on_expand}
description="v1.0.0 | Source: {update_source}"
@@ -118,9 +119,9 @@
class="btn btn-sm preset-filled-tertiary hover:preset-filled-primary-500 text-[10px] w-full"
>
{#if is_checking}
<span class="fas fa-spinner fa-spin mr-2"></span> Checking...
<LoaderCircle size="0.85em" class="animate-spin mr-1" /> Checking...
{:else}
<span class="fas fa-search mr-2"></span> Check for Updates
<Search size="0.85em" class="mr-1" /> Check for Updates
{/if}
</button>
@@ -138,7 +139,7 @@
onclick={handle_install}
class="btn btn-sm preset-filled-success hover:preset-filled-primary-500 text-[10px] w-full animate-bounce mt-2 shadow-lg"
>
<span class="fas fa-magic mr-2"></span> Install & Relaunch
<Wand2 size="0.85em" class="mr-1" /> Install & Relaunch
</button>
{/if}
</div>

View File

@@ -20,11 +20,25 @@
import { listen, idle, onIdle, restartCountdown } from 'svelte-idle';
import {
// Brain,
// House, Library,
LoaderCircle,
// RefreshCw,
Satellite
Satellite,
MapPin,
Laptop,
BedDouble,
MousePointer,
Wifi,
Network,
X,
CalendarDays,
Clock,
Biohazard,
Search,
GraduationCap,
Info,
ZoomIn,
Minimize2,
Monitor,
List
} from '@lucide/svelte';
// *** Import Aether specific variables and functions
@@ -640,14 +654,14 @@
}}
title="Toggle Edit Mode to show location options and more"
>
<span class="fas fa-map-marker-alt"></span>
<MapPin size="1em" />
<span class="sr-only">Location:</span>
</button>
{$lq__event_location_obj?.name}
</h3>
{:else}
<div class="flex flex-row gap-1 items-center justify-center">
<span class="fas fa-spinner fa-spin mx-1"></span>
<LoaderCircle size="1em" class="animate-spin mx-1" />
<span>Loading event...</span>
</div>
{/if}
@@ -725,7 +739,7 @@
<div
class="flex flex-row items-center justify-center p-8 opacity-50"
>
<span class="fas fa-map-marker-alt mx-2 text-2xl"></span>
<MapPin size="1.5em" class="mx-2" />
<span>Please select a location from the menu</span>
</div>
{/if}
@@ -783,11 +797,11 @@
title="Toggle Edit Mode to show location options and more"
>
<span class="sr-only">Location:</span>
<span class="fas fa-map-marker-alt"></span>
<MapPin size="1em" />
</button>
{$lq__event_location_obj?.name}
{#if $lq__event_device_obj?.name}
<span class="fas fa-laptop mx-1"></span>
<Laptop size="1em" class="mx-1" />
{$lq__event_device_obj?.name}
{/if}
</div>
@@ -799,10 +813,10 @@
title="The user is currently {$idle ? 'idle' : 'active'}"
>
{#if $idle}
<span class="fas fa-bed mx-1"></span>
<BedDouble size="1em" class="mx-1" />
<span class="hidden group-hover:inline"> Idle </span>
{:else}
<span class="fas fa-mouse-pointer mx-1"></span>
<MousePointer size="1em" class="mx-1" />
<span class="hidden group-hover:inline"> Active </span>
{/if}
</span>
@@ -811,7 +825,7 @@
class="group px-2 py-0.5 rounded-md transition-colors duration-300"
title="Online status = {online?.current}"
>
<span class="fas fa-wifi mx-1"></span>
<Wifi size="1em" class="mx-1" />
{online?.current ? '' : 'Offline!'}
</span>
@@ -828,10 +842,10 @@
: 'disconnected'} API: {$ae_api?.base_url}"
>
{#if $events_sess.launcher.ws_connect_status == 'connected'}
<span class="fas fa-sitemap mx-1 text-green-700"></span>
<Network size="1em" class="mx-1 text-green-700" />
<span class="hidden group-hover:inline"> WS Connected </span>
{:else}
<span class="fas fa-times mx-1"></span>
<X size="1em" class="mx-1" />
<span class="hidden group-hover:inline"> WS Disconnected </span>
{/if}
</span>
@@ -862,11 +876,11 @@
class="current_datetime font-mono px-2 hover:font-bold hover:bg-white dark:hover:bg-slate-700 transition-colors"
>
<span class="hidden md:inline">
<span class="fas fa-calendar-alt"></span>
<CalendarDays size="1em" />
{ae_util.iso_datetime_formatter($time, 'date_full_no_year')}
</span>
<span class="hidden sm:inline">
<span class="fas fa-clock"></span>
<Clock size="1em" />
</span>
{#if $events_loc.launcher?.time_hours == 12}
{ae_util.iso_datetime_formatter($time, 'time_12_long')}
@@ -884,7 +898,7 @@
class:opacity-25={!$ae_loc.trusted_access}
class:hover:opacity-75={!$ae_loc.trusted_access}
>
<span class="fas fa-biohazard"></span>
<Biohazard size="1em" />
<span class="hidden">Launcher Config</span>
</button>
</div>
@@ -923,7 +937,7 @@
href="/events/{$events_slct.event_id}"
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500"
>
<span class="fas fa-search m-1"></span>
<Search size="1em" class="m-1" />
Session Search
</a>
{#if $events_slct?.event_location_id}
@@ -931,7 +945,7 @@
href="/events/{$events_slct.event_id}/location/{$events_slct.event_location_id}"
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500"
>
<span class="fas fa-map-marker m-1"></span>
<MapPin size="1em" class="m-1" />
View Selected Location
</a>
{/if}
@@ -940,7 +954,7 @@
href="/events/{$events_slct.event_id}/session/{$events_slct.event_session_id}"
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500"
>
<span class="fas fa-chalkboard-teacher m-1"></span>
<GraduationCap size="1em" class="m-1" />
View Selected Session
</a>
{/if}
@@ -974,7 +988,7 @@
onclick={() => ($events_loc.launcher.hide_drawer__debug = true)}
class="mb-4 dark:text-white"
>
<span class="fas fa-times"></span>
<X size="1em" />
<span class="hidden">Close Debug Drawer</span>
</button>
</div>
@@ -1022,7 +1036,7 @@
}}
title="Close Modal"
>
<span class="fas fa-times my-1.5"></span>
<X size="1em" class="my-1.5" />
<span class="hidden group-hover:inline"> Close</span>
</button>
{/snippet}
@@ -1068,7 +1082,7 @@
/>
{:else}
<div class="flex flex-row items-center justify-center p-4">
<span class="fas fa-info-circle mx-1"></span>
<Info size="1em" class="mx-1" />
<span>No image selected</span>
</div>
{/if}
@@ -1103,10 +1117,10 @@
: 'Fit image to screen'}
>
{#if modal_zoom_fit}
<span class="fas fa-search-plus mr-1"></span>
<ZoomIn size="1em" class="mr-1" />
<span class="hidden sm:inline">Zoom</span>
{:else}
<span class="fas fa-compress mr-1"></span>
<Minimize2 size="1em" class="mr-1" />
<span class="hidden sm:inline">Fit</span>
{/if}
</button>
@@ -1127,8 +1141,8 @@
$events_sess.launcher.ws_connect_status != 'connected'}
title="Close poster on this device and on the remote display (screensaver resumes)"
>
<span class="fas fa-tv mr-1"></span>
<span class="fas fa-times"></span>
<Monitor size="1em" class="mr-1" />
<X size="1em" />
<span class="hidden sm:inline ml-1">Close Both</span>
</button>
@@ -1147,7 +1161,7 @@
$events_sess.launcher.ws_connect_status != 'connected')}
title="Close poster on this device only — remote display keeps showing"
>
<span class="fas fa-list mr-1"></span>
<List size="1em" class="mr-1" />
<span class="hidden sm:inline">Back to List</span>
</button>
</div>

View File

@@ -32,6 +32,7 @@
import Launcher_Cfg_Screen_Saver from './cfg_components/launcher_cfg_screen_saver.svelte';
import Launcher_Cfg_App_Modes from './cfg_components/launcher_cfg_app_modes.svelte';
import Launcher_Cfg_Local_Actions from './cfg_components/launcher_cfg_local_actions.svelte';
import { Settings, Pencil, X, SlidersHorizontal, Monitor, Code, RefreshCw, Bug } from 'lucide-svelte';
// UI Tab State
// Tabs are audience-oriented:
@@ -73,7 +74,7 @@
<h2
class="text-center text-lg font-bold text-gray-700 dark:text-gray-200"
>
<span class="fas fa-cog mr-2 opacity-50"></span>
<Settings size="1em" class="mr-2 opacity-50" />
Launcher Configuration
</h2>
@@ -90,7 +91,7 @@
class:hover:opacity-60={!$ae_loc.edit_mode}
title="{$ae_loc.edit_mode ? 'Disable' : 'Enable'} Edit Mode"
>
<span class="fas fa-pencil-alt text-xs"></span>
<Pencil size="0.75em" />
<span class="sr-only">Toggle Edit Mode</span>
</button>
@@ -99,7 +100,7 @@
onclick={() => ($events_loc.launcher.hide_drawer__cfg = true)}
class="btn btn-icon dark:text-white hover:bg-surface-500/10 transition-colors"
>
<span class="fas fa-times"></span>
<X size="1em" />
<span class="sr-only">Close Config</span>
</button>
</div>
@@ -123,7 +124,7 @@
class:preset-tonal-surface={active_tab !== 'setup'}
title="Display presets, interface toggles, WS controller, screen saver"
>
<span class="fas fa-sliders-h mr-1"></span> Setup
<SlidersHorizontal size="0.85em" class="mr-1" /> Setup
</button>
<button
type="button"
@@ -133,7 +134,7 @@
class:preset-tonal-surface={active_tab !== 'device'}
title="Sync engine, device health &amp; native OS controls"
>
<span class="fas fa-desktop mr-1"></span> Device
<Monitor size="0.85em" class="mr-1" /> Device
</button>
{#if $ae_loc.edit_mode}
<button
@@ -144,7 +145,7 @@
class:preset-tonal-surface={active_tab !== 'dev'}
title="Developer &amp; debug tools"
>
<span class="fas fa-code mr-1"></span> Dev
<Code size="0.85em" class="mr-1" /> Dev
</button>
{/if}
</div>
@@ -192,7 +193,7 @@
{/if}
{:else}
<div class="py-3 text-center opacity-40 italic text-xs flex flex-col gap-1 items-center">
<span class="fas fa-desktop text-lg opacity-30"></span>
<Monitor size="1.2em" class="opacity-30" />
<p>Native OS controls available in Aether Desktop.</p>
<p class="text-[9px]">Enable Edit Mode to preview.</p>
</div>
@@ -223,7 +224,7 @@
onclick={() => ($events_loc.launcher.hide_drawer__cfg = true)}
class="btn btn-sm preset-tonal-surface hover:preset-filled-surface-500 transition-all"
>
<span class="fas fa-times mr-2"></span>
<X size="0.85em" class="mr-1" />
Close
</button>
@@ -232,7 +233,7 @@
onclick={() => location.reload()}
class="btn btn-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition-all"
>
<span class="fas fa-sync-alt mr-2"></span>
<RefreshCw size="0.85em" class="mr-1" />
Reload
</button>
</div>
@@ -244,7 +245,7 @@
($events_loc.launcher.hide_drawer__debug = false)}
class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500 transition-all w-full"
>
<span class="fas fa-bug mr-2"></span>
<Bug size="0.85em" class="mr-1" />
Debug Panel
</button>
{/if}

View File

@@ -63,6 +63,7 @@
events_slct
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { LoaderCircle, AlertTriangle, AlertCircle, BarChart2, Send, FolderOpen, CalendarDays, Save, Monitor, Laptop } from 'lucide-svelte';
import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte';
@@ -275,15 +276,9 @@
>
{#snippet label()}
{#if screen_saver_exts.includes(event_file_obj.extension)}
<span
class="fas fa-chart-bar m-1"
class:hidden={hide_launch_icon}
></span> Open Poster
<BarChart2 size="1em" class="{hide_launch_icon ? 'hidden' : ''} m-1" /> Open Poster
{:else}
<span
class="fas fa-paper-plane m-1"
class:hidden={hide_launch_icon}
></span>
<Send size="1em" class="{hide_launch_icon ? 'hidden' : ''} m-1" />
{ae_util.shorten_filename({
filename: event_file_obj.filename,
max_length: max_filename_length
@@ -303,7 +298,7 @@
{@const file_id = event_file_obj.hosted_file_id}
<span class="shrink text-xs border-r border-gray-400 pr-1">
{#await ae_promises[event_file_id]}
<span class="fas fa-spinner fa-spin mx-0.5"></span>
<LoaderCircle size="1em" class="inline animate-spin mx-0.5" />
<span>
{#if $ae_sess.api_download_kv[file_id]}
{$ae_sess.api_download_kv[file_id]
@@ -313,23 +308,17 @@
{/if}
</span>
{:then result}
<span
class="fas fa-{ae_util.file_extension_icon(
event_file_obj.extension
)} mx-0.5"
></span>
{@const FileIcon = ae_util.file_extension_icon_lucide(event_file_obj.extension)}
<svelte:component this={FileIcon} size="1em" class="inline mx-0.5" />
{event_file_obj.extension}
{#if result === null || result === false}
<span class="text-error-500"
><span
class="fas fa-exclamation-triangle mx-1"
></span>Failed!</span
><AlertTriangle size="1em" class="inline mx-1" />Failed!</span
>
{/if}
{:catch error}
<span class="text-error-500" title={error?.message}
><span class="fas fa-exclamation-circle mx-0.5"
></span>Error!</span
><AlertCircle size="1em" class="inline mx-0.5" />Error!</span
>
{/await}
</span>
@@ -383,20 +372,16 @@
class:preset-tonal-warning={event_file_obj?.open_in_os == 'mac'}
disabled={!$ae_loc.trusted_access}
>
{#if event_file_obj?.open_in_os == 'win'}<span
class="fab fa-windows m-1"
></span>
{:else if event_file_obj?.open_in_os == 'mac'}<span
class="fab fa-apple m-1"
></span>
{:else}<span class="fas fa-folder-open m-1"></span>{/if}
{#if event_file_obj?.open_in_os == 'win'}<Monitor size="1em" class="m-1" />
{:else if event_file_obj?.open_in_os == 'mac'}<Laptop size="1em" class="m-1" />
{:else}<FolderOpen size="1em" class="m-1" />{/if}
</button>
<span
class="event_file_created_on text-xs text-center flex flex-row gap-1 items-center justify-end w-24 md:w-44 preset-filled-surface-100-900 rounded px-1 py-0.5"
class:hidden={hide_created_on}
>
<span class="fas fa-calendar-day"></span>
<CalendarDays size="0.85em" class="inline" />
<span class="w-18"
>{ae_util.iso_datetime_formatter(
event_file_obj.created_on,
@@ -409,7 +394,7 @@
class="event_file_size text-xs text-center flex flex-row gap-1 items-center justify-end preset-filled-surface-100-900 w-22 max-w-28 rounded py-0.5"
class:hidden={hide_size}
>
<span class="fas fa-save"></span>
<Save size="0.85em" class="inline" />
{#if event_file_obj.file_size}{ae_util.format_bytes(
event_file_obj.file_size
)}{/if}

View File

@@ -32,6 +32,7 @@
// import { events_func } from '$lib/ae_events_functions';
import Event_launcher_file_cont from './launcher_file_cont.svelte';
import { User, Users, Archive } from 'lucide-svelte';
// export let slct_event_presentation_id: string;
@@ -55,10 +56,10 @@
<strong>
{#if lq__event_presenter_obj?.given_name && lq__event_presenter_obj?.given_name != 'Group'}
<span class="fas fa-user"></span>
<User size="0.85em" class="inline" />
{lq__event_presenter_obj?.full_name}
{:else if lq__event_presenter_obj?.given_name == 'Group'}
<span class="fas fa-users"></span>
<Users size="0.85em" class="inline" />
{lq__event_presenter_obj?.affiliations}
{:else}
--not set--
@@ -78,7 +79,7 @@
<div>
<div class="text-xs text-surface-600-400">
<strong>
<span class="fas fa-file-archive"></span>
<Archive size="1em" class="inline" />
Presenter Files:
{#if $ae_loc.administrator_access && $ae_loc.edit_mode}
({$lq__event_file_obj_li?.length}&times;)

View File

@@ -32,6 +32,7 @@
// import { events_func } from '$lib/ae_events_functions';
import Event_launcher_file_cont from './launcher_file_cont.svelte';
import { User, Users, Archive } from 'lucide-svelte';
// export let slct_event_presentation_id: string;
@@ -55,10 +56,10 @@
<strong class:hidden={hide_name}>
{#if lq__event_presenter_obj?.given_name && lq__event_presenter_obj?.given_name != 'Group'}
<span class="fas fa-user"></span>
<User size="0.85em" class="inline" />
{lq__event_presenter_obj?.full_name}
{:else if lq__event_presenter_obj?.given_name == 'Group'}
<span class="fas fa-users"></span>
<Users size="0.85em" class="inline" />
{lq__event_presenter_obj?.affiliations}
{:else}
--not set--

View File

@@ -39,6 +39,7 @@
events_trigger
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { LoaderCircle, Barcode, AlertTriangle, Archive, Image, Monitor, User, Users } from 'lucide-svelte';
// Event Session (Main View Trigger)
// WHY: We use a simple derived observable. The template handles the $ prefix.
@@ -155,7 +156,7 @@
{#if $events_sess.launcher.loading__session_id_status}
<span class="absolute top-0 right-0 text-sm text-center text-gray-400">
<span class="fas fa-spinner fa-spin"></span>
<LoaderCircle size="1em" class="inline animate-spin" />
Loading session information...
</span>
<!-- {:else}
@@ -243,7 +244,7 @@
class="shrink-0 text-base text-gray-500 font-normal p-1"
title="Session code {$lq__event_session_obj.code}"
>
<span class="fas fa-barcode"></span>
<Barcode size="1em" class="inline" />
{$lq__event_session_obj?.code}
</span>
{/if}
@@ -256,9 +257,9 @@
{#if $lq__event_session_obj?.file_count_all === 0}
<p class="text-2xl text-center text-red-500 font-bold">
<span class="fas fa-exclamation-triangle"></span>
<AlertTriangle size="1em" class="inline" />
Warning
<span class="fas fa-exclamation-triangle"></span>
<AlertTriangle size="1em" class="inline" />
<br />
No files available show for this session.
</p>
@@ -269,7 +270,7 @@
<div>
<div class="text-xs text-surface-600-400">
<strong>
<span class="fas fa-file-archive"></span>
<Archive size="1em" class="inline" />
Session Files:
<span
@@ -349,10 +350,10 @@
<div class="text-xs text-surface-600-400">
<strong>
{#if type_code == 'poster'}
<span class="fas fa-image"></span>
<Image size="1em" class="inline" />
Posters:
{:else}
<span class="fas fa-tv"></span>
<Monitor size="1em" class="inline" />
Presentations:
{/if}
{#if $ae_loc.administrator_access && $ae_loc.edit_mode}
@@ -396,14 +397,12 @@
class="event_presentation_single_presenter italic text-sm text-gray-500"
>
{#if $lq__event_presenter_obj_li[index]?.given_name && $lq__event_presenter_obj_li[index]?.given_name != 'Group'}
<span class="fas fa-user"
></span>
<User size="0.85em" class="inline" />
{$lq__event_presenter_obj_li[
index
]?.full_name}
{:else if $lq__event_presenter_obj_li[index]?.given_name == 'Group'}
<span class="fas fa-users"
></span>
<Users size="0.85em" class="inline" />
{$lq__event_presenter_obj_li[
index
]?.affiliations}
@@ -470,7 +469,7 @@
</section>
{/if}<!-- end type_code !== 'poster' -->
{:else}
<span class="fas fa-spinner fa-spin"></span>
<LoaderCircle size="1em" class="inline animate-spin" />
No session selected
{/if}
</div>

View File

@@ -28,6 +28,7 @@
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
import Event_launcher_file_cont from './launcher_file_cont.svelte';
import { LoaderCircle, Images, Image, User, Users } from 'lucide-svelte';
import Launcher_presentation_view from './launcher_presentation_view.svelte';
import Launcher_presenter_view_posters from './launcher_presenter_view_posters.svelte';
@@ -83,7 +84,7 @@
{#if $events_sess.launcher?.loading__session_id_status}
<span class="absolute top-0 right-0 text-sm text-gray-400 flex items-center gap-1 p-1 z-10">
<span class="fas fa-spinner fa-spin"></span>
<LoaderCircle size="1em" class="animate-spin" />
Loading...
</span>
{/if}
@@ -105,7 +106,7 @@
class="text-base font-bold line-clamp-1 grow min-w-0"
title={$lq__event_session_obj.name}
>
<span class="fas fa-images mr-1.5 text-primary-500 opacity-70"></span>
<Images size="1em" class="inline mr-1.5 text-primary-500 opacity-70" />
{$lq__event_session_obj.name}
</h2>
@@ -174,14 +175,14 @@
{#if $lq__event_presentation_obj_li === undefined}
<!-- Still resolving from Dexie -->
<div class="flex items-center justify-center gap-2 p-10 opacity-40 grow">
<span class="fas fa-spinner fa-spin text-2xl"></span>
<LoaderCircle size="2em" class="animate-spin" />
<span>Loading posters…</span>
</div>
{:else if $lq__event_presentation_obj_li.length === 0}
<!-- Loaded but empty -->
<div class="flex flex-col items-center justify-center gap-3 p-12 opacity-40 text-center grow">
<span class="fas fa-image text-5xl"></span>
<Image size="3em" />
<p class="text-lg font-medium">No posters in this session yet.</p>
</div>
@@ -295,9 +296,7 @@
"
>
{#if presenter.given_name && presenter.given_name !== 'Group'}
<span
class="fas fa-user text-[11px] opacity-50 shrink-0 mt-px"
></span>
<User size="0.7em" class="opacity-50 shrink-0 mt-px" />
<span
class="font-medium text-surface-700 dark:text-surface-300"
>{presenter.full_name}</span
@@ -311,9 +310,7 @@
</span>
{/if}
{:else if presenter.given_name === 'Group'}
<span
class="fas fa-users text-[11px] opacity-50 shrink-0 mt-px"
></span>
<Users size="0.7em" class="opacity-50 shrink-0 mt-px" />
<span
class="font-medium text-surface-700 dark:text-surface-300"
>{presenter.affiliations}</span
@@ -359,7 +356,7 @@
{:else}
<!-- No session selected or still loading -->
<div class="flex items-center justify-center gap-2 p-8 opacity-40 grow">
<span class="fas fa-spinner fa-spin"></span>
<LoaderCircle size="1em" class="animate-spin" />
<span>No session selected</span>
</div>
{/if}

View File

@@ -18,7 +18,7 @@
* theme mode without hunting through the system menu or requiring admin access.
*/
import { Moon, Sun } from '@lucide/svelte';
import { Moon, Sun, Eye, EyeOff } from '@lucide/svelte';
import { ae_loc } from '$lib/stores/ae_stores';
import { events_loc } from '$lib/stores/ae_events_stores';
@@ -54,10 +54,10 @@
title="Toggle visibility of hidden and draft files in the launcher file list."
>
{#if $events_loc.launcher.show_content__hidden_files}
<span class="fas fa-eye-slash m-1 text-neutral-800/80"></span>
<EyeOff size="0.85em" class="m-1 text-neutral-800/80" />
Hide Files
{:else}
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
<Eye size="0.85em" class="m-1 text-neutral-800/80" />
All Files
{/if}
</button>
@@ -77,10 +77,10 @@
title="Toggle visibility of hidden and cancelled sessions in the launcher session list."
>
{#if $events_loc.launcher.show_content__hidden_sessions}
<span class="fas fa-eye-slash m-1 text-neutral-800/80"></span>
<EyeOff size="0.85em" class="m-1 text-neutral-800/80" />
Hide Sessions
{:else}
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
<Eye size="0.85em" class="m-1 text-neutral-800/80" />
All Sessions
{/if}
</button>

View File

@@ -74,6 +74,7 @@
events_trigger
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { LoaderCircle, Check } from 'lucide-svelte';
// export let slct_event_session_id: any;
@@ -164,9 +165,9 @@
<!-- This should fade out once the data is loaded. -->
{#await ae_promises[slct_event_location_id ?? '']}
<span class="fas fa-spinner fa-spin text-blue-500"></span>
<LoaderCircle size="0.85em" class="inline animate-spin text-blue-500" />
{:then result}
<span class="fas fa-check text-green-500/80"></span>
<Check size="0.85em" class="inline text-green-500/80" />
{/await}
</strong>
</div>

View File

@@ -91,6 +91,7 @@
events_trigger
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { LoaderCircle, Check, CalendarCheck, CalendarDays, Image, EyeOff } from 'lucide-svelte';
// export let slct__event_session_id: any;
@@ -218,9 +219,9 @@
<!-- This should fade out once the data is loaded. -->
{#await ae_promises.slct__event_session_id}
<span class="fas fa-spinner fa-spin text-blue-500"></span>
<LoaderCircle size="0.85em" class="inline animate-spin text-blue-500" />
{:then result}
<span class="fas fa-check text-green-500/80"></span>
<Check size="0.85em" class="inline text-green-500/80" />
{/await}
</strong>
</div>
@@ -314,9 +315,9 @@
class="border-r border-surface-400-600 pr-1 min-w-20 shrink-0"
>
{#if slct__event_session_id === event_session_obj?.id}
<span class="fas fa-calendar-check"></span>
<CalendarCheck size="0.85em" class="inline" />
{:else}
<span class="fas fa-calendar-alt"></span>
<CalendarDays size="0.85em" class="inline" />
{/if}
<span
class="text-xs"
@@ -344,15 +345,15 @@
"
>
{#if event_session_obj?.type_code == 'poster'}
<span class="fas fa-image mr-1 text-primary-500" title="Digital Poster Session"></span>
<span title="Digital Poster Session"><Image size="0.85em" class="inline mr-1 text-primary-500" /></span>
{/if}
<!-- Distinct icon styles distinguish the two hidden states:
amber = hide (globally hidden — draft, cancelled, or admin-only)
muted = hide_event_launcher (suppressed in Launcher view only) -->
{#if event_session_obj?.hide}
<span class="fas fa-eye-slash mr-1 text-warning-600" title="Hidden session"></span>
<span title="Hidden session"><EyeOff size="0.85em" class="inline mr-1 text-warning-600" /></span>
{:else if event_session_obj?.hide_event_launcher}
<span class="fas fa-eye-slash mr-1 opacity-60" title="Hidden from Launcher"></span>
<span title="Hidden from Launcher"><EyeOff size="0.85em" class="inline mr-1 opacity-60" /></span>
{/if}
{event_session_obj?.name}
</span>