feat(launcher): wallpaper auto-apply from device config

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>
This commit is contained in:
Scott Idem
2026-05-13 18:31:39 -04:00
parent 324f3a97ac
commit 17e522f826
5 changed files with 406 additions and 4 deletions

View File

@@ -384,13 +384,33 @@ export async function control_presentation({
// 4. System Management (Phase 5+)
export async function set_wallpaper({ path }: { path: string }) {
export async function set_wallpaper({
path,
url,
url_external,
display = 'all',
api_key,
account_id
}: {
/** Local file path (existing behavior). */
path?: string;
/** HTTPS URL — downloaded to ~/Library/Caches/OSIT/wallpaper/ before applying. */
url?: string;
/** Optional separate URL for the external/projector display only. */
url_external?: string;
/** Which display(s) to target. Defaults to 'all'. */
display?: 'all' | 'primary' | 'external';
/** Aether API key passed as x-aether-api-key header on the download request. */
api_key?: string;
/** Aether account ID passed as x-account-id header on the download request. */
account_id?: string;
}) {
if (!native || !native.set_wallpaper)
return {
success: false,
error: 'Native handler set_wallpaper not available'
};
return await native.set_wallpaper({ path });
return await native.set_wallpaper({ path, url, url_external, display, api_key, account_id });
}
export async function update_app(args: {

View File

@@ -39,12 +39,17 @@ export interface LauncherLocState {
section_state__health: SectionState;
section_state__native_os: SectionState;
section_state__launch_timing: SectionState;
section_state__wallpaper: SectionState;
section_state__sync_timers: SectionState;
section_state__updates: SectionState;
section_state__controller: SectionState;
section_state__screen_saver: SectionState;
section_state__app_modes: SectionState;
section_state__local_actions: SectionState;
/** URL last successfully applied as wallpaper on this device. Used to detect remote config changes. */
wallpaper_applied_url: string | null;
/** URL last applied to the external display (when url_external is configured). */
wallpaper_applied_url_external: string | null;
datetime_format: string;
time_format: string;
time_hours: 12 | 24;
@@ -160,6 +165,7 @@ export const launcher_loc_defaults: LauncherLocState = {
section_state__health: 'auto',
section_state__native_os: 'collapsed',
section_state__launch_timing: 'collapsed',
section_state__wallpaper: 'collapsed',
section_state__sync_timers: 'collapsed',
section_state__updates: 'collapsed',
section_state__controller: 'auto',
@@ -208,7 +214,9 @@ export const launcher_loc_defaults: LauncherLocState = {
controller: 'local',
controller_group_code: 'launcher-00',
controller_client_id: null,
native_test_mode: false
native_test_mode: false,
wallpaper_applied_url: null,
wallpaper_applied_url_external: null
// controller_cmd: null,
// controller_trigger_send: null,
};