@zappdev/runtime 0.5.0-alpha.0 → 0.6.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dock.ts CHANGED
@@ -13,24 +13,39 @@
13
13
 
14
14
  import { getBridge } from "./bridge";
15
15
 
16
+ // In worker contexts, __zappBridge.dock is a sync host dispatcher that
17
+ // calls darwin_dock_* directly. Webview fallback uses IPC-style post.
18
+ function dockHost(): ((action: string, args?: unknown) => void) | null {
19
+ const host = (globalThis as any).__zappBridge;
20
+ return host?.dock ?? null;
21
+ }
22
+
16
23
  export const Dock = {
17
24
  /** Show the app icon in the dock/taskbar. */
18
25
  showIcon(): void {
26
+ const host = dockHost();
27
+ if (host) { host("showIcon"); return; }
19
28
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:showIcon", a: {} }));
20
29
  },
21
30
 
22
31
  /** Hide the app icon from the dock/taskbar. */
23
32
  hideIcon(): void {
33
+ const host = dockHost();
34
+ if (host) { host("hideIcon"); return; }
24
35
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:hideIcon", a: {} }));
25
36
  },
26
37
 
27
38
  /** Set a text badge on the dock icon (e.g. "5", "new"). */
28
39
  setBadge(label: string): void {
40
+ const host = dockHost();
41
+ if (host) { host("setBadge", { label }); return; }
29
42
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:setBadge", a: { label } }));
30
43
  },
31
44
 
32
45
  /** Remove the badge from the dock icon. */
33
46
  removeBadge(): void {
47
+ const host = dockHost();
48
+ if (host) { host("removeBadge"); return; }
34
49
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:removeBadge", a: {} }));
35
50
  },
36
51
 
@@ -38,6 +53,8 @@ export const Dock = {
38
53
  * @param type "informational" (bounces once) or "critical" (bounces until activated). Default: "informational"
39
54
  */
40
55
  bounce(type: "informational" | "critical" = "informational"): void {
56
+ const host = dockHost();
57
+ if (host) { host("bounce", { type: type === "critical" ? 1 : 0 }); return; }
41
58
  (getBridge() as any).post(JSON.stringify({
42
59
  t: 4, m: "dock:bounce", a: { type: type === "critical" ? 1 : 0 },
43
60
  }));
@@ -45,11 +62,15 @@ export const Dock = {
45
62
 
46
63
  /** Set a custom dock icon from a file path. */
47
64
  setIcon(path: string): void {
65
+ const host = dockHost();
66
+ if (host) { host("setIcon", { path }); return; }
48
67
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:setIcon", a: { path } }));
49
68
  },
50
69
 
51
70
  /** Reset the dock icon to the app bundle default. */
52
71
  resetIcon(): void {
72
+ const host = dockHost();
73
+ if (host) { host("resetIcon"); return; }
53
74
  (getBridge() as any).post(JSON.stringify({ t: 4, m: "dock:resetIcon", a: {} }));
54
75
  },
55
76
  };
package/notification.ts CHANGED
@@ -20,6 +20,16 @@
20
20
  import { getBridge } from "./bridge";
21
21
  import { Events } from "./events";
22
22
 
23
+ // In worker contexts, __zappBridge.notif is a dispatcher host object that
24
+ // routes directly to darwin_notification_* C functions. We prefer it when
25
+ // available to avoid the webview IPC roundtrip (bridge.invoke sends JSON
26
+ // over WKWebView's userContentController). The webview path is the
27
+ // fallback — it's the only option there.
28
+ function notifHost(): ((action: string, args?: unknown) => unknown) | null {
29
+ const host = (globalThis as any).__zappBridge;
30
+ return host?.notif ?? null;
31
+ }
32
+
23
33
  export interface NotificationAction {
24
34
  id: string;
25
35
  title: string;
@@ -72,26 +82,52 @@ export type PermissionStatus = "granted" | "denied" | "not-determined" | "provis
72
82
 
73
83
  export const Notification = {
74
84
  async requestPermission(): Promise<PermissionStatus> {
85
+ const host = notifHost();
86
+ if (host) {
87
+ // In workers we can't easily wait on an async permission prompt — fall
88
+ // back to returning the current status. Users of headless workers
89
+ // typically request permission from a webview first anyway.
90
+ const r = host("getPermission") as { status: string };
91
+ return r.status as PermissionStatus;
92
+ }
75
93
  const result = await getBridge().invoke("__notif:requestPermission") as { status: string };
76
94
  return result.status as PermissionStatus;
77
95
  },
78
96
 
79
97
  async getPermissionStatus(): Promise<PermissionStatus> {
98
+ const host = notifHost();
99
+ if (host) {
100
+ const r = host("getPermission") as { status: string };
101
+ return r.status as PermissionStatus;
102
+ }
80
103
  const result = await getBridge().invoke("__notif:getPermission") as { status: string };
81
104
  return result.status as PermissionStatus;
82
105
  },
83
106
 
84
107
  async show(options: NotificationOptions): Promise<string> {
108
+ const host = notifHost();
109
+ if (host) {
110
+ const r = host("show", options) as { id: string };
111
+ return r.id;
112
+ }
85
113
  const result = await getBridge().invoke("__notif:show", options as any) as { id: string };
86
114
  return result.id;
87
115
  },
88
116
 
89
117
  async schedule(options: ScheduleOptions): Promise<string> {
118
+ const host = notifHost();
119
+ if (host) {
120
+ const delaySeconds = "seconds" in options.trigger ? options.trigger.seconds : 0;
121
+ const r = host("schedule", { ...options, delaySeconds }) as { id: string };
122
+ return r.id;
123
+ }
90
124
  const result = await getBridge().invoke("__notif:schedule", options as any) as { id: string };
91
125
  return result.id;
92
126
  },
93
127
 
94
128
  async registerCategory(category: NotificationCategory): Promise<void> {
129
+ // Worker path not wired — registerCategory needs typed-struct args that
130
+ // don't fit the simple dispatcher. Fall back to webview IPC.
95
131
  await getBridge().invoke("__notif:registerCategory", category as any);
96
132
  },
97
133
 
@@ -100,20 +136,28 @@ export const Notification = {
100
136
  },
101
137
 
102
138
  async cancel(id: string): Promise<void> {
139
+ const host = notifHost();
140
+ if (host) { host("cancel", { id }); return; }
103
141
  await getBridge().invoke("__notif:cancel", { id } as any);
104
142
  },
105
143
 
106
144
  async cancelAll(): Promise<void> {
145
+ const host = notifHost();
146
+ if (host) { host("cancelAll"); return; }
107
147
  await getBridge().invoke("__notif:cancelAll");
108
148
  },
109
149
 
110
150
  /** Remove a specific delivered notification from notification center. */
111
151
  async removeDelivered(id: string): Promise<void> {
152
+ const host = notifHost();
153
+ if (host) { host("removeDelivered", { id }); return; }
112
154
  await getBridge().invoke("__notif:removeDelivered", { id } as any);
113
155
  },
114
156
 
115
157
  /** Remove all delivered notifications from notification center. */
116
158
  async removeAllDelivered(): Promise<void> {
159
+ const host = notifHost();
160
+ if (host) { host("removeAllDelivered"); return; }
117
161
  await getBridge().invoke("__notif:removeAllDelivered");
118
162
  },
119
163
 
@@ -122,6 +166,8 @@ export const Notification = {
122
166
  * The notification must have been shown with an explicit `id`.
123
167
  */
124
168
  async update(id: string, options: Partial<NotificationOptions>): Promise<void> {
169
+ const host = notifHost();
170
+ if (host) { host("update", { id, ...options }); return; }
125
171
  await getBridge().invoke("__notif:update", { id, ...options } as any);
126
172
  },
127
173
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zappdev/runtime",
3
- "version": "0.5.0-alpha.0",
3
+ "version": "0.6.0-alpha.0",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "types": "index.ts",
package/window.ts CHANGED
@@ -112,6 +112,13 @@ export const Window = {
112
112
 
113
113
  /** Create a new window. Returns a handle for the new window. */
114
114
  async create(opts?: Partial<WindowOptions>): Promise<WindowHandle> {
115
+ // Worker context: call the createWindow host directly (sync C call).
116
+ const host = (globalThis as any).__zappBridge;
117
+ if (host?.createWindow) {
118
+ const r = host.createWindow(opts ?? {}) as { windowId: string };
119
+ return createWindowHandle(r.windowId);
120
+ }
121
+ // Webview context: async IPC roundtrip through the WKWebView bridge.
115
122
  const result = await getBridge().invoke("__window:create", opts ?? {}) as { windowId: string };
116
123
  return createWindowHandle(result.windowId);
117
124
  },