@raydiant/playlist-window-manager 0.19.0 → 0.20.0-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/PlaylistWindowManager.d.ts +1 -0
- package/build/PlaylistWindowManager.js +7 -0
- package/build/PresentationWindow.d.ts +3 -1
- package/build/PresentationWindow.js +26 -2
- package/build/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/PlaylistWindowManager.ts +11 -1
- package/src/PresentationWindow.ts +34 -3
- package/src/types.ts +6 -0
|
@@ -89,6 +89,7 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
89
89
|
private evalRuleEngine;
|
|
90
90
|
private handleEnableInterruptLock;
|
|
91
91
|
private handleDisableInterruptLock;
|
|
92
|
+
private handleAnalyticsEvent;
|
|
92
93
|
private handleCurrentPresentationComplete;
|
|
93
94
|
private handleCurrentPresentationError;
|
|
94
95
|
private handleNextPresentationError;
|
|
@@ -109,6 +109,11 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
|
|
|
109
109
|
_this.endCurrentPresentation();
|
|
110
110
|
}
|
|
111
111
|
};
|
|
112
|
+
_this.handleAnalyticsEvent = function (event) {
|
|
113
|
+
// Emit the event on the current window. Only the current window should
|
|
114
|
+
// send analytics events since the next window is not visible.
|
|
115
|
+
_this.emitCurrentWindowEvent('window_analytics_event', event);
|
|
116
|
+
};
|
|
112
117
|
_this.handleCurrentPresentationComplete = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
113
118
|
var logger, isThrottled, now, timeSinceLastComplete, delay, _a, next, preview, nextPreviewPresentationId;
|
|
114
119
|
var _this = this;
|
|
@@ -693,6 +698,7 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
|
|
|
693
698
|
this.currentWindow.onError(this.handleCurrentPresentationError);
|
|
694
699
|
this.currentWindow.onEnableInterruptLock(this.handleEnableInterruptLock);
|
|
695
700
|
this.currentWindow.onDisableInterruptLock(this.handleDisableInterruptLock);
|
|
701
|
+
this.currentWindow.onAnalyticsEvent(this.handleAnalyticsEvent);
|
|
696
702
|
return [4 /*yield*/, this.currentWindow.load()];
|
|
697
703
|
case 1:
|
|
698
704
|
_a.sent();
|
|
@@ -896,6 +902,7 @@ var PlaylistWindowManager = /** @class */ (function (_super) {
|
|
|
896
902
|
this.currentWindow.onError(this.handleCurrentPresentationError);
|
|
897
903
|
this.currentWindow.onEnableInterruptLock(this.handleEnableInterruptLock);
|
|
898
904
|
this.currentWindow.onDisableInterruptLock(this.handleDisableInterruptLock);
|
|
905
|
+
this.currentWindow.onAnalyticsEvent(this.handleAnalyticsEvent);
|
|
899
906
|
}
|
|
900
907
|
// Play new current window.
|
|
901
908
|
this.playCurrentWindow();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as RE from '@raydiant/playlist-rule-engine';
|
|
2
2
|
import PlaylistWindowManagerState from './PlaylistWindowManagerState';
|
|
3
3
|
import PlaylistWindowManager from './PlaylistWindowManager';
|
|
4
|
-
import { Presentation, ApplicationVersion, Theme, Device, PresentationWindowRenderer, WindowBounds, Logger, BuilderState, WorkerState } from './types';
|
|
4
|
+
import { Presentation, ApplicationVersion, Theme, Device, PresentationWindowRenderer, WindowBounds, Logger, BuilderState, WorkerState, AnalyticsEvent } from './types';
|
|
5
5
|
export interface PresentationWindowOptions {
|
|
6
6
|
windowManager?: PlaylistWindowManager;
|
|
7
7
|
windowId: string;
|
|
@@ -49,6 +49,7 @@ export default class PresentationWindow {
|
|
|
49
49
|
private isChildWindowLocked;
|
|
50
50
|
private enableInterruptLockCallback;
|
|
51
51
|
private disableInterruptLockCallback;
|
|
52
|
+
private analyticsEventCallback;
|
|
52
53
|
private builderState;
|
|
53
54
|
private presentation;
|
|
54
55
|
private playlistWindowManagerState;
|
|
@@ -73,6 +74,7 @@ export default class PresentationWindow {
|
|
|
73
74
|
onError(callback: ((err: Error) => void) | null): void;
|
|
74
75
|
onEnableInterruptLock(callback: (() => void) | null): void;
|
|
75
76
|
onDisableInterruptLock(callback: (() => void) | null): void;
|
|
77
|
+
onAnalyticsEvent(callback: ((event: AnalyticsEvent) => void) | null): void;
|
|
76
78
|
isReady(): boolean;
|
|
77
79
|
isComplete(): boolean;
|
|
78
80
|
isPlaying(): boolean;
|
|
@@ -67,6 +67,15 @@ var defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.0/index.html';
|
|
|
67
67
|
var isValidNumber = function (value) {
|
|
68
68
|
return typeof value === 'number' && !isNaN(value);
|
|
69
69
|
};
|
|
70
|
+
var isValidAnalyticsEvent = function (value) {
|
|
71
|
+
return value &&
|
|
72
|
+
typeof value === 'object' &&
|
|
73
|
+
typeof value.type === 'string' &&
|
|
74
|
+
typeof value.source === 'string' &&
|
|
75
|
+
(typeof value.productCategory === 'string' ||
|
|
76
|
+
value.productCategory === undefined ||
|
|
77
|
+
value.productCategory === null);
|
|
78
|
+
};
|
|
70
79
|
var PresentationWindow = /** @class */ (function () {
|
|
71
80
|
function PresentationWindow(options) {
|
|
72
81
|
var _this = this;
|
|
@@ -87,6 +96,7 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
87
96
|
this.isChildWindowLocked = {};
|
|
88
97
|
this.enableInterruptLockCallback = null;
|
|
89
98
|
this.disableInterruptLockCallback = null;
|
|
99
|
+
this.analyticsEventCallback = null;
|
|
90
100
|
this.forceMute = false;
|
|
91
101
|
this.error = null;
|
|
92
102
|
this.workerState = {};
|
|
@@ -168,6 +178,12 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
168
178
|
}
|
|
169
179
|
break;
|
|
170
180
|
}
|
|
181
|
+
case 'analytics-event': {
|
|
182
|
+
if (this.analyticsEventCallback && isValidAnalyticsEvent(payload)) {
|
|
183
|
+
this.analyticsEventCallback(payload);
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
171
187
|
default: {
|
|
172
188
|
this.logWarning("Received unknown embedded message type: " + type);
|
|
173
189
|
}
|
|
@@ -400,6 +416,9 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
400
416
|
PresentationWindow.prototype.onDisableInterruptLock = function (callback) {
|
|
401
417
|
this.disableInterruptLockCallback = callback;
|
|
402
418
|
};
|
|
419
|
+
PresentationWindow.prototype.onAnalyticsEvent = function (callback) {
|
|
420
|
+
this.analyticsEventCallback = callback;
|
|
421
|
+
};
|
|
403
422
|
PresentationWindow.prototype.isReady = function () {
|
|
404
423
|
// TODO: To support the 'ready' event in embedded apps, they will need to tell the
|
|
405
424
|
// runtime that it should wait for ready instead of DOMLoaded. This could be a "wait
|
|
@@ -523,7 +542,7 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
523
542
|
}
|
|
524
543
|
url = this.getEmbeddedAppUrl();
|
|
525
544
|
this.logInfo("Create window '" + windowId + "' for embedded app url '" + url + "'");
|
|
526
|
-
return [4 /*yield*/, this.createAndLoadWindow(
|
|
545
|
+
return [4 /*yield*/, this.createAndLoadWindow(url,
|
|
527
546
|
// Embedded apps should not have a backgroundColor because some sites expect
|
|
528
547
|
// the browser default of white will be applied.
|
|
529
548
|
'#ffffff', this.handleEmbeddedMessage)];
|
|
@@ -766,6 +785,9 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
766
785
|
windowManager.on('window_end_error', function (metadata) {
|
|
767
786
|
parentWindowManager.emit('window_end_error', metadata);
|
|
768
787
|
});
|
|
788
|
+
windowManager.on('window_analytics_event', function (metadata) {
|
|
789
|
+
parentWindowManager.emit('window_analytics_event', metadata);
|
|
790
|
+
});
|
|
769
791
|
}
|
|
770
792
|
this.windowManagers[windowName] = windowManager;
|
|
771
793
|
windowManager.setRenderer(renderer);
|
|
@@ -832,10 +854,12 @@ var PresentationWindow = /** @class */ (function () {
|
|
|
832
854
|
}
|
|
833
855
|
};
|
|
834
856
|
PresentationWindow.prototype.getEmbeddedAppUrl = function () {
|
|
857
|
+
var windowId = this.options.windowId;
|
|
835
858
|
var metadata = {
|
|
836
859
|
renderMode: this.options.isPreview ? 'preview' : 'live'
|
|
837
860
|
};
|
|
838
|
-
|
|
861
|
+
var url = embeddedApps_1.default(this.presentation, this.options.applicationVersion, metadata);
|
|
862
|
+
return this.appendWindowIdToHash(url, windowId);
|
|
839
863
|
};
|
|
840
864
|
PresentationWindow.prototype.handleReady = function () {
|
|
841
865
|
this.didReceiveReady = true;
|
package/build/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
WindowBounds,
|
|
8
8
|
Theme,
|
|
9
9
|
Logger,
|
|
10
|
-
WorkerState
|
|
10
|
+
WorkerState,
|
|
11
|
+
AnalyticsEvent
|
|
11
12
|
} from './types';
|
|
12
13
|
import PresentationWindow from './PresentationWindow';
|
|
13
14
|
import PlaylistWindowManagerState from './PlaylistWindowManagerState';
|
|
@@ -521,6 +522,8 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
521
522
|
this.currentWindow.onError(this.handleCurrentPresentationError);
|
|
522
523
|
this.currentWindow.onEnableInterruptLock(this.handleEnableInterruptLock);
|
|
523
524
|
this.currentWindow.onDisableInterruptLock(this.handleDisableInterruptLock);
|
|
525
|
+
this.currentWindow.onAnalyticsEvent(this.handleAnalyticsEvent);
|
|
526
|
+
|
|
524
527
|
await this.currentWindow.load();
|
|
525
528
|
}
|
|
526
529
|
|
|
@@ -691,6 +694,7 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
691
694
|
this.currentWindow.onDisableInterruptLock(
|
|
692
695
|
this.handleDisableInterruptLock
|
|
693
696
|
);
|
|
697
|
+
this.currentWindow.onAnalyticsEvent(this.handleAnalyticsEvent);
|
|
694
698
|
}
|
|
695
699
|
|
|
696
700
|
// Play new current window.
|
|
@@ -754,6 +758,12 @@ export default class PlaylistWindowManager extends EventEmitter {
|
|
|
754
758
|
}
|
|
755
759
|
};
|
|
756
760
|
|
|
761
|
+
private handleAnalyticsEvent = (event: AnalyticsEvent) => {
|
|
762
|
+
// Emit the event on the current window. Only the current window should
|
|
763
|
+
// send analytics events since the next window is not visible.
|
|
764
|
+
this.emitCurrentWindowEvent('window_analytics_event', event);
|
|
765
|
+
};
|
|
766
|
+
|
|
757
767
|
private handleCurrentPresentationComplete = async () => {
|
|
758
768
|
const { logger } = this.options;
|
|
759
769
|
|
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
OpenChildWindowOptions,
|
|
17
17
|
BuilderState,
|
|
18
18
|
WorkerState,
|
|
19
|
-
EmbeddedAppMetadata
|
|
19
|
+
EmbeddedAppMetadata,
|
|
20
|
+
AnalyticsEvent
|
|
20
21
|
} from './types';
|
|
21
22
|
|
|
22
23
|
export interface PresentationWindowOptions {
|
|
@@ -57,6 +58,15 @@ const defaultAppRendererUrl = 'https://apps.raydiant.com/3.0.0/index.html';
|
|
|
57
58
|
const isValidNumber = (value: any) =>
|
|
58
59
|
typeof value === 'number' && !isNaN(value);
|
|
59
60
|
|
|
61
|
+
const isValidAnalyticsEvent = (value: any): value is AnalyticsEvent =>
|
|
62
|
+
value &&
|
|
63
|
+
typeof value === 'object' &&
|
|
64
|
+
typeof value.type === 'string' &&
|
|
65
|
+
typeof value.source === 'string' &&
|
|
66
|
+
(typeof value.productCategory === 'string' ||
|
|
67
|
+
value.productCategory === undefined ||
|
|
68
|
+
value.productCategory === null);
|
|
69
|
+
|
|
60
70
|
export default class PresentationWindow {
|
|
61
71
|
private didReceiveReady: boolean = false;
|
|
62
72
|
private readyCallback: (() => void) | null = null;
|
|
@@ -76,6 +86,9 @@ export default class PresentationWindow {
|
|
|
76
86
|
private isChildWindowLocked: { [windowId: string]: boolean } = {};
|
|
77
87
|
private enableInterruptLockCallback: (() => void) | null = null;
|
|
78
88
|
private disableInterruptLockCallback: (() => void) | null = null;
|
|
89
|
+
private analyticsEventCallback:
|
|
90
|
+
| ((event: AnalyticsEvent) => void)
|
|
91
|
+
| null = null;
|
|
79
92
|
|
|
80
93
|
private builderState: BuilderState | undefined;
|
|
81
94
|
private presentation: Presentation;
|
|
@@ -264,6 +277,10 @@ export default class PresentationWindow {
|
|
|
264
277
|
this.disableInterruptLockCallback = callback;
|
|
265
278
|
}
|
|
266
279
|
|
|
280
|
+
public onAnalyticsEvent(callback: ((event: AnalyticsEvent) => void) | null) {
|
|
281
|
+
this.analyticsEventCallback = callback;
|
|
282
|
+
}
|
|
283
|
+
|
|
267
284
|
public isReady() {
|
|
268
285
|
// TODO: To support the 'ready' event in embedded apps, they will need to tell the
|
|
269
286
|
// runtime that it should wait for ready instead of DOMLoaded. This could be a "wait
|
|
@@ -408,7 +425,7 @@ export default class PresentationWindow {
|
|
|
408
425
|
this.logInfo(`Create window '${windowId}' for embedded app url '${url}'`);
|
|
409
426
|
|
|
410
427
|
await this.createAndLoadWindow(
|
|
411
|
-
|
|
428
|
+
url,
|
|
412
429
|
// Embedded apps should not have a backgroundColor because some sites expect
|
|
413
430
|
// the browser default of white will be applied.
|
|
414
431
|
'#ffffff',
|
|
@@ -671,6 +688,9 @@ export default class PresentationWindow {
|
|
|
671
688
|
windowManager.on('window_end_error', metadata => {
|
|
672
689
|
parentWindowManager.emit('window_end_error', metadata);
|
|
673
690
|
});
|
|
691
|
+
windowManager.on('window_analytics_event', metadata => {
|
|
692
|
+
parentWindowManager.emit('window_analytics_event', metadata);
|
|
693
|
+
});
|
|
674
694
|
}
|
|
675
695
|
|
|
676
696
|
this.windowManagers[windowName] = windowManager;
|
|
@@ -741,15 +761,19 @@ export default class PresentationWindow {
|
|
|
741
761
|
}
|
|
742
762
|
|
|
743
763
|
private getEmbeddedAppUrl() {
|
|
764
|
+
const { windowId } = this.options;
|
|
765
|
+
|
|
744
766
|
const metadata: EmbeddedAppMetadata = {
|
|
745
767
|
renderMode: this.options.isPreview ? 'preview' : 'live'
|
|
746
768
|
};
|
|
747
769
|
|
|
748
|
-
|
|
770
|
+
const url = createEmbeddedApp(
|
|
749
771
|
this.presentation,
|
|
750
772
|
this.options.applicationVersion,
|
|
751
773
|
metadata
|
|
752
774
|
);
|
|
775
|
+
|
|
776
|
+
return this.appendWindowIdToHash(url, windowId);
|
|
753
777
|
}
|
|
754
778
|
|
|
755
779
|
private handleEmbeddedMessage = async (type: string, payload?: any) => {
|
|
@@ -850,6 +874,13 @@ export default class PresentationWindow {
|
|
|
850
874
|
break;
|
|
851
875
|
}
|
|
852
876
|
|
|
877
|
+
case 'analytics-event': {
|
|
878
|
+
if (this.analyticsEventCallback && isValidAnalyticsEvent(payload)) {
|
|
879
|
+
this.analyticsEventCallback(payload);
|
|
880
|
+
}
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
|
|
853
884
|
default: {
|
|
854
885
|
this.logWarning(`Received unknown embedded message type: ${type}`);
|
|
855
886
|
}
|
package/src/types.ts
CHANGED