@livepeer-frameworks/player-react 0.1.0 → 0.1.2
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 +7 -9
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +359 -0
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/cjs/assets/logomark.svg.js +8 -0
- package/dist/cjs/assets/logomark.svg.js.map +1 -0
- package/dist/cjs/components/DevModePanel.js +826 -0
- package/dist/cjs/components/DevModePanel.js.map +1 -0
- package/dist/cjs/components/DvdLogo.js +200 -0
- package/dist/cjs/components/DvdLogo.js.map +1 -0
- package/dist/cjs/components/Icons.js +439 -0
- package/dist/cjs/components/Icons.js.map +1 -0
- package/dist/cjs/components/IdleScreen.js +587 -0
- package/dist/cjs/components/IdleScreen.js.map +1 -0
- package/dist/cjs/components/LoadingScreen.js +523 -0
- package/dist/cjs/components/LoadingScreen.js.map +1 -0
- package/dist/cjs/components/Player.js +420 -0
- package/dist/cjs/components/Player.js.map +1 -0
- package/dist/cjs/components/PlayerControls.js +798 -0
- package/dist/cjs/components/PlayerControls.js.map +1 -0
- package/dist/cjs/components/PlayerErrorBoundary.js +80 -0
- package/dist/cjs/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/cjs/components/SeekBar.js +253 -0
- package/dist/cjs/components/SeekBar.js.map +1 -0
- package/dist/cjs/components/SkipIndicator.js +92 -0
- package/dist/cjs/components/SkipIndicator.js.map +1 -0
- package/dist/cjs/components/SpeedIndicator.js +43 -0
- package/dist/cjs/components/SpeedIndicator.js.map +1 -0
- package/dist/cjs/components/StatsPanel.js +202 -0
- package/dist/cjs/components/StatsPanel.js.map +1 -0
- package/dist/cjs/components/StreamStateOverlay.js +229 -0
- package/dist/cjs/components/StreamStateOverlay.js.map +1 -0
- package/dist/cjs/components/ThumbnailOverlay.js +86 -0
- package/dist/cjs/components/ThumbnailOverlay.js.map +1 -0
- package/dist/cjs/components/TitleOverlay.js +32 -0
- package/dist/cjs/components/TitleOverlay.js.map +1 -0
- package/dist/cjs/context/PlayerContext.js +46 -0
- package/dist/cjs/context/PlayerContext.js.map +1 -0
- package/dist/cjs/hooks/useMetaTrack.js +165 -0
- package/dist/cjs/hooks/useMetaTrack.js.map +1 -0
- package/dist/cjs/hooks/usePlaybackQuality.js +131 -0
- package/dist/cjs/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/cjs/hooks/usePlayerController.js +518 -0
- package/dist/cjs/hooks/usePlayerController.js.map +1 -0
- package/dist/cjs/hooks/usePlayerSelection.js +90 -0
- package/dist/cjs/hooks/usePlayerSelection.js.map +1 -0
- package/dist/cjs/hooks/useStreamState.js +360 -0
- package/dist/cjs/hooks/useStreamState.js.map +1 -0
- package/dist/cjs/hooks/useTelemetry.js +120 -0
- package/dist/cjs/hooks/useTelemetry.js.map +1 -0
- package/dist/cjs/hooks/useViewerEndpoints.js +222 -0
- package/dist/cjs/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/cjs/index.js +97 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/ui/badge.js +34 -0
- package/dist/cjs/ui/badge.js.map +1 -0
- package/dist/cjs/ui/button.js +74 -0
- package/dist/cjs/ui/button.js.map +1 -0
- package/dist/cjs/ui/context-menu.js +163 -0
- package/dist/cjs/ui/context-menu.js.map +1 -0
- package/dist/cjs/ui/slider.js +60 -0
- package/dist/cjs/ui/slider.js.map +1 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/esm/assets/logomark.svg.js +4 -0
- package/dist/esm/assets/logomark.svg.js.map +1 -0
- package/dist/esm/components/DevModePanel.js +822 -0
- package/dist/esm/components/DevModePanel.js.map +1 -0
- package/dist/esm/components/DvdLogo.js +196 -0
- package/dist/esm/components/DvdLogo.js.map +1 -0
- package/dist/esm/components/Icons.js +421 -0
- package/dist/esm/components/Icons.js.map +1 -0
- package/dist/esm/components/IdleScreen.js +582 -0
- package/dist/esm/components/IdleScreen.js.map +1 -0
- package/dist/esm/components/LoadingScreen.js +519 -0
- package/dist/esm/components/LoadingScreen.js.map +1 -0
- package/dist/esm/components/Player.js +416 -0
- package/dist/esm/components/Player.js.map +1 -0
- package/dist/esm/components/PlayerControls.js +794 -0
- package/dist/esm/components/PlayerControls.js.map +1 -0
- package/dist/esm/components/PlayerErrorBoundary.js +76 -0
- package/dist/esm/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/esm/components/SeekBar.js +249 -0
- package/dist/esm/components/SeekBar.js.map +1 -0
- package/dist/esm/components/SkipIndicator.js +88 -0
- package/dist/esm/components/SkipIndicator.js.map +1 -0
- package/dist/esm/components/SpeedIndicator.js +39 -0
- package/dist/esm/components/SpeedIndicator.js.map +1 -0
- package/dist/esm/components/StatsPanel.js +198 -0
- package/dist/esm/components/StatsPanel.js.map +1 -0
- package/dist/esm/components/StreamStateOverlay.js +224 -0
- package/dist/esm/components/StreamStateOverlay.js.map +1 -0
- package/dist/esm/components/ThumbnailOverlay.js +82 -0
- package/dist/esm/components/ThumbnailOverlay.js.map +1 -0
- package/dist/esm/components/TitleOverlay.js +28 -0
- package/dist/esm/components/TitleOverlay.js.map +1 -0
- package/dist/esm/context/PlayerContext.js +41 -0
- package/dist/esm/context/PlayerContext.js.map +1 -0
- package/dist/esm/hooks/useMetaTrack.js +163 -0
- package/dist/esm/hooks/useMetaTrack.js.map +1 -0
- package/dist/esm/hooks/usePlaybackQuality.js +129 -0
- package/dist/esm/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/esm/hooks/usePlayerController.js +516 -0
- package/dist/esm/hooks/usePlayerController.js.map +1 -0
- package/dist/esm/hooks/usePlayerSelection.js +88 -0
- package/dist/esm/hooks/usePlayerSelection.js.map +1 -0
- package/dist/esm/hooks/useStreamState.js +358 -0
- package/dist/esm/hooks/useStreamState.js.map +1 -0
- package/dist/esm/hooks/useTelemetry.js +118 -0
- package/dist/esm/hooks/useTelemetry.js.map +1 -0
- package/dist/esm/hooks/useViewerEndpoints.js +220 -0
- package/dist/esm/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/esm/index.js +23 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/ui/badge.js +31 -0
- package/dist/esm/ui/badge.js.map +1 -0
- package/dist/esm/ui/button.js +52 -0
- package/dist/esm/ui/button.js.map +1 -0
- package/dist/esm/ui/context-menu.js +132 -0
- package/dist/esm/ui/context-menu.js.map +1 -0
- package/dist/esm/ui/slider.js +38 -0
- package/dist/esm/ui/slider.js.map +1 -0
- package/dist/types/components/DvdLogo.d.ts +1 -1
- package/dist/types/components/Icons.d.ts +1 -1
- package/dist/types/components/Player.d.ts +1 -1
- package/dist/types/components/PlayerErrorBoundary.d.ts +2 -1
- package/dist/types/components/StreamStateOverlay.d.ts +2 -2
- package/dist/types/components/SubtitleRenderer.d.ts +2 -2
- package/dist/types/context/PlayerContext.d.ts +2 -2
- package/dist/types/context/index.d.ts +2 -2
- package/dist/types/hooks/useMetaTrack.d.ts +3 -3
- package/dist/types/hooks/usePlaybackQuality.d.ts +2 -2
- package/dist/types/hooks/usePlayerController.d.ts +26 -3
- package/dist/types/hooks/usePlayerSelection.d.ts +1 -1
- package/dist/types/hooks/useStreamState.d.ts +1 -1
- package/dist/types/hooks/useTelemetry.d.ts +1 -1
- package/dist/types/hooks/useViewerEndpoints.d.ts +3 -3
- package/dist/types/index.d.ts +28 -28
- package/dist/types/types.d.ts +3 -3
- package/dist/types/ui/select.d.ts +1 -1
- package/package.json +22 -14
- package/src/components/DevModePanel.tsx +244 -143
- package/src/components/DvdLogo.tsx +1 -1
- package/src/components/Icons.tsx +105 -25
- package/src/components/IdleScreen.tsx +262 -128
- package/src/components/LoadingScreen.tsx +169 -151
- package/src/components/LogoOverlay.tsx +3 -6
- package/src/components/Player.tsx +126 -59
- package/src/components/PlayerControls.tsx +384 -272
- package/src/components/PlayerErrorBoundary.tsx +7 -13
- package/src/components/SeekBar.tsx +96 -88
- package/src/components/SkipIndicator.tsx +2 -12
- package/src/components/SpeedIndicator.tsx +2 -11
- package/src/components/StatsPanel.tsx +31 -22
- package/src/components/StreamStateOverlay.tsx +105 -49
- package/src/components/SubtitleRenderer.tsx +29 -29
- package/src/components/ThumbnailOverlay.tsx +5 -6
- package/src/components/TitleOverlay.tsx +2 -8
- package/src/context/PlayerContext.tsx +4 -8
- package/src/context/index.ts +3 -3
- package/src/hooks/useMetaTrack.ts +27 -27
- package/src/hooks/usePlaybackQuality.ts +3 -3
- package/src/hooks/usePlayerController.ts +246 -138
- package/src/hooks/usePlayerSelection.ts +6 -6
- package/src/hooks/useStreamState.ts +51 -56
- package/src/hooks/useTelemetry.ts +18 -3
- package/src/hooks/useViewerEndpoints.ts +34 -23
- package/src/index.tsx +36 -28
- package/src/types.ts +8 -8
- package/src/ui/badge.tsx +6 -5
- package/src/ui/button.tsx +9 -8
- package/src/ui/context-menu.tsx +42 -61
- package/src/ui/select.tsx +13 -7
- package/src/ui/slider.tsx +18 -29
- package/dist/types/components/players/DashJsPlayer.d.ts +0 -18
- package/dist/types/components/players/HlsJsPlayer.d.ts +0 -18
- package/dist/types/components/players/MewsWsPlayer/index.d.ts +0 -18
- package/dist/types/components/players/MistPlayer.d.ts +0 -20
- package/dist/types/components/players/MistWebRTCPlayer/index.d.ts +0 -20
- package/dist/types/components/players/NativePlayer.d.ts +0 -19
- package/dist/types/components/players/VideoJsPlayer.d.ts +0 -18
- package/src/components/players/DashJsPlayer.tsx +0 -56
- package/src/components/players/HlsJsPlayer.tsx +0 -56
- package/src/components/players/MewsWsPlayer/index.tsx +0 -56
- package/src/components/players/MistPlayer.tsx +0 -60
- package/src/components/players/MistWebRTCPlayer/index.tsx +0 -59
- package/src/components/players/NativePlayer.tsx +0 -58
- package/src/components/players/VideoJsPlayer.tsx +0 -56
|
@@ -29,16 +29,19 @@ const AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {
|
|
|
29
29
|
|
|
30
30
|
const animationCycle = () => {
|
|
31
31
|
setOpacity(0.15);
|
|
32
|
-
setTimeout(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
setPosition(getRandomPosition());
|
|
36
|
-
setSize(getRandomSize());
|
|
32
|
+
setTimeout(
|
|
33
|
+
() => {
|
|
34
|
+
setOpacity(0);
|
|
37
35
|
setTimeout(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
setPosition(getRandomPosition());
|
|
37
|
+
setSize(getRandomSize());
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
animationCycle();
|
|
40
|
+
}, 200);
|
|
41
|
+
}, 1500);
|
|
42
|
+
},
|
|
43
|
+
4000 + Math.random() * 3000
|
|
44
|
+
);
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
const timeout = setTimeout(animationCycle, index * 500);
|
|
@@ -58,19 +61,21 @@ const AnimatedBubble: React.FC<AnimatedBubbleProps> = ({ index }) => {
|
|
|
58
61
|
|
|
59
62
|
return (
|
|
60
63
|
<div
|
|
61
|
-
style={
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
style={
|
|
65
|
+
{
|
|
66
|
+
position: "absolute",
|
|
67
|
+
top: `${position.top}%`,
|
|
68
|
+
left: `${position.left}%`,
|
|
69
|
+
width: `${size}px`,
|
|
70
|
+
height: `${size}px`,
|
|
71
|
+
borderRadius: "50%",
|
|
72
|
+
background: bubbleColors[index % bubbleColors.length],
|
|
73
|
+
opacity,
|
|
74
|
+
transition: "opacity 1s ease-in-out",
|
|
75
|
+
pointerEvents: "none",
|
|
76
|
+
userSelect: "none",
|
|
77
|
+
} as React.CSSProperties
|
|
78
|
+
}
|
|
74
79
|
/>
|
|
75
80
|
);
|
|
76
81
|
};
|
|
@@ -138,11 +143,11 @@ const CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHi
|
|
|
138
143
|
useEffect(() => {
|
|
139
144
|
if (containerRef.current) {
|
|
140
145
|
const container = containerRef.current;
|
|
141
|
-
container.addEventListener(
|
|
142
|
-
container.addEventListener(
|
|
146
|
+
container.addEventListener("mousemove", handleMouseMove);
|
|
147
|
+
container.addEventListener("mouseleave", handleMouseLeave);
|
|
143
148
|
return () => {
|
|
144
|
-
container.removeEventListener(
|
|
145
|
-
container.removeEventListener(
|
|
149
|
+
container.removeEventListener("mousemove", handleMouseMove);
|
|
150
|
+
container.removeEventListener("mouseleave", handleMouseLeave);
|
|
146
151
|
};
|
|
147
152
|
}
|
|
148
153
|
}, [logoSize, containerRef]);
|
|
@@ -169,7 +174,9 @@ const CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHi
|
|
|
169
174
|
height: `${logoSize * 1.4}px`,
|
|
170
175
|
borderRadius: "50%",
|
|
171
176
|
background: "rgba(122, 162, 247, 0.15)",
|
|
172
|
-
animation: isHovered
|
|
177
|
+
animation: isHovered
|
|
178
|
+
? "logoPulse 1s ease-in-out infinite"
|
|
179
|
+
: "logoPulse 3s ease-in-out infinite",
|
|
173
180
|
transform: isHovered ? "scale(1.2)" : "scale(1)",
|
|
174
181
|
transition: "transform 0.3s ease-out",
|
|
175
182
|
pointerEvents: "none",
|
|
@@ -179,20 +186,22 @@ const CenterLogo: React.FC<CenterLogoProps> = ({ containerRef, scale = 0.2, onHi
|
|
|
179
186
|
src={logomarkAsset}
|
|
180
187
|
alt="FrameWorks Logo"
|
|
181
188
|
onClick={handleLogoClick}
|
|
182
|
-
style={
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
style={
|
|
190
|
+
{
|
|
191
|
+
width: `${logoSize}px`,
|
|
192
|
+
height: `${logoSize}px`,
|
|
193
|
+
position: "relative",
|
|
194
|
+
zIndex: 1,
|
|
195
|
+
filter: isHovered
|
|
196
|
+
? "drop-shadow(0 6px 12px rgba(36, 40, 59, 0.4)) brightness(1.1)"
|
|
197
|
+
: "drop-shadow(0 4px 8px rgba(36, 40, 59, 0.3))",
|
|
198
|
+
transform: isHovered ? "scale(1.1)" : "scale(1)",
|
|
199
|
+
transition: "all 0.3s ease-out",
|
|
200
|
+
cursor: isHovered ? "pointer" : "default",
|
|
201
|
+
userSelect: "none",
|
|
202
|
+
WebkitUserDrag: "none",
|
|
203
|
+
} as React.CSSProperties
|
|
204
|
+
}
|
|
196
205
|
/>
|
|
197
206
|
</div>
|
|
198
207
|
);
|
|
@@ -214,45 +223,103 @@ function StatusIcon({ status }: { status?: StreamStatus }) {
|
|
|
214
223
|
const iconClass = "w-5 h-5";
|
|
215
224
|
|
|
216
225
|
// Spinner for loading states
|
|
217
|
-
if (
|
|
226
|
+
if (
|
|
227
|
+
status === "INITIALIZING" ||
|
|
228
|
+
status === "BOOTING" ||
|
|
229
|
+
status === "WAITING_FOR_DATA" ||
|
|
230
|
+
!status
|
|
231
|
+
) {
|
|
218
232
|
return (
|
|
219
|
-
<svg
|
|
220
|
-
|
|
221
|
-
|
|
233
|
+
<svg
|
|
234
|
+
className={`${iconClass} animate-spin`}
|
|
235
|
+
fill="none"
|
|
236
|
+
viewBox="0 0 24 24"
|
|
237
|
+
style={{ color: "hsl(var(--tn-yellow, 40 95% 64%))" }}
|
|
238
|
+
>
|
|
239
|
+
<circle
|
|
240
|
+
className="opacity-25"
|
|
241
|
+
cx="12"
|
|
242
|
+
cy="12"
|
|
243
|
+
r="10"
|
|
244
|
+
stroke="currentColor"
|
|
245
|
+
strokeWidth="4"
|
|
246
|
+
/>
|
|
247
|
+
<path
|
|
248
|
+
className="opacity-75"
|
|
249
|
+
fill="currentColor"
|
|
250
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
251
|
+
/>
|
|
222
252
|
</svg>
|
|
223
253
|
);
|
|
224
254
|
}
|
|
225
255
|
|
|
226
256
|
// Offline icon
|
|
227
|
-
if (status ===
|
|
257
|
+
if (status === "OFFLINE") {
|
|
228
258
|
return (
|
|
229
|
-
<svg
|
|
230
|
-
|
|
259
|
+
<svg
|
|
260
|
+
className={iconClass}
|
|
261
|
+
fill="none"
|
|
262
|
+
viewBox="0 0 24 24"
|
|
263
|
+
stroke="currentColor"
|
|
264
|
+
style={{ color: "hsl(var(--tn-red, 348 100% 72%))" }}
|
|
265
|
+
>
|
|
266
|
+
<path
|
|
267
|
+
strokeLinecap="round"
|
|
268
|
+
strokeLinejoin="round"
|
|
269
|
+
strokeWidth={2}
|
|
270
|
+
d="M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414"
|
|
271
|
+
/>
|
|
231
272
|
</svg>
|
|
232
273
|
);
|
|
233
274
|
}
|
|
234
275
|
|
|
235
276
|
// Error icon
|
|
236
|
-
if (status ===
|
|
277
|
+
if (status === "ERROR" || status === "INVALID") {
|
|
237
278
|
return (
|
|
238
|
-
<svg
|
|
239
|
-
|
|
279
|
+
<svg
|
|
280
|
+
className={iconClass}
|
|
281
|
+
fill="none"
|
|
282
|
+
viewBox="0 0 24 24"
|
|
283
|
+
stroke="currentColor"
|
|
284
|
+
style={{ color: "hsl(var(--tn-red, 348 100% 72%))" }}
|
|
285
|
+
>
|
|
286
|
+
<path
|
|
287
|
+
strokeLinecap="round"
|
|
288
|
+
strokeLinejoin="round"
|
|
289
|
+
strokeWidth={2}
|
|
290
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
291
|
+
/>
|
|
240
292
|
</svg>
|
|
241
293
|
);
|
|
242
294
|
}
|
|
243
295
|
|
|
244
296
|
// Default spinner
|
|
245
297
|
return (
|
|
246
|
-
<svg
|
|
298
|
+
<svg
|
|
299
|
+
className={`${iconClass} animate-spin`}
|
|
300
|
+
fill="none"
|
|
301
|
+
viewBox="0 0 24 24"
|
|
302
|
+
style={{ color: "hsl(var(--tn-cyan, 193 100% 75%))" }}
|
|
303
|
+
>
|
|
247
304
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
248
|
-
<path
|
|
305
|
+
<path
|
|
306
|
+
className="opacity-75"
|
|
307
|
+
fill="currentColor"
|
|
308
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
309
|
+
/>
|
|
249
310
|
</svg>
|
|
250
311
|
);
|
|
251
312
|
}
|
|
252
313
|
|
|
253
|
-
const StatusOverlay: React.FC<StatusOverlayProps> = ({
|
|
254
|
-
|
|
255
|
-
|
|
314
|
+
const StatusOverlay: React.FC<StatusOverlayProps> = ({
|
|
315
|
+
status,
|
|
316
|
+
message,
|
|
317
|
+
percentage,
|
|
318
|
+
error,
|
|
319
|
+
onRetry,
|
|
320
|
+
}) => {
|
|
321
|
+
const showRetry = (status === "ERROR" || status === "INVALID") && onRetry;
|
|
322
|
+
const showProgress = status === "INITIALIZING" && percentage !== undefined;
|
|
256
323
|
const displayMessage = error || message;
|
|
257
324
|
|
|
258
325
|
return (
|
|
@@ -352,50 +419,51 @@ interface Hitmarker {
|
|
|
352
419
|
const playHitmarkerSound = () => {
|
|
353
420
|
try {
|
|
354
421
|
// Embedded hitmarker sound as base64 data URL
|
|
355
|
-
const hitmarkerDataUrl =
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
422
|
+
const hitmarkerDataUrl =
|
|
423
|
+
"data:audio/mpeg;base64,SUQzBAAAAAAANFRDT04AAAAHAAADT3RoZXIAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAA" +
|
|
424
|
+
"AAD/+1QAAAAAAAAAAAAAAAAAAAAA" +
|
|
425
|
+
"AAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAYAAAnAADs7Ozs7Ozs7Ozs7Ozs7OztiYmJiYmJiYmJi" +
|
|
426
|
+
"YmJiYmJiYomJiYmJiYmJiYmJiYmJiYmxsbGxsbGxsbGxsbGxsbGxsdjY2NjY2NjY2NjY2NjY2NjY////" +
|
|
427
|
+
"/////////////////wAAAABMYXZjNTcuMTAAAAAAAAAAAAAAAAAkAkAAAAAAAAAJwOuMZun/+5RkAA8S" +
|
|
428
|
+
"/F23AGAaAi0AF0AAAAAInXsEAIRXyQ8D4OQgjEhE3cO7ujuHF0XCOu4G7xKbi3Funu7u7p9dw7unu7u7" +
|
|
429
|
+
"p7u7u6fXcW7om7u7uiU3dxdT67u7p7uHdxelN3cW6fXcW7oXXd3eJTd3d0+u4t3iXdw4up70W4uiPruL" +
|
|
430
|
+
"DzMw8Pz79Y99JfkyfPv5/h9uTJoy79Y99Y97q3vyZPJk0ZfrL6x73Vn+J35dKKS/STQyQ8CAiCPNuRAO" +
|
|
431
|
+
"OqquAx+fzJeBKDAsgAMBuWcBsHKhjJTcCwIALyAvABbI0ZIcCmP8jHJe8gZAdVRp2TpnU/kUXV4iQuBA" +
|
|
432
|
+
"AkAQgisLPvwQ2Jz7wIkIpQ8QOl/KFy75w+2HpTFnRqXLQo0fzlSYRe5Ce9yZMEzRM4xesu95Mo8QQsoM" +
|
|
433
|
+
"H4gLg+fJqkmY3GZJE2kwGfMECJiAdIttoEa2yotfC7jsS2mjKgbzAfEMeiwZpGSUFCQwPKQiWXh0TnkN" +
|
|
434
|
+
"or5SmrKvwHlX2zFxKxPCzRL/+5RkIwADvUxLawwb0GdF6Y1hJlgNNJk+DSRwyQwI6AD2JCiBmhaff0dz" +
|
|
435
|
+
"CEBjgFABAcDNFc3YAEV4hQn0L/QvQnevom+n13eIjoTvABLrHg/L9RzdWXYonHbbbE2K0pX+gkL2g56R" +
|
|
436
|
+
"iwrbuWwhoABzQoMKOAIGAfE4UKk6BhSIJpECBq0CEYmZKYIiAJt72H24dNou7y/Ee7a/3v+MgySemSTY" +
|
|
437
|
+
"mnBAFwIAAGfCJ8/D9YfkwQEBcP38uA1d/EB1T5dZKEsgnuhwZirY5fIMRMdRn7U4OcN2m5NWeYdcPBwX" +
|
|
438
|
+
"DBOsJF1DBYks62pAURqz1hGoGHH/QIoRC80tYAJ8g4f3MPD51sywAbhAn/X9P/75tvZww3gZ3pYPDx/+" +
|
|
439
|
+
"ACO/7//ffHj/D/AAfATC4DYGFA3MRABo0lqWjBOl2yAda1C1BdhduXgm8FGnAQB/lDiEi6j9qw9EHigI" +
|
|
440
|
+
"IOLB6F1eIPd+T6Agc4//lMo6+k3tdttJY2gArU7cN07m2FLSm4gCjyz/+5RECwACwSRZawkdLFGi2mVh" +
|
|
441
|
+
"5h4LfFdPVPGACViTavaeMAAV0UkkEsDhxxJwqF04on002mZah8w9+5ItfSAoyZa1dchnPpLmAEKrVMRA" +
|
|
442
|
+
"//sD8w0WsB4xiw4JqaZMB45TdpIuXXUPf8Bpa35p/jQIAOAuZkmUeJoM5W6L2gqqO6rTuHjUTDnhy4Qi" +
|
|
443
|
+
"K348vtFysOizShoHbBpsPRYcSINCbiN4XOLPPAgq3dW2Ga7SlyiKXBV7W1RQl5BiiVGkwayJfEnPxgXk" +
|
|
444
|
+
"QeZxxzyhTuLO2XFUDDstoc6CkM1J8QZAjUN3bM8580cRygNfmPAELGjIH0Z/0A+8csyH/4eHvgAf8APg" +
|
|
445
|
+
"ABmZ98AARAADP////Dw8PHEmIpgGttpJQJsmZjq5nPQ8j5VqWW1evqdjP182PA6tHJZgkC5iSbEQkyJS" +
|
|
446
|
+
"z/BvP3eucLKN0+Wiza4feKKFBqiAEBAMXyYni5NZc16CDl/QY9j6BAcWSmQYcIcoMHYoQNBiIBgIBUAz" +
|
|
447
|
+
"QUMSnjj/+5RkCwADsFLffjEAAjrJe63JHACO6WtlnPMACKaCK1uMMADU5dI6JhW2cam98UlRmY4ihyKF" +
|
|
448
|
+
"rNsgpZd5PYgBALnYofKEt82De0GbW1DLibvFDK+bSeOm8qKdqUFZ7uiK8XMPHyqm3pTxUvcunUfxXEo9" +
|
|
449
|
+
"RNe5b/8vfCD3kzDN7vTtHyaIcntVDAYBAUBAAAAQBI2vguYNsHWm5AR3mZtZib8WAHFvz2Kf9//iYvlR" +
|
|
450
|
+
"B/+n///////////+UH7XoIDMoJAEAMtj8JshJPRwklVqNSpYnalfE+VzNCAISCoxVHEpIo/WrTiMvP7V" +
|
|
451
|
+
"TujOPnOglLbMLN/pq/d2Y4lRJIkSnPlUSJEjSKJqM41d88zWtMzP+fCOORmc9NeM+f1nnO//efM52/fG" +
|
|
452
|
+
"/ef385+5u+u1bRJkwU8FAkEItZpkRYeQYcAgZTEYlaZa2yROLeC0qdX73rZJJ/d2f6v6Or0u/+5FBYcn" +
|
|
453
|
+
"g0MlCiQTR9GUU5LScmSuSlH00IWqXA6jlw4BEcD/+5REEAAi3RtU+eYbGF1E+lk9g0YJzLUgh7BlQVGT" +
|
|
454
|
+
"ZJD0jKhhTNVilqrMzFRK+x/szcMKBWKep4NP1A0DR6RESkTp5Z1Q9Y8REgqMg1DpUBPleeqlRQcerBpM" +
|
|
455
|
+
"jiURHVD4XwAALhAgbxxlxYD5OFkG8oQRPB2EpsxSCNVlgcYUqoAyiVJmaARlkwplICfPoUy/zWEzM2pc" +
|
|
456
|
+
"NYzAQNJDSniEYecSEqxFEzQqEvUFGnvzwUfcRlpZ9T2LCR5QdDQDDhKICAjpJCagpRo9UQRPClZZlg6E" +
|
|
457
|
+
"p9DMTkTl+okuhRIVIzAQEf9L+Mx/DUjqmqN6kX7M36lS4zgLyJV3iV6j3xF8kJduJawVw1nndAlBaLLg" +
|
|
458
|
+
"JupwsTcLkxmJgFLgSzoCmHjSNGSqkGPCpnNqTXIwolf6qlVWN+q/su37HzgrES1pWGg3KnWh0FXCVniJ" +
|
|
459
|
+
"9K5b4iCrpLEuIcFTqwkVLFiqgaDqCCSMVWqxBAVCFOLVrVahm2ahUThUKJnmFCw15hD0Qhb/+5REEAhC" +
|
|
460
|
+
"YSRCSQEb4FOGaBUMI6JIRYC0QIB2SQsgGpgwDghgIlS6FU8VBXDoiBp5Y9gtkVnhEhYBdJFQ7kQ3w1yp" +
|
|
461
|
+
"0NB2CoNPEttZ1/aeDUAAA26FEghWgEKNVAVWkFAQEmMK2Uwk/qI0hqUb/4epVIZH1ai6szf6kzH1f2ar" +
|
|
462
|
+
"xYGS9FcOsN5UlJLQt///+oo0FRDTUQ0FBQr9f5LxXP+mEUfk0AIrf/5GRmQ0//mX//ZbLP5b5GrWSz+W" +
|
|
463
|
+
"SkZMrWyyyy2GRqyggVRyMv////////st//sn/yyVDI1l8mVgoYGDCOqiqIQBxmvxWCggTpZZZD//aWfy" +
|
|
464
|
+
"yWf/y/7KGDA0ssBggTof9k/+WS/8slQyMp/5Nfln8WAqGcUbULCrKxT9ISF+kKsxQWpMQU1FMy4xMDCq" +
|
|
465
|
+
"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" +
|
|
466
|
+
"qqqqqqqqqqqqqqqqqqqqqqqqqqo=";
|
|
399
467
|
|
|
400
468
|
const audio = new Audio(hitmarkerDataUrl);
|
|
401
469
|
audio.volume = 0.3;
|
|
@@ -425,8 +493,8 @@ const createSyntheticHitmarkerSound = () => {
|
|
|
425
493
|
oscillator2.frequency.setValueAtTime(3600, audioContext.currentTime);
|
|
426
494
|
oscillator2.frequency.exponentialRampToValueAtTime(1800, audioContext.currentTime + 0.04);
|
|
427
495
|
|
|
428
|
-
oscillator1.type =
|
|
429
|
-
oscillator2.type =
|
|
496
|
+
oscillator1.type = "triangle";
|
|
497
|
+
oscillator2.type = "sine";
|
|
430
498
|
|
|
431
499
|
gainNode1.gain.setValueAtTime(0, audioContext.currentTime);
|
|
432
500
|
gainNode1.gain.linearRampToValueAtTime(0.4, audioContext.currentTime + 0.002);
|
|
@@ -490,19 +558,19 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
490
558
|
y,
|
|
491
559
|
};
|
|
492
560
|
|
|
493
|
-
setHitmarkers(prev => [...prev, newHitmarker]);
|
|
561
|
+
setHitmarkers((prev) => [...prev, newHitmarker]);
|
|
494
562
|
playHitmarkerSound();
|
|
495
563
|
|
|
496
564
|
setTimeout(() => {
|
|
497
|
-
setHitmarkers(prev => prev.filter(h => h.id !== newHitmarker.id));
|
|
565
|
+
setHitmarkers((prev) => prev.filter((h) => h.id !== newHitmarker.id));
|
|
498
566
|
}, 600);
|
|
499
567
|
};
|
|
500
568
|
|
|
501
569
|
// Inject CSS animations
|
|
502
570
|
useEffect(() => {
|
|
503
|
-
const styleId =
|
|
571
|
+
const styleId = "idle-screen-animations";
|
|
504
572
|
if (!document.getElementById(styleId)) {
|
|
505
|
-
const style = document.createElement(
|
|
573
|
+
const style = document.createElement("style");
|
|
506
574
|
style.id = styleId;
|
|
507
575
|
style.textContent = `
|
|
508
576
|
@keyframes fadeInOut {
|
|
@@ -542,11 +610,12 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
542
610
|
<div
|
|
543
611
|
ref={containerRef}
|
|
544
612
|
className="fw-player-root"
|
|
545
|
-
style={
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
613
|
+
style={
|
|
614
|
+
{
|
|
615
|
+
position: "absolute",
|
|
616
|
+
inset: 0,
|
|
617
|
+
zIndex: 5,
|
|
618
|
+
background: `
|
|
550
619
|
linear-gradient(135deg,
|
|
551
620
|
hsl(var(--tn-bg-dark, 235 21% 11%)) 0%,
|
|
552
621
|
hsl(var(--tn-bg, 233 23% 17%)) 25%,
|
|
@@ -555,19 +624,20 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
555
624
|
hsl(var(--tn-bg-dark, 235 21% 11%)) 100%
|
|
556
625
|
)
|
|
557
626
|
`,
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
627
|
+
backgroundSize: "400% 400%",
|
|
628
|
+
animation: "gradientShift 16s ease-in-out infinite",
|
|
629
|
+
display: "flex",
|
|
630
|
+
flexDirection: "column",
|
|
631
|
+
alignItems: "center",
|
|
632
|
+
justifyContent: "center",
|
|
633
|
+
overflow: "hidden",
|
|
634
|
+
borderRadius: "0",
|
|
635
|
+
userSelect: "none",
|
|
636
|
+
} as React.CSSProperties
|
|
637
|
+
}
|
|
568
638
|
>
|
|
569
639
|
{/* Hitmarkers */}
|
|
570
|
-
{hitmarkers.map(hitmarker => (
|
|
640
|
+
{hitmarkers.map((hitmarker) => (
|
|
571
641
|
<div
|
|
572
642
|
key={hitmarker.id}
|
|
573
643
|
style={{
|
|
@@ -581,10 +651,62 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
581
651
|
height: "40px",
|
|
582
652
|
}}
|
|
583
653
|
>
|
|
584
|
-
<div
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
654
|
+
<div
|
|
655
|
+
style={{
|
|
656
|
+
position: "absolute",
|
|
657
|
+
top: "25%",
|
|
658
|
+
left: "25%",
|
|
659
|
+
width: "12px",
|
|
660
|
+
height: "3px",
|
|
661
|
+
backgroundColor: "#ffffff",
|
|
662
|
+
transform: "translate(-50%, -50%) rotate(45deg)",
|
|
663
|
+
animation: "hitmarkerFade45 0.6s ease-out forwards",
|
|
664
|
+
boxShadow: "0 0 8px rgba(255, 255, 255, 0.8)",
|
|
665
|
+
borderRadius: "1px",
|
|
666
|
+
}}
|
|
667
|
+
/>
|
|
668
|
+
<div
|
|
669
|
+
style={{
|
|
670
|
+
position: "absolute",
|
|
671
|
+
top: "25%",
|
|
672
|
+
left: "75%",
|
|
673
|
+
width: "12px",
|
|
674
|
+
height: "3px",
|
|
675
|
+
backgroundColor: "#ffffff",
|
|
676
|
+
transform: "translate(-50%, -50%) rotate(-45deg)",
|
|
677
|
+
animation: "hitmarkerFadeNeg45 0.6s ease-out forwards",
|
|
678
|
+
boxShadow: "0 0 8px rgba(255, 255, 255, 0.8)",
|
|
679
|
+
borderRadius: "1px",
|
|
680
|
+
}}
|
|
681
|
+
/>
|
|
682
|
+
<div
|
|
683
|
+
style={{
|
|
684
|
+
position: "absolute",
|
|
685
|
+
top: "75%",
|
|
686
|
+
left: "25%",
|
|
687
|
+
width: "12px",
|
|
688
|
+
height: "3px",
|
|
689
|
+
backgroundColor: "#ffffff",
|
|
690
|
+
transform: "translate(-50%, -50%) rotate(-45deg)",
|
|
691
|
+
animation: "hitmarkerFadeNeg45 0.6s ease-out forwards",
|
|
692
|
+
boxShadow: "0 0 8px rgba(255, 255, 255, 0.8)",
|
|
693
|
+
borderRadius: "1px",
|
|
694
|
+
}}
|
|
695
|
+
/>
|
|
696
|
+
<div
|
|
697
|
+
style={{
|
|
698
|
+
position: "absolute",
|
|
699
|
+
top: "75%",
|
|
700
|
+
left: "75%",
|
|
701
|
+
width: "12px",
|
|
702
|
+
height: "3px",
|
|
703
|
+
backgroundColor: "#ffffff",
|
|
704
|
+
transform: "translate(-50%, -50%) rotate(45deg)",
|
|
705
|
+
animation: "hitmarkerFade45 0.6s ease-out forwards",
|
|
706
|
+
boxShadow: "0 0 8px rgba(255, 255, 255, 0.8)",
|
|
707
|
+
borderRadius: "1px",
|
|
708
|
+
}}
|
|
709
|
+
/>
|
|
588
710
|
</div>
|
|
589
711
|
))}
|
|
590
712
|
|
|
@@ -598,7 +720,16 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
598
720
|
width: `${Math.random() * 4 + 2}px`,
|
|
599
721
|
height: `${Math.random() * 4 + 2}px`,
|
|
600
722
|
borderRadius: "50%",
|
|
601
|
-
background: [
|
|
723
|
+
background: [
|
|
724
|
+
"#7aa2f7",
|
|
725
|
+
"#bb9af7",
|
|
726
|
+
"#9ece6a",
|
|
727
|
+
"#73daca",
|
|
728
|
+
"#7dcfff",
|
|
729
|
+
"#f7768e",
|
|
730
|
+
"#e0af68",
|
|
731
|
+
"#2ac3de",
|
|
732
|
+
][index % 8],
|
|
602
733
|
opacity: 0,
|
|
603
734
|
animation: `floatUp ${8 + Math.random() * 4}s linear infinite`,
|
|
604
735
|
animationDelay: `${Math.random() * 8}s`,
|
|
@@ -613,7 +744,10 @@ export const IdleScreen: React.FC<IdleScreenProps> = ({
|
|
|
613
744
|
))}
|
|
614
745
|
|
|
615
746
|
{/* Center logo */}
|
|
616
|
-
<CenterLogo
|
|
747
|
+
<CenterLogo
|
|
748
|
+
containerRef={containerRef as React.RefObject<HTMLDivElement>}
|
|
749
|
+
onHitmarker={createHitmarker}
|
|
750
|
+
/>
|
|
617
751
|
|
|
618
752
|
{/* DVD Logo */}
|
|
619
753
|
<DvdLogo parentRef={containerRef as React.RefObject<HTMLDivElement>} scale={0.08} />
|