Commit 3ce8478
feat(one): bridge in-app notifications to native OS notifications (#25)
* feat(one): bridge in-app notifications to native OS notifications
ObjectOS One is a desktop client, but notifications were in-app only — the
Console bell (`sys_inbox_message`, ADR-0030 L5) is invisible when the window is
backgrounded, which is exactly when notifications matter. This adds a webview
bridge that mirrors new inbox messages to native OS notifications (macOS
Notification Center / Windows toast / Linux libnotify).
`assets/notification-bridge.js` is injected into every page alongside
update-banner.js (combined into one initialization script in windows.rs). It
no-ops outside the Console and outside Tauri. On the Console it polls the
canonical inbox object via the data API (`GET /api/v1/data/sys_inbox_message`
— the dedicated `/api/v1/notifications` route isn't mounted in this runtime),
dedupes by id (localStorage, baselined on first load so the backlog isn't
replayed), and when the window is backgrounded fires a native notification per
new message, badges the dock with the count missed while away (cleared on
focus), and focuses + deep-links on click (best-effort via the plugin's action
event).
No new Rust deps or capabilities needed: tauri-plugin-notification is already
registered (lib.rs) and `notification:default` + window show/focus perms are
already granted; withGlobalTauri exposes the JS API.
Verified the data contract end-to-end against a live 9.7.0 runtime: inserting a
real sys_inbox_message row, the bridge's fetch+parse extracts
title/body(body_md)/actionUrl(action_url)/id/createdAt correctly. The native
firing path (sendNotification/badge/focus) needs an actual Tauri build to
exercise — out of reach here (no cargo); the plumbing is in place.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(one): route notification bridge through Rust commands
The first cut assumed Tauri plugin/window JS APIs are on `window.__TAURI__`
(`.notification.sendNotification`, `.window…setBadgeCount`, `.app`). They are
not: this app's `withGlobalTauri` exposes only `core`/`event`, and every native
op here goes through a Rust `#[tauri::command]` called via `core.invoke` (see
prefs.html / update-banner.js). As written the bridge would have fired nothing —
the permission gate (`T.notification`) would stay false.
Rework to match the codebase:
- add Rust commands `notify_native`, `set_badge`, `notif_request_permission`
(commands.rs) and register them (lib.rs); they call the already-registered
notification plugin + the main window's badge from Rust, bypassing the JS ACL
(no capability changes needed);
- the bridge now calls them via `core.invoke` and drops all `T.notification`/
`.window`/`.app` usage; the tested poll/parse path is unchanged.
Compiler-verified: `cargo check` passes (toolchain installed locally), so the
Tauri APIs (`notification().builder().show()`, `set_badge_count`,
`request_permission`) are correct. Still needs a real desktop build to see a
toast actually render (and macOS authorization typically wants a signed bundle).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(one): log when a native notification is surfaced
Lightweight observability for the notification bridge (content-free — no
title/body logged). Verified the app builds and launches via `tauri dev`
(toolchain installed locally); the sidecar loads Auth+Audit so sys_notification
exists and the inbox path is live.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 919000c commit 3ce8478
4 files changed
Lines changed: 191 additions & 2 deletions
Lines changed: 144 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
11 | 45 | | |
12 | 46 | | |
13 | 47 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
49 | 52 | | |
50 | 53 | | |
51 | 54 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
24 | 32 | | |
25 | 33 | | |
26 | 34 | | |
27 | 35 | | |
28 | 36 | | |
29 | 37 | | |
30 | | - | |
| 38 | + | |
31 | 39 | | |
32 | 40 | | |
33 | 41 | | |
| |||
0 commit comments