stormcloud-video-player 0.1.3 → 0.1.4
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/README.md +25 -0
- package/package.json +37 -5
- package/rollup.config.js +0 -51
- package/src/index.ts +0 -20
- package/src/player/StormcloudVideoPlayer.ts +0 -1123
- package/src/sdk/ima.ts +0 -369
- package/src/types.ts +0 -124
- package/src/ui/StormcloudVideoPlayer.tsx +0 -258
- package/src/utils/tracking.ts +0 -251
- package/tsconfig.json +0 -49
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from "react";
|
|
2
|
-
import { StormcloudVideoPlayer } from "../player/StormcloudVideoPlayer";
|
|
3
|
-
import type { StormcloudVideoPlayerConfig } from "../types";
|
|
4
|
-
|
|
5
|
-
export type StormcloudVideoPlayerProps = Omit<
|
|
6
|
-
StormcloudVideoPlayerConfig,
|
|
7
|
-
"videoElement"
|
|
8
|
-
> &
|
|
9
|
-
React.VideoHTMLAttributes<HTMLVideoElement> & {
|
|
10
|
-
onReady?: (player: StormcloudVideoPlayer) => void;
|
|
11
|
-
wrapperClassName?: string;
|
|
12
|
-
wrapperStyle?: React.CSSProperties;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const StormcloudVideoPlayerComponent: React.FC<
|
|
16
|
-
StormcloudVideoPlayerProps
|
|
17
|
-
> = (props) => {
|
|
18
|
-
const {
|
|
19
|
-
src,
|
|
20
|
-
autoplay,
|
|
21
|
-
muted,
|
|
22
|
-
lowLatencyMode,
|
|
23
|
-
allowNativeHls,
|
|
24
|
-
driftToleranceMs,
|
|
25
|
-
adSchedule,
|
|
26
|
-
immediateManifestAds,
|
|
27
|
-
debugAdTiming,
|
|
28
|
-
showCustomControls,
|
|
29
|
-
onVolumeToggle,
|
|
30
|
-
onFullscreenToggle,
|
|
31
|
-
onControlClick,
|
|
32
|
-
onReady,
|
|
33
|
-
wrapperClassName,
|
|
34
|
-
wrapperStyle,
|
|
35
|
-
className,
|
|
36
|
-
style,
|
|
37
|
-
controls,
|
|
38
|
-
playsInline,
|
|
39
|
-
preload,
|
|
40
|
-
poster,
|
|
41
|
-
children,
|
|
42
|
-
...restVideoAttrs
|
|
43
|
-
} = props;
|
|
44
|
-
|
|
45
|
-
const videoRef = useRef<HTMLVideoElement | null>(null);
|
|
46
|
-
const playerRef = useRef<StormcloudVideoPlayer | null>(null);
|
|
47
|
-
const [adStatus, setAdStatus] = React.useState<{
|
|
48
|
-
showAds: boolean;
|
|
49
|
-
currentIndex: number;
|
|
50
|
-
totalAds: number;
|
|
51
|
-
}>({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
52
|
-
|
|
53
|
-
const [shouldShowNativeControls, setShouldShowNativeControls] =
|
|
54
|
-
React.useState(true);
|
|
55
|
-
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (typeof window === "undefined") return;
|
|
58
|
-
const el = videoRef.current;
|
|
59
|
-
if (!el || !src) return;
|
|
60
|
-
|
|
61
|
-
if (playerRef.current) {
|
|
62
|
-
try {
|
|
63
|
-
playerRef.current.destroy();
|
|
64
|
-
} catch {}
|
|
65
|
-
playerRef.current = null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const cfg: StormcloudVideoPlayerConfig = {
|
|
69
|
-
src,
|
|
70
|
-
videoElement: el,
|
|
71
|
-
} as StormcloudVideoPlayerConfig;
|
|
72
|
-
if (autoplay !== undefined) cfg.autoplay = autoplay;
|
|
73
|
-
if (muted !== undefined) cfg.muted = muted;
|
|
74
|
-
if (lowLatencyMode !== undefined) cfg.lowLatencyMode = lowLatencyMode;
|
|
75
|
-
if (allowNativeHls !== undefined) cfg.allowNativeHls = allowNativeHls;
|
|
76
|
-
if (driftToleranceMs !== undefined) cfg.driftToleranceMs = driftToleranceMs;
|
|
77
|
-
if (adSchedule !== undefined) cfg.adSchedule = adSchedule;
|
|
78
|
-
if (immediateManifestAds !== undefined)
|
|
79
|
-
cfg.immediateManifestAds = immediateManifestAds;
|
|
80
|
-
if (debugAdTiming !== undefined) cfg.debugAdTiming = debugAdTiming;
|
|
81
|
-
if (showCustomControls !== undefined)
|
|
82
|
-
cfg.showCustomControls = showCustomControls;
|
|
83
|
-
if (onVolumeToggle !== undefined) cfg.onVolumeToggle = onVolumeToggle;
|
|
84
|
-
if (onFullscreenToggle !== undefined)
|
|
85
|
-
cfg.onFullscreenToggle = onFullscreenToggle;
|
|
86
|
-
if (onControlClick !== undefined) cfg.onControlClick = onControlClick;
|
|
87
|
-
|
|
88
|
-
const player = new StormcloudVideoPlayer(cfg);
|
|
89
|
-
playerRef.current = player;
|
|
90
|
-
player
|
|
91
|
-
.load()
|
|
92
|
-
.then(() => {
|
|
93
|
-
const showNative = player.shouldShowNativeControls();
|
|
94
|
-
setShouldShowNativeControls(showNative);
|
|
95
|
-
onReady?.(player);
|
|
96
|
-
})
|
|
97
|
-
.catch(() => {});
|
|
98
|
-
|
|
99
|
-
return () => {
|
|
100
|
-
try {
|
|
101
|
-
player.destroy();
|
|
102
|
-
} catch {}
|
|
103
|
-
playerRef.current = null;
|
|
104
|
-
};
|
|
105
|
-
}, [
|
|
106
|
-
src,
|
|
107
|
-
autoplay,
|
|
108
|
-
muted,
|
|
109
|
-
lowLatencyMode,
|
|
110
|
-
allowNativeHls,
|
|
111
|
-
driftToleranceMs,
|
|
112
|
-
immediateManifestAds,
|
|
113
|
-
debugAdTiming,
|
|
114
|
-
showCustomControls,
|
|
115
|
-
onVolumeToggle,
|
|
116
|
-
onFullscreenToggle,
|
|
117
|
-
onControlClick,
|
|
118
|
-
onReady,
|
|
119
|
-
]);
|
|
120
|
-
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
if (!playerRef.current) return;
|
|
123
|
-
if (adSchedule) {
|
|
124
|
-
try {
|
|
125
|
-
playerRef.current.setAdSchedule(adSchedule);
|
|
126
|
-
} catch {}
|
|
127
|
-
}
|
|
128
|
-
}, [adSchedule]);
|
|
129
|
-
|
|
130
|
-
useEffect(() => {
|
|
131
|
-
if (!playerRef.current) return;
|
|
132
|
-
|
|
133
|
-
const checkAdStatus = () => {
|
|
134
|
-
if (playerRef.current) {
|
|
135
|
-
const showAds = playerRef.current.isShowingAds();
|
|
136
|
-
const currentIndex = playerRef.current.getCurrentAdIndex();
|
|
137
|
-
const totalAds = playerRef.current.getTotalAdsInBreak();
|
|
138
|
-
|
|
139
|
-
setAdStatus((prev) => {
|
|
140
|
-
if (
|
|
141
|
-
prev.showAds !== showAds ||
|
|
142
|
-
prev.currentIndex !== currentIndex ||
|
|
143
|
-
prev.totalAds !== totalAds
|
|
144
|
-
) {
|
|
145
|
-
return { showAds, currentIndex, totalAds };
|
|
146
|
-
}
|
|
147
|
-
return prev;
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const interval = setInterval(checkAdStatus, 500);
|
|
153
|
-
return () => clearInterval(interval);
|
|
154
|
-
}, []);
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
<div
|
|
158
|
-
className={wrapperClassName}
|
|
159
|
-
style={{ position: "relative", overflow: "hidden", ...wrapperStyle }}
|
|
160
|
-
>
|
|
161
|
-
<video
|
|
162
|
-
ref={videoRef}
|
|
163
|
-
className={className}
|
|
164
|
-
style={{ display: "block", width: "100%", height: "100%", ...style }}
|
|
165
|
-
controls={shouldShowNativeControls && controls}
|
|
166
|
-
playsInline={playsInline}
|
|
167
|
-
preload={preload}
|
|
168
|
-
poster={poster}
|
|
169
|
-
{...restVideoAttrs}
|
|
170
|
-
>
|
|
171
|
-
{children}
|
|
172
|
-
</video>
|
|
173
|
-
|
|
174
|
-
{adStatus.showAds && adStatus.totalAds > 0 && (
|
|
175
|
-
<div
|
|
176
|
-
style={{
|
|
177
|
-
position: "absolute",
|
|
178
|
-
top: "10px",
|
|
179
|
-
right: "10px",
|
|
180
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
181
|
-
color: "white",
|
|
182
|
-
padding: "4px 8px",
|
|
183
|
-
borderRadius: "4px",
|
|
184
|
-
fontSize: "12px",
|
|
185
|
-
fontFamily: "Arial, sans-serif",
|
|
186
|
-
zIndex: 10,
|
|
187
|
-
}}
|
|
188
|
-
>
|
|
189
|
-
Ad {adStatus.currentIndex}/{adStatus.totalAds}
|
|
190
|
-
</div>
|
|
191
|
-
)}
|
|
192
|
-
|
|
193
|
-
{!shouldShowNativeControls && showCustomControls && (
|
|
194
|
-
<div
|
|
195
|
-
style={{
|
|
196
|
-
position: "absolute",
|
|
197
|
-
bottom: "10px",
|
|
198
|
-
right: "10px",
|
|
199
|
-
display: "flex",
|
|
200
|
-
gap: "8px",
|
|
201
|
-
zIndex: 10,
|
|
202
|
-
}}
|
|
203
|
-
>
|
|
204
|
-
{onVolumeToggle && (
|
|
205
|
-
<button
|
|
206
|
-
onClick={onVolumeToggle}
|
|
207
|
-
style={{
|
|
208
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
209
|
-
color: "white",
|
|
210
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
211
|
-
borderRadius: "4px",
|
|
212
|
-
padding: "8px",
|
|
213
|
-
cursor: "pointer",
|
|
214
|
-
fontSize: "14px",
|
|
215
|
-
}}
|
|
216
|
-
title="Toggle Volume"
|
|
217
|
-
>
|
|
218
|
-
🔊
|
|
219
|
-
</button>
|
|
220
|
-
)}
|
|
221
|
-
|
|
222
|
-
{onFullscreenToggle && (
|
|
223
|
-
<button
|
|
224
|
-
onClick={onFullscreenToggle}
|
|
225
|
-
style={{
|
|
226
|
-
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
|
227
|
-
color: "white",
|
|
228
|
-
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
229
|
-
borderRadius: "4px",
|
|
230
|
-
padding: "8px",
|
|
231
|
-
cursor: "pointer",
|
|
232
|
-
fontSize: "14px",
|
|
233
|
-
}}
|
|
234
|
-
title="Toggle Fullscreen"
|
|
235
|
-
>
|
|
236
|
-
⤢
|
|
237
|
-
</button>
|
|
238
|
-
)}
|
|
239
|
-
</div>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
|
-
{onControlClick && (
|
|
243
|
-
<div
|
|
244
|
-
onClick={onControlClick}
|
|
245
|
-
style={{
|
|
246
|
-
position: "absolute",
|
|
247
|
-
top: 0,
|
|
248
|
-
left: 0,
|
|
249
|
-
right: 0,
|
|
250
|
-
bottom: 0,
|
|
251
|
-
zIndex: 1,
|
|
252
|
-
cursor: "pointer",
|
|
253
|
-
}}
|
|
254
|
-
/>
|
|
255
|
-
)}
|
|
256
|
-
</div>
|
|
257
|
-
);
|
|
258
|
-
};
|
package/src/utils/tracking.ts
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import type { ClientInfo, TrackingData, HeartbeatData } from "../types";
|
|
2
|
-
|
|
3
|
-
export function getClientInfo(): ClientInfo {
|
|
4
|
-
const ua = navigator.userAgent;
|
|
5
|
-
const platform = navigator.platform;
|
|
6
|
-
const vendor = navigator.vendor || "";
|
|
7
|
-
const maxTouchPoints = navigator.maxTouchPoints || 0;
|
|
8
|
-
const memory = (navigator as any).deviceMemory || null;
|
|
9
|
-
const hardwareConcurrency = navigator.hardwareConcurrency || 1;
|
|
10
|
-
|
|
11
|
-
const screenInfo = {
|
|
12
|
-
width: screen?.width,
|
|
13
|
-
height: screen?.height,
|
|
14
|
-
availWidth: screen?.availWidth,
|
|
15
|
-
availHeight: screen?.availHeight,
|
|
16
|
-
orientation: (screen?.orientation as any)?.type || "",
|
|
17
|
-
pixelDepth: screen?.pixelDepth,
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
let deviceType: "tv" | "mobile" | "tablet" | "desktop" = "desktop";
|
|
21
|
-
let brand = "Unknown";
|
|
22
|
-
let os = "Unknown";
|
|
23
|
-
let model = "";
|
|
24
|
-
let isSmartTV = false;
|
|
25
|
-
let isAndroid = false;
|
|
26
|
-
let isWebView = false;
|
|
27
|
-
let isWebApp = false;
|
|
28
|
-
|
|
29
|
-
if (ua.includes("Web0S")) {
|
|
30
|
-
brand = "LG";
|
|
31
|
-
os = "webOS";
|
|
32
|
-
isSmartTV = true;
|
|
33
|
-
deviceType = "tv";
|
|
34
|
-
const webosMatch = ua.match(/Web0S\/([^\s]+)/);
|
|
35
|
-
model = webosMatch ? `webOS ${webosMatch[1]}` : "webOS TV";
|
|
36
|
-
} else if (ua.includes("Tizen")) {
|
|
37
|
-
brand = "Samsung";
|
|
38
|
-
os = "Tizen";
|
|
39
|
-
isSmartTV = true;
|
|
40
|
-
deviceType = "tv";
|
|
41
|
-
const tizenMatch = ua.match(/Tizen\/([^\s]+)/);
|
|
42
|
-
const tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
|
|
43
|
-
model = tizenMatch
|
|
44
|
-
? `Tizen ${tizenMatch[1]} ${tvMatch}`.trim()
|
|
45
|
-
: "Tizen TV";
|
|
46
|
-
} else if (ua.includes("Philips")) {
|
|
47
|
-
brand = "Philips";
|
|
48
|
-
os = "Saphi";
|
|
49
|
-
isSmartTV = true;
|
|
50
|
-
deviceType = "tv";
|
|
51
|
-
} else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
|
|
52
|
-
brand = "Sharp";
|
|
53
|
-
os = "Android TV";
|
|
54
|
-
isSmartTV = true;
|
|
55
|
-
deviceType = "tv";
|
|
56
|
-
} else if (
|
|
57
|
-
ua.includes("Android") &&
|
|
58
|
-
(ua.includes("Sony") || vendor.includes("Sony"))
|
|
59
|
-
) {
|
|
60
|
-
brand = "Sony";
|
|
61
|
-
os = "Android TV";
|
|
62
|
-
isSmartTV = true;
|
|
63
|
-
deviceType = "tv";
|
|
64
|
-
} else if (
|
|
65
|
-
ua.includes("Android") &&
|
|
66
|
-
(ua.includes("NetCast") || ua.includes("LG"))
|
|
67
|
-
) {
|
|
68
|
-
brand = "LG";
|
|
69
|
-
os = "Android TV";
|
|
70
|
-
isSmartTV = true;
|
|
71
|
-
deviceType = "tv";
|
|
72
|
-
} else if (ua.includes(" Roku") || ua.includes("Roku/")) {
|
|
73
|
-
brand = "Roku";
|
|
74
|
-
os = "Roku OS";
|
|
75
|
-
isSmartTV = true;
|
|
76
|
-
deviceType = "tv";
|
|
77
|
-
} else if (ua.includes("AppleTV")) {
|
|
78
|
-
brand = "Apple";
|
|
79
|
-
os = "tvOS";
|
|
80
|
-
isSmartTV = true;
|
|
81
|
-
deviceType = "tv";
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (ua.includes("Android")) {
|
|
85
|
-
isAndroid = true;
|
|
86
|
-
os = "Android";
|
|
87
|
-
deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
ua.includes("Android") &&
|
|
91
|
-
(maxTouchPoints === 0 ||
|
|
92
|
-
ua.includes("Google TV") ||
|
|
93
|
-
ua.includes("XiaoMi"))
|
|
94
|
-
) {
|
|
95
|
-
deviceType = "tv";
|
|
96
|
-
isSmartTV = true;
|
|
97
|
-
brand = brand === "Unknown" ? "Android TV" : brand;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
|
|
101
|
-
if (androidModelMatch && androidModelMatch[1]) {
|
|
102
|
-
model = androidModelMatch[1];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (/iPad|iPhone|iPod/.test(ua)) {
|
|
107
|
-
os = "iOS";
|
|
108
|
-
deviceType = "mobile";
|
|
109
|
-
brand = "Apple";
|
|
110
|
-
if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
|
|
111
|
-
deviceType = "tablet";
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
|
|
116
|
-
if (ua.includes("Windows")) {
|
|
117
|
-
os = "Windows";
|
|
118
|
-
deviceType = "desktop";
|
|
119
|
-
} else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
|
|
120
|
-
os = "macOS";
|
|
121
|
-
deviceType = "desktop";
|
|
122
|
-
if (maxTouchPoints > 1) deviceType = "tablet";
|
|
123
|
-
} else if (ua.includes("Linux")) {
|
|
124
|
-
os = "Linux";
|
|
125
|
-
deviceType = "desktop";
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (brand === "Unknown") {
|
|
130
|
-
if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
|
|
131
|
-
if (vendor.includes("Apple")) brand = "Apple";
|
|
132
|
-
if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
isWebView = /wv|WebView|Linux; U;/.test(ua);
|
|
136
|
-
|
|
137
|
-
if (window?.outerHeight === 0 && window?.outerWidth === 0) {
|
|
138
|
-
isWebView = true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
isWebApp =
|
|
142
|
-
window.matchMedia("(display-mode: standalone)").matches ||
|
|
143
|
-
(window.navigator as any).standalone === true ||
|
|
144
|
-
window.screen?.orientation?.angle !== undefined;
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
brand,
|
|
148
|
-
os,
|
|
149
|
-
model: model || ua.substring(0, 50) + "...",
|
|
150
|
-
deviceType,
|
|
151
|
-
isSmartTV,
|
|
152
|
-
isAndroid,
|
|
153
|
-
isWebView,
|
|
154
|
-
isWebApp,
|
|
155
|
-
domain: window.location.hostname,
|
|
156
|
-
origin: window.location.origin,
|
|
157
|
-
path: window.location.pathname,
|
|
158
|
-
userAgent: ua,
|
|
159
|
-
vendor,
|
|
160
|
-
platform,
|
|
161
|
-
screen: screenInfo,
|
|
162
|
-
hardwareConcurrency,
|
|
163
|
-
deviceMemory: memory,
|
|
164
|
-
maxTouchPoints,
|
|
165
|
-
language: navigator.language,
|
|
166
|
-
languages: navigator.languages?.join(",") || "",
|
|
167
|
-
cookieEnabled: navigator.cookieEnabled,
|
|
168
|
-
doNotTrack: navigator.doNotTrack || "",
|
|
169
|
-
referrer: document.referrer,
|
|
170
|
-
visibilityState: document.visibilityState,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export async function getBrowserID(clientInfo: ClientInfo): Promise<string> {
|
|
175
|
-
const fingerprintString = JSON.stringify(clientInfo);
|
|
176
|
-
const hashBuffer = await crypto.subtle.digest(
|
|
177
|
-
"SHA-256",
|
|
178
|
-
new TextEncoder().encode(fingerprintString)
|
|
179
|
-
);
|
|
180
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
181
|
-
const hashHex = hashArray
|
|
182
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
183
|
-
.join("");
|
|
184
|
-
return hashHex;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export async function sendInitialTracking(): Promise<void> {
|
|
188
|
-
try {
|
|
189
|
-
const clientInfo = getClientInfo();
|
|
190
|
-
const browserId = await getBrowserID(clientInfo);
|
|
191
|
-
|
|
192
|
-
const trackingData: TrackingData = {
|
|
193
|
-
browserId,
|
|
194
|
-
...clientInfo,
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const response = await fetch(
|
|
198
|
-
"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track",
|
|
199
|
-
{
|
|
200
|
-
method: "POST",
|
|
201
|
-
headers: { "Content-Type": "application/json" },
|
|
202
|
-
body: JSON.stringify(trackingData),
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
if (!response.ok) {
|
|
207
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const data = await response.json();
|
|
211
|
-
console.log(
|
|
212
|
-
"[StormcloudVideoPlayer] Initial tracking data sent successfully:",
|
|
213
|
-
data
|
|
214
|
-
);
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.error(
|
|
217
|
-
"[StormcloudVideoPlayer] Error sending initial tracking data:",
|
|
218
|
-
error
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export async function sendHeartbeat(): Promise<void> {
|
|
224
|
-
try {
|
|
225
|
-
const clientInfo = getClientInfo();
|
|
226
|
-
const browserId = await getBrowserID(clientInfo);
|
|
227
|
-
|
|
228
|
-
const heartbeatData: HeartbeatData = {
|
|
229
|
-
browserId,
|
|
230
|
-
timestamp: new Date().toISOString(),
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
const response = await fetch(
|
|
234
|
-
"https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat",
|
|
235
|
-
{
|
|
236
|
-
method: "POST",
|
|
237
|
-
headers: { "Content-Type": "application/json" },
|
|
238
|
-
body: JSON.stringify(heartbeatData),
|
|
239
|
-
}
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
if (!response.ok) {
|
|
243
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const data = await response.json();
|
|
247
|
-
console.log("[StormcloudVideoPlayer] Heartbeat sent successfully:", data);
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
|
|
250
|
-
}
|
|
251
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Visit https://aka.ms/tsconfig to read more about this file
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
// File Layout
|
|
5
|
-
"rootDir": "src",
|
|
6
|
-
"outDir": "dist",
|
|
7
|
-
|
|
8
|
-
// Environment Settings
|
|
9
|
-
// See also https://aka.ms/tsconfig/module
|
|
10
|
-
"module": "esnext",
|
|
11
|
-
"target": "es2020",
|
|
12
|
-
"types": [],
|
|
13
|
-
"lib": ["es2020", "dom"],
|
|
14
|
-
// For nodejs:
|
|
15
|
-
// "lib": ["esnext"],
|
|
16
|
-
// "types": ["node"],
|
|
17
|
-
// and npm install -D @types/node
|
|
18
|
-
|
|
19
|
-
// Other Outputs
|
|
20
|
-
"sourceMap": true,
|
|
21
|
-
"declaration": true,
|
|
22
|
-
"declarationMap": true,
|
|
23
|
-
|
|
24
|
-
// Stricter Typechecking Options
|
|
25
|
-
"noUncheckedIndexedAccess": true,
|
|
26
|
-
"exactOptionalPropertyTypes": true,
|
|
27
|
-
|
|
28
|
-
// Style Options
|
|
29
|
-
// "noImplicitReturns": true,
|
|
30
|
-
// "noImplicitOverride": true,
|
|
31
|
-
// "noUnusedLocals": true,
|
|
32
|
-
// "noUnusedParameters": true,
|
|
33
|
-
// "noFallthroughCasesInSwitch": true,
|
|
34
|
-
// "noPropertyAccessFromIndexSignature": true,
|
|
35
|
-
|
|
36
|
-
// Recommended Options
|
|
37
|
-
"strict": true,
|
|
38
|
-
"jsx": "react-jsx",
|
|
39
|
-
"verbatimModuleSyntax": true,
|
|
40
|
-
"isolatedModules": true,
|
|
41
|
-
"noUncheckedSideEffectImports": true,
|
|
42
|
-
"moduleDetection": "force",
|
|
43
|
-
"skipLibCheck": true,
|
|
44
|
-
|
|
45
|
-
"moduleResolution": "bundler",
|
|
46
|
-
"esModuleInterop": true,
|
|
47
|
-
"resolveJsonModule": true,
|
|
48
|
-
}
|
|
49
|
-
}
|