Session log — Zoom Apps, Shape A polish and notifications
← All session logs
Session log — Zoom Apps, Shape A polish and notifications
Summary
Picked up from this morning's session log (footer fix, webinar support, notifications still pending) and worked through a long evening of debugging plus three polish features. Final state: Camera Monitor v0.7.0 is built and waiting for the user to test it in the morning, with all of A, B, C polish complete.
The big debugging arc was around macOS notifications. After the morning fix that moved notification firing into the main process, no banners were appearing despite the IPC chain returning true. Worked through several false leads before finding two real problems and one user-environment cause:
- The bot was showing in its own roster again (regression). The
getCurrentUser().userIdwas different from the userId reported in roster events, so the original userId-based filter missed it. Added a display-name fallback filter. peer-video-state-changeis unreliable in the Web SDK 3.13.2 build, butuser-updatedfires correctly. Thepeer-video-state-changewas racing withuser-updatedand changingvideoOnfirst, so by the time the transition detector compared the old value, it had already been overwritten as the new value. The off-to-on transition therefore looked like off-to-off, no notification fired. Solution: do all videoOn mutation AND transition detection insideupsertUser(called fromuser-updated), and demotepeer-video-state-changeto logging only.- After all the code was right, banners still did not appear. Eventually traced to macOS Do Not Disturb / Focus mode being on. Toggling DND off restored notifications immediately.
After notifications were proven working, walked through the user's trajectory of A then B then C polish features. All three now built and packaged.
Decisions
- Renderer-side detection of camera transitions is now done exclusively in
upsertUser.peer-video-state-changeis observation-only. Single source of truth, no race conditions. - Bot identity filter uses both
myUserIdandmyDisplayNameas a fallback, because the SDK'sgetCurrentUser()userId does not always match what shows up in roster events. - Session reports are written in three formats: HTML for browsing/sharing, TXT for grep/email, CSV for Excel/Sheets analysis. All three written together on Leave. Stored at
~/Documents/Camera Monitor Logs/. - HTML report has dark-mode-aware styling, color-coded events, per-participant total ON time summary at the bottom.
- CSV columns chosen for analysis utility:
meeting_id, bot_name, timestamp_iso, participant, event, was_on_seconds. ISO timestamps so reports across multiple meetings sort correctly. - Configurable notification threshold (“at least N seconds before firing”) is set in seconds, default 0 (immediate). Pending notifications cancel automatically if the camera comes back on within the window. Logs continue recording every transition regardless.
- Snooze is a button-and-dropdown, not a checkbox. Dropdown picks duration (1m, 5m, 15m, 30m, 1h), button starts the snooze and shows a live countdown like “Cancel snooze (4:32)”. Click button again to cancel early. Snooze suppresses both off and on notifications. Logs continue.
- Notify-on-camera-on is a separate optional checkbox, default OFF. Operator opts in if they want the symmetrical “they are back” alerts.
- All notification preferences and the snooze duration choice persist via localStorage between launches.
Changes made
renderer/renderer.js: reworkedupsertUserto be the sole authority for video state; demotedpeer-video-state-changeto logging only; added session-log infrastructure with three builders (buildLogText,buildLogHtml,buildLogCsv); added “View past logs” button; added pending-notification map with threshold delay; added snooze logic with countdown tick; addedfireCameraOnNotification; added richer error logging and Zoom error-dialog text capture; added Join URL parser with stale-tk auto-clear.renderer/index.html: added Join URL input, Registration token input, notify-on-camera-on checkbox, snooze button + duration dropdown.renderer/styles.css: styles for num-input, checkbox-row, snooze-row, snooze button active state, dropdown.main.js: addednotify:camera-onIPC handler mirroringnotify:camera-off. Both use Electron's main-process Notification class so the macOS bundle identity is correct.package.json: bumped through 0.4.1, 0.4.2, 0.4.3, 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.6.0, 0.7.0 as features landed. Final shippable:Zoom Companion/dist/Camera Monitor-0.7.0-arm64.dmg.- Updated project memory to reflect the v0.7.0 state and the full set of lessons learned.
Follow-ups
- User to install v0.7.0 in the morning and verify the four polish items: notify-on-camera-on checkbox, snooze button countdown, snooze cancellation, and that all earlier features (logs, threshold, leave teardown, popup blocking, bot filtering) are still intact.
- If everything passes, three options on the table next: distribute v0.7.0 to the studio team, tackle OBF for cross-account meetings, or move to Shape B (server-side bot). The user explicitly mentioned wanting to get to OBF.
- If a regression appears in v0.7.0, the most likely culprits are the new snooze logic interfering with the notification chain, or the new notify-on path causing duplicate fires. The renderer logs
[upsertUser],[notify], and[snooze]lines would pinpoint quickly vianpm run dev. - Cosmetic improvement still outstanding: the txt log header column dashes are slightly misaligned with the actual data underneath. Trivial fix, not blocking anything.