@vouchfor/embeds 0.0.0-experiment.5d16720 → 0.0.0-experiment.607fdcd
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/dist/es/components/Embed/controllers/fetcher.d.ts +0 -7
- package/dist/es/components/Embed/controllers/tracking.d.ts +3 -2
- package/dist/es/components/Embed/index.d.ts +66 -0
- package/dist/es/embeds.js +896 -618
- package/dist/es/embeds.js.map +1 -1
- package/dist/es/utils/env.d.ts +5 -11
- package/dist/iife/embeds.iife.js +327 -374
- package/dist/iife/embeds.iife.js.map +1 -1
- package/package.json +6 -6
- package/src/components/Embed/Embed.stories.ts +7 -20
- package/src/components/Embed/controllers/fetcher.ts +63 -45
- package/src/components/Embed/controllers/tracking.ts +67 -59
- package/src/components/Embed/index.ts +13 -19
- package/src/utils/env.ts +18 -32
- package/dist/es/components/Embed/controllers/event-forwarder.d.ts +0 -14
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vouchfor/embeds",
|
3
|
-
"version": "0.0.0-experiment.
|
3
|
+
"version": "0.0.0-experiment.607fdcd",
|
4
4
|
"license": "MIT",
|
5
5
|
"author": "Aaron Williams",
|
6
6
|
"main": "dist/es/embeds.js",
|
@@ -26,7 +26,7 @@
|
|
26
26
|
"lint:staged": "lint-staged",
|
27
27
|
"prepublishOnly": "yarn build",
|
28
28
|
"size": "size-limit",
|
29
|
-
"storybook": "yarn prebuild && storybook dev -p
|
29
|
+
"storybook": "yarn prebuild && storybook dev -p 6007",
|
30
30
|
"prebuild": "yarn build:deps && yarn generate:manifest",
|
31
31
|
"test": "true"
|
32
32
|
},
|
@@ -35,12 +35,12 @@
|
|
35
35
|
"**/*.{md,json,yml}": "prettier --write"
|
36
36
|
},
|
37
37
|
"dependencies": {
|
38
|
-
"@lit/task": "1.0.0",
|
39
|
-
"@vouchfor/media-player": "0.0.0-experiment.
|
38
|
+
"@lit/task": "^1.0.0",
|
39
|
+
"@vouchfor/media-player": "0.0.0-experiment.607fdcd",
|
40
40
|
"uuid": "^9.0.1"
|
41
41
|
},
|
42
42
|
"peerDependencies": {
|
43
|
-
"lit": "^3.0
|
43
|
+
"lit": "^3.1.0"
|
44
44
|
},
|
45
45
|
"devDependencies": {
|
46
46
|
"@esm-bundle/chai": "^4.3.4-fix.0",
|
@@ -62,7 +62,7 @@
|
|
62
62
|
"eslint": "^8.50.0",
|
63
63
|
"eslint-plugin-import": "^2.28.1",
|
64
64
|
"lint-staged": "^14.0.1",
|
65
|
-
"lit": "^
|
65
|
+
"lit": "^3.1.0",
|
66
66
|
"prettier": "^3.0.3",
|
67
67
|
"react": "^18.2.0",
|
68
68
|
"react-dom": "^18.2.0",
|
@@ -10,30 +10,18 @@ type EmbedArgs = EmbedProps & {
|
|
10
10
|
showVouch?: boolean;
|
11
11
|
};
|
12
12
|
|
13
|
-
const _Embed = ({
|
14
|
-
vouchId,
|
15
|
-
templateId,
|
16
|
-
preload,
|
17
|
-
autoplay,
|
18
|
-
env,
|
19
|
-
apiKey,
|
20
|
-
controls,
|
21
|
-
|
22
|
-
resolution,
|
23
|
-
aspectRatio
|
24
|
-
}: EmbedArgs) => {
|
13
|
+
const _Embed = ({ vouchId, templateId, preload, autoplay, env, apiKey, controls, aspectRatio }: EmbedArgs) => {
|
25
14
|
return html`
|
26
15
|
<div style="height: 100vh">
|
27
16
|
<vouch-embed
|
28
17
|
env=${ifDefined(env)}
|
29
18
|
apiKey=${ifDefined(apiKey)}
|
30
|
-
?autoplay=${autoplay}
|
31
19
|
vouchId=${ifDefined(vouchId)}
|
32
20
|
templateId=${ifDefined(templateId)}
|
33
|
-
resolution=${ifDefined(resolution)}
|
34
|
-
aspectRatio=${ifDefined(aspectRatio)}
|
35
|
-
preload=${ifDefined(preload)}
|
36
21
|
.controls=${controls}
|
22
|
+
?autoplay=${autoplay}
|
23
|
+
preload=${ifDefined(preload)}
|
24
|
+
aspectRatio=${ifDefined(aspectRatio)}
|
37
25
|
></vouch-embed>
|
38
26
|
</div>
|
39
27
|
`;
|
@@ -51,11 +39,10 @@ type Story = StoryObj<EmbedArgs>;
|
|
51
39
|
|
52
40
|
const Embed: Story = {
|
53
41
|
args: {
|
54
|
-
env: '
|
42
|
+
env: 'local',
|
55
43
|
apiKey: 'TVik9uTMgE-PD25UTHIS6gyl0hMBWC7AT4dkpdlLBT4VIfDWZJrQiCk6Ak7m1',
|
56
44
|
vouchId: '6JQEIPeStt',
|
57
|
-
templateId: '
|
58
|
-
resolution: 1080,
|
45
|
+
templateId: '357fc118-e179-4171-9446-ff2b8e9d1b29',
|
59
46
|
aspectRatio: 0,
|
60
47
|
preload: 'none',
|
61
48
|
autoplay: false
|
@@ -63,7 +50,7 @@ const Embed: Story = {
|
|
63
50
|
argTypes: {
|
64
51
|
env: {
|
65
52
|
control: 'radio',
|
66
|
-
options: ['
|
53
|
+
options: ['local', 'dev', 'staging', 'prod']
|
67
54
|
},
|
68
55
|
preload: {
|
69
56
|
control: 'radio',
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Task } from '@lit/task';
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
2
3
|
|
3
4
|
import type { Embed, EmbedProps } from '..';
|
4
|
-
import type { TemplateInstance } from '@vouchfor/canvas-video';
|
5
5
|
import type { ReactiveControllerHost } from 'lit';
|
6
6
|
import type { Environment } from '~/utils/env';
|
7
7
|
|
@@ -21,8 +21,6 @@ class FetcherController {
|
|
21
21
|
host: EmbedHost;
|
22
22
|
|
23
23
|
private _fetching = false;
|
24
|
-
private _vouch: EmbedProps['data'] | null = null;
|
25
|
-
private _template: TemplateInstance | null = null;
|
26
24
|
|
27
25
|
set fetching(value) {
|
28
26
|
if (this._fetching !== value) {
|
@@ -34,51 +32,67 @@ class FetcherController {
|
|
34
32
|
return this._fetching;
|
35
33
|
}
|
36
34
|
|
37
|
-
|
38
|
-
if (this._vouch !== value) {
|
39
|
-
this._vouch = value;
|
40
|
-
this.host.requestUpdate();
|
41
|
-
}
|
42
|
-
}
|
43
|
-
get vouch() {
|
44
|
-
return this._vouch;
|
45
|
-
}
|
46
|
-
|
47
|
-
set template(value) {
|
48
|
-
if (this._template !== value) {
|
49
|
-
this._template = value;
|
50
|
-
this.host.requestUpdate();
|
51
|
-
}
|
52
|
-
}
|
53
|
-
get template() {
|
54
|
-
return this._template;
|
55
|
-
}
|
56
|
-
|
57
|
-
private async getVouch(env: Environment, apiKey: string, vouchId?: string) {
|
35
|
+
private getVouch = async (env: Environment, apiKey: string, vouchId: string) => {
|
58
36
|
const { embedApiUrl } = getEnvUrls(env);
|
59
37
|
|
60
|
-
|
61
|
-
|
38
|
+
const cacheCheck = uuidv4();
|
39
|
+
const res = await fetch(`${embedApiUrl}/vouches/${vouchId}`, {
|
40
|
+
method: 'GET',
|
41
|
+
headers: [
|
42
|
+
['X-Api-Key', apiKey],
|
43
|
+
['X-Cache-Check', cacheCheck]
|
44
|
+
]
|
45
|
+
});
|
46
|
+
|
47
|
+
const vouch = await res.json();
|
48
|
+
this.host.dispatchEvent(new CustomEvent('vouch:loaded', { detail: vouchId }));
|
49
|
+
|
50
|
+
// HACK: we're currently using API Gateway caching on the embed API without any invalidation logic,
|
51
|
+
// so to ensure that the cache stays up to date, whenever we detect a cache hit we trigger another
|
52
|
+
// API call with the `Cache-Control` header which will re-fill the cache
|
53
|
+
const resCacheCheck = res?.headers?.get('X-Cache-Check');
|
54
|
+
if (resCacheCheck !== cacheCheck) {
|
55
|
+
fetch(`${embedApiUrl}/vouches/${vouchId}`, {
|
62
56
|
method: 'GET',
|
63
|
-
headers: [
|
64
|
-
|
57
|
+
headers: [
|
58
|
+
['X-Api-Key', apiKey],
|
59
|
+
['Cache-Control', 'max-age=0']
|
60
|
+
]
|
61
|
+
});
|
65
62
|
}
|
66
63
|
|
67
|
-
return
|
68
|
-
}
|
64
|
+
return vouch;
|
65
|
+
};
|
69
66
|
|
70
|
-
private async
|
67
|
+
private getTemplate = async (env: Environment, apiKey: string, templateId: string) => {
|
71
68
|
const { embedApiUrl } = getEnvUrls(env);
|
72
69
|
|
73
|
-
|
74
|
-
|
70
|
+
const cacheCheck = uuidv4();
|
71
|
+
const res = await fetch(`${embedApiUrl}/templates/${templateId}`, {
|
72
|
+
method: 'GET',
|
73
|
+
headers: [
|
74
|
+
['X-Api-Key', apiKey],
|
75
|
+
['X-Cache-Check', cacheCheck]
|
76
|
+
]
|
77
|
+
});
|
78
|
+
const template = await res.json();
|
79
|
+
|
80
|
+
// HACK: we're currently using API Gateway caching on the embed API without any invalidation logic,
|
81
|
+
// so to ensure that the cache stays up to date, whenever we detect a cache hit we trigger another
|
82
|
+
// API call with the `Cache-Control` header which will re-fill the cache
|
83
|
+
const resCacheCheck = res?.headers?.get('X-Cache-Check');
|
84
|
+
if (resCacheCheck !== cacheCheck) {
|
85
|
+
fetch(`${embedApiUrl}/templates/${templateId}`, {
|
75
86
|
method: 'GET',
|
76
|
-
headers: [
|
77
|
-
|
87
|
+
headers: [
|
88
|
+
['X-Api-Key', apiKey],
|
89
|
+
['Cache-Control', 'max-age=0']
|
90
|
+
]
|
91
|
+
});
|
78
92
|
}
|
79
93
|
|
80
|
-
return
|
81
|
-
}
|
94
|
+
return template;
|
95
|
+
};
|
82
96
|
|
83
97
|
constructor(host: EmbedHost) {
|
84
98
|
this.host = host;
|
@@ -86,22 +100,26 @@ class FetcherController {
|
|
86
100
|
this.host,
|
87
101
|
async ([env, apiKey, data, vouchId, templateId]: TaskDeps) => {
|
88
102
|
try {
|
89
|
-
|
90
|
-
|
103
|
+
host.vouch = undefined;
|
104
|
+
host.template = undefined;
|
91
105
|
|
92
106
|
if (data) {
|
93
|
-
|
94
|
-
|
95
|
-
|
107
|
+
let template;
|
108
|
+
if (templateId) {
|
109
|
+
this.fetching = true;
|
110
|
+
template = await this.getTemplate(env, apiKey, templateId);
|
111
|
+
}
|
112
|
+
host.vouch = data;
|
113
|
+
host.template = template ?? data?.settings?.template?.instance;
|
96
114
|
} else if (vouchId) {
|
97
115
|
this.fetching = true;
|
98
116
|
|
99
117
|
const [vouch, template] = await Promise.all([
|
100
118
|
this.getVouch(env, apiKey, vouchId),
|
101
|
-
this.getTemplate(env, apiKey, templateId)
|
119
|
+
templateId ? this.getTemplate(env, apiKey, templateId) : null
|
102
120
|
]);
|
103
|
-
|
104
|
-
|
121
|
+
host.vouch = vouch;
|
122
|
+
host.template = template ?? vouch?.settings?.template?.instance;
|
105
123
|
}
|
106
124
|
} finally {
|
107
125
|
this.fetching = false;
|
@@ -6,13 +6,13 @@ import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
6
6
|
|
7
7
|
import { getEnvUrls } from '~/utils/env';
|
8
8
|
|
9
|
-
|
9
|
+
// In seconds due to checking against node.currentTime
|
10
|
+
const STREAMED_THROTTLE = 10;
|
10
11
|
|
11
12
|
type EmbedHost = ReactiveControllerHost & Embed;
|
12
13
|
|
13
14
|
type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
|
14
15
|
type TrackingPayload = {
|
15
|
-
vouchId: string;
|
16
16
|
answerId?: string;
|
17
17
|
streamStart?: number;
|
18
18
|
streamEnd?: number;
|
@@ -36,8 +36,9 @@ class TrackingController implements ReactiveController {
|
|
36
36
|
private _hasPlayed = false;
|
37
37
|
private _hasLoaded: BooleanMap = {};
|
38
38
|
private _answersViewed: BooleanMap = {};
|
39
|
-
private
|
40
|
-
private
|
39
|
+
private _streamStartTime: TimeMap = {};
|
40
|
+
private _streamLatestTime: TimeMap = {};
|
41
|
+
private _currentlyPlayingVideo: VideoEventDetail | null = null;
|
41
42
|
|
42
43
|
constructor(host: EmbedHost) {
|
43
44
|
this.host = host;
|
@@ -45,12 +46,10 @@ class TrackingController implements ReactiveController {
|
|
45
46
|
}
|
46
47
|
|
47
48
|
private _findVouchId() {
|
48
|
-
if (this.host.
|
49
|
-
|
50
|
-
return this.host.data.uuid;
|
51
|
-
}
|
52
|
-
return this.host.data.id;
|
49
|
+
if (this.host.vouch) {
|
50
|
+
return this.host.vouch.id;
|
53
51
|
}
|
52
|
+
return null;
|
54
53
|
}
|
55
54
|
|
56
55
|
private _createVisitor = (visitorId: string) => {
|
@@ -116,7 +115,7 @@ class TrackingController implements ReactiveController {
|
|
116
115
|
});
|
117
116
|
|
118
117
|
return {
|
119
|
-
source:
|
118
|
+
source: this.host.trackingSource,
|
120
119
|
time: new Date(),
|
121
120
|
region,
|
122
121
|
country,
|
@@ -128,16 +127,24 @@ class TrackingController implements ReactiveController {
|
|
128
127
|
};
|
129
128
|
};
|
130
129
|
|
131
|
-
private _sendTrackingEvent = (event: TrackingEvent, payload
|
130
|
+
private _sendTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
|
131
|
+
const vouchId = this._findVouchId();
|
132
|
+
|
133
|
+
if (!vouchId || this.host.disableTracking) {
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
|
132
137
|
const { publicApiUrl } = getEnvUrls(this.host.env);
|
133
138
|
const { client, tab, request, visitor } = this._getUids();
|
134
139
|
|
135
|
-
// Don't send tracking if we don't have a source
|
136
140
|
navigator.sendBeacon(
|
137
141
|
`${publicApiUrl}/api/events`,
|
138
142
|
JSON.stringify({
|
139
143
|
event,
|
140
|
-
payload
|
144
|
+
payload: {
|
145
|
+
vouchId,
|
146
|
+
...payload
|
147
|
+
},
|
141
148
|
context: {
|
142
149
|
'x-uid-client': client,
|
143
150
|
'x-uid-tab': tab,
|
@@ -156,87 +163,74 @@ class TrackingController implements ReactiveController {
|
|
156
163
|
|
157
164
|
// Only send loaded event once per session
|
158
165
|
if (!this._hasLoaded[vouchId]) {
|
159
|
-
this._sendTrackingEvent('VOUCH_LOADED'
|
160
|
-
vouchId
|
161
|
-
});
|
166
|
+
this._sendTrackingEvent('VOUCH_LOADED');
|
162
167
|
this._hasLoaded[vouchId] = true;
|
163
168
|
}
|
164
169
|
};
|
165
170
|
|
166
171
|
private _handlePlay = () => {
|
167
|
-
const vouchId = this._findVouchId();
|
168
|
-
|
169
|
-
if (!vouchId) {
|
170
|
-
return;
|
171
|
-
}
|
172
|
-
|
173
172
|
// Only send the video played event once per session
|
174
173
|
if (!this._hasPlayed) {
|
175
174
|
this._sendTrackingEvent('VIDEO_PLAYED', {
|
176
|
-
vouchId,
|
177
175
|
streamStart: this.host.currentTime
|
178
176
|
});
|
179
177
|
this._hasPlayed = true;
|
180
178
|
}
|
181
179
|
};
|
182
180
|
|
183
|
-
private _handleVideoPlay = ({ detail: { id, node } }: CustomEvent<VideoEventDetail>) => {
|
184
|
-
const vouchId = this._findVouchId();
|
185
|
-
if (!vouchId) {
|
186
|
-
return;
|
187
|
-
}
|
181
|
+
private _handleVideoPlay = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
188
182
|
// Only increment play count once per session
|
189
|
-
if (!this._answersViewed[
|
183
|
+
if (!this._answersViewed[key]) {
|
190
184
|
this._sendTrackingEvent('VOUCH_RESPONSE_VIEWED', {
|
191
|
-
vouchId,
|
192
185
|
answerId: id
|
193
186
|
});
|
194
|
-
this._answersViewed[
|
187
|
+
this._answersViewed[key] = true;
|
195
188
|
}
|
196
|
-
|
197
|
-
this.
|
189
|
+
|
190
|
+
this._streamStartTime[key] = node.currentTime;
|
191
|
+
this._streamLatestTime[key] = node.currentTime;
|
198
192
|
};
|
199
193
|
|
200
|
-
private _handleVideoTimeUpdate = ({ detail: { id, node } }: CustomEvent<VideoEventDetail>) => {
|
201
|
-
|
202
|
-
if (!
|
203
|
-
|
194
|
+
private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
195
|
+
// We only want to count any time that the video is actually playing
|
196
|
+
if (!this.host.paused) {
|
197
|
+
this._currentlyPlayingVideo = { id, key, node };
|
198
|
+
this._streamLatestTime[key] = node.currentTime;
|
204
199
|
}
|
205
|
-
|
200
|
+
|
206
201
|
if (
|
202
|
+
!node.paused &&
|
207
203
|
!this.host.paused &&
|
208
204
|
// Only fire the video seeked event when this video is the active one
|
209
205
|
id === this.host.scene?.video?.id &&
|
210
206
|
// Throttle the frequency that we send streamed events while playing
|
211
|
-
|
207
|
+
this._streamLatestTime[key] - this._streamStartTime[key] > STREAMED_THROTTLE
|
212
208
|
) {
|
213
209
|
this._sendTrackingEvent('VIDEO_STREAMED', {
|
214
|
-
vouchId,
|
215
210
|
answerId: id,
|
216
|
-
streamStart: this.
|
217
|
-
streamEnd:
|
211
|
+
streamStart: this._streamStartTime[key],
|
212
|
+
streamEnd: this._streamLatestTime[key]
|
218
213
|
});
|
219
|
-
|
220
|
-
this.
|
214
|
+
|
215
|
+
this._streamStartTime[key] = node.currentTime;
|
221
216
|
}
|
222
217
|
};
|
223
218
|
|
224
|
-
private _handleVideoPause = ({ detail: { id,
|
225
|
-
|
226
|
-
if (
|
227
|
-
|
219
|
+
private _handleVideoPause = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
|
220
|
+
// Don't send a tracking event when seeking backwards
|
221
|
+
if (this._streamLatestTime[key] > this._streamStartTime[key]) {
|
222
|
+
// Send a video streamed event any time the video pauses then reset the streamed state
|
223
|
+
// We do this to capture the last bit of time that the video was played between the previous
|
224
|
+
// stream event and the video being paused manually or stopping because it ended
|
225
|
+
this._sendTrackingEvent('VIDEO_STREAMED', {
|
226
|
+
answerId: id,
|
227
|
+
streamStart: this._streamStartTime[key],
|
228
|
+
streamEnd: this._streamLatestTime[key]
|
229
|
+
});
|
228
230
|
}
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
this._sendTrackingEvent('VIDEO_STREAMED', {
|
233
|
-
vouchId,
|
234
|
-
answerId: id,
|
235
|
-
streamStart: this._streamedTime[id],
|
236
|
-
streamEnd: node.currentTime
|
237
|
-
});
|
238
|
-
delete this._streamedTime[id];
|
239
|
-
delete this._streamedPrevTimestamp[id];
|
231
|
+
this._currentlyPlayingVideo = null;
|
232
|
+
delete this._streamStartTime[key];
|
233
|
+
delete this._streamLatestTime[key];
|
240
234
|
};
|
241
235
|
|
242
236
|
hostConnected() {
|
@@ -250,6 +244,20 @@ class TrackingController implements ReactiveController {
|
|
250
244
|
}
|
251
245
|
|
252
246
|
hostDisconnected() {
|
247
|
+
if (this._currentlyPlayingVideo) {
|
248
|
+
const { id, key } = this._currentlyPlayingVideo;
|
249
|
+
if (this._streamLatestTime[key] > this._streamStartTime[key]) {
|
250
|
+
// Send a video streamed event any time the video pauses then reset the streamed state
|
251
|
+
// We do this to capture the last bit of time that the video was played between the previous
|
252
|
+
// stream event and the video being paused manually or stopping because it ended
|
253
|
+
this._sendTrackingEvent('VIDEO_STREAMED', {
|
254
|
+
answerId: id,
|
255
|
+
streamStart: this._streamStartTime[key],
|
256
|
+
streamEnd: this._streamLatestTime[key]
|
257
|
+
});
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
253
261
|
this.host.removeEventListener('vouch:loaded', this._handleVouchLoaded);
|
254
262
|
this.host.mediaPlayer?.removeEventListener('play', this._handlePlay);
|
255
263
|
this.host.mediaPlayer?.removeEventListener('video:play', this._handleVideoPlay);
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { html, LitElement } from 'lit';
|
2
|
-
import { customElement, property } from 'lit/decorators.js';
|
2
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
3
3
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
4
4
|
import { createRef, ref } from 'lit/directives/ref.js';
|
5
5
|
|
6
|
-
import type { Scene } from '@vouchfor/canvas-video';
|
6
|
+
import type { Scene, TemplateInstance } from '@vouchfor/canvas-video';
|
7
7
|
import type { MediaPlayer, MediaPlayerProps } from '@vouchfor/media-player';
|
8
8
|
import type { Ref } from 'lit/directives/ref.js';
|
9
9
|
import type { Environment } from '~/utils/env';
|
@@ -14,12 +14,11 @@ import { TrackingController } from './controllers/tracking';
|
|
14
14
|
|
15
15
|
import '@vouchfor/media-player';
|
16
16
|
|
17
|
-
type EmbedProps = Pick<
|
18
|
-
MediaPlayerProps,
|
19
|
-
'data' | 'resolution' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'
|
20
|
-
> & {
|
17
|
+
type EmbedProps = Pick<MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'> & {
|
21
18
|
env: Environment;
|
22
19
|
apiKey: string;
|
20
|
+
disableTracking?: boolean;
|
21
|
+
trackingSource?: string;
|
23
22
|
vouchId?: string;
|
24
23
|
templateId?: string;
|
25
24
|
};
|
@@ -34,13 +33,13 @@ class Embed extends LitElement {
|
|
34
33
|
|
35
34
|
@property({ type: String }) env: EmbedProps['env'] = 'prod';
|
36
35
|
@property({ type: String }) apiKey: EmbedProps['apiKey'] = '';
|
36
|
+
@property({ type: Boolean }) disableTracking: EmbedProps['disableTracking'] = false;
|
37
|
+
@property({ type: String }) trackingSource: EmbedProps['trackingSource'] = 'embed';
|
37
38
|
|
39
|
+
@property({ type: Array }) controls: EmbedProps['controls'];
|
38
40
|
@property({ type: String }) preload: EmbedProps['preload'] = 'auto';
|
39
41
|
@property({ type: Boolean }) autoplay: EmbedProps['autoplay'] = false;
|
40
|
-
|
41
|
-
@property({ type: Number }) resolution: EmbedProps['resolution'] = 1080;
|
42
42
|
@property({ type: Number }) aspectRatio: EmbedProps['aspectRatio'] = 0;
|
43
|
-
@property({ type: Array }) controls: EmbedProps['controls'];
|
44
43
|
|
45
44
|
private eventController = new EventForwardController(this, [
|
46
45
|
'durationchange',
|
@@ -60,6 +59,7 @@ class Embed extends LitElement {
|
|
60
59
|
'waiting',
|
61
60
|
|
62
61
|
'video:loadeddata',
|
62
|
+
'video:seeking',
|
63
63
|
'video:seeked',
|
64
64
|
'video:play',
|
65
65
|
'video:playing',
|
@@ -74,13 +74,8 @@ class Embed extends LitElement {
|
|
74
74
|
// @ts-ignore
|
75
75
|
private _trackingController = new TrackingController(this);
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
}
|
80
|
-
|
81
|
-
get template() {
|
82
|
-
return this._fetcherController.template;
|
83
|
-
}
|
77
|
+
@state() vouch: EmbedProps['data'];
|
78
|
+
@state() template: TemplateInstance | undefined;
|
84
79
|
|
85
80
|
get fetching() {
|
86
81
|
return this._fetcherController.fetching;
|
@@ -176,18 +171,17 @@ class Embed extends LitElement {
|
|
176
171
|
|
177
172
|
render() {
|
178
173
|
return html`
|
179
|
-
<vmp-media-player
|
174
|
+
<vmp-new-media-player
|
180
175
|
${ref(this._mediaPlayerRef)}
|
181
176
|
${this.eventController.register()}
|
182
177
|
?autoplay=${this.autoplay}
|
183
178
|
?loading=${this.fetching}
|
184
179
|
.data=${this.vouch}
|
185
180
|
.template=${this.template}
|
186
|
-
resolution=${ifDefined(this.resolution)}
|
187
181
|
aspectRatio=${ifDefined(this.aspectRatio)}
|
188
182
|
preload=${ifDefined(this.preload)}
|
189
183
|
.controls=${this.controls}
|
190
|
-
></vmp-media-player>
|
184
|
+
></vmp-new-media-player>
|
191
185
|
`;
|
192
186
|
}
|
193
187
|
}
|
package/src/utils/env.ts
CHANGED
@@ -1,15 +1,11 @@
|
|
1
|
-
type Environment = 'dev' | 'staging' | 'prod';
|
1
|
+
type Environment = 'local' | 'dev' | 'staging' | 'prod';
|
2
2
|
|
3
3
|
type GetEnvUrlsReturn = {
|
4
|
-
marketingUrl: string;
|
5
4
|
videoUrl: string;
|
6
5
|
publicApiUrl: string;
|
7
6
|
embedApiUrl: string;
|
8
|
-
publicRecorderUrl: string;
|
9
7
|
};
|
10
8
|
|
11
|
-
const marketingUrl = 'https://vouchfor.com';
|
12
|
-
|
13
9
|
const devVideoUrl = 'https://d2rxhdlm2q91uk.cloudfront.net';
|
14
10
|
const stagingVideoUrl = 'https://d1ix11aj5kfygl.cloudfront.net';
|
15
11
|
const prodVideoUrl = 'https://d157jlwnudd93d.cloudfront.net';
|
@@ -18,61 +14,51 @@ const devPublicApiUrl = 'https://bshyfw4h5a.execute-api.ap-southeast-2.amazonaws
|
|
18
14
|
const stagingPublicApiUrl = 'https://gyzw7rpbq3.execute-api.ap-southeast-2.amazonaws.com/staging';
|
19
15
|
const prodPublicApiUrl = 'https://vfcjuim1l3.execute-api.ap-southeast-2.amazonaws.com/prod';
|
20
16
|
|
21
|
-
const
|
22
|
-
const
|
23
|
-
const
|
24
|
-
|
25
|
-
const devPublicRecorderUrl = 'https://dev.vouchfor.com';
|
26
|
-
const stagingPublicRecorderUrl = 'https://staging.vouchfor.com';
|
27
|
-
const prodPublicRecorderUrl = 'https://app.vouchfor.com';
|
17
|
+
const localEmbedApiUrl = 'http://localhost:6060/v2';
|
18
|
+
const devEmbedApiUrl = 'https://embed-dev.vouchfor.com/v2';
|
19
|
+
const stagingEmbedApiUrl = 'https://embed-staging.vouchfor.com/v2';
|
20
|
+
const prodEmbedApiUrl = 'https://embed.vouchfor.com/v2';
|
28
21
|
|
29
22
|
// We are handling the case where env is an unknown string so the ts error is a lie
|
30
23
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
31
24
|
// @ts-ignore
|
32
25
|
function getEnvUrls(env: Environment): GetEnvUrlsReturn {
|
33
|
-
if (!['dev', 'staging', 'prod'].includes(env)) {
|
26
|
+
if (!['local', 'dev', 'staging', 'prod'].includes(env)) {
|
34
27
|
throw new Error(`Unknown environment: ${env}`);
|
35
28
|
}
|
36
29
|
|
30
|
+
if (env === 'local') {
|
31
|
+
return {
|
32
|
+
videoUrl: devVideoUrl,
|
33
|
+
publicApiUrl: devPublicApiUrl,
|
34
|
+
embedApiUrl: localEmbedApiUrl
|
35
|
+
};
|
36
|
+
}
|
37
|
+
|
37
38
|
if (env === 'dev') {
|
38
39
|
return {
|
39
|
-
marketingUrl,
|
40
40
|
videoUrl: devVideoUrl,
|
41
41
|
publicApiUrl: devPublicApiUrl,
|
42
|
-
embedApiUrl: devEmbedApiUrl
|
43
|
-
publicRecorderUrl: devPublicRecorderUrl
|
42
|
+
embedApiUrl: devEmbedApiUrl
|
44
43
|
};
|
45
44
|
}
|
46
45
|
|
47
46
|
if (env === 'staging') {
|
48
47
|
return {
|
49
|
-
marketingUrl,
|
50
48
|
videoUrl: stagingVideoUrl,
|
51
49
|
publicApiUrl: stagingPublicApiUrl,
|
52
|
-
embedApiUrl: stagingEmbedApiUrl
|
53
|
-
publicRecorderUrl: stagingPublicRecorderUrl
|
50
|
+
embedApiUrl: stagingEmbedApiUrl
|
54
51
|
};
|
55
52
|
}
|
56
53
|
|
57
54
|
if (env === 'prod') {
|
58
55
|
return {
|
59
|
-
marketingUrl,
|
60
56
|
videoUrl: prodVideoUrl,
|
61
57
|
publicApiUrl: prodPublicApiUrl,
|
62
|
-
embedApiUrl: prodEmbedApiUrl
|
63
|
-
publicRecorderUrl: prodPublicRecorderUrl
|
58
|
+
embedApiUrl: prodEmbedApiUrl
|
64
59
|
};
|
65
60
|
}
|
66
61
|
}
|
67
62
|
|
68
|
-
export {
|
69
|
-
marketingUrl,
|
70
|
-
devEmbedApiUrl,
|
71
|
-
stagingEmbedApiUrl,
|
72
|
-
prodEmbedApiUrl,
|
73
|
-
devPublicRecorderUrl,
|
74
|
-
stagingPublicRecorderUrl,
|
75
|
-
prodPublicRecorderUrl,
|
76
|
-
getEnvUrls
|
77
|
-
};
|
63
|
+
export { devEmbedApiUrl, stagingEmbedApiUrl, prodEmbedApiUrl, getEnvUrls };
|
78
64
|
export type { Environment };
|
@@ -1,14 +0,0 @@
|
|
1
|
-
import type { Embed } from '..';
|
2
|
-
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
3
|
-
type EmbedHost = ReactiveControllerHost & Embed;
|
4
|
-
declare class EventForwardController implements ReactiveController {
|
5
|
-
host: EmbedHost;
|
6
|
-
private _events;
|
7
|
-
private _cleanup;
|
8
|
-
private _forwardElementRef;
|
9
|
-
constructor(host: EmbedHost, events: string[]);
|
10
|
-
register(): import("lit-html/directive.js").DirectiveResult<typeof import("lit-html/directives/ref.js").RefDirective>;
|
11
|
-
hostConnected(): void;
|
12
|
-
hostDisconnected(): void;
|
13
|
-
}
|
14
|
-
export { EventForwardController };
|