@raydiant/playlist-window-manager 0.27.1 → 0.27.3-rc.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/build/BrowserWindowRenderer.d.ts +1 -0
- package/build/BrowserWindowRenderer.js +9 -2
- package/build/PlaylistWindowManager.d.ts +2 -0
- package/build/PlaylistWindowManager.js +9 -0
- package/build/PresentationWindow.d.ts +2 -0
- package/build/PresentationWindow.js +12 -0
- package/build/embeddedApps.js +2 -0
- package/build/embeddedApps.test.js +8 -0
- package/build/preload.js +102 -1
- package/build/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/BrowserWindowRenderer.ts +13 -2
- package/src/PlaylistWindowManager.ts +14 -0
- package/src/PresentationWindow.ts +16 -0
- package/src/embeddedApps.test.ts +15 -0
- package/src/embeddedApps.ts +1 -0
- package/src/preload.ts +122 -1
- package/src/types.ts +5 -0
|
@@ -31,6 +31,7 @@ export default class BrowserWindowRenderer implements PresentationWindowRenderer
|
|
|
31
31
|
removeWindow(windowId: string): Promise<void>;
|
|
32
32
|
sendMessageString(windowId: string, message: string): void;
|
|
33
33
|
sendMessageObject(windowId: string, type: string, payload?: any): void;
|
|
34
|
+
sendOnlineStatus(windowId: string, isOnline: boolean): void;
|
|
34
35
|
muteWindow(windowId: string): void;
|
|
35
36
|
unMuteWindow(windowId: string): void;
|
|
36
37
|
private getWindow;
|
|
@@ -90,7 +90,7 @@ var BrowserWindowRenderer = /** @class */ (function () {
|
|
|
90
90
|
* This option fixes window not being able to take fullscreen leaving
|
|
91
91
|
* 1px gap at the right and bottom of the screen.
|
|
92
92
|
*/
|
|
93
|
-
resizable: false,
|
|
93
|
+
// resizable: false,
|
|
94
94
|
frame: this.opts.frame,
|
|
95
95
|
hasShadow: this.opts.hasShadow,
|
|
96
96
|
webPreferences: {
|
|
@@ -133,7 +133,7 @@ var BrowserWindowRenderer = /** @class */ (function () {
|
|
|
133
133
|
* This option fixes window not being able to take fullscreen leaving
|
|
134
134
|
* 1px gap at the right and bottom of the screen.
|
|
135
135
|
*/
|
|
136
|
-
resizable: false,
|
|
136
|
+
// resizable: false,
|
|
137
137
|
frame: this.opts.frame,
|
|
138
138
|
// NOTE: useWindowPool: true does not work with renderChildWindowsAsBrowserViews: false
|
|
139
139
|
// because the parent can't be changed after creating the BrowserWindow.
|
|
@@ -320,6 +320,13 @@ var BrowserWindowRenderer = /** @class */ (function () {
|
|
|
320
320
|
}
|
|
321
321
|
window.view.webContents.send('electron-main', { type: type, payload: payload });
|
|
322
322
|
};
|
|
323
|
+
BrowserWindowRenderer.prototype.sendOnlineStatus = function (windowId, isOnline) {
|
|
324
|
+
var window = this.getWindow(windowId);
|
|
325
|
+
if (!window) {
|
|
326
|
+
throw new Error("Failed to send isOnline status to window, missing window id '".concat(windowId, "'"));
|
|
327
|
+
}
|
|
328
|
+
window.view.webContents.send('online-status', isOnline);
|
|
329
|
+
};
|
|
323
330
|
BrowserWindowRenderer.prototype.muteWindow = function (windowId) {
|
|
324
331
|
var window = this.getWindow(windowId);
|
|
325
332
|
if (!window) {
|
|
@@ -20,6 +20,7 @@ export interface PlaylistWindowManagerOptions {
|
|
|
20
20
|
onEnableInterruptLock?: () => void;
|
|
21
21
|
onDisableInterruptLock?: () => void;
|
|
22
22
|
getTerminal?: () => Terminal | null;
|
|
23
|
+
getOnlineStatus?: () => boolean;
|
|
23
24
|
}
|
|
24
25
|
export default class PlaylistWindowManager extends EventEmitter {
|
|
25
26
|
private options;
|
|
@@ -80,6 +81,7 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
80
81
|
sendChargeResponse(response: ChargeResponse): void;
|
|
81
82
|
sendCharge(charge: Charge): void;
|
|
82
83
|
sendTerminal(terminal: Terminal | null): void;
|
|
84
|
+
sendOnlineStatus(isOnline: boolean): void;
|
|
83
85
|
private createWindow;
|
|
84
86
|
private loadCurrentWindow;
|
|
85
87
|
private shouldPreload;
|
|
@@ -676,6 +676,14 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
|
|
|
676
676
|
this.nextWindow.sendTerminal(terminal);
|
|
677
677
|
}
|
|
678
678
|
};
|
|
679
|
+
PlaylistWindowManager.prototype.sendOnlineStatus = function (isOnline) {
|
|
680
|
+
if (this.currentWindow) {
|
|
681
|
+
this.currentWindow.sendOnlineStatus(isOnline);
|
|
682
|
+
}
|
|
683
|
+
if (this.nextWindow) {
|
|
684
|
+
this.nextWindow.sendOnlineStatus(isOnline);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
679
687
|
PlaylistWindowManager.prototype.createWindow = function (pr) {
|
|
680
688
|
var _a = this.options, readyTimeoutDurationSeconds = _a.readyTimeoutDurationSeconds, appRendererUrl = _a.appRendererUrl, appRendererOfflineSupport = _a.appRendererOfflineSupport, backgroundColor = _a.backgroundColor, device = _a.device, logger = _a.logger, windowName = _a.windowName, parentWindowId = _a.parentWindowId, isPreview = _a.isPreview;
|
|
681
689
|
if (!this.ruleEngine) {
|
|
@@ -721,6 +729,7 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
|
|
|
721
729
|
isPreview: isPreview,
|
|
722
730
|
workerState: this.workerState,
|
|
723
731
|
getTerminal: this.options.getTerminal,
|
|
732
|
+
getOnlineStatus: this.options.getOnlineStatus,
|
|
724
733
|
});
|
|
725
734
|
};
|
|
726
735
|
PlaylistWindowManager.prototype.loadCurrentWindow = function () {
|
|
@@ -33,6 +33,7 @@ export interface PresentationWindowOptions {
|
|
|
33
33
|
[key: string]: string;
|
|
34
34
|
}) => void;
|
|
35
35
|
getTerminal?: () => Terminal | null;
|
|
36
|
+
getOnlineStatus?: () => boolean;
|
|
36
37
|
}
|
|
37
38
|
export default class PresentationWindow {
|
|
38
39
|
private options;
|
|
@@ -102,6 +103,7 @@ export default class PresentationWindow {
|
|
|
102
103
|
sendChargeResponse(response: ChargeResponse): void;
|
|
103
104
|
sendCharge(charge: Charge): void;
|
|
104
105
|
sendTerminal(terminal: Terminal | null): void;
|
|
106
|
+
sendOnlineStatus(isOnline: boolean): void;
|
|
105
107
|
private isEmbeddedApp;
|
|
106
108
|
private allChildWindowManagersReady;
|
|
107
109
|
private checkIsReadyCallback;
|
|
@@ -755,6 +755,17 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
755
755
|
return wm.sendTerminal(terminal);
|
|
756
756
|
});
|
|
757
757
|
};
|
|
758
|
+
PresentationWindow.prototype.sendOnlineStatus = function (isOnline) {
|
|
759
|
+
var _a = this.options, windowId = _a.windowId, renderer = _a.renderer;
|
|
760
|
+
// Send online-status event. This Separate from sendMessageObject since we
|
|
761
|
+
// are bypassing Raydiant SDK message receivers.
|
|
762
|
+
if (renderer.sendOnlineStatus) {
|
|
763
|
+
renderer.sendOnlineStatus(windowId, isOnline);
|
|
764
|
+
}
|
|
765
|
+
Object.values(this.windowManagers).forEach(function (wm) {
|
|
766
|
+
wm.sendOnlineStatus(isOnline);
|
|
767
|
+
});
|
|
768
|
+
};
|
|
758
769
|
PresentationWindow.prototype.isEmbeddedApp = function () {
|
|
759
770
|
var _a = this.options, applicationVersion = _a.applicationVersion, isPreview = _a.isPreview;
|
|
760
771
|
// If the application has a source url, always use it for rendering the preview.
|
|
@@ -1068,6 +1079,7 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
1068
1079
|
}
|
|
1069
1080
|
},
|
|
1070
1081
|
getTerminal: this.options.getTerminal,
|
|
1082
|
+
getOnlineStatus: this.options.getOnlineStatus,
|
|
1071
1083
|
});
|
|
1072
1084
|
// Hook up child window manager events to bubble up to the parent.
|
|
1073
1085
|
if (parentWindowManager) {
|
package/build/embeddedApps.js
CHANGED
|
@@ -56,6 +56,8 @@ function createEmbeddedApp(presentation, applicationVersion, metadata) {
|
|
|
56
56
|
value = presentation.applicationVariables[queryParamName];
|
|
57
57
|
if (value === undefined)
|
|
58
58
|
value = '';
|
|
59
|
+
if (value === null)
|
|
60
|
+
value = '';
|
|
59
61
|
if (Array.isArray(value)) {
|
|
60
62
|
value = JSON.stringify(value);
|
|
61
63
|
}
|
|
@@ -149,3 +149,11 @@ test('Replaces $deviceId with empty string when in the query string and metadata
|
|
|
149
149
|
});
|
|
150
150
|
expect((0, embeddedApps_1.default)(presentation, applicationVersion, createMetadata())).toBe("https://example.com/content?device=");
|
|
151
151
|
});
|
|
152
|
+
test('Replaces null with empty string', function () {
|
|
153
|
+
expect((0, embeddedApps_1.default)(createPresentation({
|
|
154
|
+
applicationVariables: { file: null },
|
|
155
|
+
}), createApplicationVersion({
|
|
156
|
+
embeddedUrlFormat: "https://example.come?image=:file",
|
|
157
|
+
presentationProperties: [{ type: 'file', name: 'file' }],
|
|
158
|
+
}), createMetadata())).toBe("https://example.come?image=");
|
|
159
|
+
});
|
package/build/preload.js
CHANGED
|
@@ -4,7 +4,7 @@ var electron_1 = require("electron");
|
|
|
4
4
|
var internals = {
|
|
5
5
|
sendMessage: function (windowId, type, payload) {
|
|
6
6
|
electron_1.ipcRenderer.send(windowId, type, payload);
|
|
7
|
-
}
|
|
7
|
+
},
|
|
8
8
|
};
|
|
9
9
|
// Set __RAYDIANT_INTERNALS on window so it is accessible in to the running application.
|
|
10
10
|
window.__RAYDIANT_INTERNALS = internals;
|
|
@@ -18,3 +18,104 @@ electron_1.ipcRenderer.on('electron-main', function (_, message) {
|
|
|
18
18
|
console.error('Failed to handle message from main process, receiveMessage is not defined');
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
|
+
// Create a custom event that mimics the behavior of the native online/offline events.
|
|
22
|
+
function makeWindowEvent(type) {
|
|
23
|
+
var event = new Event(type);
|
|
24
|
+
Object.defineProperty(event, 'srcElement', {
|
|
25
|
+
get: function () { return window; },
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(event, 'target', {
|
|
28
|
+
get: function () { return window; },
|
|
29
|
+
});
|
|
30
|
+
return event;
|
|
31
|
+
}
|
|
32
|
+
// Synchronously get the initial online status. This is handled in photon by the renderer
|
|
33
|
+
// service. Calling sendSync avoids a flash of incorrect status when loading or refreshing
|
|
34
|
+
// the page.
|
|
35
|
+
var isOnline = electron_1.ipcRenderer.sendSync('get-online-status');
|
|
36
|
+
// Listen for online status changes from the main process.
|
|
37
|
+
electron_1.ipcRenderer.on('online-status', function (_, nextIsOnline) {
|
|
38
|
+
console.log("Online status: ".concat(nextIsOnline));
|
|
39
|
+
if (nextIsOnline !== isOnline) {
|
|
40
|
+
console.log('Online status changed, updating navigator.onLine');
|
|
41
|
+
isOnline = nextIsOnline;
|
|
42
|
+
var events_1 = makeWindowEvent(isOnline ? 'online' : 'offline');
|
|
43
|
+
var listeners = isOnline ? onlineListeners : offlineListeners;
|
|
44
|
+
console.log("Running ".concat(isOnline ? 'online' : 'offline', " listeners, count: ").concat(listeners.size));
|
|
45
|
+
listeners.forEach(function (listener) {
|
|
46
|
+
if (typeof listener === 'function') {
|
|
47
|
+
listener(events_1);
|
|
48
|
+
}
|
|
49
|
+
else if (listener.handleEvent) {
|
|
50
|
+
listener.handleEvent(events_1);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
// Replace navigator.onLine with our implementation that uses a the device’s local connectivity
|
|
56
|
+
// service. This will allow apps to receive an accurate and reliable value for navigator.onLine
|
|
57
|
+
// when running on the device.
|
|
58
|
+
Object.defineProperty(navigator, 'onLine', {
|
|
59
|
+
get: function () {
|
|
60
|
+
console.log("navigator.onLine called, returning ".concat(isOnline));
|
|
61
|
+
return isOnline;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
var offlineListeners = new Set();
|
|
65
|
+
var onlineListeners = new Set();
|
|
66
|
+
var originalAddEventListener = window.addEventListener.bind(window);
|
|
67
|
+
Object.defineProperty(window, 'addEventListener', {
|
|
68
|
+
value: function (type, listener) {
|
|
69
|
+
if (type === 'online') {
|
|
70
|
+
console.log("Intercepted online addEventListener");
|
|
71
|
+
onlineListeners.add(listener);
|
|
72
|
+
}
|
|
73
|
+
else if (type === 'offline') {
|
|
74
|
+
console.log("Intercepted offline addEventListener");
|
|
75
|
+
offlineListeners.add(listener);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return originalAddEventListener(type, listener);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
var originalRemoveEventListener = window.removeEventListener.bind(window);
|
|
83
|
+
Object.defineProperty(window, 'removeEventListener', {
|
|
84
|
+
value: function (type, listener) {
|
|
85
|
+
if (type === 'online') {
|
|
86
|
+
console.log("Intercepted online removeEventListener");
|
|
87
|
+
onlineListeners.delete(listener);
|
|
88
|
+
}
|
|
89
|
+
else if (type === 'offline') {
|
|
90
|
+
console.log("Intercepted offline removeEventListener");
|
|
91
|
+
offlineListeners.delete(listener);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return originalRemoveEventListener(type, listener);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
// // TODO: Remove this (for local dev only).
|
|
99
|
+
// (window as any).simulateOnline = () => {
|
|
100
|
+
// isOnline = true;
|
|
101
|
+
// console.log(`Running online listeners, count: ${onlineListeners.size}`);
|
|
102
|
+
// onlineListeners.forEach((listener) => {
|
|
103
|
+
// if (typeof listener === 'function') {
|
|
104
|
+
// listener(makeWindowEvent('online'));
|
|
105
|
+
// } else if (listener.handleEvent) {
|
|
106
|
+
// listener.handleEvent(makeWindowEvent('online'));
|
|
107
|
+
// }
|
|
108
|
+
// });
|
|
109
|
+
// };
|
|
110
|
+
// // TODO: Remove this (for local dev only).
|
|
111
|
+
// (window as any).simulateOffline = () => {
|
|
112
|
+
// isOnline = false;
|
|
113
|
+
// console.log(`Running offline listeners, count: ${offlineListeners.size}`);
|
|
114
|
+
// offlineListeners.forEach((listener) => {
|
|
115
|
+
// if (typeof listener === 'function') {
|
|
116
|
+
// listener(makeWindowEvent('offline'));
|
|
117
|
+
// } else if (listener.handleEvent) {
|
|
118
|
+
// listener.handleEvent(makeWindowEvent('offline'));
|
|
119
|
+
// }
|
|
120
|
+
// });
|
|
121
|
+
// };
|
package/build/types.d.ts
CHANGED
|
@@ -112,6 +112,7 @@ export interface PresentationWindowRenderer {
|
|
|
112
112
|
sendMessageObject(windowId: string, type: string, payload?: any): void;
|
|
113
113
|
muteWindow(windowId: string): void;
|
|
114
114
|
unMuteWindow(windowId: string): void;
|
|
115
|
+
sendOnlineStatus?(windowId: string, isOnline: boolean): void;
|
|
115
116
|
}
|
|
116
117
|
export interface OpenChildWindowOptions {
|
|
117
118
|
windowId: string;
|
package/package.json
CHANGED
|
@@ -67,7 +67,7 @@ export default class BrowserWindowRenderer
|
|
|
67
67
|
* This option fixes window not being able to take fullscreen leaving
|
|
68
68
|
* 1px gap at the right and bottom of the screen.
|
|
69
69
|
*/
|
|
70
|
-
resizable: false,
|
|
70
|
+
// resizable: false,
|
|
71
71
|
frame: this.opts.frame,
|
|
72
72
|
hasShadow: this.opts.hasShadow,
|
|
73
73
|
webPreferences: {
|
|
@@ -119,7 +119,7 @@ export default class BrowserWindowRenderer
|
|
|
119
119
|
* This option fixes window not being able to take fullscreen leaving
|
|
120
120
|
* 1px gap at the right and bottom of the screen.
|
|
121
121
|
*/
|
|
122
|
-
resizable: false,
|
|
122
|
+
// resizable: false,
|
|
123
123
|
frame: this.opts.frame,
|
|
124
124
|
// NOTE: useWindowPool: true does not work with renderChildWindowsAsBrowserViews: false
|
|
125
125
|
// because the parent can't be changed after creating the BrowserWindow.
|
|
@@ -348,6 +348,17 @@ export default class BrowserWindowRenderer
|
|
|
348
348
|
window.view.webContents.send('electron-main', { type, payload });
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
public sendOnlineStatus(windowId: string, isOnline: boolean) {
|
|
352
|
+
const window = this.getWindow(windowId);
|
|
353
|
+
if (!window) {
|
|
354
|
+
throw new Error(
|
|
355
|
+
`Failed to send isOnline status to window, missing window id '${windowId}'`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
window.view.webContents.send('online-status', isOnline);
|
|
360
|
+
}
|
|
361
|
+
|
|
351
362
|
public muteWindow(windowId: string) {
|
|
352
363
|
const window = this.getWindow(windowId);
|
|
353
364
|
if (!window) {
|
|
@@ -78,6 +78,9 @@ export interface PlaylistWindowManagerOptions {
|
|
|
78
78
|
|
|
79
79
|
// Called when a window needs the current terminal object.
|
|
80
80
|
getTerminal?: () => Terminal | null;
|
|
81
|
+
|
|
82
|
+
// Called when a window needs to check if the device is online.
|
|
83
|
+
getOnlineStatus?: () => boolean;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
// Wait at least 3 seconds before restarting or moving onto the next window
|
|
@@ -488,6 +491,16 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
488
491
|
}
|
|
489
492
|
}
|
|
490
493
|
|
|
494
|
+
public sendOnlineStatus(isOnline: boolean) {
|
|
495
|
+
if (this.currentWindow) {
|
|
496
|
+
this.currentWindow.sendOnlineStatus(isOnline);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (this.nextWindow) {
|
|
500
|
+
this.nextWindow.sendOnlineStatus(isOnline);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
491
504
|
private createWindow(pr: RE.NextPresentationID): PresentationWindow {
|
|
492
505
|
const {
|
|
493
506
|
readyTimeoutDurationSeconds,
|
|
@@ -555,6 +568,7 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
555
568
|
isPreview,
|
|
556
569
|
workerState: this.workerState,
|
|
557
570
|
getTerminal: this.options.getTerminal,
|
|
571
|
+
getOnlineStatus: this.options.getOnlineStatus,
|
|
558
572
|
});
|
|
559
573
|
}
|
|
560
574
|
|
|
@@ -59,6 +59,7 @@ export interface PresentationWindowOptions {
|
|
|
59
59
|
string: { [key: string]: string }
|
|
60
60
|
) => void;
|
|
61
61
|
getTerminal?: () => Terminal | null;
|
|
62
|
+
getOnlineStatus?: () => boolean;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
// TODO: Automatically inject latest version when building in CI.
|
|
@@ -525,6 +526,20 @@ export default class PresentationWindow {
|
|
|
525
526
|
);
|
|
526
527
|
}
|
|
527
528
|
|
|
529
|
+
public sendOnlineStatus(isOnline: boolean) {
|
|
530
|
+
const { windowId, renderer } = this.options;
|
|
531
|
+
// Send online-status event. This Separate from sendMessageObject since we
|
|
532
|
+
// are bypassing Raydiant SDK message receivers.
|
|
533
|
+
|
|
534
|
+
if (renderer.sendOnlineStatus) {
|
|
535
|
+
renderer.sendOnlineStatus(windowId, isOnline);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
Object.values(this.windowManagers).forEach((wm) => {
|
|
539
|
+
wm.sendOnlineStatus(isOnline);
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
528
543
|
private isEmbeddedApp() {
|
|
529
544
|
const { applicationVersion, isPreview } = this.options;
|
|
530
545
|
|
|
@@ -876,6 +891,7 @@ export default class PresentationWindow {
|
|
|
876
891
|
}
|
|
877
892
|
},
|
|
878
893
|
getTerminal: this.options.getTerminal,
|
|
894
|
+
getOnlineStatus: this.options.getOnlineStatus,
|
|
879
895
|
});
|
|
880
896
|
|
|
881
897
|
// Hook up child window manager events to bubble up to the parent.
|
package/src/embeddedApps.test.ts
CHANGED
|
@@ -277,3 +277,18 @@ test('Replaces $deviceId with empty string when in the query string and metadata
|
|
|
277
277
|
createEmbeddedApp(presentation, applicationVersion, createMetadata())
|
|
278
278
|
).toBe(`https://example.com/content?device=`);
|
|
279
279
|
});
|
|
280
|
+
|
|
281
|
+
test('Replaces null with empty string', () => {
|
|
282
|
+
expect(
|
|
283
|
+
createEmbeddedApp(
|
|
284
|
+
createPresentation({
|
|
285
|
+
applicationVariables: { file: null },
|
|
286
|
+
}),
|
|
287
|
+
createApplicationVersion({
|
|
288
|
+
embeddedUrlFormat: `https://example.come?image=:file`,
|
|
289
|
+
presentationProperties: [{ type: 'file', name: 'file' }],
|
|
290
|
+
}),
|
|
291
|
+
createMetadata()
|
|
292
|
+
)
|
|
293
|
+
).toBe(`https://example.come?image=`);
|
|
294
|
+
});
|
package/src/embeddedApps.ts
CHANGED
package/src/preload.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface RaydiantInternals {
|
|
|
8
8
|
const internals: RaydiantInternals = {
|
|
9
9
|
sendMessage: (windowId: string, type: string, payload?: any) => {
|
|
10
10
|
ipcRenderer.send(windowId, type, payload);
|
|
11
|
-
}
|
|
11
|
+
},
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
// Set __RAYDIANT_INTERNALS on window so it is accessible in to the running application.
|
|
@@ -25,3 +25,124 @@ ipcRenderer.on('electron-main', (_: IpcRendererEvent, message: string) => {
|
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
|
+
|
|
29
|
+
// Create a custom event that mimics the behavior of the native online/offline events.
|
|
30
|
+
function makeWindowEvent(type: string) {
|
|
31
|
+
const event = new Event(type);
|
|
32
|
+
|
|
33
|
+
Object.defineProperty(event, 'srcElement', {
|
|
34
|
+
get: () => window,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
Object.defineProperty(event, 'target', {
|
|
38
|
+
get: () => window,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return event;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Synchronously get the initial online status. This is handled in photon by the renderer
|
|
45
|
+
// service. Calling sendSync avoids a flash of incorrect status when loading or refreshing
|
|
46
|
+
// the page.
|
|
47
|
+
let isOnline = ipcRenderer.sendSync('get-online-status');
|
|
48
|
+
|
|
49
|
+
// Listen for online status changes from the main process.
|
|
50
|
+
ipcRenderer.on(
|
|
51
|
+
'online-status',
|
|
52
|
+
(_: IpcRendererEvent, nextIsOnline: boolean) => {
|
|
53
|
+
console.log(`Online status: ${nextIsOnline}`);
|
|
54
|
+
|
|
55
|
+
if (nextIsOnline !== isOnline) {
|
|
56
|
+
console.log('Online status changed, updating navigator.onLine');
|
|
57
|
+
isOnline = nextIsOnline;
|
|
58
|
+
|
|
59
|
+
const events = makeWindowEvent(isOnline ? 'online' : 'offline');
|
|
60
|
+
const listeners = isOnline ? onlineListeners : offlineListeners;
|
|
61
|
+
|
|
62
|
+
console.log(
|
|
63
|
+
`Running ${isOnline ? 'online' : 'offline'} listeners, count: ${
|
|
64
|
+
listeners.size
|
|
65
|
+
}`
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
listeners.forEach((listener) => {
|
|
69
|
+
if (typeof listener === 'function') {
|
|
70
|
+
listener(events);
|
|
71
|
+
} else if (listener.handleEvent) {
|
|
72
|
+
listener.handleEvent(events);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
// Replace navigator.onLine with our implementation that uses a the device’s local connectivity
|
|
80
|
+
// service. This will allow apps to receive an accurate and reliable value for navigator.onLine
|
|
81
|
+
// when running on the device.
|
|
82
|
+
Object.defineProperty(navigator, 'onLine', {
|
|
83
|
+
get: () => {
|
|
84
|
+
console.log(`navigator.onLine called, returning ${isOnline}`);
|
|
85
|
+
return isOnline;
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const offlineListeners = new Set<EventListenerOrEventListenerObject>();
|
|
90
|
+
const onlineListeners = new Set<EventListenerOrEventListenerObject>();
|
|
91
|
+
|
|
92
|
+
const originalAddEventListener = window.addEventListener.bind(window);
|
|
93
|
+
Object.defineProperty(window, 'addEventListener', {
|
|
94
|
+
value: (type: string, listener: EventListenerOrEventListenerObject) => {
|
|
95
|
+
if (type === 'online') {
|
|
96
|
+
console.log(`Intercepted online addEventListener`);
|
|
97
|
+
onlineListeners.add(listener);
|
|
98
|
+
} else if (type === 'offline') {
|
|
99
|
+
console.log(`Intercepted offline addEventListener`);
|
|
100
|
+
offlineListeners.add(listener);
|
|
101
|
+
} else {
|
|
102
|
+
return originalAddEventListener(type, listener);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const originalRemoveEventListener = window.removeEventListener.bind(window);
|
|
108
|
+
Object.defineProperty(window, 'removeEventListener', {
|
|
109
|
+
value: (type: string, listener: EventListenerOrEventListenerObject) => {
|
|
110
|
+
if (type === 'online') {
|
|
111
|
+
console.log(`Intercepted online removeEventListener`);
|
|
112
|
+
onlineListeners.delete(listener);
|
|
113
|
+
} else if (type === 'offline') {
|
|
114
|
+
console.log(`Intercepted offline removeEventListener`);
|
|
115
|
+
offlineListeners.delete(listener);
|
|
116
|
+
} else {
|
|
117
|
+
return originalRemoveEventListener(type, listener);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// // TODO: Remove this (for local dev only).
|
|
123
|
+
// (window as any).simulateOnline = () => {
|
|
124
|
+
// isOnline = true;
|
|
125
|
+
|
|
126
|
+
// console.log(`Running online listeners, count: ${onlineListeners.size}`);
|
|
127
|
+
// onlineListeners.forEach((listener) => {
|
|
128
|
+
// if (typeof listener === 'function') {
|
|
129
|
+
// listener(makeWindowEvent('online'));
|
|
130
|
+
// } else if (listener.handleEvent) {
|
|
131
|
+
// listener.handleEvent(makeWindowEvent('online'));
|
|
132
|
+
// }
|
|
133
|
+
// });
|
|
134
|
+
// };
|
|
135
|
+
|
|
136
|
+
// // TODO: Remove this (for local dev only).
|
|
137
|
+
// (window as any).simulateOffline = () => {
|
|
138
|
+
// isOnline = false;
|
|
139
|
+
|
|
140
|
+
// console.log(`Running offline listeners, count: ${offlineListeners.size}`);
|
|
141
|
+
// offlineListeners.forEach((listener) => {
|
|
142
|
+
// if (typeof listener === 'function') {
|
|
143
|
+
// listener(makeWindowEvent('offline'));
|
|
144
|
+
// } else if (listener.handleEvent) {
|
|
145
|
+
// listener.handleEvent(makeWindowEvent('offline'));
|
|
146
|
+
// }
|
|
147
|
+
// });
|
|
148
|
+
// };
|
package/src/types.ts
CHANGED
|
@@ -139,6 +139,11 @@ export interface PresentationWindowRenderer {
|
|
|
139
139
|
|
|
140
140
|
// Called when unmuting a window.
|
|
141
141
|
unMuteWindow(windowId: string): void;
|
|
142
|
+
|
|
143
|
+
// Called when sending isOnline status to the inner window. This is used to override
|
|
144
|
+
// the navigator.isOnline property in the inner window. This is only defined for Electron
|
|
145
|
+
// renderers. Browser renderers do not need to override navigator.isOnline.
|
|
146
|
+
sendOnlineStatus?(windowId: string, isOnline: boolean): void;
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
export interface OpenChildWindowOptions {
|