@raydiant/playlist-window-manager 0.20.0 → 0.21.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.
@@ -10,11 +10,35 @@ var __assign = (this && this.__assign) || function () {
10
10
  };
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
13
36
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
38
  return new (P || (P = Promise))(function (resolve, reject) {
15
39
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
40
  function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
- function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
42
  step((generator = generator.apply(thisArg, _arguments || [])).next());
19
43
  });
20
44
  };
@@ -24,7 +48,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
24
48
  function verb(n) { return function (v) { return step([n, v]); }; }
25
49
  function step(op) {
26
50
  if (f) throw new TypeError("Generator is already executing.");
27
- while (_) try {
51
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
52
  if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
53
  if (y = 0, t) op = [op[0] & 2, t.value];
30
54
  switch (op[0]) {
@@ -45,19 +69,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
45
69
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
70
  }
47
71
  };
48
- var __importStar = (this && this.__importStar) || function (mod) {
49
- if (mod && mod.__esModule) return mod;
50
- var result = {};
51
- if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
52
- result["default"] = mod;
53
- return result;
54
- };
55
72
  var __importDefault = (this && this.__importDefault) || function (mod) {
56
73
  return (mod && mod.__esModule) ? mod : { "default": mod };
57
74
  };
58
75
  Object.defineProperty(exports, "__esModule", { value: true });
59
76
  var RE = __importStar(require("@raydiant/playlist-rule-engine"));
60
77
  var fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
78
+ var uuid_1 = require("uuid");
61
79
  var embeddedApps_1 = __importDefault(require("./embeddedApps"));
62
80
  var PlaylistWindowManager_1 = __importDefault(require("./PlaylistWindowManager"));
63
81
  var WindowTimeoutError_1 = __importDefault(require("./WindowTimeoutError"));
@@ -86,7 +104,6 @@ var PresentationWindow = /** @class */ (function () {
86
104
  this.completeCallback = null;
87
105
  this.errorCallback = null;
88
106
  this.readyTimeout = null;
89
- // private completeThrottleTimeout: ReturnType<typeof setTimeout> | null = null;
90
107
  this.windowManagers = {};
91
108
  this.focusedWindowManager = null;
92
109
  this.didEmbeddedAppLoad = false;
@@ -102,79 +119,83 @@ var PresentationWindow = /** @class */ (function () {
102
119
  this.workerState = {};
103
120
  this.workerSubscriptions = new Set();
104
121
  this.runtimeSubscriptions = new Set();
122
+ this.previewSubscriptions = new Set();
123
+ this.previewState = { inputs: {} };
124
+ this.createObjectURLResolvers = {};
125
+ this.createObjectURLTimeouts = {};
105
126
  this.handleEmbeddedMessage = function (type, payload) { return __awaiter(_this, void 0, void 0, function () {
106
127
  var windowId, workerState;
107
128
  return __generator(this, function (_a) {
108
129
  windowId = this.options.windowId;
109
130
  switch (type) {
110
131
  case 'ready': {
111
- this.logInfo("Received 'ready' from window '" + windowId + "'");
132
+ this.logInfo("Received 'ready' from window '".concat(windowId, "'"));
112
133
  this.handleReady();
113
134
  break;
114
135
  }
115
136
  case 'complete': {
116
137
  if (payload === undefined) {
117
- this.logInfo("Received 'complete' from window '" + windowId + "'");
138
+ this.logInfo("Received 'complete' from window '".concat(windowId, "'"));
118
139
  this.handleComplete();
119
140
  }
120
141
  else {
121
- this.logInfo("Received 'complete' with error from window '" + windowId + ", error=" + payload + "'");
142
+ this.logInfo("Received 'complete' with error from window '".concat(windowId, ", error=").concat(payload, "'"));
122
143
  this.handleError(payload);
123
144
  }
124
145
  break;
125
146
  }
126
147
  case 'runtime-subscribe': {
127
148
  if (typeof payload === 'string') {
128
- this.logInfo("Received 'runtime-subscribe' from window '" + windowId + "'");
149
+ this.logInfo("Received 'runtime-subscribe' from window '".concat(windowId, "'"));
129
150
  // The payload is the event name (ex. 'play').
130
151
  this.runtimeSubscriptions.add(payload);
131
152
  // Immediately send play if the app if already playing.
132
153
  if (this.isPlaying()) {
133
- this.sendMessage('play');
154
+ this.sendMessageString('play');
134
155
  }
135
156
  }
136
157
  else {
137
- this.logWarning("Invalid payload for runtime-subscribe message: " + payload);
158
+ this.logWarning("Invalid payload for runtime-subscribe message: ".concat(payload));
138
159
  }
139
160
  break;
140
161
  }
141
162
  case 'runtime-unsubscribe': {
142
163
  if (typeof payload === 'string') {
143
- this.logInfo("Received 'runtime-unsubscribe' from window '" + windowId + "'");
164
+ this.logInfo("Received 'runtime-unsubscribe' from window '".concat(windowId, "'"));
144
165
  // The payload is the event name (ex. 'play').
145
166
  this.runtimeSubscriptions.delete(payload);
146
167
  }
147
168
  else {
148
- this.logWarning("Invalid payload for runtime-subscribe message: " + payload);
169
+ this.logWarning("Invalid payload for runtime-subscribe message: ".concat(payload));
149
170
  }
150
171
  break;
151
172
  }
152
173
  case 'worker-subscribe': {
153
174
  if (typeof payload === 'string') {
154
- this.logInfo("Received 'worker-subscribe' from window '" + windowId + "'");
175
+ this.logInfo("Received 'worker-subscribe' from window '".concat(windowId, "'"));
155
176
  // The payload is the worker name.
156
177
  this.workerSubscriptions.add(payload);
157
178
  workerState = this.workerState[payload];
158
179
  if (workerState !== undefined) {
159
- this.sendMessage('worker-state', {
180
+ this.sendMessageString('worker-state', {
160
181
  name: payload,
161
- state: workerState
182
+ state: workerState,
162
183
  });
163
184
  }
164
185
  }
165
186
  else {
166
- this.logWarning("Invalid payload for worker-subscribe message: " + payload);
187
+ this.logWarning("Invalid payload for worker-subscribe message: ".concat(payload));
167
188
  }
168
189
  break;
169
190
  }
170
191
  case 'worker-unsubscribe': {
171
192
  if (typeof payload === 'string') {
172
- this.logInfo("Received 'worker-unsubscribe' from window '" + windowId + "'");
193
+ this.logInfo("Received 'worker-unsubscribe' from window '".concat(windowId, "'"));
173
194
  // The payload is the worker name.
174
195
  this.workerSubscriptions.delete(payload);
175
196
  }
176
197
  else {
177
- this.logWarning("Invalid payload for worker-unsubscribe message: " + payload);
198
+ this.logWarning("Invalid payload for worker-unsubscribe message: ".concat(payload));
178
199
  }
179
200
  break;
180
201
  }
@@ -184,8 +205,48 @@ var PresentationWindow = /** @class */ (function () {
184
205
  }
185
206
  break;
186
207
  }
208
+ case 'create-object-url-result': {
209
+ if (isValidCreateObjectURLResultPayload(payload)) {
210
+ // Resolve promise with the local blob URL.
211
+ if (this.createObjectURLResolvers[payload.requestId]) {
212
+ this.createObjectURLResolvers[payload.requestId](payload.url);
213
+ delete this.createObjectURLResolvers[payload.requestId];
214
+ }
215
+ // Clear the timeout for the request.
216
+ if (this.createObjectURLTimeouts[payload.requestId]) {
217
+ clearTimeout(this.createObjectURLTimeouts[payload.requestId]);
218
+ delete this.createObjectURLTimeouts[payload.requestId];
219
+ }
220
+ }
221
+ else {
222
+ this.logWarning("Invalid payload for create-object-url-result message: ".concat(payload));
223
+ }
224
+ break;
225
+ }
226
+ case 'preview-subscribe': {
227
+ if (typeof payload === 'string') {
228
+ this.logInfo("Received 'preview-subscribe' from window '".concat(windowId, "'"));
229
+ // The payload is the event name (ex. 'inputs').
230
+ this.previewSubscriptions.add(payload);
231
+ }
232
+ else {
233
+ this.logWarning("Invalid payload for preview-subscribe message: ".concat(payload));
234
+ }
235
+ break;
236
+ }
237
+ case 'preview-unsubscribe': {
238
+ if (typeof payload === 'string') {
239
+ this.logInfo("Received 'preview-unsubscribe' from window '".concat(windowId, "'"));
240
+ // The payload is the event name (ex. 'inputs').
241
+ this.previewSubscriptions.delete(payload);
242
+ }
243
+ else {
244
+ this.logWarning("Invalid payload for preview-subscribe message: ".concat(payload));
245
+ }
246
+ break;
247
+ }
187
248
  default: {
188
- this.logWarning("Received unknown embedded message type: " + type);
249
+ this.logWarning("Received unknown embedded message type: ".concat(type));
189
250
  }
190
251
  }
191
252
  return [2 /*return*/];
@@ -196,33 +257,33 @@ var PresentationWindow = /** @class */ (function () {
196
257
  return __generator(this, function (_b) {
197
258
  _a = this.options, windowId = _a.windowId, onPresentationProperties = _a.onPresentationProperties;
198
259
  if (type === 'loaded') {
199
- this.logInfo("Received 'loaded' from window '" + windowId + "'");
260
+ this.logInfo("Received 'loaded' from window '".concat(windowId, "'"));
200
261
  this.sendRenderMessage();
201
262
  }
202
263
  if (type === 'presentation_ready') {
203
- this.logInfo("Received 'presentation_ready' from window '" + windowId + "'");
264
+ this.logInfo("Received 'presentation_ready' from window '".concat(windowId, "'"));
204
265
  this.handleReady();
205
266
  }
206
267
  if (type === 'presentation_complete') {
207
- this.logInfo("Received 'presentation_complete' from window '" + windowId + "'");
268
+ this.logInfo("Received 'presentation_complete' from window '".concat(windowId, "'"));
208
269
  this.handleComplete();
209
270
  }
210
271
  if (type === 'enable_interrupt_lock') {
211
- this.logInfo("Received 'enable_interrupt_lock' from window '" + windowId + "'");
272
+ this.logInfo("Received 'enable_interrupt_lock' from window '".concat(windowId, "'"));
212
273
  this.enableInteruptLock();
213
274
  }
214
275
  if (type === 'disable_interrupt_lock') {
215
- this.logInfo("Received 'disable_interrupt_lock' from window '" + windowId + "'");
276
+ this.logInfo("Received 'disable_interrupt_lock' from window '".concat(windowId, "'"));
216
277
  this.disableInteruptLock();
217
278
  }
218
279
  if (type === 'open_child_window') {
219
- this.logInfo("Received 'open_child_window' from window '" + windowId + "', windowId=" + payload.windowId + " playlistId=" + payload.playlistId + " isMuted=" + payload.isMuted + " x=" + payload.x + " y=" + payload.y + " width=" + payload.width + " height=" + payload.height);
280
+ this.logInfo("Received 'open_child_window' from window '".concat(windowId, "', windowId=").concat(payload.windowId, " playlistId=").concat(payload.playlistId, " isMuted=").concat(payload.isMuted, " x=").concat(payload.x, " y=").concat(payload.y, " width=").concat(payload.width, " height=").concat(payload.height));
220
281
  if (this.isValidOpenChildWindowPayload(payload)) {
221
282
  this.openChildWindow(payload.windowId, payload.playlistId, {
222
283
  x: Math.round(payload.x),
223
284
  y: Math.round(payload.y),
224
285
  width: Math.round(payload.width),
225
- height: Math.round(payload.height)
286
+ height: Math.round(payload.height),
226
287
  }, payload.isMuted, payload.isFocused, payload.theme);
227
288
  }
228
289
  else {
@@ -231,20 +292,20 @@ var PresentationWindow = /** @class */ (function () {
231
292
  }
232
293
  if (type === 'close_child_window') {
233
294
  // TODO: Validate close_child_window message payload.
234
- this.logInfo("Received 'close_child_window', windowId=" + payload.windowId);
295
+ this.logInfo("Received 'close_child_window', windowId=".concat(payload.windowId));
235
296
  this.closeChildWindow(payload.windowId);
236
297
  }
237
298
  if (type === 'log_error') {
238
- this.handleError("Received error from window '" + windowId + "', error=" + JSON.stringify(payload));
299
+ this.handleError("Received error from window '".concat(windowId, "', error=").concat(JSON.stringify(payload)));
239
300
  }
240
301
  if (type === 'log_info') {
241
- this.logInfo("Received info log from window '" + windowId + "', message=" + JSON.stringify(payload));
302
+ this.logInfo("Received info log from window '".concat(windowId, "', message=").concat(JSON.stringify(payload)));
242
303
  }
243
304
  if (type === 'log_debug') {
244
- this.logDebug("Received info debug from window '" + windowId + "', message=" + JSON.stringify(payload));
305
+ this.logDebug("Received info debug from window '".concat(windowId, "', message=").concat(JSON.stringify(payload)));
245
306
  }
246
307
  if (type === 'presentation_properties') {
247
- this.logInfo("Received 'presentation_properties' from window '" + windowId + "'");
308
+ this.logInfo("Received 'presentation_properties' from window '".concat(windowId, "'"));
248
309
  if (onPresentationProperties) {
249
310
  onPresentationProperties(payload.properties, payload.strings);
250
311
  }
@@ -303,7 +364,7 @@ var PresentationWindow = /** @class */ (function () {
303
364
  wm.show(false);
304
365
  }
305
366
  });
306
- this.logInfo("Show window '" + windowId + "' isMuted=" + isMuted + " isFocused=" + isFocused + (isChildWindowFocused ? " isChildWindowFocused=true" : ''));
367
+ this.logInfo("Show window '".concat(windowId, "' isMuted=").concat(isMuted, " isFocused=").concat(isFocused).concat(isChildWindowFocused ? " isChildWindowFocused=true" : ''));
307
368
  };
308
369
  PresentationWindow.prototype.hide = function () {
309
370
  var _a = this.options, windowId = _a.windowId, renderer = _a.renderer;
@@ -345,11 +406,11 @@ var PresentationWindow = /** @class */ (function () {
345
406
  return [4 /*yield*/, renderer.removeWindow(windowId)];
346
407
  case 2:
347
408
  _b.sent();
348
- this.logInfo("Removed window '" + windowId + "'");
409
+ this.logInfo("Removed window '".concat(windowId, "'"));
349
410
  return [3 /*break*/, 4];
350
411
  case 3:
351
412
  err_1 = _b.sent();
352
- this.logError("Failed to remove window '" + windowId + "' with '" + err_1.message + "'");
413
+ this.logError("Failed to remove window '".concat(windowId, "' with '").concat(err_1.message, "'"));
353
414
  return [3 /*break*/, 4];
354
415
  case 4: return [2 /*return*/];
355
416
  }
@@ -377,7 +438,7 @@ var PresentationWindow = /** @class */ (function () {
377
438
  }, durationMs);
378
439
  }
379
440
  if (!this.isEmbeddedApp()) {
380
- this.sendMessage('play');
441
+ this.sendMessageString('play');
381
442
  // Play any child window managers.
382
443
  Object.values(this.windowManagers).forEach(function (wm) {
383
444
  // We only want to trigger play on child windows the first play of the main window or if
@@ -389,7 +450,7 @@ var PresentationWindow = /** @class */ (function () {
389
450
  }
390
451
  else if (this.runtimeSubscriptions.has('play')) {
391
452
  // If the embedded app has subscribed to the play event, send it a play event.
392
- this.sendMessage('play');
453
+ this.sendMessageString('play');
393
454
  }
394
455
  this.lastPlayedAt = new Date();
395
456
  };
@@ -461,25 +522,34 @@ var PresentationWindow = /** @class */ (function () {
461
522
  };
462
523
  PresentationWindow.prototype.reload = function () {
463
524
  return __awaiter(this, void 0, void 0, function () {
464
- var _a, applicationVersion, windowId, url;
525
+ var _a, applicationVersion, windowId, updatedInputs, url;
465
526
  return __generator(this, function (_b) {
466
527
  switch (_b.label) {
467
528
  case 0:
468
529
  _a = this.options, applicationVersion = _a.applicationVersion, windowId = _a.windowId;
469
- if (!this.isEmbeddedApp()) return [3 /*break*/, 3];
470
- if (!applicationVersion.embeddedUrlFormat) return [3 /*break*/, 2];
530
+ if (!this.isEmbeddedApp()) return [3 /*break*/, 4];
531
+ if (!applicationVersion.embeddedUrlFormat) return [3 /*break*/, 3];
532
+ if (!this.previewSubscriptions.has('inputs')) return [3 /*break*/, 1];
533
+ this.logInfo("Reload window '".concat(windowId, "' for embedded app preview state"));
534
+ updatedInputs = transformInputValues(this.presentation.applicationVariables);
535
+ if (!(0, fast_deep_equal_1.default)(updatedInputs, this.previewState.inputs)) {
536
+ this.sendMessageObject('preview-inputs', updatedInputs);
537
+ }
538
+ this.previewState.inputs = updatedInputs;
539
+ return [3 /*break*/, 3];
540
+ case 1:
471
541
  url = this.getEmbeddedAppUrl();
472
- this.logInfo("Reload window '" + windowId + "' for embedded app url '" + url + "'");
542
+ this.logInfo("Reload window '".concat(windowId, "' for embedded app url '").concat(url, "'"));
473
543
  return [4 /*yield*/, this.loadWindow(url)];
474
- case 1:
544
+ case 2:
475
545
  _b.sent();
476
- _b.label = 2;
477
- case 2: return [3 /*break*/, 4];
478
- case 3:
479
- this.logInfo("Reload window '" + windowId + "'");
546
+ _b.label = 3;
547
+ case 3: return [3 /*break*/, 5];
548
+ case 4:
549
+ this.logInfo("Reload window '".concat(windowId, "'"));
480
550
  this.sendRenderMessage();
481
- _b.label = 4;
482
- case 4: return [2 /*return*/];
551
+ _b.label = 5;
552
+ case 5: return [2 /*return*/];
483
553
  }
484
554
  });
485
555
  });
@@ -488,9 +558,19 @@ var PresentationWindow = /** @class */ (function () {
488
558
  // Do no support conditional properties for embedded apps. We will likely
489
559
  // change the way conditional properties work.
490
560
  if (!this.isEmbeddedApp()) {
491
- this.sendMessage('run_get_properties', builderState);
561
+ this.sendMessageString('run_get_properties', builderState);
492
562
  }
493
563
  };
564
+ PresentationWindow.prototype.createObjectURL = function (blob) {
565
+ return __awaiter(this, void 0, void 0, function () {
566
+ return __generator(this, function (_a) {
567
+ if (this.isEmbeddedApp()) {
568
+ return [2 /*return*/, this.createObjectURLForEmbeddedApp(blob)];
569
+ }
570
+ return [2 /*return*/, URL.createObjectURL(blob)];
571
+ });
572
+ });
573
+ };
494
574
  PresentationWindow.prototype.isEmbeddedApp = function () {
495
575
  var _a = this.options, applicationVersion = _a.applicationVersion, isPreview = _a.isPreview;
496
576
  // If the application has a source url, always use it for rendering the preview.
@@ -538,10 +618,10 @@ var PresentationWindow = /** @class */ (function () {
538
618
  case 0:
539
619
  _a = this.options, windowId = _a.windowId, applicationVersion = _a.applicationVersion;
540
620
  if (!applicationVersion.embeddedUrlFormat) {
541
- throw new Error("Error loading embedded app, missing embeddedUrlFormat for '" + applicationVersion.id + "'");
621
+ throw new Error("Error loading embedded app, missing embeddedUrlFormat for '".concat(applicationVersion.id, "'"));
542
622
  }
543
623
  url = this.getEmbeddedAppUrl();
544
- this.logInfo("Create window '" + windowId + "' for embedded app url '" + url + "'");
624
+ this.logInfo("Create window '".concat(windowId, "' for embedded app url '").concat(url, "'"));
545
625
  return [4 /*yield*/, this.createAndLoadWindow(url,
546
626
  // Embedded apps should not have a backgroundColor because some sites expect
547
627
  // the browser default of white will be applied.
@@ -562,7 +642,7 @@ var PresentationWindow = /** @class */ (function () {
562
642
  switch (_c.label) {
563
643
  case 0:
564
644
  _a = this.options, windowId = _a.windowId, _b = _a.appRendererUrl, appRendererUrl = _b === void 0 ? defaultAppRendererUrl : _b, backgroundColor = _a.backgroundColor;
565
- this.logInfo("Create window '" + windowId + "'");
645
+ this.logInfo("Create window '".concat(windowId, "'"));
566
646
  return [4 /*yield*/, this.createAndLoadWindow(this.appendWindowIdToHash(appRendererUrl, windowId), backgroundColor || '#000000', // Default to black bg for Raydiant apps
567
647
  this.handleLegacyMessage)];
568
648
  case 1:
@@ -588,14 +668,14 @@ var PresentationWindow = /** @class */ (function () {
588
668
  bounds: bounds,
589
669
  backgroundColor: backgroundColor,
590
670
  receiveMessageCallback: receiveMessageCallback,
591
- errorCallback: this.handleError
671
+ errorCallback: this.handleError,
592
672
  });
593
673
  // Mute new window. This ensures preloaded windows are muted by default and
594
674
  // prevents opening an audio channel on the device for SYB playback. When using
595
675
  // the BrowserWindowRenderer this will call setAudioMuted(true) but the IFrameRenderer
596
676
  // has no API for muting so we rely on apps that use mute presentation props to be
597
677
  // initially muted before playing.
598
- this.logInfo("Mute window " + windowId);
678
+ this.logInfo("Mute window ".concat(windowId));
599
679
  renderer.muteWindow(windowId);
600
680
  return [4 /*yield*/, this.loadWindow(url)];
601
681
  case 1:
@@ -618,22 +698,31 @@ var PresentationWindow = /** @class */ (function () {
618
698
  return [4 /*yield*/, renderer.loadWindow(windowId, url)];
619
699
  case 2:
620
700
  _b.sent();
621
- this.logInfo("Loaded window '" + windowId + "'");
701
+ this.logInfo("Loaded window '".concat(windowId, "'"));
622
702
  return [3 /*break*/, 4];
623
703
  case 3:
624
704
  err_2 = _b.sent();
625
- this.handleError(new WindowLoadError_1.default("Failed to load window with '" + err_2.message + "'"));
705
+ this.handleError(new WindowLoadError_1.default("Failed to load window with '".concat(err_2.message, "'")));
626
706
  return [3 /*break*/, 4];
627
707
  case 4: return [2 /*return*/];
628
708
  }
629
709
  });
630
710
  });
631
711
  };
632
- PresentationWindow.prototype.sendMessage = function (type, payload) {
712
+ // Send a JSON stringified message to the renderer. This is the legacy way of sending
713
+ // messages and should be deprecated in favor of sendMessageObject.
714
+ PresentationWindow.prototype.sendMessageString = function (type, payload) {
633
715
  var _a = this.options, windowId = _a.windowId, renderer = _a.renderer;
634
716
  var message = JSON.stringify({ type: type, payload: payload, windowId: windowId });
635
- this.logInfo("Sending '" + type + "' to window '" + windowId + "'");
636
- renderer.sendMessage(windowId, message);
717
+ this.logInfo("Sending '".concat(type, "' to window '").concat(windowId, "'"));
718
+ renderer.sendMessageString(windowId, message);
719
+ };
720
+ // Send a message object to the renderer. This is the preferred way of sending messages
721
+ // going forward since it allows for more complex payloads like ArrayBuffers (for File Inputs).
722
+ PresentationWindow.prototype.sendMessageObject = function (type, payload) {
723
+ var _a = this.options, windowId = _a.windowId, renderer = _a.renderer;
724
+ this.logInfo("Sending '".concat(type, "' to window '").concat(windowId, "'"));
725
+ renderer.sendMessageObject(windowId, type, payload);
637
726
  };
638
727
  PresentationWindow.prototype.waitForPesentationReady = function () {
639
728
  var _this = this;
@@ -650,7 +739,7 @@ var PresentationWindow = /** @class */ (function () {
650
739
  clearTimeout(_this.readyTimeout);
651
740
  }
652
741
  _this.readyTimeout = setTimeout(function () {
653
- _this.handleError(new WindowTimeoutError_1.default("Window " + windowId + " timed out after " + readyTimeoutDurationSeconds + " seconds"));
742
+ _this.handleError(new WindowTimeoutError_1.default("Window ".concat(windowId, " timed out after ").concat(readyTimeoutDurationSeconds, " seconds")));
654
743
  // Resolve the promise is the window times out. This ensures windowManager.load() resolves
655
744
  // even if the current window times out. Fixes an issue where the boot screen isn't removed
656
745
  // if the first presentation times out.
@@ -686,26 +775,26 @@ var PresentationWindow = /** @class */ (function () {
686
775
  // IFrames do not have a mute/unmute API so we are overriding any mute properties
687
776
  // to support muting MZ zones when using the IFrameRenderer (SecondScreen).
688
777
  if (this.forceMute) {
689
- this.sendMessage('render', {
778
+ this.sendMessageString('render', {
690
779
  builderState: this.builderState,
691
- presentation: __assign({}, this.presentation, { applicationVariables: __assign({}, this.presentation.applicationVariables, {
780
+ presentation: __assign(__assign({}, this.presentation), { applicationVariables: __assign(__assign({}, this.presentation.applicationVariables), {
692
781
  // TODO: We need a better way to identify mute properties (ie. PropType.mute())
693
782
  // Force mute the presentation, existing apps use either mute or muted.
694
783
  mute: true, muted: true }) }),
695
784
  theme: this.buildTheme(),
696
785
  applicationVersion: applicationVersion,
697
786
  device: device,
698
- isPreview: isPreview
787
+ isPreview: isPreview,
699
788
  });
700
789
  }
701
790
  else {
702
- this.sendMessage('render', {
791
+ this.sendMessageString('render', {
703
792
  builderState: this.builderState,
704
793
  presentation: this.presentation,
705
794
  theme: this.buildTheme(),
706
795
  applicationVersion: applicationVersion,
707
796
  device: device,
708
- isPreview: isPreview
797
+ isPreview: isPreview,
709
798
  });
710
799
  }
711
800
  };
@@ -727,14 +816,14 @@ var PresentationWindow = /** @class */ (function () {
727
816
  prevRuleEngine = windowManager.getRuleEngine();
728
817
  prevForceMute = windowManager.getForceMute();
729
818
  didBoundsChange = prevBounds
730
- ? !fast_deep_equal_1.default(bounds, prevBounds)
819
+ ? !(0, fast_deep_equal_1.default)(bounds, prevBounds)
731
820
  : true;
732
821
  if (didBoundsChange) {
733
822
  windowManager.updateBounds(bounds);
734
823
  }
735
824
  didForceMuteChange = forceMute !== prevForceMute;
736
825
  didThemeOverrideChange = prevThemeOverride
737
- ? !fast_deep_equal_1.default(themeOverride, prevThemeOverride)
826
+ ? !(0, fast_deep_equal_1.default)(themeOverride, prevThemeOverride)
738
827
  : true;
739
828
  if (didForceMuteChange || didThemeOverrideChange) {
740
829
  windowManager.setThemeOverride(themeOverride);
@@ -762,14 +851,14 @@ var PresentationWindow = /** @class */ (function () {
762
851
  x: bounds.x,
763
852
  y: bounds.y,
764
853
  width: bounds.width,
765
- height: bounds.height
854
+ height: bounds.height,
766
855
  },
767
856
  backgroundColor: 'transparent',
768
857
  themeOverride: themeOverride,
769
858
  forceMute: forceMute,
770
859
  isPreview: isPreview,
771
860
  onEnableInterruptLock: function () { return _this.enableInteruptLock(windowName); },
772
- onDisableInterruptLock: function () { return _this.disableInteruptLock(windowName); }
861
+ onDisableInterruptLock: function () { return _this.disableInteruptLock(windowName); },
773
862
  });
774
863
  // Hook up child window manager events to bubble up to the parent.
775
864
  if (parentWindowManager) {
@@ -824,7 +913,7 @@ var PresentationWindow = /** @class */ (function () {
824
913
  delete this.windowManagers[windowName];
825
914
  }
826
915
  else {
827
- this.logWarning("Failed to close child window manager for '" + windowName + "'.");
916
+ this.logWarning("Failed to close child window manager for '".concat(windowName, "'."));
828
917
  }
829
918
  };
830
919
  PresentationWindow.prototype.enableInteruptLock = function (windowName) {
@@ -856,9 +945,9 @@ var PresentationWindow = /** @class */ (function () {
856
945
  PresentationWindow.prototype.getEmbeddedAppUrl = function () {
857
946
  var windowId = this.options.windowId;
858
947
  var metadata = {
859
- renderMode: this.options.isPreview ? 'preview' : 'live'
948
+ renderMode: this.options.isPreview ? 'preview' : 'live',
860
949
  };
861
- var url = embeddedApps_1.default(this.presentation, this.options.applicationVersion, metadata);
950
+ var url = (0, embeddedApps_1.default)(this.presentation, this.options.applicationVersion, metadata);
862
951
  return this.appendWindowIdToHash(url, windowId);
863
952
  };
864
953
  PresentationWindow.prototype.handleReady = function () {
@@ -897,7 +986,7 @@ var PresentationWindow = /** @class */ (function () {
897
986
  publishedAt: publishedAt,
898
987
  playlistId: playlistId,
899
988
  playlistName: playlistName,
900
- rule: rule
989
+ rule: rule,
901
990
  };
902
991
  };
903
992
  PresentationWindow.prototype.metadata = function () {
@@ -911,10 +1000,10 @@ var PresentationWindow = /** @class */ (function () {
911
1000
  var workerState = state[workerName];
912
1001
  var previousWorkerState = this.workerState[workerName];
913
1002
  if (workerState !== undefined &&
914
- !fast_deep_equal_1.default(workerState, previousWorkerState)) {
915
- this.sendMessage('worker-state', {
1003
+ !(0, fast_deep_equal_1.default)(workerState, previousWorkerState)) {
1004
+ this.sendMessageString('worker-state', {
916
1005
  name: workerName,
917
- state: workerState
1006
+ state: workerState,
918
1007
  });
919
1008
  }
920
1009
  }
@@ -933,15 +1022,15 @@ var PresentationWindow = /** @class */ (function () {
933
1022
  {
934
1023
  type: 'equals',
935
1024
  left: { var: ['target', 'hasPlaylists'] },
936
- right: { const: false }
937
- }
938
- ]
1025
+ right: { const: false },
1026
+ },
1027
+ ],
939
1028
  }
940
1029
  : {
941
1030
  // A global rule was not provided so we don't need to combine the rule with an AND.
942
1031
  type: 'equals',
943
1032
  left: { var: ['target', 'hasPlaylists'] },
944
- right: { const: false }
1033
+ right: { const: false },
945
1034
  });
946
1035
  };
947
1036
  PresentationWindow.prototype.isValidOpenChildWindowPayload = function (payload) {
@@ -978,6 +1067,72 @@ var PresentationWindow = /** @class */ (function () {
978
1067
  var isMutedMultizone = appVars.muteZone1 === true && appVars.muteZone2 === true;
979
1068
  return isMutedMultizone;
980
1069
  };
1070
+ PresentationWindow.prototype.createObjectURLForEmbeddedApp = function (blob) {
1071
+ var _this = this;
1072
+ return new Promise(function (resolve, reject) {
1073
+ // Handle multiple concurrent createObjectURL calls by creating a request id for each
1074
+ // call. We send the request id along with the message to the running app and the app
1075
+ // sends the request id back with the result so we can resolve the correct promise.
1076
+ var requestId = (0, uuid_1.v4)();
1077
+ _this.createObjectURLResolvers[requestId] = resolve;
1078
+ // Start a timer to reject the promise if the app doesn't respond with the create object
1079
+ // url result within 1 second. This should be more or less instant.
1080
+ _this.createObjectURLTimeouts[requestId] = setTimeout(function () {
1081
+ var error = new Error("Timed out waiting for the create-object-url-result message for request id ".concat(requestId));
1082
+ reject(error);
1083
+ delete _this.createObjectURLResolvers[requestId];
1084
+ delete _this.createObjectURLTimeouts[requestId];
1085
+ }, 1000);
1086
+ // Create a FileReader object to read the file data as an ArrayBuffer.
1087
+ var reader = new FileReader();
1088
+ reader.addEventListener('load', function () {
1089
+ var buffer = reader.result;
1090
+ // Check if buffer is an ArrayBuffer
1091
+ if (buffer instanceof ArrayBuffer) {
1092
+ // Send the ArrayBuffer to the running app to create the local file blob URL.
1093
+ _this.sendMessageObject('create-object-url', { requestId: requestId, buffer: buffer });
1094
+ }
1095
+ }, false);
1096
+ reader.readAsArrayBuffer(blob);
1097
+ return '';
1098
+ });
1099
+ };
981
1100
  return PresentationWindow;
982
1101
  }());
983
1102
  exports.default = PresentationWindow;
1103
+ var isValidCreateObjectURLResultPayload = function (payload) {
1104
+ return (
1105
+ // Ensure payload is an object.
1106
+ typeof payload === 'object' &&
1107
+ payload !== null &&
1108
+ // Ensure requestId is a string.
1109
+ 'requestId' in payload &&
1110
+ typeof payload['requestId'] === 'string' &&
1111
+ // Ensure payload.file is an object.
1112
+ 'url' in payload &&
1113
+ typeof payload['url'] === 'string');
1114
+ };
1115
+ var transformInputValues = function (inputs) {
1116
+ var transformed = {};
1117
+ // Recursively traverse inputs, transforming any file input values to remove internal
1118
+ // properties like file_upload_id.
1119
+ for (var _i = 0, _a = Object.entries(inputs); _i < _a.length; _i++) {
1120
+ var _b = _a[_i], key = _b[0], value = _b[1];
1121
+ if (typeof value === 'object' && value !== null && 'url' in value) {
1122
+ // Value is a file input, strip out the file_upload_id property.
1123
+ transformed[key] = { url: value.url };
1124
+ }
1125
+ else if (Array.isArray(value)) {
1126
+ // Value is an array input, traverse each item in the array for file input values.
1127
+ transformed[key] = [];
1128
+ for (var _c = 0, value_1 = value; _c < value_1.length; _c++) {
1129
+ var item = value_1[_c];
1130
+ transformed[key].push(transformInputValues(item));
1131
+ }
1132
+ }
1133
+ else {
1134
+ transformed[key] = value;
1135
+ }
1136
+ }
1137
+ return transformed;
1138
+ };