feat(launcher): implement LaunchProfile system — MasterKey replacement
- 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.
This commit is contained in:
382
src/lib/ae_events/ae_launcher__default_launch_profiles.ts
Normal file
382
src/lib/ae_events/ae_launcher__default_launch_profiles.ts
Normal file
@@ -0,0 +1,382 @@
|
||||
/**
|
||||
* ae_launcher__default_launch_profiles.ts
|
||||
*
|
||||
* Built-in launch profiles for the Aether Events Launcher — the Svelte-side
|
||||
* replacement for the legacy OSIT MasterKey Swift app.
|
||||
*
|
||||
* These are the last-resort defaults. Override priority (high → low):
|
||||
* 1. event_file.cfg_json.display_override — per-file, display_mode only
|
||||
* 2. event_device.data_json.launch_profiles[ext] — full profile, per device (API)
|
||||
* 3. $events_loc.launcher.launch_profiles[ext] — local persistent override
|
||||
* 4. DEFAULT_LAUNCH_PROFILES[ext] — these built-ins
|
||||
* 5. DEFAULT_LAUNCH_PROFILES['default'] — catch-all
|
||||
*
|
||||
* Keys are lowercase file extensions without the dot: "pptx", "key", "pdf", etc.
|
||||
* The special key "default" catches any unrecognised extension.
|
||||
*
|
||||
* post_script formats:
|
||||
* - Plain string → run as AppleScript via run_osascript() (macOS only)
|
||||
* - "shell:..." prefix → run as shell command via run_cmd()
|
||||
*
|
||||
* Reserved for future use (not yet read anywhere):
|
||||
* - speed_factor: number — delay multiplier for slower machines (1.0 = normal)
|
||||
* - url: string — for URL-type presentations (e.g. Google Slides)
|
||||
*/
|
||||
|
||||
export interface LaunchProfile {
|
||||
/** Human-readable label for status messages */
|
||||
app: string;
|
||||
/** Display layout to set before opening. 'extend' only applied if external display found. */
|
||||
display_mode: 'extend' | 'mirror' | 'none';
|
||||
/**
|
||||
* Shell command to open the file. {{path}} is replaced with the resolved temp path.
|
||||
* If omitted, falls back to open_local_file_v2(path) — OS default handler.
|
||||
*/
|
||||
open_cmd?: string;
|
||||
/**
|
||||
* Script to run after the file opens and post_delay_ms has elapsed.
|
||||
* Plain string → AppleScript (macOS). "shell:" prefix → shell command.
|
||||
*/
|
||||
post_script?: string;
|
||||
/** Milliseconds to wait after open_cmd before running post_script. Default: 2000 */
|
||||
post_delay_ms?: number;
|
||||
|
||||
// --- Reserved for future use — not yet implemented ---
|
||||
// speed_factor?: number;
|
||||
// url?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_LAUNCH_PROFILES: Record<string, LaunchProfile> = {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// macOS presentation formats
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
pptx: {
|
||||
app: 'Microsoft PowerPoint',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "Microsoft PowerPoint" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "Microsoft PowerPoint"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "Microsoft PowerPoint"
|
||||
keystroke return using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
ppt: {
|
||||
app: 'Microsoft PowerPoint',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "Microsoft PowerPoint" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "Microsoft PowerPoint"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "Microsoft PowerPoint"
|
||||
keystroke return using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
key: {
|
||||
app: 'Keynote',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "Keynote" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "Keynote"
|
||||
activate
|
||||
start (front document)
|
||||
end tell`
|
||||
},
|
||||
|
||||
odp: {
|
||||
app: 'LibreOffice',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "LibreOffice" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "LibreOffice"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "soffice"
|
||||
key code 96
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
pdf: {
|
||||
app: 'Adobe Acrobat Reader DC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "Adobe Acrobat Reader DC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "Adobe Acrobat Reader DC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "AdobeReader"
|
||||
keystroke "l" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Media (VLC) — mirror display
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
mp4: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
mkv: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
mov: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
mpeg: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
avi: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
flv: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
ogg: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
ogv: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
mp3: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
wmv: {
|
||||
app: 'VLC',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||
post_delay_ms: 2000,
|
||||
post_script: `tell application "VLC"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "VLC"
|
||||
keystroke "f" using command down
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Windows / Parallels variants — longer post_delay_ms (Parallels needs more time)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
pptxwin: {
|
||||
app: 'Microsoft Office PowerPoint (Windows)',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "Microsoft Office PowerPoint" "{{path}}"',
|
||||
post_delay_ms: 3000,
|
||||
post_script: `tell application "Microsoft Office PowerPoint"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
key code 96
|
||||
end tell`
|
||||
},
|
||||
|
||||
pptwin: {
|
||||
app: 'Microsoft Office PowerPoint (Windows)',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "Microsoft Office PowerPoint" "{{path}}"',
|
||||
post_delay_ms: 3000,
|
||||
post_script: `tell application "Microsoft Office PowerPoint"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
key code 96
|
||||
end tell`
|
||||
},
|
||||
|
||||
odpwin: {
|
||||
app: 'LibreOffice (Windows)',
|
||||
display_mode: 'extend',
|
||||
open_cmd: 'open -a "LibreOffice" "{{path}}"',
|
||||
post_delay_ms: 3000,
|
||||
post_script: `tell application "LibreOffice"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "soffice"
|
||||
key code 96
|
||||
end tell
|
||||
end tell`
|
||||
},
|
||||
|
||||
pdfwin: {
|
||||
app: 'Acrobat Reader (Windows)',
|
||||
display_mode: 'mirror',
|
||||
open_cmd: 'open -a "Acrobat Reader Windows" "{{path}}"',
|
||||
post_delay_ms: 3000,
|
||||
post_script: `tell application "Acrobat Reader Windows"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
key code 108 using control down
|
||||
end tell`
|
||||
},
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Catch-all — OS default handler, no display change
|
||||
// Works on macOS (open) and Linux (xdg-open via open_local_file_v2)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
default: {
|
||||
app: 'OS Default',
|
||||
display_mode: 'none'
|
||||
// No open_cmd — execution falls through to open_local_file_v2(path)
|
||||
// No post_script
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of the built-in profile for the given extension,
|
||||
* with a display_override applied if provided.
|
||||
*
|
||||
* Falls back to 'default' if no specific profile exists.
|
||||
*/
|
||||
export function resolve_launch_profile(
|
||||
extension: string,
|
||||
display_override?: 'extend' | 'mirror' | 'none' | null,
|
||||
device_profiles?: Record<string, LaunchProfile> | null,
|
||||
local_profiles?: Record<string, LaunchProfile> | null
|
||||
): LaunchProfile {
|
||||
const ext = (extension || '').toLowerCase().replace(/^\./, '');
|
||||
|
||||
// Priority: device config → local config → built-ins → default
|
||||
const source =
|
||||
device_profiles?.[ext] ??
|
||||
device_profiles?.['default'] ??
|
||||
local_profiles?.[ext] ??
|
||||
local_profiles?.['default'] ??
|
||||
DEFAULT_LAUNCH_PROFILES[ext] ??
|
||||
DEFAULT_LAUNCH_PROFILES['default'];
|
||||
|
||||
const profile = { ...source };
|
||||
|
||||
// Per-file display override wins over everything
|
||||
if (display_override) {
|
||||
profile.display_mode = display_override;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
Reference in New Issue
Block a user