Compare commits
2 Commits
054775b0f8
...
a5f2ae3835
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5f2ae3835 | ||
|
|
b3ce65f7f6 |
@@ -30,20 +30,36 @@ guessing defaults.
|
|||||||
`copy_from_cache_to_temp` + `run_osascript` / `run_cmd` directly instead of the all-in-one
|
`copy_from_cache_to_temp` + `run_osascript` / `run_cmd` directly instead of the all-in-one
|
||||||
`launch_from_cache`. Finer error handling at each step (verify copy succeeded before
|
`launch_from_cache`. Finer error handling at each step (verify copy succeeded before
|
||||||
attempting script; surface failure clearly in UI).
|
attempting script; surface failure clearly in UI).
|
||||||
- [ ] **[Launcher] Error handling + fallback** — when the launch script fails, offer fallback
|
- [x] **[Launcher] Error handling + fallback (2026-05-14)** — post-script failure is non-fatal: surfaces `'fallback'` status with error detail (file already open). If `open_cmd` itself fails, falls back to `open_local_file_v2` (OS default); surfaces combined error detail if that also fails. UI renders `'open'` / `'fallback'` / `'error'` states distinctly.
|
||||||
to `open_local_file_v2` (OS default handler) rather than silently failing. Show error detail
|
|
||||||
in the launcher file row so staff can diagnose onsite.
|
|
||||||
- [ ] **[Launcher] Slide control scripts in Svelte config** — `control_presentation` AppleScript
|
- [ ] **[Launcher] Slide control scripts in Svelte config** — `control_presentation` AppleScript
|
||||||
one-liners are hardcoded in Electron. Move to device config (`data_json.control_scripts`) or
|
one-liners are hardcoded in Electron (`shell_handlers.ts` lines 149–159). The Svelte side
|
||||||
Svelte constants so slide nav behavior (e.g. keystroke vs. AppleScript command) can be adjusted
|
(`launcher_cfg_native_os.svelte`) already calls `native.control_presentation({ app, action })`
|
||||||
without a rebuild. Wire through `run_osascript` directly.
|
with next/prev/start/stop buttons wired and working. The Electron IPC call is stable enough
|
||||||
- [ ] **[Launcher] `kill_processes` target list in config** — process names to kill on cleanup
|
for current shows.
|
||||||
are currently caller-hardcoded. Allow device config to specify the process name list per
|
|
||||||
file type / app, so adding a new presentation app doesn't require a Svelte code change.
|
**Remaining (post June 10):** Move scripts to device config (`data_json.control_scripts`) or
|
||||||
- [ ] **[Launcher] Launcher config UI — launch_profiles editor** — add a Technical Mode panel
|
Svelte constants so behavior can be changed without an Electron rebuild. Replace
|
||||||
in the Launcher config (tabbed settings) to view and edit `launch_profiles` entries on the
|
`native.control_presentation()` call with `native.run_osascript(script)` using the
|
||||||
active device record. PATCH via `event_device` V3 CRUD. Lets OSIT staff tune launch behavior onsite
|
config-resolved script string. The `run_osascript` primitive is already in place; this is
|
||||||
without needing phpMyAdmin or a code deploy.
|
purely a wiring/config task. Low priority — hardcoded scripts work fine for PowerPoint and
|
||||||
|
Keynote for now.
|
||||||
|
- [ ] **[Launcher] `kill_processes` target list in config** — The `kill_processes` IPC primitive
|
||||||
|
exists in Electron and is exposed via `electron_relay.ts`, but **is never called from anywhere
|
||||||
|
in Svelte** — no routes, no config components, no file launch flow. No UI exists for it yet.
|
||||||
|
|
||||||
|
**What needs doing (post June 10):**
|
||||||
|
- Decide where the "kill on cleanup" action lives: end of `handle_open_file()` (auto), or a
|
||||||
|
manual "Kill Apps" button in Native OS config, or both.
|
||||||
|
- Process names should come from device config (`data_json.kill_process_li`) with a built-in
|
||||||
|
fallback list (e.g. `['Microsoft PowerPoint', 'Keynote', 'LibreOffice Impress']`).
|
||||||
|
- The Native OS config section (`launcher_cfg_native_os.svelte`) is the natural home for a
|
||||||
|
manual kill button; auto-cleanup on file open would go in `launcher_file_cont.svelte`.
|
||||||
|
|
||||||
|
**Device tab length note:** The Device tab now has 6 collapsible sections (Sync Timers, Health,
|
||||||
|
Native OS, Wallpaper, Launch Timing, Updates). Consider moving Launch Timing + a future Kill
|
||||||
|
Apps control into a dedicated **"Presentation"** section or a fourth tab to keep Device focused
|
||||||
|
on machine/OS concerns rather than per-app launch behavior.
|
||||||
|
- [x] **[Launcher] Launcher config UI — launch_profiles editor (2026-05-14)** — Launch Timing section in `launcher_cfg_launch_timing.svelte` exposes per-profile `post_delay_ms` overrides with Save/Reset per row. PATCHes `event_device.other_json.launcher.launch_profiles` via V3 CRUD. Wired into `launcher_cfg.svelte`. Shown under Technical Mode (`$ae_loc.edit_mode`).
|
||||||
- [ ] **[Launcher] End-to-end test on macOS** — test pptx and key opens on a real podium Mac
|
- [ ] **[Launcher] End-to-end test on macOS** — test pptx and key opens on a real podium Mac
|
||||||
before May 26 setup day. Verify: file copies to tmp correctly, script fires, app opens in
|
before May 26 setup day. Verify: file copies to tmp correctly, script fires, app opens in
|
||||||
slideshow mode, error fallback works.
|
slideshow mode, error fallback works.
|
||||||
@@ -209,19 +225,9 @@ suddenly jumps to 0 errors, verify it's not because a bad `.d.ts` replaced a pac
|
|||||||
- [x] **Finish Jitsi Reports filters** — added Novi UUID exclusion plus meeting-name whitelist
|
- [x] **Finish Jitsi Reports filters** — added Novi UUID exclusion plus meeting-name whitelist
|
||||||
filtering, with room-level unique counts based on Novi UUID when present. (2026-05-06)
|
filtering, with room-level unique counts based on Novi UUID when present. (2026-05-06)
|
||||||
|
|
||||||
### [PWA] Service worker ignoring `chrome-extension://` requests
|
### ~~[PWA] Service worker ignoring `chrome-extension://` requests~~ ✅ Fixed (2026-05-14)
|
||||||
Browser console shows repeated errors:
|
Guard added to `src/service-worker.js` fetch handler: `if (!event.request.url.startsWith('http')) return;`
|
||||||
```text
|
Also skips cross-origin requests entirely (origin check). No console errors from extension URLs.
|
||||||
TypeError: Failed to execute 'put' on 'Cache': Request scheme 'chrome-extension' is unsupported
|
|
||||||
```
|
|
||||||
The service worker's fetch/install handler is trying to cache requests with `chrome-extension://`
|
|
||||||
URLs (injected by browser extensions), which the Cache API rejects. Fix: filter out non-`http`/`https`
|
|
||||||
requests before attempting to cache. In the service worker fetch handler, add a guard:
|
|
||||||
```js
|
|
||||||
if (!event.request.url.startsWith('http')) return; // skip chrome-extension:// etc.
|
|
||||||
```
|
|
||||||
Locate in `static/service-worker.js` or the Vite PWA plugin config. Low severity — doesn't break
|
|
||||||
functionality, but pollutes the console and may cause unhandled promise rejections.
|
|
||||||
|
|
||||||
### [CSS] Global placeholder text color — too dark in light mode
|
### [CSS] Global placeholder text color — too dark in light mode
|
||||||
Placeholder text inherits full input text color in light mode (Tailwind CSS default), making
|
Placeholder text inherits full input text color in light mode (Tailwind CSS default), making
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ function make_vlc_mirror_profile(): LaunchProfile {
|
|||||||
app: 'VLC',
|
app: 'VLC',
|
||||||
display_mode: 'mirror',
|
display_mode: 'mirror',
|
||||||
open_cmd: 'open -a "VLC" "{{path}}"',
|
open_cmd: 'open -a "VLC" "{{path}}"',
|
||||||
post_delay_ms: 2000,
|
post_delay_ms: 1500,
|
||||||
post_script: `tell application "VLC"
|
post_script: `tell application "VLC"
|
||||||
activate
|
activate
|
||||||
end tell
|
end tell
|
||||||
|
|||||||
@@ -145,13 +145,18 @@ async function _refresh_journal_id_background({
|
|||||||
obj_li: [result],
|
obj_li: [result],
|
||||||
log_lvl
|
log_lvl
|
||||||
});
|
});
|
||||||
await db_save_ae_obj_li__ae_obj({
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
db_instance: db_journals,
|
try {
|
||||||
table_name: 'journal',
|
await db_save_ae_obj_li__ae_obj({
|
||||||
obj_li: processed,
|
db_instance: db_journals,
|
||||||
properties_to_save,
|
table_name: 'journal',
|
||||||
log_lvl
|
obj_li: processed,
|
||||||
});
|
properties_to_save,
|
||||||
|
log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal (quota?):', save_error);
|
||||||
|
}
|
||||||
// Yield to microtask queue so Dexie liveQuery observers fire before we return
|
// Yield to microtask queue so Dexie liveQuery observers fire before we return
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -333,13 +338,18 @@ async function _refresh_journal_li_background({
|
|||||||
obj_li: results,
|
obj_li: results,
|
||||||
log_lvl
|
log_lvl
|
||||||
});
|
});
|
||||||
await db_save_ae_obj_li__ae_obj({
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
db_instance: db_journals,
|
try {
|
||||||
table_name: 'journal',
|
await db_save_ae_obj_li__ae_obj({
|
||||||
obj_li: processed,
|
db_instance: db_journals,
|
||||||
properties_to_save,
|
table_name: 'journal',
|
||||||
log_lvl
|
obj_li: processed,
|
||||||
});
|
properties_to_save,
|
||||||
|
log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal (quota?):', save_error);
|
||||||
|
}
|
||||||
// Yield to microtask queue so Dexie liveQuery observers fire before we return
|
// Yield to microtask queue so Dexie liveQuery observers fire before we return
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -418,14 +428,18 @@ export async function create_ae_obj__journal({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
await db_save_ae_obj_li__ae_obj({
|
try {
|
||||||
db_instance: db_journals,
|
await db_save_ae_obj_li__ae_obj({
|
||||||
table_name: 'journal',
|
db_instance: db_journals,
|
||||||
obj_li: processed_obj_li,
|
table_name: 'journal',
|
||||||
properties_to_save: properties_to_save,
|
obj_li: processed_obj_li,
|
||||||
log_lvl: log_lvl
|
properties_to_save: properties_to_save,
|
||||||
});
|
log_lvl: log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return journal_obj_create_result;
|
return journal_obj_create_result;
|
||||||
} else {
|
} else {
|
||||||
@@ -531,14 +545,18 @@ export async function update_ae_obj__journal({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
await db_save_ae_obj_li__ae_obj({
|
try {
|
||||||
db_instance: db_journals,
|
await db_save_ae_obj_li__ae_obj({
|
||||||
table_name: 'journal',
|
db_instance: db_journals,
|
||||||
obj_li: processed_obj_li,
|
table_name: 'journal',
|
||||||
properties_to_save: properties_to_save,
|
obj_li: processed_obj_li,
|
||||||
log_lvl: log_lvl
|
properties_to_save: properties_to_save,
|
||||||
});
|
log_lvl: log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -46,14 +46,19 @@ export async function load_ae_obj_id__journal_entry({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// Save the updated results list to the database.
|
||||||
await db_save_ae_obj_li__ae_obj({
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
db_instance: db_journals,
|
try {
|
||||||
table_name: 'journal_entry',
|
await db_save_ae_obj_li__ae_obj({
|
||||||
obj_li: processed_obj_li,
|
db_instance: db_journals,
|
||||||
properties_to_save: properties_to_save,
|
table_name: 'journal_entry',
|
||||||
log_lvl: log_lvl
|
obj_li: processed_obj_li,
|
||||||
});
|
properties_to_save: properties_to_save,
|
||||||
|
log_lvl: log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return journal_entry_obj_get_result;
|
return journal_entry_obj_get_result;
|
||||||
} else {
|
} else {
|
||||||
@@ -153,19 +158,24 @@ export async function load_ae_obj_li__journal_entry({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// Save the updated results list to the database.
|
||||||
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Saving to DB...');
|
console.log('Saving to DB...');
|
||||||
}
|
}
|
||||||
await db_save_ae_obj_li__ae_obj({
|
try {
|
||||||
db_instance: db_journals,
|
await db_save_ae_obj_li__ae_obj({
|
||||||
table_name: 'journal_entry',
|
db_instance: db_journals,
|
||||||
obj_li: processed_obj_li,
|
table_name: 'journal_entry',
|
||||||
properties_to_save: properties_to_save,
|
obj_li: processed_obj_li,
|
||||||
log_lvl: log_lvl
|
properties_to_save: properties_to_save,
|
||||||
});
|
log_lvl: log_lvl
|
||||||
if (log_lvl) {
|
});
|
||||||
console.log('DB save completed.');
|
if (log_lvl) {
|
||||||
|
console.log('DB save completed.');
|
||||||
|
}
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return journal_entry_obj_li_get_result;
|
return journal_entry_obj_li_get_result;
|
||||||
@@ -237,14 +247,18 @@ export async function create_ae_obj__journal_entry({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
await db_save_ae_obj_li__ae_obj({
|
try {
|
||||||
db_instance: db_journals,
|
await db_save_ae_obj_li__ae_obj({
|
||||||
table_name: 'journal_entry',
|
db_instance: db_journals,
|
||||||
obj_li: processed_obj_li,
|
table_name: 'journal_entry',
|
||||||
properties_to_save: properties_to_save,
|
obj_li: processed_obj_li,
|
||||||
log_lvl: log_lvl
|
properties_to_save: properties_to_save,
|
||||||
});
|
log_lvl: log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return journal_entry_obj_create_result;
|
return journal_entry_obj_create_result;
|
||||||
} else {
|
} else {
|
||||||
@@ -457,13 +471,18 @@ export async function qry__journal_entry({
|
|||||||
journal_id,
|
journal_id,
|
||||||
log_lvl
|
log_lvl
|
||||||
});
|
});
|
||||||
await db_save_ae_obj_li__ae_obj({
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
db_instance: db_journals,
|
try {
|
||||||
table_name: 'journal_entry',
|
await db_save_ae_obj_li__ae_obj({
|
||||||
obj_li: processed_obj_li,
|
db_instance: db_journals,
|
||||||
properties_to_save,
|
table_name: 'journal_entry',
|
||||||
log_lvl
|
obj_li: processed_obj_li,
|
||||||
});
|
properties_to_save,
|
||||||
|
log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return valid_result_li;
|
return valid_result_li;
|
||||||
} else {
|
} else {
|
||||||
@@ -588,14 +607,18 @@ export async function update_ae_obj__journal_entry({
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log('Processed object list:', processed_obj_li);
|
console.log('Processed object list:', processed_obj_li);
|
||||||
}
|
}
|
||||||
// Save the updated results list to the database
|
// IDB write is optional caching — quota failures must not discard the API result.
|
||||||
await db_save_ae_obj_li__ae_obj({
|
try {
|
||||||
db_instance: db_journals,
|
await db_save_ae_obj_li__ae_obj({
|
||||||
table_name: 'journal_entry',
|
db_instance: db_journals,
|
||||||
obj_li: processed_obj_li,
|
table_name: 'journal_entry',
|
||||||
properties_to_save: properties_to_save,
|
obj_li: processed_obj_li,
|
||||||
log_lvl: log_lvl
|
properties_to_save: properties_to_save,
|
||||||
});
|
log_lvl: log_lvl
|
||||||
|
});
|
||||||
|
} catch (save_error) {
|
||||||
|
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -848,13 +871,13 @@ const properties_to_save = [
|
|||||||
// 'description',
|
// 'description',
|
||||||
|
|
||||||
'content',
|
'content',
|
||||||
'content_md_html',
|
// content_md_html is computed from content on every load — not stored to save IDB quota
|
||||||
'content_html',
|
'content_html',
|
||||||
'content_json',
|
'content_json',
|
||||||
'content_encrypted',
|
'content_encrypted',
|
||||||
|
|
||||||
'history',
|
'history',
|
||||||
'history_md_html',
|
// history_md_html is computed from history on every load — not stored to save IDB quota
|
||||||
'history_encrypted',
|
'history_encrypted',
|
||||||
|
|
||||||
'passcode_hash',
|
'passcode_hash',
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ async function reset_profile_delay(profile_name: string) {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-right text-[9px] leading-tight opacity-65">
|
<div class="text-right text-[9px] min-w-22 leading-tight opacity-65">
|
||||||
<div>
|
<div>
|
||||||
Built-in:
|
Built-in:
|
||||||
{row.profile.post_delay_ms ?? 'n/a'} ms
|
{row.profile.post_delay_ms ?? 'n/a'} ms
|
||||||
|
|||||||
Reference in New Issue
Block a user