Introduces badge_layout_epson_4x6_fanfold.css (layout code badge_4x6_fanfold)
for the Axonius Adapt 2026 June show. Wires @page size to 4in×6in in the print
page and cleans up the stale 4in×12in default. Imports new CSS in badge component.
Measured stock: 4in × 6in portrait with 5/8in lanyard hole 1/4in from top.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three redundant store fields encoding the same AM/PM choice replaced with a single
`use_12h: boolean` in PresMgmtLocState. iso_datetime_formatter gains a third param
(use_12h: boolean | null = null) that auto-resolves 24h↔12h format name variants via
a symmetric FORMAT_PAIRS lookup — null default leaves all ~100 existing call sites intact.
Toggle surfaces in three places: Clock icon in session time chip (hidden button, same
visual), event Options modal Display section, and session Options modal Display section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, searching by presenter name in pres_mgmt returned no results
because event_presenter_li_qry_str / event_presentation_li_qry_str were
never requested or stored.
Changes:
- ae_types.ts: add event_presentation_li_qry_str + event_presenter_li_qry_str
to ae_EventSession interface
- db_events.ts: same two fields added to Session Dexie interface
- ae_events__event_session.ts:
* add ft_presentation_search_qry_str param
* auto-upgrade view to 'alt' when either ft_presenter or ft_presentation
search is used (backend requires v_event_session_w_file_count for these)
* add both fields to properties_to_save so they persist to Dexie cache
- +page.svelte (pres_mgmt):
* pass ft_presenter_search_qry_str + ft_presentation_search_qry_str in API call
* local IDB fast path now checks both new fields
* client-side filter guard also checks both new fields
Two Svelte-side bugs causing account_name to always show 'Account Name Not Set':
1. ae_core__site.ts: background site_domain refresh only pushed cfg_json back
into $ae_loc after a stale cache hit. Now also pushes account_name and
account_code when the store holds a placeholder value.
2. +layout.ts: duplicate ae_loc_init['account_name'] assignment at line ~475
was overwriting the correct one at line ~385 with a different fallback string
('Account Name Not Set' vs 'Ghost Account'). Removed the duplicate.
Also includes user-intentional changes during testing:
- events/+page.svelte: typo fix ('You access' -> 'Your access'); Pres Mgmt /
Launcher / Badges / Leads buttons now gated on trusted_access && edit_mode
- events/+page.ts: event list limit 25 -> 7
- events/[event_id]/+page.svelte: user edit
Running gsettings on the dev workstation resets monitors on every test cycle.
Linux Electron handler now returns linux_test_mode:true with would_run details
instead of applying. Svelte cfg component shows a debug popup (mirrors Native
Test Mode style). Background sync logs to console and leaves applied-URL unset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- electron_relay: add restore_macos_default_wallpaper() — uses run_osascript
to find first .heic in /System/Library/Desktop Pictures/ (version-agnostic)
- wallpaper cfg: Restore macOS Default button (native or edit_mode); clears
applied-URL tracking so next configured URL re-applies correctly
- wallpaper cfg: fix Apply Now / Save & Apply enabled when only external URL
is filled; display target becomes 'external' to leave built-in unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Stores wallpaper URL(s) in event_device.other_json.launcher.wallpaper and
auto-applies on all native Launcher instances within one heartbeat cycle (~60s),
eliminating manual per-Mac setup at events.
- electron_relay: typed set_wallpaper wrapper (url, url_external, display, auth headers)
- launcher_defaults: wallpaper_applied_url tracking + section_state__wallpaper
- launcher_cfg_wallpaper: new config section — save to device config + apply now
- launcher_cfg: add wallpaper section to device tab
- launcher_background_sync: auto-apply if config URL changed since last apply;
external-only config targets only the secondary display, leaving built-in unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix 1 (stale error_detail):
open_file_error_detail is now cleared at the start of every mode's
branch (native, onsite, default) alongside open_file_clicked=true.
Previously it was cleared mid-way through the native flow (Step 1),
so a stale error from a previous failed run could flash briefly.
Fix 2 (stuck 'Opening...' during post_script sleep):
After the Step 4 open call returns (run_cmd or open_local_file_v2),
update the status message immediately to 'App opened — running setup...'
so the button doesn't appear frozen for the full post_delay_ms wait.
Fix 3 (safety valve for hanging native calls):
A 60s setTimeout is registered at the start of the native branch.
If any native IPC call hangs indefinitely and the existing per-path
reset timeouts never fire, this force-resets open_file_clicked after
60s. All normal paths complete within ~8s so this only triggers on
true hangs. ERR_NETWORK_CHANGED cannot re-enter the download path
because the open_file_clicked guard blocks re-entry.
shell.openPath always resolves on the Electron side, but if the Svelte
renderer navigates before the IPC reply arrives, the promise rejects
with 'reply was never sent'. The file is already open at that point.
Catch the rejection and treat it as success on both call sites (Step 4
primary path and Step 7 fallback). This eliminates the unhandled
promise error without masking real failures.
URL files: event_file.filename = 'https://...' is now a first-class
file type in the launcher.
- is_url derived rune detects https/http filename prefix
- URL branch in handle_open_file() runs before cache/native branches
(no download, no temp copy, no hash)
- Offline guard: warns and blocks click if navigator.onLine is false;
online/offline listeners registered only for URL rows (no-op on files)
- Native mode: opens via native.open_external({ url, app: 'chrome' })
with silent fallback to default browser
- Browser mode: window.open() with noopener
- display_mode default: 'mirror' (URLs typically just need the screen
mirrored, not extended presenter view)
- Button badge shows Link2 icon + WifiOff warning when offline
- Button text uses event_file.title as label (falls back to URL)
- Test mode popup: skips Steps 1-2 (N/A), shows open_external call
DEFAULT_LAUNCH_PROFILES: add 'url' key (display_mode: 'mirror')
Electron TODO: added set_display_layout / displayplacer per-device
config task to aether_app_native_electron/documentation/TODO_AGENTS.md
with full contract details and resources
The sleep step was running unconditionally, meaning files that open
with the 'default' catch-all profile (zip, unknown ext, etc.) would
wait 2 seconds for no reason — there's no AppleScript to prepare for.
Gate the sleep inside the post_script check so it only delays when
there's actually automation to run after app launch.
Also update the test mode popup to show '0ms — skipped (no post_script)'
and display post_delay_ms as '(default: 2000ms)' when unset.
Enables testing the LaunchProfile system from any device (no Mac/Electron
needed). When active, the Open button simulates the full native flow and
shows a debug popup with everything that WOULD be sent to Electron.
- ae_events_stores__launcher_defaults.ts: add native_test_mode boolean
(persisted, default false) to LauncherLocState and launcher_loc_defaults.
- launcher_cfg_app_modes.svelte: add Native Test Mode checkbox toggle in
the Advanced Toggles (Edit Mode Only) section with active-state warning.
- launcher_file_cont.svelte:
- Add test_mode_popup_open/test_mode_popup_data state vars.
- Add branch 0 in handle_open_file(): when native_test_mode + app_mode=native,
skip all Electron calls; resolve the real LaunchProfile, build a data
snapshot, open the debug popup.
- Debug popup shows: file info, simulated temp path, cache/copy pass,
resolved LaunchProfile fields, set_display_layout call, open command
(run_cmd or open_local_file_v2 fallback), sleep delay, post-script
(AppleScript or shell: prefix). Click backdrop or Close to dismiss.
- Add ae_launcher__default_launch_profiles.ts with LaunchProfile interface,
DEFAULT_LAUNCH_PROFILES constant, and resolve_launch_profile() helper.
Covers pptx/ppt/key/odp/pdf, all VLC media formats, Windows/Parallels
variants (pptxwin/pptwin/odpwin/pdfwin), and a catch-all 'default'.
- Replace get_launch_script_template() with get_launch_profile() in
launcher_file_cont.svelte. Override priority: device API config >
local persistent config > built-in defaults > 'default' catch-all.
- Rewrite handle_open_file() native branch with 9-step profile-driven flow:
copy_from_cache_to_temp → resolve profile → set_display_layout (silent fail)
→ open (run_cmd or OS default) → sleep(post_delay_ms) → run post_script
→ fallback to OS default on open failure → surface status/error detail.
- Add open_file_error_detail state var; show error pre block in status
alert for native error state, show fallback note for fallback state.
- Add display override toggle button in event_file_meta (visible when
trusted_access + is_native): cycles null → extend → mirror → null,
PATCHes event_file.cfg_json.display_override via V3 CRUD.
- Fix download button to use hosted_file_id instead of id (which resolved
to event_file_id via _process_generic_props, hitting the wrong endpoint)
- Fix Dexie file table query in event_file_obj_tbl_wrapper to use _id
fields (the indexed ones) instead of _id_random variants
- Remove _random fields from properties_to_save in event, event_session
- Drop _id_random fallbacks from launcher device ID resolution and
background sync heartbeat
- Clean up dead comments and old FA anchor in post edit component
- Update TODO__Agents.md: BGH section removed, CMSC/Axonius shows added,
download button fix marked complete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The outer bordered div was always in the DOM; only the label and input
inside were hidden during upload, leaving a visible empty dashed box.
Apply the same hidden guard to the container div.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass track_progress: true to post_object so the XHR path fires live
percent_completed events, making the upload % display functional.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Trusted-access users (Pres Mgmt admins) were getting file_list_status='ready'
when selecting .ppt/.doc/.xls files, so the prominent warning banner never
rendered — only the small per-row warning in the file table was visible.
- element_input_files_tbl: introduce 'warn_legacy' status for trusted users;
show a yellow warning banner (vs red blocked banner for non-trusted users)
- ae_comp__event_files_upload: change button disabled check from != 'ready'
to === 'blocked_legacy' so 'warn_legacy' does not accidentally block upload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refresh_location_config() was missing inc_file_li:true, so location-level
files were never fetched from the API and lq__location_event_file_obj_li
always returned empty from Dexie. Files only appeared when Pres Mgmt had
previously loaded them on the same device.
Also added a reactive $effect so files load immediately when the operator
switches rooms, rather than waiting up to 60s for the next timer tick.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Set post_object timeout to 1200000ms (20 min) for hosted file uploads;
the 90s default was killing large presentation file uploads
- Guard result[0] access in .then() to prevent crash when upload
times out or is aborted (TypeError: can't access property "hosted_file_id")
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On session click/hover, the menu was calling load_ae_obj_id__event_session
directly AND then navigating via goto(), which re-runs +page.ts and calls
it again. Both fired concurrently on cold cache, causing two identical API
requests for the same session.
Fix: remove the direct load call entirely. The goto() promise is assigned
to ae_promises.slct__event_session_id so the existing #await spinner still
works — it now reflects actual navigation + page.ts load time rather than
a redundant parallel fetch. Remove events_func and ae_api imports (unused).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- menu_session_list: move class:hidden to <li> so fixed-height rows fully collapse
- launcher/+layout.svelte: sort sessions by start_datetime (ascending) instead of name
- Rename hide_content__draft_files → show_content__internal_files (default false);
remove redundant show_content__draft_files; rename prop hide_draft →
show_internal_purpose_files in launcher_file_cont; update all 7 call sites and
the menu_launcher_controls toggle. Now hides admin/draft/outline purpose files
by default with consistent naming across the flag, prop, and toggle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- launcher_file_cont: add 'admin' file_purpose to hide_draft filter (alongside outline/draft)
- element_manage_event_file_li: remove event_file_id from data_kv passed to update_ae_obj;
it was being sent in the PATCH body causing 'Unknown column event_file_id in SET' (400)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add +page.ts to trigger load_ae_obj_li__event_location on page load (locations
were never fetched without a manual trigger)
- Fix ae_comp__event_session_obj_li_wrapper: query used event_location_id_random
(deprecated index) instead of event_location_id, causing empty session lists
under each location
- Wire hide__session_poc to pres_mgmt_loc.current.show__session_li_poc_field so
the Options toggle actually takes effect in the per-location session list
- Also set hide__session_location=true since location is implicit in that context
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On a fresh Electron install the events_loc persisted store has no
app_mode value set, causing the native file launch path to fall through
to a browser save dialog. Auto-initialise app_mode='native' in the
launcher layout when is_native is detected so all three modes (default,
onsite, native) continue to work correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract session search form into ae_comp__pres_mgmt_session_search.svelte
(parallels ae_comp__badge_search.svelte); removes ~145 lines from +page.svelte
- Add time window filter: Clock icon toggle button reveals compact before/after
selects; trusted users get 3d/7d options; active state highlighted in amber
- Add passes_hide_filter to IDB fast path to mirror API qry_hidden logic and
eliminate the hidden-session blink on revalidation
- Add passes_time_window applied to both IDB fast path and API results
- Add time window state fields to PresMgmtLocState + pres_mgmt_loc_defaults
- Add contextual warning in "No sessions found" when time filter is active
- badges: hide "Start Here" button for trusted_access users; tweak button shade
- badges: scope placeholder CSS fix to input only (not textarea)
- Add MODULE__AE_Events_PressMgmt_Launcher.md doc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old guard locked on badge ID after the first liveQuery tick. If
Dexie had a cached badge without cfg_json.font_sizes, the guard fired
with no sizes to apply, then blocked the SWR background refresh that
delivered the real saved sizes. Result: font sizes appeared unsaved on
any browser that had visited the badge before sizes were set.
Fix: track the cfg_json string last applied (_font_sizes_applied_cfg)
instead of just the badge ID. Re-applies whenever cfg_json changes on
a background refresh, but skips if local sizes have drifted from the
last apply (user is mid-adjustment — auto-save will sync shortly).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tailwind v4 renders placeholder text too dark on light backgrounds,
making it indistinguishable from real input values. Same scoped CSS
fix already applied to ae_comp__badge_print_controls.svelte.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
badge_type_code_li was returning [] when the template had no badge_type_list,
causing the Badge Type field to be hidden entirely in the Staff section.
Add same fallback default as create form and search filter.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was at the bottom after print position controls — now first item in
Staff Adjustments, before Hide/Unhide Badge, where staff expect it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was: visible to everyone pre-print, Trusted+Edit for reprints.
Now: Administrator + Edit Mode only (all three locations).
Temporarily restricted for Axonius 2026 — restore broader access after event.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- default_badge_type_code_li now matches ae_comp__badge_search.svelte list
(attendee, sponsor, staff, guest, volunteer, member, nonmember, test)
- badge_type_code initializes to 'attendee' (In-Person Attendee)
- $effect re-applies preferred default when template badge_type_list loads async,
falling back to first item if 'attendee' isn't in the template's list
- Remove the blank '-- Select Badge Type --' placeholder option
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>