feat(launcher): Oral/Poster Kiosk mode preset toggle + ae_mode WS command
Adds a two-button Session Mode Preset toggle in Display & App Modes cfg:
- 'Oral / Default' restores all menus/headers/iframe off
- 'Poster Kiosk' sets iframe=true + hides menu, header, footer
When WS is connected (local_push or remote controller), tapping a preset
sends ae_mode:poster / ae_mode:oral to all connected devices so an operator
can reconfigure the whole room from one device.
ae_mode:{poster|oral} command handler added to handle_ws_recv() in
+layout.svelte — receives and applies the same preset on remote devices.
This commit is contained in:
@@ -1,12 +1,55 @@
|
||||
<script lang="ts">
|
||||
import { ae_loc } from '$lib/stores/ae_stores';
|
||||
import { events_loc } from '$lib/stores/ae_events_stores';
|
||||
import { events_loc, events_sess } from '$lib/stores/ae_events_stores';
|
||||
import Launcher_Cfg_Section from './launcher_cfg_section.svelte';
|
||||
|
||||
interface Props {
|
||||
on_expand?: () => void;
|
||||
}
|
||||
let { on_expand }: Props = $props();
|
||||
|
||||
// Poster Kiosk mode presets:
|
||||
// iframe=true hides global site chrome
|
||||
// hide__launcher_menu/header/footer removes all launcher panels
|
||||
// Oral/Default restores everything.
|
||||
// WHY: A single tap lets event staff reconfigure a device (or all WS-connected
|
||||
// remote devices) for a session type without touching individual toggles.
|
||||
const POSTER_PRESET = {
|
||||
iframe: true,
|
||||
hide__launcher_menu: true,
|
||||
hide__launcher_header: true,
|
||||
hide__launcher_footer: true
|
||||
};
|
||||
const ORAL_PRESET = {
|
||||
iframe: false,
|
||||
hide__launcher_menu: false,
|
||||
hide__launcher_header: false,
|
||||
hide__launcher_footer: false
|
||||
};
|
||||
|
||||
// Detect current mode: if both iframe AND hide_menu are on, we're in poster mode.
|
||||
// Individual overrides are still possible via the checkboxes below.
|
||||
let is_poster_mode = $derived(
|
||||
$ae_loc.iframe === true && $events_loc.launcher.hide__launcher_menu === true
|
||||
);
|
||||
|
||||
function apply_mode(mode: 'poster' | 'oral') {
|
||||
const preset = mode === 'poster' ? POSTER_PRESET : ORAL_PRESET;
|
||||
$ae_loc.iframe = preset.iframe;
|
||||
$events_loc.launcher.hide__launcher_menu = preset.hide__launcher_menu;
|
||||
$events_loc.launcher.hide__launcher_header = preset.hide__launcher_header;
|
||||
$events_loc.launcher.hide__launcher_footer = preset.hide__launcher_footer;
|
||||
|
||||
// Push to WS-connected remote devices when we're acting as a controller.
|
||||
// Only send when connected so the UI button doesn't silently no-op.
|
||||
if (
|
||||
$events_loc.launcher.ws_connect &&
|
||||
($events_loc.launcher.controller === 'local_push' || $events_loc.launcher.controller === 'remote')
|
||||
) {
|
||||
$events_sess.launcher.controller_cmd = `ae_mode:${mode}`;
|
||||
$events_sess.launcher.controller_trigger_send = 'trigger';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Launcher_Cfg_Section
|
||||
@@ -18,6 +61,38 @@
|
||||
>
|
||||
<!-- Content omitted for brevity, preserved in file -->
|
||||
<div class="col-span-full flex flex-col gap-3">
|
||||
<!-- 0. Oral / Poster Kiosk Mode Preset Toggle -->
|
||||
<div class="flex flex-col gap-1">
|
||||
<p class="text-[9px] font-bold uppercase opacity-50 ml-1">Session Mode Preset</p>
|
||||
<div class="grid grid-cols-2 gap-1 bg-surface-500/5 p-1 rounded-lg">
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => apply_mode('oral')}
|
||||
class="btn btn-xs font-bold text-[10px]"
|
||||
class:preset-filled-secondary={!is_poster_mode}
|
||||
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>
|
||||
Oral / Default
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => apply_mode('poster')}
|
||||
class="btn btn-xs font-bold text-[10px]"
|
||||
class:preset-filled-primary={is_poster_mode}
|
||||
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>
|
||||
Poster Kiosk
|
||||
</button>
|
||||
</div>
|
||||
{#if $events_loc.launcher.ws_connect && ($events_loc.launcher.controller === 'local_push' || $events_loc.launcher.controller === 'remote')}
|
||||
<p class="text-[8px] opacity-40 italic ml-1">Applies to all connected WS devices</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- 1. App Mode Selection -->
|
||||
<div class="flex flex-col gap-1">
|
||||
<p class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||
|
||||
@@ -415,6 +415,21 @@
|
||||
else if (zoom_target === 'zoom') modal_zoom_fit = false;
|
||||
} else if (cmd.startsWith('ae_refresh:')) {
|
||||
if (cmd.split(':')[1] == 'now') location.reload();
|
||||
} else if (cmd.startsWith('ae_mode:')) {
|
||||
// WHY: Allows a controller to remotely push a display mode preset
|
||||
// (e.g. switch all poster kiosks into kiosk mode without touching each device).
|
||||
const mode_target = cmd.split(':')[1];
|
||||
if (mode_target === 'poster') {
|
||||
$ae_loc.iframe = true;
|
||||
$events_loc.launcher.hide__launcher_menu = true;
|
||||
$events_loc.launcher.hide__launcher_header = true;
|
||||
$events_loc.launcher.hide__launcher_footer = true;
|
||||
} else if (mode_target === 'oral') {
|
||||
$ae_loc.iframe = false;
|
||||
$events_loc.launcher.hide__launcher_menu = false;
|
||||
$events_loc.launcher.hide__launcher_header = false;
|
||||
$events_loc.launcher.hide__launcher_footer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user