@raydiant/playlist-window-manager 0.27.3-rc.2 → 0.28.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.
@@ -13,6 +13,7 @@ export default class BrowserViewRenderer implements PresentationWindowRenderer {
13
13
  removeWindow(windowId: string): Promise<void>;
14
14
  sendMessageString(windowId: string, message: string): void;
15
15
  sendMessageObject(windowId: string, type: string, payload?: any): void;
16
+ sendOnlineStatus(windowId: string, isOnline: boolean): void;
16
17
  muteWindow(windowId: string): void;
17
18
  unMuteWindow(windowId: string): void;
18
19
  private getWindow;
@@ -191,6 +191,13 @@ var BrowserViewRenderer = /** @class */ (function () {
191
191
  }
192
192
  window.view.webContents.send('electron-main', { type: type, payload: payload });
193
193
  };
194
+ BrowserViewRenderer.prototype.sendOnlineStatus = function (windowId, isOnline) {
195
+ var window = this.getWindow(windowId);
196
+ if (!window) {
197
+ throw new Error("Failed to send isOnline status to window, missing window id '".concat(windowId, "'"));
198
+ }
199
+ window.view.webContents.send('online-status', isOnline);
200
+ };
194
201
  BrowserViewRenderer.prototype.muteWindow = function (windowId) {
195
202
  var window = this.getWindow(windowId);
196
203
  if (!window) {
@@ -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.
@@ -4,6 +4,7 @@ export default class IFrameRenderer implements PresentationWindowRenderer {
4
4
  private windows;
5
5
  constructor(container: HTMLElement);
6
6
  createWindow({ windowId, bounds, backgroundColor, receiveMessageCallback, }: CreateWindowOptions): Promise<void>;
7
+ private loadWindowResolvers;
7
8
  loadWindow(windowId: string, url: string): Promise<void>;
8
9
  updateWindowBounds(windowId: string, bounds: WindowBounds): void;
9
10
  showWindow(windowId: string, isFocused: boolean): void;
@@ -42,6 +42,7 @@ var IFrameRenderer = /** @class */ (function () {
42
42
  var _this = this;
43
43
  this.container = container;
44
44
  this.windows = {};
45
+ this.loadWindowResolvers = [];
45
46
  this.globalMessageHandler = function (event) {
46
47
  // Ignore messages that don't start with the message prefix.
47
48
  if (typeof event.data === 'string' && event.data.startsWith(namespace)) {
@@ -106,18 +107,35 @@ var IFrameRenderer = /** @class */ (function () {
106
107
  });
107
108
  };
108
109
  IFrameRenderer.prototype.loadWindow = function (windowId, url) {
110
+ var _this = this;
109
111
  var window = this.getWindow(windowId);
110
112
  if (!window) {
111
113
  throw new Error("Failed to update window bounds, missing window id '".concat(windowId, "'"));
112
114
  }
113
115
  // Return a promise that resolves then the window has successfully loaded.
114
116
  return new Promise(function (resolve, reject) {
115
- window.frame.onload = function () {
116
- resolve();
117
- };
118
- window.frame.onerror = function () {
119
- reject(new Error("Error loading window for '".concat(url, "'")));
120
- };
117
+ _this.loadWindowResolvers.push([resolve, reject]);
118
+ // If we reassign onload, we may lost any pending promise called previously.
119
+ // Basically, if this function is called a first time, then it's called a
120
+ // second time without the first one completes load, the resolve callback
121
+ // will never be called, and the code that is awaiting for the promise will
122
+ // never be fulfilled.
123
+ if (!window.frame.onload) {
124
+ window.frame.onload = function () {
125
+ while (_this.loadWindowResolvers.length) {
126
+ var resolve_1 = (_this.loadWindowResolvers.shift() || [])[0];
127
+ resolve_1 === null || resolve_1 === void 0 ? void 0 : resolve_1();
128
+ }
129
+ };
130
+ }
131
+ if (!window.frame.onerror) {
132
+ window.frame.onerror = function () {
133
+ while (_this.loadWindowResolvers.length) {
134
+ var _a = _this.loadWindowResolvers.shift() || [], _ = _a[0], reject_1 = _a[1];
135
+ reject_1 === null || reject_1 === void 0 ? void 0 : reject_1(new Error("Error loading window for '".concat(url, "'")));
136
+ }
137
+ };
138
+ }
121
139
  window.frame.src = url;
122
140
  });
123
141
  };
@@ -757,11 +757,13 @@ var PresentationWindow = /** @class */ (function () {
757
757
  };
758
758
  PresentationWindow.prototype.sendOnlineStatus = function (isOnline) {
759
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.
760
+ // Send online-status event. We are not using sendMessageObject since we
761
+ // are bypassing Raydiant SDK's message receivers and communicating directly
762
+ // with the preload script.
762
763
  if (renderer.sendOnlineStatus) {
763
764
  renderer.sendOnlineStatus(windowId, isOnline);
764
765
  }
766
+ // Forward the event to the child window managers.
765
767
  Object.values(this.windowManagers).forEach(function (wm) {
766
768
  wm.sendOnlineStatus(isOnline);
767
769
  });
package/build/preload.js CHANGED
@@ -59,6 +59,7 @@ Object.defineProperty(navigator, 'onLine', {
59
59
  });
60
60
  var offlineListeners = new Set();
61
61
  var onlineListeners = new Set();
62
+ // Intercept online/offline add event listeners so we can call them when online status changes.
62
63
  var originalAddEventListener = window.addEventListener.bind(window);
63
64
  Object.defineProperty(window, 'addEventListener', {
64
65
  value: function (type, listener) {
@@ -73,6 +74,7 @@ Object.defineProperty(window, 'addEventListener', {
73
74
  }
74
75
  },
75
76
  });
77
+ // Intercept online/offline remove event listeners so we can remove our custom listeners.
76
78
  var originalRemoveEventListener = window.removeEventListener.bind(window);
77
79
  Object.defineProperty(window, 'removeEventListener', {
78
80
  value: function (type, listener) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raydiant/playlist-window-manager",
3
- "version": "0.27.3-rc.2",
3
+ "version": "0.28.1",
4
4
  "description": "Window manager for playlist playback.",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -154,6 +154,17 @@ export default class BrowserViewRenderer implements PresentationWindowRenderer {
154
154
  window.view.webContents.send('electron-main', { type, payload });
155
155
  }
156
156
 
157
+ public sendOnlineStatus(windowId: string, isOnline: boolean) {
158
+ const window = this.getWindow(windowId);
159
+ if (!window) {
160
+ throw new Error(
161
+ `Failed to send isOnline status to window, missing window id '${windowId}'`
162
+ );
163
+ }
164
+
165
+ window.view.webContents.send('online-status', isOnline);
166
+ }
167
+
157
168
  public muteWindow(windowId: string) {
158
169
  const window = this.getWindow(windowId);
159
170
  if (!window) {
@@ -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.
@@ -69,6 +69,8 @@ export default class IFrameRenderer implements PresentationWindowRenderer {
69
69
  this.container.appendChild(frame);
70
70
  }
71
71
 
72
+ private loadWindowResolvers: Array<[() => void, (err: Error) => void]> = [];
73
+
72
74
  public loadWindow(windowId: string, url: string) {
73
75
  const window = this.getWindow(windowId);
74
76
  if (!window) {
@@ -79,13 +81,30 @@ export default class IFrameRenderer implements PresentationWindowRenderer {
79
81
 
80
82
  // Return a promise that resolves then the window has successfully loaded.
81
83
  return new Promise<void>((resolve, reject) => {
82
- window.frame.onload = () => {
83
- resolve();
84
- };
84
+ this.loadWindowResolvers.push([resolve, reject]);
85
+
86
+ // If we reassign onload, we may lost any pending promise called previously.
87
+ // Basically, if this function is called a first time, then it's called a
88
+ // second time without the first one completes load, the resolve callback
89
+ // will never be called, and the code that is awaiting for the promise will
90
+ // never be fulfilled.
91
+ if (!window.frame.onload) {
92
+ window.frame.onload = () => {
93
+ while (this.loadWindowResolvers.length) {
94
+ const [resolve] = this.loadWindowResolvers.shift() || [];
95
+ resolve?.();
96
+ }
97
+ };
98
+ }
85
99
 
86
- window.frame.onerror = () => {
87
- reject(new Error(`Error loading window for '${url}'`));
88
- };
100
+ if (!window.frame.onerror) {
101
+ window.frame.onerror = () => {
102
+ while (this.loadWindowResolvers.length) {
103
+ const [_, reject] = this.loadWindowResolvers.shift() || [];
104
+ reject?.(new Error(`Error loading window for '${url}'`));
105
+ }
106
+ };
107
+ }
89
108
 
90
109
  window.frame.src = url;
91
110
  });
@@ -528,13 +528,15 @@ export default class PresentationWindow {
528
528
 
529
529
  public sendOnlineStatus(isOnline: boolean) {
530
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
531
 
532
+ // Send online-status event. We are not using sendMessageObject since we
533
+ // are bypassing Raydiant SDK's message receivers and communicating directly
534
+ // with the preload script.
534
535
  if (renderer.sendOnlineStatus) {
535
536
  renderer.sendOnlineStatus(windowId, isOnline);
536
537
  }
537
538
 
539
+ // Forward the event to the child window managers.
538
540
  Object.values(this.windowManagers).forEach((wm) => {
539
541
  wm.sendOnlineStatus(isOnline);
540
542
  });
package/src/preload.ts CHANGED
@@ -79,6 +79,7 @@ Object.defineProperty(navigator, 'onLine', {
79
79
  const offlineListeners = new Set<EventListenerOrEventListenerObject>();
80
80
  const onlineListeners = new Set<EventListenerOrEventListenerObject>();
81
81
 
82
+ // Intercept online/offline add event listeners so we can call them when online status changes.
82
83
  const originalAddEventListener = window.addEventListener.bind(window);
83
84
  Object.defineProperty(window, 'addEventListener', {
84
85
  value: (type: string, listener: EventListenerOrEventListenerObject) => {
@@ -92,6 +93,7 @@ Object.defineProperty(window, 'addEventListener', {
92
93
  },
93
94
  });
94
95
 
96
+ // Intercept online/offline remove event listeners so we can remove our custom listeners.
95
97
  const originalRemoveEventListener = window.removeEventListener.bind(window);
96
98
  Object.defineProperty(window, 'removeEventListener', {
97
99
  value: (type: string, listener: EventListenerOrEventListenerObject) => {