@raydiant/playlist-window-manager 0.0.0-test-32 → 0.0.0-test30

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.
@@ -87,6 +87,7 @@ var BrowserViewRenderer = /** @class */ (function () {
87
87
  view: new electron_1.BrowserView({
88
88
  webPreferences: {
89
89
  preload: path.join(__dirname, 'preload.js'),
90
+ contextIsolation: false,
90
91
  },
91
92
  }),
92
93
  bounds: bounds || __assign(__assign({}, this.mainWindow.getBounds()), { x: 0, y: 0 }),
@@ -10,6 +10,7 @@ interface BrowserWindowRendererOptions {
10
10
  renderChildWindowsAsBrowserViews: boolean;
11
11
  useWindowPool: boolean;
12
12
  logger: Logger;
13
+ fullscreen?: boolean;
13
14
  proxySettings?: ProxySettings;
14
15
  windowCrashHandler?: () => void;
15
16
  }
@@ -87,13 +87,17 @@ var BrowserWindowRenderer = /** @class */ (function () {
87
87
  this.offscreenWindow = new electron_1.BrowserWindow({
88
88
  show: false,
89
89
  frame: this.opts.frame,
90
+ fullscreen: this.opts.fullscreen,
90
91
  hasShadow: this.opts.hasShadow,
91
92
  webPreferences: {
92
93
  preload: path.join(__dirname, 'preload.js'),
94
+ contextIsolation: false,
93
95
  },
94
96
  });
95
97
  this.proxySettings = null;
96
- this.offscreenWindow.setBounds(opts.bounds);
98
+ if (!opts.fullscreen) {
99
+ this.offscreenWindow.setBounds(opts.bounds);
100
+ }
97
101
  if (opts.proxySettings) {
98
102
  this.proxySettings = opts.proxySettings;
99
103
  }
@@ -118,11 +122,13 @@ var BrowserWindowRenderer = /** @class */ (function () {
118
122
  ? this.createOrGetPooledBrowserView(windowId, {
119
123
  webPreferences: {
120
124
  preload: path.join(__dirname, 'preload.js'),
125
+ contextIsolation: false,
121
126
  },
122
127
  })
123
128
  : this.createOrGetPooledBrowserWindow(windowId, {
124
129
  show: false,
125
130
  frame: this.opts.frame,
131
+ fullscreen: this.opts.fullscreen,
126
132
  // NOTE: useWindowPool: true does not work with renderChildWindowsAsBrowserViews: false
127
133
  // because the parent can't be changed after creating the BrowserWindow.
128
134
  parent: parentWindowId
@@ -132,6 +138,7 @@ var BrowserWindowRenderer = /** @class */ (function () {
132
138
  hasShadow: this.opts.hasShadow,
133
139
  webPreferences: {
134
140
  preload: path.join(__dirname, 'preload.js'),
141
+ contextIsolation: false,
135
142
  },
136
143
  }),
137
144
  // If we are creating a child window and renderChildWindowsAsBrowserViews is false that means
@@ -172,7 +179,9 @@ var BrowserWindowRenderer = /** @class */ (function () {
172
179
  // Electron issue: https://github.com/electron/electron/issues/20357
173
180
  window.view.setBackgroundColor(backgroundColor === 'transparent' ? '#00000000' : backgroundColor);
174
181
  }
175
- window.view.setBounds(window.bounds);
182
+ if (!this.opts.fullscreen) {
183
+ window.view.setBounds(window.bounds);
184
+ }
176
185
  if (!this.proxySettings) return [3 /*break*/, 2];
177
186
  return [4 /*yield*/, window.view.webContents.session.setProxy(this.proxySettings)];
178
187
  case 1:
@@ -9,6 +9,7 @@ export interface PlaylistWindowManagerOptions {
9
9
  device?: Device;
10
10
  readyTimeoutDurationSeconds?: number;
11
11
  appRendererUrl?: string;
12
+ appRendererOfflineSupport?: boolean;
12
13
  bounds?: WindowBounds;
13
14
  backgroundColor?: string;
14
15
  themeOverride?: Theme;
@@ -677,7 +677,7 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
677
677
  }
678
678
  };
679
679
  PlaylistWindowManager.prototype.createWindow = function (pr) {
680
- var _a = this.options, readyTimeoutDurationSeconds = _a.readyTimeoutDurationSeconds, appRendererUrl = _a.appRendererUrl, backgroundColor = _a.backgroundColor, device = _a.device, logger = _a.logger, windowName = _a.windowName, parentWindowId = _a.parentWindowId, isPreview = _a.isPreview;
680
+ 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
681
  if (!this.ruleEngine) {
682
682
  throw new Error('Attempted to create window but ruleEngine was not provided');
683
683
  }
@@ -712,6 +712,7 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
712
712
  forceMute: this.forceMute,
713
713
  readyTimeoutDurationSeconds: readyTimeoutDurationSeconds,
714
714
  appRendererUrl: appRendererUrl,
715
+ appRendererOfflineSupport: appRendererOfflineSupport,
715
716
  bounds: this.bounds,
716
717
  backgroundColor: backgroundColor,
717
718
  playlistWindowManagerState: this.state,
@@ -940,6 +941,10 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
940
941
  // Swap windows.
941
942
  this.currentWindow = this.nextWindow;
942
943
  if (this.currentWindow) {
944
+ // Restore this.currentPresentation value since if this.removeCurrentWindow()
945
+ // was called then this.currentPresentation was set to null.
946
+ // This fixes an issue where publishing a playlist with single presentation results
947
+ // in two iFrames created. See CX-2602 for more details.
943
948
  this.currentPresentation = nextPresentation;
944
949
  this.currentWindow.onComplete(this.handleCurrentPresentationComplete);
945
950
  this.currentWindow.onError(this.handleCurrentPresentationError);
@@ -23,6 +23,7 @@ export interface PresentationWindowOptions {
23
23
  renderer: PresentationWindowRenderer;
24
24
  readyTimeoutDurationSeconds?: number;
25
25
  appRendererUrl?: string;
26
+ appRendererOfflineSupport?: boolean;
26
27
  bounds?: WindowBounds;
27
28
  backgroundColor?: string;
28
29
  isPreview?: boolean;
@@ -102,7 +103,7 @@ export default class PresentationWindow {
102
103
  private isEmbeddedApp;
103
104
  private allChildWindowManagersReady;
104
105
  private checkIsReadyCallback;
105
- private appendWindowIdToHash;
106
+ private getFullAppRendererUrl;
106
107
  private loadEmbeddedApp;
107
108
  private loadLegacyApp;
108
109
  private createAndLoadWindow;
@@ -81,7 +81,7 @@ var PlaylistWindowManager_1 = __importDefault(require("./PlaylistWindowManager")
81
81
  var WindowTimeoutError_1 = __importDefault(require("./WindowTimeoutError"));
82
82
  var WindowLoadError_1 = __importDefault(require("./WindowLoadError"));
83
83
  // TODO: Automatically inject latest version when building in CI.
84
- var defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.4/index.html';
84
+ var defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.7/index.html';
85
85
  var isValidNumber = function (value) {
86
86
  return typeof value === 'number' && !isNaN(value);
87
87
  };
@@ -690,10 +690,14 @@ var PresentationWindow = /** @class */ (function () {
690
690
  }
691
691
  }
692
692
  };
693
- PresentationWindow.prototype.appendWindowIdToHash = function (urlStr, windowId) {
694
- var url = new URL(urlStr);
693
+ PresentationWindow.prototype.getFullAppRendererUrl = function (_a) {
694
+ var appRendererUrl = _a.appRendererUrl, windowId = _a.windowId, appRendererOfflineSupport = _a.appRendererOfflineSupport;
695
+ var url = new URL(appRendererUrl);
695
696
  var hashParams = new URLSearchParams(url.hash.slice(1));
696
697
  hashParams.set('__raydiantWindowId', windowId);
698
+ if (appRendererOfflineSupport === true) {
699
+ hashParams.set('__raydiantOfflineSupport', 'true');
700
+ }
697
701
  url.hash = hashParams.toString();
698
702
  return url.toString();
699
703
  };
@@ -724,13 +728,17 @@ var PresentationWindow = /** @class */ (function () {
724
728
  };
725
729
  PresentationWindow.prototype.loadLegacyApp = function () {
726
730
  return __awaiter(this, void 0, void 0, function () {
727
- var _a, windowId, _b, appRendererUrl, backgroundColor;
731
+ var _a, windowId, _b, appRendererUrl, appRendererOfflineSupport, backgroundColor;
728
732
  return __generator(this, function (_c) {
729
733
  switch (_c.label) {
730
734
  case 0:
731
- _a = this.options, windowId = _a.windowId, _b = _a.appRendererUrl, appRendererUrl = _b === void 0 ? defaultAppRendererUrl : _b, backgroundColor = _a.backgroundColor;
735
+ _a = this.options, windowId = _a.windowId, _b = _a.appRendererUrl, appRendererUrl = _b === void 0 ? defaultAppRendererUrl : _b, appRendererOfflineSupport = _a.appRendererOfflineSupport, backgroundColor = _a.backgroundColor;
732
736
  this.logInfo("Create window '".concat(windowId, "'"));
733
- return [4 /*yield*/, this.createAndLoadWindow(this.appendWindowIdToHash(appRendererUrl, windowId), backgroundColor || '#000000', // Default to black bg for Raydiant apps
737
+ return [4 /*yield*/, this.createAndLoadWindow(this.getFullAppRendererUrl({
738
+ appRendererUrl: appRendererUrl,
739
+ windowId: windowId,
740
+ appRendererOfflineSupport: appRendererOfflineSupport,
741
+ }), backgroundColor || '#000000', // Default to black bg for Raydiant apps
734
742
  this.handleLegacyMessage)];
735
743
  case 1:
736
744
  _c.sent();
@@ -1034,12 +1042,16 @@ var PresentationWindow = /** @class */ (function () {
1034
1042
  }
1035
1043
  };
1036
1044
  PresentationWindow.prototype.getEmbeddedAppUrl = function () {
1037
- var windowId = this.options.windowId;
1045
+ var _a = this.options, windowId = _a.windowId, appRendererOfflineSupport = _a.appRendererOfflineSupport;
1038
1046
  var metadata = {
1039
1047
  renderMode: this.options.isPreview ? 'preview' : 'live',
1040
1048
  };
1041
1049
  var url = (0, embeddedApps_1.default)(this.presentation, this.options.applicationVersion, metadata);
1042
- return this.appendWindowIdToHash(url, windowId);
1050
+ return this.getFullAppRendererUrl({
1051
+ appRendererUrl: url,
1052
+ windowId: windowId,
1053
+ appRendererOfflineSupport: appRendererOfflineSupport,
1054
+ });
1043
1055
  };
1044
1056
  PresentationWindow.prototype.handleReady = function () {
1045
1057
  this.didReceiveReady = true;
@@ -24,6 +24,9 @@ function createEmbeddedApp(presentation, applicationVersion, metadata) {
24
24
  if (metadataKey === 'renderMode') {
25
25
  value = metadata.renderMode;
26
26
  }
27
+ else if (metadataKey === 'token') {
28
+ value = presentation.token;
29
+ }
27
30
  }
28
31
  else {
29
32
  // Don't replace variables that are numbers to allow setting
@@ -121,3 +121,10 @@ test('File input uses url as value', function () {
121
121
  presentationProperties: [{ type: 'file', name: 'file' }],
122
122
  }), createMetadata())).toBe("https://example.come?image=".concat(encodeURIComponent('https://image.png')));
123
123
  });
124
+ test('Replaces $token with presentation token', function () {
125
+ var presentation = createPresentation({ token: 'abc' });
126
+ var applicationVersion = createApplicationVersion({
127
+ embeddedUrlFormat: 'https://example.com?token=:$token',
128
+ });
129
+ expect((0, embeddedApps_1.default)(presentation, applicationVersion, createMetadata())).toBe('https://example.com?token=abc');
130
+ });
package/build/types.d.ts CHANGED
@@ -19,6 +19,7 @@ export interface Presentation {
19
19
  playlistId: string;
20
20
  }>;
21
21
  };
22
+ token?: string;
22
23
  }
23
24
  export interface ApplicationVersion {
24
25
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raydiant/playlist-window-manager",
3
- "version": "0.0.0-test-32",
3
+ "version": "0.0.0-test30",
4
4
  "description": "Window manager for playlist playback.",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "@types/jschannel": "^1.0.1",
23
23
  "@types/jest": "^24.0.15",
24
24
  "@types/uuid": "8.3.0",
25
- "electron": "10.1.5",
25
+ "electron": "28.1.2",
26
26
  "jest": "^24.8.0",
27
27
  "ts-jest": "^24.0.2",
28
28
  "typescript": "^4.1.2"
@@ -37,6 +37,7 @@ export default class BrowserViewRenderer implements PresentationWindowRenderer {
37
37
  view: new BrowserView({
38
38
  webPreferences: {
39
39
  preload: path.join(__dirname, 'preload.js'),
40
+ contextIsolation: false,
40
41
  },
41
42
  }),
42
43
 
@@ -5,9 +5,9 @@ import {
5
5
  ipcMain,
6
6
  IpcMainEvent,
7
7
  Event,
8
- Details,
9
8
  BrowserWindowConstructorOptions,
10
9
  BrowserViewConstructorOptions,
10
+ RenderProcessGoneDetails,
11
11
  } from 'electron';
12
12
  import {
13
13
  PresentationWindowRenderer,
@@ -32,7 +32,10 @@ interface BrowserWindowRendererWindow {
32
32
  payload?: any
33
33
  ) => void;
34
34
  unresponsiveCallback: () => void;
35
- renderProcessGoneCallback: (event: Event, details: Details) => void;
35
+ renderProcessGoneCallback: (
36
+ event: Event,
37
+ details: RenderProcessGoneDetails
38
+ ) => void;
36
39
  }
37
40
 
38
41
  interface BrowserWindowRendererOptions {
@@ -42,6 +45,7 @@ interface BrowserWindowRendererOptions {
42
45
  renderChildWindowsAsBrowserViews: boolean;
43
46
  useWindowPool: boolean;
44
47
  logger: Logger;
48
+ fullscreen?: boolean;
45
49
  proxySettings?: ProxySettings;
46
50
  windowCrashHandler?: () => void;
47
51
  }
@@ -61,9 +65,11 @@ export default class BrowserWindowRenderer
61
65
  private offscreenWindow = new BrowserWindow({
62
66
  show: false,
63
67
  frame: this.opts.frame,
68
+ fullscreen: this.opts.fullscreen,
64
69
  hasShadow: this.opts.hasShadow,
65
70
  webPreferences: {
66
71
  preload: path.join(__dirname, 'preload.js'),
72
+ contextIsolation: false,
67
73
  },
68
74
  });
69
75
 
@@ -72,7 +78,9 @@ export default class BrowserWindowRenderer
72
78
  private logger: Logger;
73
79
 
74
80
  constructor(private opts: BrowserWindowRendererOptions) {
75
- this.offscreenWindow.setBounds(opts.bounds);
81
+ if (!opts.fullscreen) {
82
+ this.offscreenWindow.setBounds(opts.bounds);
83
+ }
76
84
  if (opts.proxySettings) {
77
85
  this.proxySettings = opts.proxySettings;
78
86
  }
@@ -101,11 +109,13 @@ export default class BrowserWindowRenderer
101
109
  ? this.createOrGetPooledBrowserView(windowId, {
102
110
  webPreferences: {
103
111
  preload: path.join(__dirname, 'preload.js'),
112
+ contextIsolation: false,
104
113
  },
105
114
  })
106
115
  : this.createOrGetPooledBrowserWindow(windowId, {
107
116
  show: false,
108
117
  frame: this.opts.frame,
118
+ fullscreen: this.opts.fullscreen,
109
119
  // NOTE: useWindowPool: true does not work with renderChildWindowsAsBrowserViews: false
110
120
  // because the parent can't be changed after creating the BrowserWindow.
111
121
  parent: parentWindowId
@@ -115,6 +125,7 @@ export default class BrowserWindowRenderer
115
125
  hasShadow: this.opts.hasShadow,
116
126
  webPreferences: {
117
127
  preload: path.join(__dirname, 'preload.js'),
128
+ contextIsolation: false,
118
129
  },
119
130
  }),
120
131
  // If we are creating a child window and renderChildWindowsAsBrowserViews is false that means
@@ -148,7 +159,10 @@ export default class BrowserWindowRenderer
148
159
  );
149
160
  },
150
161
 
151
- renderProcessGoneCallback: (_: Event, details: Details) => {
162
+ renderProcessGoneCallback: (
163
+ _: Event,
164
+ details: RenderProcessGoneDetails
165
+ ) => {
152
166
  this.logger.error(
153
167
  `Window received 'render-process-gone' event. Reason: ${details.reason}`,
154
168
  { windowId }
@@ -191,7 +205,9 @@ export default class BrowserWindowRenderer
191
205
  );
192
206
  }
193
207
 
194
- window.view.setBounds(window.bounds);
208
+ if (!this.opts.fullscreen) {
209
+ window.view.setBounds(window.bounds);
210
+ }
195
211
 
196
212
  if (this.proxySettings) {
197
213
  await window.view.webContents.session.setProxy(this.proxySettings);
@@ -40,6 +40,10 @@ export interface PlaylistWindowManagerOptions {
40
40
  // Override the default app renderer url
41
41
  appRendererUrl?: string;
42
42
 
43
+ // App renderer offline support.
44
+ // If true, the app renderer will be using service worker to cache resources for offline support.
45
+ appRendererOfflineSupport?: boolean;
46
+
43
47
  // The bounds of the window manager, used for child windows
44
48
  bounds?: WindowBounds;
45
49
 
@@ -488,6 +492,7 @@ export default class PlaylistWindowManager extends EventEmitter {
488
492
  const {
489
493
  readyTimeoutDurationSeconds,
490
494
  appRendererUrl,
495
+ appRendererOfflineSupport,
491
496
  backgroundColor,
492
497
  device,
493
498
  logger,
@@ -541,6 +546,7 @@ export default class PlaylistWindowManager extends EventEmitter {
541
546
  forceMute: this.forceMute,
542
547
  readyTimeoutDurationSeconds,
543
548
  appRendererUrl,
549
+ appRendererOfflineSupport,
544
550
  bounds: this.bounds,
545
551
  backgroundColor,
546
552
  playlistWindowManagerState: this.state,
@@ -698,6 +704,8 @@ export default class PlaylistWindowManager extends EventEmitter {
698
704
  nextPreviewPresentationId = preview.presentationId;
699
705
  }
700
706
 
707
+ // Save reference to next presentation since later call to
708
+ // this.removeCurrentWindow() will set this.currentPresentation to null.
701
709
  const nextPresentation = this.nextPresentation;
702
710
  // Set this.currentPresentationId before removing the current window to avoid timing issues with previewCheck
703
711
  // triggering during removeCurrentWindow. Current presentation id needs to be set to the next
@@ -735,6 +743,10 @@ export default class PlaylistWindowManager extends EventEmitter {
735
743
  // Swap windows.
736
744
  this.currentWindow = this.nextWindow;
737
745
  if (this.currentWindow) {
746
+ // Restore this.currentPresentation value since if this.removeCurrentWindow()
747
+ // was called then this.currentPresentation was set to null.
748
+ // This fixes an issue where publishing a playlist with single presentation results
749
+ // in two iFrames created. See CX-2602 for more details.
738
750
  this.currentPresentation = nextPresentation;
739
751
  this.currentWindow.onComplete(this.handleCurrentPresentationComplete);
740
752
  this.currentWindow.onError(this.handleCurrentPresentationError);
@@ -47,6 +47,7 @@ export interface PresentationWindowOptions {
47
47
  renderer: PresentationWindowRenderer;
48
48
  readyTimeoutDurationSeconds?: number;
49
49
  appRendererUrl?: string;
50
+ appRendererOfflineSupport?: boolean;
50
51
  bounds?: WindowBounds;
51
52
  backgroundColor?: string;
52
53
  isPreview?: boolean;
@@ -60,7 +61,7 @@ export interface PresentationWindowOptions {
60
61
  }
61
62
 
62
63
  // TODO: Automatically inject latest version when building in CI.
63
- const defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.4/index.html';
64
+ const defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.7/index.html';
64
65
 
65
66
  const isValidNumber = (value: any) =>
66
67
  typeof value === 'number' && !isNaN(value);
@@ -488,10 +489,21 @@ export default class PresentationWindow {
488
489
  }
489
490
  }
490
491
 
491
- private appendWindowIdToHash(urlStr: string, windowId: string) {
492
- const url = new URL(urlStr);
492
+ private getFullAppRendererUrl({
493
+ appRendererUrl,
494
+ windowId,
495
+ appRendererOfflineSupport,
496
+ }: {
497
+ appRendererUrl: string;
498
+ windowId: string;
499
+ appRendererOfflineSupport: boolean | undefined;
500
+ }) {
501
+ const url = new URL(appRendererUrl);
493
502
  const hashParams = new URLSearchParams(url.hash.slice(1));
494
503
  hashParams.set('__raydiantWindowId', windowId);
504
+ if (appRendererOfflineSupport === true) {
505
+ hashParams.set('__raydiantOfflineSupport', 'true');
506
+ }
495
507
  url.hash = hashParams.toString();
496
508
 
497
509
  return url.toString();
@@ -525,13 +537,18 @@ export default class PresentationWindow {
525
537
  const {
526
538
  windowId,
527
539
  appRendererUrl = defaultAppRendererUrl,
540
+ appRendererOfflineSupport,
528
541
  backgroundColor,
529
542
  } = this.options;
530
543
 
531
544
  this.logInfo(`Create window '${windowId}'`);
532
545
 
533
546
  await this.createAndLoadWindow(
534
- this.appendWindowIdToHash(appRendererUrl, windowId),
547
+ this.getFullAppRendererUrl({
548
+ appRendererUrl,
549
+ windowId,
550
+ appRendererOfflineSupport,
551
+ }),
535
552
  backgroundColor || '#000000', // Default to black bg for Raydiant apps
536
553
  this.handleLegacyMessage
537
554
  );
@@ -861,7 +878,7 @@ export default class PresentationWindow {
861
878
  }
862
879
 
863
880
  private getEmbeddedAppUrl() {
864
- const { windowId } = this.options;
881
+ const { windowId, appRendererOfflineSupport } = this.options;
865
882
 
866
883
  const metadata: EmbeddedAppMetadata = {
867
884
  renderMode: this.options.isPreview ? 'preview' : 'live',
@@ -873,7 +890,11 @@ export default class PresentationWindow {
873
890
  metadata
874
891
  );
875
892
 
876
- return this.appendWindowIdToHash(url, windowId);
893
+ return this.getFullAppRendererUrl({
894
+ appRendererUrl: url,
895
+ windowId,
896
+ appRendererOfflineSupport,
897
+ });
877
898
  }
878
899
 
879
900
  private handleEmbeddedMessage = async (type: string, payload?: any) => {
@@ -229,3 +229,14 @@ test('File input uses url as value', () => {
229
229
  `https://example.come?image=${encodeURIComponent('https://image.png')}`
230
230
  );
231
231
  });
232
+
233
+ test('Replaces $token with presentation token', () => {
234
+ const presentation = createPresentation({ token: 'abc' });
235
+ const applicationVersion = createApplicationVersion({
236
+ embeddedUrlFormat: 'https://example.com?token=:$token',
237
+ });
238
+
239
+ expect(
240
+ createEmbeddedApp(presentation, applicationVersion, createMetadata())
241
+ ).toBe('https://example.com?token=abc');
242
+ });
@@ -32,6 +32,8 @@ export default function createEmbeddedApp(
32
32
  const metadataKey = variableName.slice(1);
33
33
  if (metadataKey === 'renderMode') {
34
34
  value = metadata.renderMode;
35
+ } else if (metadataKey === 'token') {
36
+ value = presentation.token;
35
37
  }
36
38
  } else {
37
39
  // Don't replace variables that are numbers to allow setting
package/src/types.ts CHANGED
@@ -16,6 +16,7 @@ export interface Presentation {
16
16
  };
17
17
  presentationsPlaylists: Array<{ playlistId: string }>;
18
18
  };
19
+ token?: string;
19
20
  }
20
21
 
21
22
  export interface ApplicationVersion {