opentray 0.4.1 → 0.5.1
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/README.md +70 -3
- package/assets/lynx-review/main.lynx.bundle +0 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +182 -239
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-Db-tztnj.mjs → client-B_zxQOo5.mjs} +11 -1
- package/dist/client-B_zxQOo5.mjs.map +1 -0
- package/dist/{client-C_zT7PEt.d.mts → client-h6gZdeOk.d.mts} +3 -2
- package/dist/client-h6gZdeOk.d.mts.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{local-broker-mQmeVLF5.mjs → local-broker-CEIHPBcK.mjs} +15 -17
- package/dist/local-broker-CEIHPBcK.mjs.map +1 -0
- package/dist/node.d.mts +1 -1
- package/dist/node.d.mts.map +1 -1
- package/dist/node.mjs +1 -1
- package/package.json +10 -8
- package/dist/client-C_zT7PEt.d.mts.map +0 -1
- package/dist/client-Db-tztnj.mjs.map +0 -1
- package/dist/local-broker-mQmeVLF5.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as createClient } from "./client-
|
|
3
|
-
import { a as inspectDaemon, c as stopDaemon, i as createNodeDaemonDriver, n as resolveDaemonPaths, o as restartDaemon, r as readPackageVersion, s as startDaemon, t as connectLocalBroker } from "./local-broker-
|
|
2
|
+
import { t as createClient } from "./client-B_zxQOo5.mjs";
|
|
3
|
+
import { a as inspectDaemon, c as stopDaemon, i as createNodeDaemonDriver, n as resolveDaemonPaths, o as restartDaemon, r as readPackageVersion, s as startDaemon, t as connectLocalBroker } from "./local-broker-CEIHPBcK.mjs";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { existsSync, realpathSync } from "node:fs";
|
|
7
7
|
import { dirname, join, resolve } from "node:path";
|
|
8
8
|
//#region src/smoke/daemon-lynx.ts
|
|
9
9
|
const menuLabels$1 = new Map([
|
|
10
|
-
[1, "Show
|
|
11
|
-
[2, "
|
|
12
|
-
[3, "Hide Window"],
|
|
10
|
+
[1, "Show Window"],
|
|
11
|
+
[2, "Hide Window"],
|
|
13
12
|
[99, "Quit Smoke"]
|
|
14
13
|
]);
|
|
15
14
|
const DEFAULT_LYNX_BUNDLE_ENV = "OPENTRAY_LYNX_BUNDLE";
|
|
15
|
+
const DEFAULT_LYNX_HOST_FEATURES_ENV = "OPENTRAY_LYNX_HOST_FEATURES";
|
|
16
16
|
const DEFAULT_REVIEW_BUNDLE_RELATIVE_PATH = "assets/lynx-review/main.lynx.bundle";
|
|
17
|
+
const LYNX_HOST_FEATURES = [
|
|
18
|
+
"nativeWindowApi",
|
|
19
|
+
"bindWindowGlobals",
|
|
20
|
+
"nativeScreenApi",
|
|
21
|
+
"bindScreenGlobals",
|
|
22
|
+
"frameless"
|
|
23
|
+
];
|
|
17
24
|
const runDaemonLynxSmoke = async (options = {}) => {
|
|
18
25
|
const bundlePath = resolveLynxBundlePath(options.bundlePath);
|
|
26
|
+
const hostFeatures = resolveLynxHostFeatures(options.featureExpression);
|
|
27
|
+
if (process.env.OPENTRAY_LYNX_DEBUG) console.log(`lynx debug modes: ${process.env.OPENTRAY_LYNX_DEBUG}`);
|
|
28
|
+
if (process.env[DEFAULT_LYNX_HOST_FEATURES_ENV]) console.log(`lynx host features: ${process.env[DEFAULT_LYNX_HOST_FEATURES_ENV]}`);
|
|
29
|
+
if (process.env.OPENTRAY_LYNX_DEBUG_LOG_PATH) console.log(`lynx debug log path: ${process.env.OPENTRAY_LYNX_DEBUG_LOG_PATH}`);
|
|
19
30
|
const connection = await connectLocalBroker();
|
|
20
31
|
const client = createClient(connection, { requestIdPrefix: "daemon-lynx" });
|
|
21
32
|
console.log(`connected: endpoint=${connection.endpoint} session=${connection.sessionId}`);
|
|
@@ -37,16 +48,11 @@ const runDaemonLynxSmoke = async (options = {}) => {
|
|
|
37
48
|
{
|
|
38
49
|
type: "item",
|
|
39
50
|
id: 1,
|
|
40
|
-
title: "Show
|
|
51
|
+
title: "Show Window"
|
|
41
52
|
},
|
|
42
53
|
{
|
|
43
54
|
type: "item",
|
|
44
55
|
id: 2,
|
|
45
|
-
title: "Show Fixed Window"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
type: "item",
|
|
49
|
-
id: 3,
|
|
50
56
|
title: "Hide Window"
|
|
51
57
|
},
|
|
52
58
|
{ type: "separator" },
|
|
@@ -69,21 +75,13 @@ const runDaemonLynxSmoke = async (options = {}) => {
|
|
|
69
75
|
let closed = false;
|
|
70
76
|
let exitTimer;
|
|
71
77
|
let resolveClosed;
|
|
72
|
-
const show = async (
|
|
73
|
-
|
|
74
|
-
type: "show",
|
|
78
|
+
const show = async () => {
|
|
79
|
+
const command = createLynxShowCommand({
|
|
75
80
|
bundlePath,
|
|
76
|
-
|
|
77
|
-
width: mode === "fixed" ? 720 : void 0,
|
|
78
|
-
height: mode === "fixed" ? 420 : void 0,
|
|
79
|
-
minWidth: 320,
|
|
80
|
-
minHeight: 220,
|
|
81
|
-
maxWidth: 960,
|
|
82
|
-
maxHeight: 720,
|
|
83
|
-
nativeWindowApi: true,
|
|
84
|
-
bindWindowGlobals: true
|
|
81
|
+
hostFeatures
|
|
85
82
|
});
|
|
86
|
-
|
|
83
|
+
await tray.commandExtension("lynx", command);
|
|
84
|
+
console.log(`lynx command: show features=${describeLynxHostFeatures(hostFeatures)} bundle=${bundlePath}`);
|
|
87
85
|
};
|
|
88
86
|
const hide = async () => {
|
|
89
87
|
await tray.commandExtension("lynx", { type: "hide" });
|
|
@@ -106,12 +104,9 @@ const runDaemonLynxSmoke = async (options = {}) => {
|
|
|
106
104
|
const handleMenuClick = async (itemId) => {
|
|
107
105
|
switch (itemId) {
|
|
108
106
|
case 1:
|
|
109
|
-
await show(
|
|
107
|
+
await show();
|
|
110
108
|
return;
|
|
111
109
|
case 2:
|
|
112
|
-
await show("fixed");
|
|
113
|
-
return;
|
|
114
|
-
case 3:
|
|
115
110
|
await hide();
|
|
116
111
|
return;
|
|
117
112
|
case 99:
|
|
@@ -143,8 +138,8 @@ const runDaemonLynxSmoke = async (options = {}) => {
|
|
|
143
138
|
}, duration);
|
|
144
139
|
}
|
|
145
140
|
try {
|
|
146
|
-
await show(
|
|
147
|
-
console.log(
|
|
141
|
+
await show();
|
|
142
|
+
console.log(`use the tray menu to re-show or hide the window, or press Ctrl+C to exit; features=${describeLynxHostFeatures(hostFeatures)}`);
|
|
148
143
|
} catch (error) {
|
|
149
144
|
await connection.close();
|
|
150
145
|
process.off("SIGINT", onSignal);
|
|
@@ -166,6 +161,39 @@ const resolveLynxBundlePath = (value) => {
|
|
|
166
161
|
if (!existsSync(absolutePath)) throw new Error(`lynx smoke bundle does not exist: ${absolutePath}`);
|
|
167
162
|
return realpathSync(absolutePath);
|
|
168
163
|
};
|
|
164
|
+
const resolveLynxHostFeatures = (expression = process.env[DEFAULT_LYNX_HOST_FEATURES_ENV] ?? "") => {
|
|
165
|
+
const features = createEmptyLynxHostFeatures();
|
|
166
|
+
for (const rawToken of expression.split(",")) {
|
|
167
|
+
const token = rawToken.trim();
|
|
168
|
+
if (token.length === 0) continue;
|
|
169
|
+
applyLynxHostFeatureToken(features, token);
|
|
170
|
+
}
|
|
171
|
+
return features;
|
|
172
|
+
};
|
|
173
|
+
const createLynxShowCommand = ({ bundlePath, hostFeatures }) => {
|
|
174
|
+
const command = {
|
|
175
|
+
type: "show",
|
|
176
|
+
bundlePath,
|
|
177
|
+
width: 720,
|
|
178
|
+
height: 420,
|
|
179
|
+
minWidth: 320,
|
|
180
|
+
minHeight: 220,
|
|
181
|
+
maxWidth: 960,
|
|
182
|
+
maxHeight: 720,
|
|
183
|
+
nativeWindowApi: hostFeatures.nativeWindowApi,
|
|
184
|
+
bindWindowGlobals: hostFeatures.bindWindowGlobals,
|
|
185
|
+
nativeScreenApi: hostFeatures.nativeScreenApi,
|
|
186
|
+
bindScreenGlobals: hostFeatures.bindScreenGlobals,
|
|
187
|
+
title: `OpenTray Lynx Smoke (${describeLynxHostFeatures(hostFeatures)})`,
|
|
188
|
+
icon: createVisibleIcon$1()
|
|
189
|
+
};
|
|
190
|
+
if (hostFeatures.frameless) command.style = { frameless: true };
|
|
191
|
+
return command;
|
|
192
|
+
};
|
|
193
|
+
const describeLynxHostFeatures = (features) => {
|
|
194
|
+
const enabled = LYNX_HOST_FEATURES.filter((feature) => features[feature]);
|
|
195
|
+
return enabled.length === 0 ? "baseline" : enabled.join(",");
|
|
196
|
+
};
|
|
169
197
|
const resolveBundledReviewBundlePath = (moduleUrl = import.meta.url) => {
|
|
170
198
|
let currentDir = dirname(fileURLToPath(moduleUrl));
|
|
171
199
|
while (true) {
|
|
@@ -175,6 +203,45 @@ const resolveBundledReviewBundlePath = (moduleUrl = import.meta.url) => {
|
|
|
175
203
|
currentDir = parent;
|
|
176
204
|
}
|
|
177
205
|
};
|
|
206
|
+
function createEmptyLynxHostFeatures() {
|
|
207
|
+
return {
|
|
208
|
+
nativeWindowApi: false,
|
|
209
|
+
bindWindowGlobals: false,
|
|
210
|
+
nativeScreenApi: false,
|
|
211
|
+
bindScreenGlobals: false,
|
|
212
|
+
frameless: false
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function applyLynxHostFeatureToken(features, rawToken) {
|
|
216
|
+
const disabled = rawToken.startsWith("!");
|
|
217
|
+
const token = disabled ? rawToken.slice(1) : rawToken;
|
|
218
|
+
if (token === "*" || token === "full") {
|
|
219
|
+
for (const feature of LYNX_HOST_FEATURES) features[feature] = !disabled;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (token === "baseline") {
|
|
223
|
+
for (const feature of LYNX_HOST_FEATURES) features[feature] = false;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (!isLynxHostFeature(token)) throw new Error(`unsupported Lynx host feature token: ${rawToken}; supported tokens: baseline, full, *, !<feature>, ${LYNX_HOST_FEATURES.join(", ")}`);
|
|
227
|
+
features[token] = !disabled;
|
|
228
|
+
if (token === "nativeWindowApi" && disabled) {
|
|
229
|
+
features.bindWindowGlobals = false;
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (token === "nativeScreenApi" && disabled) {
|
|
233
|
+
features.bindScreenGlobals = false;
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (token === "bindWindowGlobals" && !disabled) {
|
|
237
|
+
features.nativeWindowApi = true;
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (token === "bindScreenGlobals" && !disabled) features.nativeScreenApi = true;
|
|
241
|
+
}
|
|
242
|
+
function isLynxHostFeature(value) {
|
|
243
|
+
return LYNX_HOST_FEATURES.includes(value);
|
|
244
|
+
}
|
|
178
245
|
function createVisibleIcon$1() {
|
|
179
246
|
const width = 32;
|
|
180
247
|
const height = 32;
|
|
@@ -194,20 +261,7 @@ function createVisibleIcon$1() {
|
|
|
194
261
|
}
|
|
195
262
|
//#endregion
|
|
196
263
|
//#region src/smoke/daemon-tray.ts
|
|
197
|
-
const menuLabels = new Map([
|
|
198
|
-
[1, "Primary Action"],
|
|
199
|
-
[3, "Checked Capability"],
|
|
200
|
-
[4, "Radio: Active"],
|
|
201
|
-
[5, "Radio: Passive"],
|
|
202
|
-
[6, "Nested Action"],
|
|
203
|
-
[7, "Nested Check"],
|
|
204
|
-
[8, "WebView: Show HTML"],
|
|
205
|
-
[9, "WebView: Navigate"],
|
|
206
|
-
[10, "WebView: Post Message"],
|
|
207
|
-
[11, "WebView: Evaluate"],
|
|
208
|
-
[12, "WebView: Hide"],
|
|
209
|
-
[99, "Quit Demo"]
|
|
210
|
-
]);
|
|
264
|
+
const menuLabels = new Map([[1, "Open WebView"]]);
|
|
211
265
|
const runDaemonTraySmoke = async () => {
|
|
212
266
|
const connection = await connectLocalBroker();
|
|
213
267
|
const client = createClient(connection, { requestIdPrefix: "daemon-smoke" });
|
|
@@ -223,93 +277,15 @@ const runDaemonTraySmoke = async () => {
|
|
|
223
277
|
title: "OpenTray",
|
|
224
278
|
tooltip: {
|
|
225
279
|
title: "OpenTray",
|
|
226
|
-
description: "
|
|
280
|
+
description: "Single primary tray action; macOS direct-triggers without opening a menu"
|
|
227
281
|
},
|
|
228
282
|
icon: createVisibleIcon(),
|
|
229
|
-
menu: { items: [
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
type: "item",
|
|
237
|
-
id: 2,
|
|
238
|
-
title: "Disabled Action",
|
|
239
|
-
enabled: false
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
type: "check",
|
|
243
|
-
id: 3,
|
|
244
|
-
title: "Checked Capability",
|
|
245
|
-
checked: true
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
type: "radio",
|
|
249
|
-
id: 4,
|
|
250
|
-
title: "Radio: Active",
|
|
251
|
-
group: 1,
|
|
252
|
-
checked: true
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
type: "radio",
|
|
256
|
-
id: 5,
|
|
257
|
-
title: "Radio: Passive",
|
|
258
|
-
group: 1
|
|
259
|
-
},
|
|
260
|
-
{ type: "separator" },
|
|
261
|
-
{
|
|
262
|
-
type: "submenu",
|
|
263
|
-
title: "Nested Actions",
|
|
264
|
-
items: [{
|
|
265
|
-
type: "item",
|
|
266
|
-
id: 6,
|
|
267
|
-
title: "Nested Action"
|
|
268
|
-
}, {
|
|
269
|
-
type: "check",
|
|
270
|
-
id: 7,
|
|
271
|
-
title: "Nested Check",
|
|
272
|
-
checked: false
|
|
273
|
-
}]
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
type: "submenu",
|
|
277
|
-
title: "WebView Commands",
|
|
278
|
-
items: [
|
|
279
|
-
{
|
|
280
|
-
type: "item",
|
|
281
|
-
id: 8,
|
|
282
|
-
title: "Show HTML"
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
type: "item",
|
|
286
|
-
id: 9,
|
|
287
|
-
title: "Navigate"
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
type: "item",
|
|
291
|
-
id: 10,
|
|
292
|
-
title: "Post Message"
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
type: "item",
|
|
296
|
-
id: 11,
|
|
297
|
-
title: "Evaluate JS"
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
type: "item",
|
|
301
|
-
id: 12,
|
|
302
|
-
title: "Hide"
|
|
303
|
-
}
|
|
304
|
-
]
|
|
305
|
-
},
|
|
306
|
-
{ type: "separator" },
|
|
307
|
-
{
|
|
308
|
-
type: "item",
|
|
309
|
-
id: 99,
|
|
310
|
-
title: "Quit Demo"
|
|
311
|
-
}
|
|
312
|
-
] }
|
|
283
|
+
menu: { items: [{
|
|
284
|
+
type: "item",
|
|
285
|
+
id: 1,
|
|
286
|
+
title: "Open WebView",
|
|
287
|
+
primaryEvent: true
|
|
288
|
+
}] }
|
|
313
289
|
});
|
|
314
290
|
console.log(`tray: ${tray.trayId}`);
|
|
315
291
|
await connection.request({
|
|
@@ -320,10 +296,8 @@ const runDaemonTraySmoke = async () => {
|
|
|
320
296
|
path: "@opentray/ext-webview"
|
|
321
297
|
});
|
|
322
298
|
console.log("webview extension requested through the generic load-ext path");
|
|
323
|
-
console.log("
|
|
299
|
+
console.log("click the tray icon: macOS should direct-trigger the single primary action without opening a menu");
|
|
324
300
|
let closed = false;
|
|
325
|
-
let messageCount = 0;
|
|
326
|
-
let evalCount = 0;
|
|
327
301
|
let exitTimer;
|
|
328
302
|
const shutdown = async () => {
|
|
329
303
|
if (closed) return;
|
|
@@ -335,63 +309,56 @@ const runDaemonTraySmoke = async () => {
|
|
|
335
309
|
await tray.commandExtension("webview", command);
|
|
336
310
|
};
|
|
337
311
|
const handleMenuClick = async (itemId) => {
|
|
338
|
-
if (itemId ===
|
|
339
|
-
|
|
340
|
-
|
|
312
|
+
if (itemId === 1) {
|
|
313
|
+
const trayBounds = await tray.getBounds();
|
|
314
|
+
console.log(`tray bounds: ${JSON.stringify(trayBounds)}`);
|
|
315
|
+
await commandWebview({
|
|
316
|
+
type: "show",
|
|
317
|
+
html: createWebviewDemoHtml(),
|
|
318
|
+
width: 420,
|
|
319
|
+
height: 260,
|
|
320
|
+
title: "OpenTray WebView Smoke",
|
|
321
|
+
icon: {
|
|
322
|
+
type: "href",
|
|
323
|
+
href: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="
|
|
324
|
+
},
|
|
325
|
+
style: {
|
|
326
|
+
frameless: true,
|
|
327
|
+
transparent: true,
|
|
328
|
+
keepOnTop: true,
|
|
329
|
+
platform: { macos: {
|
|
330
|
+
material: "hudWindow",
|
|
331
|
+
materialState: "active"
|
|
332
|
+
} }
|
|
333
|
+
},
|
|
334
|
+
fallbackRect: trayBounds.rect ?? {
|
|
335
|
+
x: 0,
|
|
336
|
+
y: 0,
|
|
337
|
+
width: 1,
|
|
338
|
+
height: 1
|
|
339
|
+
},
|
|
340
|
+
nativeWindowApi: true,
|
|
341
|
+
bindWindowGlobals: true,
|
|
342
|
+
nativeScreenApi: true,
|
|
343
|
+
bindScreenGlobals: true,
|
|
344
|
+
nativeTrayApi: true,
|
|
345
|
+
titleSync: {
|
|
346
|
+
documentToWindow: true,
|
|
347
|
+
windowToDocument: true
|
|
348
|
+
},
|
|
349
|
+
iconSync: true,
|
|
350
|
+
nativeApiPolicy: {
|
|
351
|
+
defaultSrc: ["'local'"],
|
|
352
|
+
window: ["https://example.com"],
|
|
353
|
+
screen: ["https://example.com"],
|
|
354
|
+
tray: ["https://example.com"],
|
|
355
|
+
titleSync: ["https://example.com"],
|
|
356
|
+
iconSync: ["https://example.com"]
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
console.log("primary tray action: webview show");
|
|
341
360
|
return;
|
|
342
361
|
}
|
|
343
|
-
if (itemId < 8 || itemId > 12) return;
|
|
344
|
-
switch (itemId) {
|
|
345
|
-
case 8:
|
|
346
|
-
await commandWebview({
|
|
347
|
-
type: "show",
|
|
348
|
-
html: createWebviewDemoHtml(),
|
|
349
|
-
width: 420,
|
|
350
|
-
height: 260,
|
|
351
|
-
fallbackRect: {
|
|
352
|
-
x: 0,
|
|
353
|
-
y: 0,
|
|
354
|
-
width: 1,
|
|
355
|
-
height: 1
|
|
356
|
-
},
|
|
357
|
-
nativeWindowApi: true,
|
|
358
|
-
bindWindowGlobals: true
|
|
359
|
-
});
|
|
360
|
-
console.log("webview command: show");
|
|
361
|
-
break;
|
|
362
|
-
case 9:
|
|
363
|
-
await commandWebview({
|
|
364
|
-
type: "navigate",
|
|
365
|
-
url: "https://example.com/opentray-status"
|
|
366
|
-
});
|
|
367
|
-
console.log("webview command: navigate");
|
|
368
|
-
break;
|
|
369
|
-
case 10:
|
|
370
|
-
messageCount += 1;
|
|
371
|
-
await commandWebview({
|
|
372
|
-
type: "postMessage",
|
|
373
|
-
payload: {
|
|
374
|
-
kind: "ping",
|
|
375
|
-
source: "opentray smoke daemon-tray",
|
|
376
|
-
count: messageCount,
|
|
377
|
-
sentAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
console.log("webview command: postMessage");
|
|
381
|
-
break;
|
|
382
|
-
case 11:
|
|
383
|
-
evalCount += 1;
|
|
384
|
-
await commandWebview({
|
|
385
|
-
type: "evaluate",
|
|
386
|
-
js: createVisibleEvaluateScript(evalCount)
|
|
387
|
-
});
|
|
388
|
-
console.log("webview command: evaluate");
|
|
389
|
-
break;
|
|
390
|
-
case 12:
|
|
391
|
-
await commandWebview({ type: "hide" });
|
|
392
|
-
console.log("webview command: hide");
|
|
393
|
-
break;
|
|
394
|
-
}
|
|
395
362
|
};
|
|
396
363
|
connection.onEvent((frame) => {
|
|
397
364
|
console.log(`broker -> client ${JSON.stringify(frame)}`);
|
|
@@ -409,19 +376,12 @@ const runDaemonTraySmoke = async () => {
|
|
|
409
376
|
}
|
|
410
377
|
const webviewSmoke = process.env.OPENTRAY_EXAMPLE_WEBVIEW_SMOKE;
|
|
411
378
|
try {
|
|
412
|
-
if (webviewSmoke === "show") await handleMenuClick(
|
|
413
|
-
|
|
379
|
+
if (webviewSmoke === "show" || webviewSmoke === "1") await handleMenuClick(1);
|
|
380
|
+
if (webviewSmoke === "1") {
|
|
414
381
|
if (exitTimer !== void 0) {
|
|
415
382
|
clearTimeout(exitTimer);
|
|
416
383
|
exitTimer = void 0;
|
|
417
384
|
}
|
|
418
|
-
for (const itemId of [
|
|
419
|
-
8,
|
|
420
|
-
10,
|
|
421
|
-
11,
|
|
422
|
-
9,
|
|
423
|
-
12
|
|
424
|
-
]) await handleMenuClick(itemId);
|
|
425
385
|
await sleep(300);
|
|
426
386
|
await shutdown();
|
|
427
387
|
}
|
|
@@ -510,47 +470,17 @@ function createWebviewDemoHtml() {
|
|
|
510
470
|
<body>
|
|
511
471
|
<main>
|
|
512
472
|
<h1>OpenTray WebView</h1>
|
|
513
|
-
<p>
|
|
473
|
+
<p>This window was opened by the single primary tray action.</p>
|
|
514
474
|
<section>
|
|
515
475
|
<div class="card">
|
|
516
|
-
<div class="label">
|
|
517
|
-
<code
|
|
518
|
-
</div>
|
|
519
|
-
<div class="card">
|
|
520
|
-
<div class="label">evaluate JS</div>
|
|
521
|
-
<code id="eval-status">Waiting for WebView Commands -> Evaluate JS</code>
|
|
476
|
+
<div class="label">primary event</div>
|
|
477
|
+
<code>macOS single primary item direct-triggered menuClick -> WebView show</code>
|
|
522
478
|
</div>
|
|
523
479
|
</section>
|
|
524
480
|
</main>
|
|
525
|
-
<script>
|
|
526
|
-
window.addEventListener("message", (event) => {
|
|
527
|
-
const target = document.getElementById("message-status");
|
|
528
|
-
if (target) {
|
|
529
|
-
target.textContent = JSON.stringify(event.data, null, 2);
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
<\/script>
|
|
533
481
|
</body>
|
|
534
482
|
</html>`;
|
|
535
483
|
}
|
|
536
|
-
function createVisibleEvaluateScript(count) {
|
|
537
|
-
return `(() => {
|
|
538
|
-
let target = document.getElementById("eval-status");
|
|
539
|
-
if (!target) {
|
|
540
|
-
const panel = document.createElement("div");
|
|
541
|
-
panel.style.cssText = "position:fixed;left:16px;right:16px;bottom:16px;z-index:2147483647;padding:12px;border-radius:12px;background:#fff8e7;color:#18220f;box-shadow:0 12px 30px rgba(0,0,0,.18);font:14px ui-rounded, sans-serif;";
|
|
542
|
-
panel.textContent = "OpenTray Evaluate JS: ";
|
|
543
|
-
target = document.createElement("code");
|
|
544
|
-
target.id = "eval-status";
|
|
545
|
-
panel.appendChild(target);
|
|
546
|
-
document.body.appendChild(panel);
|
|
547
|
-
}
|
|
548
|
-
if (target) {
|
|
549
|
-
target.textContent = "Evaluate JS updated the WebView, count=${count}, at " + new Date().toLocaleTimeString();
|
|
550
|
-
}
|
|
551
|
-
window.__OPENTRAY_DEMO__ = { evaluated: true, count: ${count} };
|
|
552
|
-
})();`;
|
|
553
|
-
}
|
|
554
484
|
function sleep(ms) {
|
|
555
485
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
556
486
|
}
|
|
@@ -566,14 +496,12 @@ const parseCliCommand = (argv) => {
|
|
|
566
496
|
name: "daemon-tray"
|
|
567
497
|
};
|
|
568
498
|
if (group === "smoke" && action === "daemon-lynx") {
|
|
569
|
-
const
|
|
570
|
-
return
|
|
571
|
-
type: "smoke",
|
|
572
|
-
name: "daemon-lynx"
|
|
573
|
-
} : {
|
|
499
|
+
const smokeOptions = parseSmokeOptions(rest);
|
|
500
|
+
return {
|
|
574
501
|
type: "smoke",
|
|
575
502
|
name: "daemon-lynx",
|
|
576
|
-
bundlePath
|
|
503
|
+
...smokeOptions.bundlePath ? { bundlePath: smokeOptions.bundlePath } : {},
|
|
504
|
+
...smokeOptions.featureExpression ? { featureExpression: smokeOptions.featureExpression } : {}
|
|
577
505
|
};
|
|
578
506
|
}
|
|
579
507
|
return { type: "help" };
|
|
@@ -597,7 +525,10 @@ const runCli = async (argv) => {
|
|
|
597
525
|
}
|
|
598
526
|
if (command.type === "smoke") {
|
|
599
527
|
if (command.name === "daemon-tray") await runDaemonTraySmoke();
|
|
600
|
-
else await runDaemonLynxSmoke(
|
|
528
|
+
else await runDaemonLynxSmoke({
|
|
529
|
+
...command.bundlePath === void 0 ? {} : { bundlePath: command.bundlePath },
|
|
530
|
+
...command.featureExpression === void 0 ? {} : { featureExpression: command.featureExpression }
|
|
531
|
+
});
|
|
601
532
|
return 0;
|
|
602
533
|
}
|
|
603
534
|
const driver = createNodeDaemonDriver(cliModulePath);
|
|
@@ -657,7 +588,7 @@ const runCli = async (argv) => {
|
|
|
657
588
|
const printHelp = () => {
|
|
658
589
|
console.error("Usage: opentray daemon <start|stop|restart|health>");
|
|
659
590
|
console.error(" opentray smoke daemon-tray");
|
|
660
|
-
console.error(" opentray smoke daemon-lynx [--bundle <path-to-main.lynx.bundle>]");
|
|
591
|
+
console.error(" opentray smoke daemon-lynx [--bundle <path-to-main.lynx.bundle>] [--features <baseline|full|*,!feature,...>]");
|
|
661
592
|
console.error(" default Lynx smoke uses the packaged review bundle");
|
|
662
593
|
};
|
|
663
594
|
const formatDaemonHealthOutput = (health) => {
|
|
@@ -683,8 +614,20 @@ const isCliEntrypoint = (argvEntryPath, modulePath) => {
|
|
|
683
614
|
return argvEntryPath === modulePath;
|
|
684
615
|
}
|
|
685
616
|
};
|
|
686
|
-
function
|
|
687
|
-
|
|
617
|
+
function parseSmokeOptions(argv) {
|
|
618
|
+
let bundlePath;
|
|
619
|
+
let featureExpression;
|
|
620
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
621
|
+
if (argv[index] === "--bundle") {
|
|
622
|
+
bundlePath = argv[index + 1];
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
if (argv[index] === "--features") featureExpression = argv[index + 1];
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
...bundlePath === void 0 ? {} : { bundlePath },
|
|
629
|
+
...featureExpression === void 0 ? {} : { featureExpression }
|
|
630
|
+
};
|
|
688
631
|
}
|
|
689
632
|
if (isCliEntrypoint(process.argv[1], cliModulePath)) runCli(process.argv.slice(2)).then((code) => {
|
|
690
633
|
process.exitCode = code;
|