@omega.js/desktop 0.51.0 → 0.53.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/README.md +18 -13
- package/dist/assets/css/core/_initialize.scss +1 -1
- package/dist/assets/js/core/app-shell.js +14 -15
- package/dist/assets/themes/_template/_theme.js +6 -6
- package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
- package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
- package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
- package/dist/assets/themes/base/_theme.js +4 -3
- package/dist/assets/themes/bootstrap/_theme.js +2 -2
- package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
- package/dist/assets/themes/classy/_theme.js +8 -6
- package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
- package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
- package/dist/assets/themes/neobrutalism/_theme.js +5 -5
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/assets/themes/newsflash/_theme.js +6 -6
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/build.js +87 -111
- package/dist/cli.js +1 -1
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/quit.js +2 -2
- package/dist/commands/cdp/relaunch.js +2 -2
- package/dist/commands/cdp/theme.js +1 -1
- package/dist/commands/clean.js +2 -2
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/install.js +3 -3
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +6 -6
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +3 -3
- package/dist/commands/runner.js +145 -48
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +4 -4
- package/dist/commands/update.js +2 -2
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/.github/workflows/build.yml +2 -0
- package/dist/defaults/AGENTS.md +17 -8
- package/dist/defaults/config/omega.json5 +7 -7
- package/dist/defaults/hooks/build/post.js +1 -1
- package/dist/defaults/hooks/build/pre.js +1 -1
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/release/post.js +1 -1
- package/dist/defaults/hooks/release/pre.js +1 -1
- package/dist/defaults/src/assets/js/components/about/index.js +3 -5
- package/dist/defaults/src/assets/js/components/main/index.js +3 -5
- package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
- package/dist/defaults/src/integrations/context-menu/index.js +2 -2
- package/dist/defaults/src/integrations/menu/index.js +3 -3
- package/dist/defaults/src/integrations/tray/index.js +3 -3
- package/dist/defaults/src/main.js +3 -5
- package/dist/defaults/src/preload.js +3 -5
- package/dist/defaults/test/README.md +2 -2
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +7 -7
- package/dist/gulp/tasks/build-config.js +8 -8
- package/dist/gulp/tasks/bundle.js +16 -16
- package/dist/gulp/tasks/defaults.js +3 -3
- package/dist/gulp/tasks/distribute.js +2 -2
- package/dist/gulp/tasks/html.js +9 -9
- package/dist/gulp/tasks/package-quick.js +3 -3
- package/dist/gulp/tasks/package.js +3 -3
- package/dist/gulp/tasks/release.js +3 -3
- package/dist/gulp/tasks/sass.js +6 -6
- package/dist/gulp/tasks/serve.js +4 -4
- package/dist/hooks/notarize-artifacts.js +1 -1
- package/dist/hooks/notarize.js +1 -1
- package/dist/index.js +5 -8
- package/dist/lib/_environment-mixin.js +50 -0
- package/dist/lib/_lifecycle-mixin.js +45 -0
- package/dist/lib/analytics.js +33 -35
- package/dist/lib/app-state.js +14 -14
- package/dist/lib/auth-flow.js +18 -18
- package/dist/lib/auth-persistence.js +12 -12
- package/dist/lib/auth.js +421 -0
- package/dist/lib/auto-updater.js +49 -49
- package/dist/lib/context-menu.js +13 -13
- package/dist/lib/context.js +19 -19
- package/dist/lib/deep-link.js +34 -34
- package/dist/lib/fontawesome.js +5 -5
- package/dist/lib/ipc.js +4 -4
- package/dist/lib/menu.js +25 -25
- package/dist/lib/protocol.js +5 -5
- package/dist/lib/remote-config.js +22 -22
- package/dist/lib/remote-scripts.js +21 -21
- package/dist/lib/restart-manager/index.js +28 -28
- package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
- package/dist/lib/sign-helpers/sign-events.js +1 -1
- package/dist/lib/startup.js +18 -13
- package/dist/lib/storage.js +10 -10
- package/dist/lib/templating.js +16 -16
- package/dist/lib/theme.js +10 -10
- package/dist/lib/tray.js +27 -27
- package/dist/lib/usage.js +11 -11
- package/dist/lib/window-manager.js +26 -26
- package/dist/main.js +398 -483
- package/dist/preload.js +236 -176
- package/dist/renderer.js +417 -391
- package/dist/runner/job-started.js +1 -1
- package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
- package/dist/test/fixtures/consumer-app/src/main.js +5 -7
- package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
- package/dist/test/harness/boot-entry.js +22 -20
- package/dist/test/harness/main-entry.js +31 -30
- package/dist/test/harness/renderer-entry.js +5 -5
- package/dist/test/harness/renderer-preload.js +137 -141
- package/dist/test/index.js +10 -10
- package/dist/test/runner.js +2 -2
- package/dist/test/runners/boot.js +7 -6
- package/dist/test/runners/electron.js +3 -2
- package/dist/test/runners/render-event.js +2 -2
- package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
- package/dist/test/suites/boot/restart-manager.test.js +2 -2
- package/dist/test/suites/boot/storage-bundled.test.js +5 -5
- package/dist/test/suites/boot/theme.test.js +13 -13
- package/dist/test/suites/build/audit.test.js +1 -1
- package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
- package/dist/test/suites/build/boot-fixture.test.js +2 -2
- package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
- package/dist/test/suites/build/brand-scss.test.js +1 -1
- package/dist/test/suites/build/build-json-bake.test.js +1 -1
- package/dist/test/suites/build/cli.test.js +2 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
- package/dist/test/suites/build/deploy-hook.test.js +3 -3
- package/dist/test/suites/build/ensure-target.test.js +2 -2
- package/dist/test/suites/build/env-delivery.test.js +2 -2
- package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
- package/dist/test/suites/build/exports.test.js +9 -8
- package/dist/test/suites/build/get-config.test.js +4 -4
- package/dist/test/suites/build/manifest-deps.test.js +1 -1
- package/dist/test/suites/build/merge-line-files.test.js +1 -1
- package/dist/test/suites/build/omega-shell.test.js +34 -2
- package/dist/test/suites/build/omega.test.js +350 -0
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner.test.js +612 -5
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
- package/dist/test/suites/build/templating.test.js +3 -3
- package/dist/test/suites/build/test-stealth.test.js +7 -9
- package/dist/test/suites/build/url-helpers.test.js +55 -56
- package/dist/test/suites/build/validate-config.test.js +2 -2
- package/dist/test/suites/build/wave5-pins.test.js +2 -2
- package/dist/test/suites/main/analytics.test.js +59 -59
- package/dist/test/suites/main/app-state.test.js +66 -66
- package/dist/test/suites/main/auth-flow.test.js +41 -41
- package/dist/test/suites/main/auth-persistence.test.js +54 -43
- package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
- package/dist/test/suites/main/auth.test.js +336 -0
- package/dist/test/suites/main/auto-updater.test.js +134 -134
- package/dist/test/suites/main/boot-sequence.test.js +37 -49
- package/dist/test/suites/main/context-menu.test.js +51 -50
- package/dist/test/suites/main/context.test.js +25 -25
- package/dist/test/suites/main/deep-link.test.js +74 -74
- package/dist/test/suites/main/fontawesome.test.js +27 -27
- package/dist/test/suites/main/ipc.test.js +35 -35
- package/dist/test/suites/main/menu.test.js +101 -100
- package/dist/test/suites/main/protocol.test.js +19 -19
- package/dist/test/suites/main/remote-config.test.js +63 -63
- package/dist/test/suites/main/remote-scripts.test.js +103 -103
- package/dist/test/suites/main/request.test.js +71 -0
- package/dist/test/suites/main/restart-manager.test.js +33 -33
- package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
- package/dist/test/suites/main/startup.test.js +26 -26
- package/dist/test/suites/main/stealth-window.test.js +1 -1
- package/dist/test/suites/main/storage.test.js +25 -25
- package/dist/test/suites/main/theme.test.js +34 -34
- package/dist/test/suites/main/tray.test.js +79 -79
- package/dist/test/suites/main/url-helpers.test.js +133 -133
- package/dist/test/suites/main/usage.test.js +25 -25
- package/dist/test/suites/main/window-bounds.test.js +27 -27
- package/dist/test/suites/main/window-manager.test.js +44 -44
- package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
- package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
- package/dist/test/suites/renderer/round-trip.test.js +3 -3
- package/dist/test/suites/renderer/tooltips.test.js +15 -15
- package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/ship-keys.js +3 -3
- package/dist/utils/signing-status.js +51 -0
- package/dist/utils/test-events.js +7 -0
- package/dist/utils/test-stealth.js +6 -6
- package/dist/utils/url-helpers.js +52 -42
- package/dist/utils/user-agent.js +44 -0
- package/dist/vendor/account/engine.js +3 -3
- package/dist/vendor/account/index.js +14 -45
- package/dist/vendor/account/resolve-account.js +44 -0
- package/dist/vendor/account/schema.js +1 -1
- package/dist/vendor/account/user.js +99 -0
- package/dist/vendor/config/client-config.js +1 -1
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +13 -12
- package/dist/vendor/config/load.js +1 -2
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/repo.js +24 -0
- package/dist/vendor/config/retired-keys.js +2 -2
- package/dist/vendor/config/schema.js +5 -8
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +1 -2
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/attach-log-file.js +1 -1
- package/dist/vendor/devkit/brand-version.js +162 -1
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/cli-router.js +3 -4
- package/dist/vendor/devkit/defaults-engine.js +9 -11
- package/dist/vendor/devkit/deploy.js +64 -4
- package/dist/vendor/devkit/git-remote.js +78 -1
- package/dist/vendor/devkit/local.js +53 -3
- package/dist/vendor/devkit/lockfile.js +127 -0
- package/dist/vendor/devkit/merge-line-files.js +2 -3
- package/dist/vendor/devkit/pack-local.js +4 -7
- package/dist/vendor/devkit/preludes/origin-heal.js +35 -49
- package/dist/vendor/devkit/target-secrets.js +34 -45
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/monitoring/env.js +2 -2
- package/dist/vendor/monitoring/index.js +1 -1
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/docs/analytics.md +8 -8
- package/docs/app-state.md +19 -19
- package/docs/audit.md +4 -4
- package/docs/{client-bridge.md → auth.md} +88 -73
- package/docs/auto-updater.md +8 -8
- package/docs/boot-sequence.md +11 -6
- package/docs/build-system.md +1 -1
- package/docs/cdp-debugging.md +1 -1
- package/docs/common-mistakes.md +7 -7
- package/docs/config-schema.md +1 -1
- package/docs/context-menu.md +13 -13
- package/docs/context.md +11 -11
- package/docs/css.md +3 -9
- package/docs/deep-link.md +25 -25
- package/docs/environment-detection.md +16 -16
- package/docs/fontawesome.md +7 -5
- package/docs/hooks.md +8 -8
- package/docs/index.md +39 -28
- package/docs/ipc.md +10 -10
- package/docs/lib-modules.md +9 -9
- package/docs/logging.md +12 -14
- package/docs/menu.md +18 -18
- package/docs/releasing.md +4 -2
- package/docs/remote-config.md +9 -9
- package/docs/remote-scripts.md +12 -12
- package/docs/restart-manager.md +8 -8
- package/docs/runner.md +12 -10
- package/docs/sentry.md +4 -4
- package/docs/shared/analytics.md +1 -1
- package/docs/shared/brands.md +1 -1
- package/docs/shared/breaking-changes.md +79 -13
- package/docs/shared/config.md +24 -21
- package/docs/shared/deploys.md +30 -7
- package/docs/shared/local-dev.md +5 -3
- package/docs/shared/logging.md +1 -1
- package/docs/shared/monitoring.md +5 -5
- package/docs/shared/testing.md +2 -2
- package/docs/shared/theming.md +1 -1
- package/docs/shared/translation.md +19 -10
- package/docs/signing.md +1 -1
- package/docs/startup.md +16 -16
- package/docs/storage.md +11 -11
- package/docs/templating.md +3 -3
- package/docs/test-boot-layer.md +12 -12
- package/docs/test-framework.md +17 -17
- package/docs/themes.md +7 -7
- package/docs/tooltips.md +2 -2
- package/docs/tray.md +31 -31
- package/docs/usage.md +7 -7
- package/docs/verts.md +1 -1
- package/docs/windows.md +22 -22
- package/package.json +3 -4
- package/dist/lib/client-bridge.js +0 -374
- package/dist/lib/logger.js +0 -4
- package/dist/test/suites/build/manager.test.js +0 -213
- package/dist/test/suites/main/client-bridge.test.js +0 -262
package/dist/preload.js
CHANGED
|
@@ -1,195 +1,255 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Consumer entry: `
|
|
1
|
+
// The preload runtime: ONE ready-made `omega` instance.
|
|
2
|
+
// Consumer entry: `const omega = require('@omega.js/desktop/preload'); omega.initialize()`.
|
|
3
3
|
// Wires contextBridge so renderer code can call `window.desktop.ipc.invoke(...)` without nodeIntegration.
|
|
4
4
|
|
|
5
5
|
const LoggerLite = require('./lib/logger-lite.js');
|
|
6
6
|
const { ENVIRONMENT_VAR } = require('./vendor/config/environment.js');
|
|
7
|
+
const { getEnvironment, isDevelopment, isProduction, isTesting, getVersion } = require('./utils/mode-helpers.js');
|
|
8
|
+
const { getFunctionsUrl, getApiUrl, getWebsiteUrl, getAuthUrl } = require('./utils/url-helpers.js');
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The preload runtime: exposes `window.desktop` to the page. This module
|
|
12
|
+
* exports ONE instance of it; a consumer never writes `new`, and awaits
|
|
13
|
+
* `initialize()` or `ready`.
|
|
14
|
+
*/
|
|
15
|
+
class Omega {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.logger = new LoggerLite('preload');
|
|
10
18
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
// Settled by initialize() with the instance: a module that did not call
|
|
20
|
+
// initialize() can still await it
|
|
21
|
+
this._readyResolve = null;
|
|
22
|
+
this.ready = new Promise((resolve) => {
|
|
23
|
+
this._readyResolve = resolve;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
15
26
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Expose `window.desktop`, wire the activity pings and the theme applier,
|
|
29
|
+
* and settle `ready`. Async even though there's nothing to await: the API
|
|
30
|
+
* stays uniform with main + renderer, so `omega.initialize().then(...)`
|
|
31
|
+
* reads the same in every entry.
|
|
32
|
+
* @returns {Promise<Omega>} the instance.
|
|
33
|
+
*/
|
|
34
|
+
async initialize() {
|
|
35
|
+
this._expose();
|
|
20
36
|
|
|
21
|
-
|
|
37
|
+
this._readyResolve(this);
|
|
22
38
|
|
|
23
|
-
|
|
24
|
-
self.logger.warn('contextBridge / ipcRenderer not available — preload running in test mode.');
|
|
25
|
-
return self;
|
|
39
|
+
return this;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
_expose() {
|
|
43
|
+
const { contextBridge, ipcRenderer } = require('electron');
|
|
44
|
+
|
|
45
|
+
// A preload loaded outside a BrowserWindow (the build-layer tests) has no bridge to expose on
|
|
46
|
+
if (!contextBridge || !ipcRenderer) {
|
|
47
|
+
this.logger.warn('contextBridge / ipcRenderer not available: preload running in test mode.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Expose a stable, namespaced surface to the renderer.
|
|
52
|
+
// Real impl in pass 2 will type the channel list and proxy storage through here.
|
|
53
|
+
contextBridge.exposeInMainWorld('desktop', {
|
|
54
|
+
// The RUNNING environment, for the one context that cannot read it: a page has
|
|
55
|
+
// no `process`, so its instance answers `OMEGA_BUILD_JSON.config.environment`,
|
|
56
|
+
// the word the BUILD was for. A test lane boots a production artifact with
|
|
57
|
+
// `OMEGA_ENVIRONMENT=testing`, so the two differ there, and a preload is Node
|
|
58
|
+
// ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). The renderer
|
|
59
|
+
// bootstrap applies this over the baked word, so it answers what main answers.
|
|
60
|
+
environment: process.env[ENVIRONMENT_VAR] || null,
|
|
61
|
+
ipc: {
|
|
62
|
+
invoke: (channel, payload) => ipcRenderer.invoke(channel, payload),
|
|
63
|
+
// Returns an unsubscribe fn (docs/ipc.md contract, same shape as the
|
|
64
|
+
// sibling onChange subscriptions below).
|
|
65
|
+
on: (channel, handler) => {
|
|
66
|
+
const wrapped = (_, payload) => handler(payload);
|
|
67
|
+
ipcRenderer.on(channel, wrapped);
|
|
68
|
+
return () => ipcRenderer.removeListener(channel, wrapped);
|
|
69
|
+
},
|
|
70
|
+
send: (channel, payload) => ipcRenderer.send(channel, payload),
|
|
46
71
|
},
|
|
47
|
-
|
|
48
|
-
},
|
|
49
|
-
storage:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return () => ipcRenderer.removeListener('desktop:storage:change', wrapped);
|
|
72
|
+
storage: {
|
|
73
|
+
get: (key, def) => ipcRenderer.invoke('desktop:storage:get', { key, def }),
|
|
74
|
+
set: (key, val) => ipcRenderer.invoke('desktop:storage:set', { key, val }),
|
|
75
|
+
delete: (key) => ipcRenderer.invoke('desktop:storage:delete', { key }),
|
|
76
|
+
has: (key) => ipcRenderer.invoke('desktop:storage:has', { key }),
|
|
77
|
+
clear: () => ipcRenderer.invoke('desktop:storage:clear'),
|
|
78
|
+
// Subscribe to changes broadcast from main. Returns an unsubscribe fn.
|
|
79
|
+
// Pass '*' as key to receive all changes.
|
|
80
|
+
onChange: (key, handler) => {
|
|
81
|
+
const wrapped = (_, payload) => {
|
|
82
|
+
if (key === '*' || payload?.key === key) {
|
|
83
|
+
handler(payload);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
ipcRenderer.on('desktop:storage:change', wrapped);
|
|
87
|
+
return () => ipcRenderer.removeListener('desktop:storage:change', wrapped);
|
|
88
|
+
},
|
|
65
89
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
// Theme: system-aware appearance. get/set proxy to main (lib/theme.js owns
|
|
91
|
+
// nativeTheme.themeSource + persistence). onChange is MATCHMEDIA-powered, not an
|
|
92
|
+
// IPC broadcast: setting themeSource flips `prefers-color-scheme` in every
|
|
93
|
+
// renderer of the app (including embedded WebContentsViews, which ipc.broadcast
|
|
94
|
+
// can never reach), so each renderer self-resolves. Returns an unsubscribe fn.
|
|
95
|
+
theme: {
|
|
96
|
+
get: () => ipcRenderer.invoke('desktop:theme:get'),
|
|
97
|
+
set: (source) => ipcRenderer.invoke('desktop:theme:set', { source }),
|
|
98
|
+
onChange: (handler) => {
|
|
99
|
+
const media = window.matchMedia('(prefers-color-scheme: dark)');
|
|
100
|
+
const wrapped = (e) => handler({ resolved: e.matches ? 'dark' : 'light' });
|
|
101
|
+
media.addEventListener('change', wrapped);
|
|
102
|
+
return () => media.removeEventListener('change', wrapped);
|
|
103
|
+
},
|
|
80
104
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
get: (name, style) => ipcRenderer.invoke('desktop:fontawesome:get', { name, style }).then((r) => r?.svg ?? null),
|
|
87
|
-
},
|
|
88
|
-
// Renderer logger — writes to console (visible in DevTools) AND forwards each
|
|
89
|
-
// call to main where it's written through electron-log's file transport. Same
|
|
90
|
-
// file (logs/runtime.log in dev, OS logs/<AppName>/runtime.log in prod) where
|
|
91
|
-
// main + preload logs land too. Each entry is scoped 'renderer' so you can
|
|
92
|
-
// grep for renderer-only output.
|
|
93
|
-
logger: makeForwardingLogger('renderer', ipcRenderer),
|
|
94
|
-
autoUpdater: {
|
|
95
|
-
getStatus: () => ipcRenderer.invoke('desktop:auto-updater:status'),
|
|
96
|
-
checkNow: () => ipcRenderer.invoke('desktop:auto-updater:check-now'),
|
|
97
|
-
installNow: () => ipcRenderer.invoke('desktop:auto-updater:install-now'),
|
|
98
|
-
// Subscribe to status broadcasts. Returns an unsubscribe fn.
|
|
99
|
-
onStatus: (handler) => {
|
|
100
|
-
const wrapped = (_, payload) => handler(payload);
|
|
101
|
-
ipcRenderer.on('desktop:auto-updater:status', wrapped);
|
|
102
|
-
return () => ipcRenderer.removeListener('desktop:auto-updater:status', wrapped);
|
|
105
|
+
// FontAwesome: resolve a bundled icon to its inline-SVG string (or null).
|
|
106
|
+
// Renderer code rarely needs this directly: @omega.js/desktop's renderer bootstrap
|
|
107
|
+
// auto-renders `<i class="fa-solid fa-*">` elements (see src/renderer.js).
|
|
108
|
+
fontawesome: {
|
|
109
|
+
get: (name, style) => ipcRenderer.invoke('desktop:fontawesome:get', { name, style }).then((r) => r?.svg ?? null),
|
|
103
110
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
usage: {
|
|
121
|
-
get: () => ipcRenderer.invoke('desktop:usage:get'),
|
|
122
|
-
},
|
|
123
|
-
// Hot config — same get/refreshNow surface as main, plus an onUpdate
|
|
124
|
-
// subscription that fires whenever main re-fetches successfully.
|
|
125
|
-
remoteConfig: {
|
|
126
|
-
get: (path) => ipcRenderer.invoke('desktop:remote-config:get', path),
|
|
127
|
-
refreshNow: () => ipcRenderer.invoke('desktop:remote-config:refresh-now'),
|
|
128
|
-
onUpdate: (handler) => {
|
|
129
|
-
const wrapped = (_, payload) => handler(payload);
|
|
130
|
-
ipcRenderer.on('desktop:remote-config:update', wrapped);
|
|
131
|
-
return () => ipcRenderer.removeListener('desktop:remote-config:update', wrapped);
|
|
111
|
+
// Renderer logger: writes to console (visible in DevTools) AND forwards each
|
|
112
|
+
// call to main where it's written through electron-log's file transport. Same
|
|
113
|
+
// file (logs/runtime.log in dev, OS logs/<AppName>/runtime.log in prod) where
|
|
114
|
+
// main + preload logs land too. Each entry is scoped 'renderer' so you can
|
|
115
|
+
// grep for renderer-only output.
|
|
116
|
+
logger: makeForwardingLogger('renderer', ipcRenderer),
|
|
117
|
+
autoUpdater: {
|
|
118
|
+
getStatus: () => ipcRenderer.invoke('desktop:auto-updater:status'),
|
|
119
|
+
checkNow: () => ipcRenderer.invoke('desktop:auto-updater:check-now'),
|
|
120
|
+
installNow: () => ipcRenderer.invoke('desktop:auto-updater:install-now'),
|
|
121
|
+
// Subscribe to status broadcasts. Returns an unsubscribe fn.
|
|
122
|
+
onStatus: (handler) => {
|
|
123
|
+
const wrapped = (_, payload) => handler(payload);
|
|
124
|
+
ipcRenderer.on('desktop:auto-updater:status', wrapped);
|
|
125
|
+
return () => ipcRenderer.removeListener('desktop:auto-updater:status', wrapped);
|
|
126
|
+
},
|
|
132
127
|
},
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
// GA4 analytics: fire-and-forget event sender. Same shape as on main, just
|
|
129
|
+
// routes through IPC so renderer code is identical.
|
|
130
|
+
analytics: {
|
|
131
|
+
event: (name, params) => ipcRenderer.send('desktop:analytics:event', { name, params }),
|
|
132
|
+
pageview: (path) => ipcRenderer.send('desktop:analytics:event', { name: 'page_view', params: path ? { page_path: path } : {} }),
|
|
133
|
+
screenview: (screenName) => ipcRenderer.send('desktop:analytics:event', { name: 'screen_view', params: screenName ? { screen_name: screenName } : {} }),
|
|
134
|
+
setUserProperties: (props) => ipcRenderer.send('desktop:analytics:set-user-properties', props),
|
|
135
|
+
getStatus: () => ipcRenderer.invoke('desktop:analytics:status'),
|
|
136
|
+
},
|
|
137
|
+
// Runtime context (geolocation / client / session / app). Read once at
|
|
138
|
+
// renderer init or whenever fresh values are needed.
|
|
139
|
+
context: {
|
|
140
|
+
get: () => ipcRenderer.invoke('desktop:context:get'),
|
|
141
|
+
},
|
|
142
|
+
// Usage stats (opens / hoursTotal / hoursThisSession).
|
|
143
|
+
usage: {
|
|
144
|
+
get: () => ipcRenderer.invoke('desktop:usage:get'),
|
|
145
|
+
},
|
|
146
|
+
// Hot config: same get/refreshNow surface as main, plus an onUpdate
|
|
147
|
+
// subscription that fires whenever main re-fetches successfully.
|
|
148
|
+
remoteConfig: {
|
|
149
|
+
get: (path) => ipcRenderer.invoke('desktop:remote-config:get', path),
|
|
150
|
+
refreshNow: () => ipcRenderer.invoke('desktop:remote-config:refresh-now'),
|
|
151
|
+
onUpdate: (handler) => {
|
|
152
|
+
const wrapped = (_, payload) => handler(payload);
|
|
153
|
+
ipcRenderer.on('desktop:remote-config:update', wrapped);
|
|
154
|
+
return () => ipcRenderer.removeListener('desktop:remote-config:update', wrapped);
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
135
158
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
} catch (e) { /* DOM not available (test mode) — skip */ }
|
|
160
|
-
|
|
161
|
-
// Theme applier — keeps `<html data-bs-theme>` matched to the RESOLVED appearance
|
|
162
|
-
// ('light'/'dark'), live, on every framework-templated page. Opt-in by presence: only pages
|
|
163
|
-
// that already carry the attribute (stamped by the page template at build) are
|
|
164
|
-
// managed — pages without it (e.g. external sites loaded in a consumer's embedded
|
|
165
|
-
// web views, which get this same preload) are never touched.
|
|
166
|
-
//
|
|
167
|
-
// This is the live-update path for ALL renderers: main flips nativeTheme.themeSource
|
|
168
|
-
// → `prefers-color-scheme` flips here → matchMedia 'change' fires → re-apply. No IPC.
|
|
169
|
-
try {
|
|
170
|
-
const media = window.matchMedia('(prefers-color-scheme: dark)');
|
|
171
|
-
const apply = () => {
|
|
172
|
-
const root = document.documentElement;
|
|
173
|
-
if (!root || !root.hasAttribute('data-bs-theme')) {
|
|
174
|
-
return;
|
|
159
|
+
// Auto-updater activity tracking: listen for renderer-side mouse / keyboard / wheel
|
|
160
|
+
// / focus events and debounce-fire an `desktop:auto-updater:activity` IPC ping to main.
|
|
161
|
+
// Main uses these pings to keep `lastActivityAt` fresh so a downloaded update only
|
|
162
|
+
// auto-installs when the user has been idle for 15+ minutes.
|
|
163
|
+
//
|
|
164
|
+
// Debounced to once per 5s, anything more granular is just noise (the threshold is
|
|
165
|
+
// 15 min; sub-second precision doesn't matter). Listeners attach in `capture` phase
|
|
166
|
+
// on `window` so renderer code can't accidentally suppress them via stopPropagation.
|
|
167
|
+
try {
|
|
168
|
+
let lastPing = 0;
|
|
169
|
+
const ACTIVITY_DEBOUNCE_MS = 5000;
|
|
170
|
+
const ping = () => {
|
|
171
|
+
const now = Date.now();
|
|
172
|
+
if (now - lastPing < ACTIVITY_DEBOUNCE_MS) return;
|
|
173
|
+
lastPing = now;
|
|
174
|
+
try { ipcRenderer.send('desktop:auto-updater:activity'); } catch (e) { /* ignore */ }
|
|
175
|
+
};
|
|
176
|
+
const events = ['mousedown', 'keydown', 'wheel', 'touchstart', 'focus'];
|
|
177
|
+
for (const ev of events) {
|
|
178
|
+
// `passive: true` so we never accidentally block scrolling; `capture: true` so we
|
|
179
|
+
// see the event before any renderer-side handler can stopPropagation it.
|
|
180
|
+
window.addEventListener(ev, ping, { passive: true, capture: true });
|
|
175
181
|
}
|
|
176
|
-
|
|
177
|
-
};
|
|
182
|
+
} catch (e) { /* DOM not available (test mode), skip */ }
|
|
178
183
|
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
// Theme applier: keeps `<html data-bs-theme>` matched to the RESOLVED appearance
|
|
185
|
+
// ('light'/'dark'), live, on every framework-templated page. Opt-in by presence: only pages
|
|
186
|
+
// that already carry the attribute (stamped by the page template at build) are
|
|
187
|
+
// managed: pages without it (e.g. external sites loaded in a consumer's embedded
|
|
188
|
+
// web views, which get this same preload) are never touched.
|
|
189
|
+
//
|
|
190
|
+
// This is the live-update path for ALL renderers: main flips nativeTheme.themeSource
|
|
191
|
+
// → `prefers-color-scheme` flips here → matchMedia 'change' fires → re-apply. No IPC.
|
|
192
|
+
try {
|
|
193
|
+
const media = window.matchMedia('(prefers-color-scheme: dark)');
|
|
194
|
+
const apply = () => {
|
|
195
|
+
const root = document.documentElement;
|
|
196
|
+
if (!root || !root.hasAttribute('data-bs-theme')) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
root.setAttribute('data-bs-theme', media.matches ? 'dark' : 'light');
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// The stamped attribute only exists once the HTML has parsed: apply at
|
|
203
|
+
// DOMContentLoaded (or immediately when the document is already past it).
|
|
204
|
+
if (document.readyState === 'loading') {
|
|
205
|
+
document.addEventListener('DOMContentLoaded', apply, { once: true });
|
|
206
|
+
} else {
|
|
207
|
+
apply();
|
|
208
|
+
}
|
|
209
|
+
media.addEventListener('change', apply);
|
|
210
|
+
} catch (e) { /* DOM not available (test mode), skip */ }
|
|
188
211
|
|
|
189
|
-
|
|
212
|
+
this.logger.log('@omega.js/desktop (preload) initialized.');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// The environment surface (#817) and the backend URL helpers: the same plain
|
|
216
|
+
// functions main and the build module call
|
|
217
|
+
getEnvironment() {
|
|
218
|
+
return getEnvironment.call(this);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
isDevelopment() {
|
|
222
|
+
return isDevelopment.call(this);
|
|
223
|
+
}
|
|
190
224
|
|
|
191
|
-
|
|
192
|
-
|
|
225
|
+
isProduction() {
|
|
226
|
+
return isProduction.call(this);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
isTesting() {
|
|
230
|
+
return isTesting.call(this);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
getVersion() {
|
|
234
|
+
return getVersion();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
getFunctionsUrl(environment) {
|
|
238
|
+
return getFunctionsUrl(this, environment);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getApiUrl(environment) {
|
|
242
|
+
return getApiUrl(this, environment);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getWebsiteUrl(environment) {
|
|
246
|
+
return getWebsiteUrl(this, environment);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
getAuthUrl(environment, returnUrl) {
|
|
250
|
+
return getAuthUrl(this, environment, returnUrl);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
193
253
|
|
|
194
254
|
// Build a console+forward logger object suitable for exposing through contextBridge
|
|
195
255
|
// to the renderer. Each method:
|
|
@@ -209,7 +269,7 @@ function makeForwardingLogger(scope, ipcRenderer) {
|
|
|
209
269
|
const fileLevel = m === 'log' ? 'info' : m;
|
|
210
270
|
out[m] = function () {
|
|
211
271
|
// Console first.
|
|
212
|
-
const args = ['[
|
|
272
|
+
const args = ['[omega]', ...Array.from(arguments)];
|
|
213
273
|
const fn = console[m] || console.log;
|
|
214
274
|
try { fn.apply(console, args); } catch (e) { /* ignore */ }
|
|
215
275
|
// Forward to main.
|
|
@@ -242,8 +302,8 @@ function serializeForIpc(args) {
|
|
|
242
302
|
});
|
|
243
303
|
}
|
|
244
304
|
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
require('./utils/url-helpers.js').attachTo(Manager);
|
|
305
|
+
// The ONE instance, initialized by the consumer's src/preload.js
|
|
306
|
+
const omega = new Omega();
|
|
248
307
|
|
|
249
|
-
module.exports =
|
|
308
|
+
module.exports = omega;
|
|
309
|
+
module.exports.Omega = Omega;
|