@livepeer-frameworks/player-svelte 0.1.3 → 0.2.3
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/DevModePanel.svelte +34 -25
- package/dist/IdleScreen.svelte +14 -4
- package/dist/LoadingScreen.svelte +92 -50
- package/dist/LoadingScreen.svelte.bak +702 -0
- package/dist/Player.svelte +206 -55
- package/dist/Player.svelte.d.ts +6 -1
- package/dist/PlayerControls.svelte +159 -74
- package/dist/PlayerControls.svelte.d.ts +7 -0
- package/dist/SeekBar.svelte +15 -14
- package/dist/SeekBar.svelte.d.ts +4 -4
- package/dist/StreamStateOverlay.svelte +20 -6
- package/dist/SubtitleRenderer.svelte +3 -3
- package/dist/SubtitleRenderer.svelte.d.ts +1 -1
- package/dist/controls/FullscreenButton.svelte +28 -0
- package/dist/controls/FullscreenButton.svelte.d.ts +3 -0
- package/dist/controls/LiveBadge.svelte +25 -0
- package/dist/controls/LiveBadge.svelte.d.ts +3 -0
- package/dist/controls/PlayButton.svelte +28 -0
- package/dist/controls/PlayButton.svelte.d.ts +3 -0
- package/dist/controls/SettingsMenu.svelte +210 -0
- package/dist/controls/SettingsMenu.svelte.d.ts +28 -0
- package/dist/controls/SkipButton.svelte +36 -0
- package/dist/controls/SkipButton.svelte.d.ts +7 -0
- package/dist/controls/TimeDisplay.svelte +18 -0
- package/dist/controls/TimeDisplay.svelte.d.ts +3 -0
- package/dist/controls/VolumeControl.svelte +28 -0
- package/dist/controls/VolumeControl.svelte.d.ts +3 -0
- package/dist/controls/index.d.ts +7 -0
- package/dist/controls/index.js +7 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -1
- package/dist/stores/i18n.d.ts +3 -0
- package/dist/stores/i18n.js +4 -0
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/index.js +2 -0
- package/dist/stores/playerController.d.ts +4 -4
- package/dist/stores/playerController.js +1 -1
- package/package.json +8 -8
- package/src/DevModePanel.svelte +34 -25
- package/src/IdleScreen.svelte +14 -4
- package/src/LoadingScreen.svelte +92 -50
- package/src/LoadingScreen.svelte.bak +702 -0
- package/src/Player.svelte +206 -55
- package/src/PlayerControls.svelte +159 -74
- package/src/SeekBar.svelte +15 -14
- package/src/StreamStateOverlay.svelte +20 -6
- package/src/SubtitleRenderer.svelte +3 -3
- package/src/controls/FullscreenButton.svelte +28 -0
- package/src/controls/LiveBadge.svelte +25 -0
- package/src/controls/PlayButton.svelte +28 -0
- package/src/controls/SettingsMenu.svelte +210 -0
- package/src/controls/SkipButton.svelte +36 -0
- package/src/controls/TimeDisplay.svelte +18 -0
- package/src/controls/VolumeControl.svelte +28 -0
- package/src/controls/index.ts +7 -0
- package/src/index.ts +10 -0
- package/src/stores/i18n.ts +7 -0
- package/src/stores/index.ts +3 -0
- package/src/stores/playerController.ts +5 -5
package/dist/Player.svelte
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Thin wrapper over PlayerController from @livepeer-frameworks/player-core
|
|
4
4
|
-->
|
|
5
5
|
<script lang="ts">
|
|
6
|
-
import { onMount } from "svelte";
|
|
6
|
+
import { onMount, setContext, type Snippet } from "svelte";
|
|
7
7
|
import IdleScreen from "./IdleScreen.svelte";
|
|
8
8
|
import SubtitleRenderer from "./SubtitleRenderer.svelte";
|
|
9
9
|
import PlayerControls from "./PlayerControls.svelte";
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
import { StatsIcon, SettingsIcon, PictureInPictureIcon } from "./icons";
|
|
24
24
|
import {
|
|
25
25
|
cn,
|
|
26
|
+
themeOverridesToStyle,
|
|
27
|
+
resolveTheme,
|
|
26
28
|
type PlaybackMode,
|
|
27
29
|
type ContentEndpoints,
|
|
28
30
|
type PlayerState,
|
|
@@ -30,11 +32,15 @@
|
|
|
30
32
|
type ContentType,
|
|
31
33
|
type EndpointInfo,
|
|
32
34
|
type PlayerMetadata,
|
|
35
|
+
type FwThemePreset,
|
|
36
|
+
type FwThemeOverrides,
|
|
37
|
+
type FwLocale,
|
|
33
38
|
} from "@livepeer-frameworks/player-core";
|
|
34
39
|
import {
|
|
35
40
|
createPlayerControllerStore,
|
|
36
41
|
type PlayerControllerStore,
|
|
37
42
|
} from "./stores/playerController";
|
|
43
|
+
import { localeStore, translatorStore } from "./stores/i18n";
|
|
38
44
|
import type { SkipDirection } from "./SkipIndicator.svelte";
|
|
39
45
|
|
|
40
46
|
// Props - aligned with React Player
|
|
@@ -57,9 +63,13 @@
|
|
|
57
63
|
forceType?: string;
|
|
58
64
|
forceSource?: number;
|
|
59
65
|
playbackMode?: PlaybackMode;
|
|
66
|
+
theme?: FwThemePreset;
|
|
67
|
+
themeOverrides?: FwThemeOverrides;
|
|
68
|
+
locale?: FwLocale;
|
|
60
69
|
};
|
|
61
70
|
onStateChange?: (state: PlayerState, context?: PlayerStateContext) => void;
|
|
62
71
|
onMetadata?: (metadata: PlayerMetadata) => void;
|
|
72
|
+
children?: Snippet;
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
let {
|
|
@@ -70,6 +80,7 @@
|
|
|
70
80
|
options = {},
|
|
71
81
|
onStateChange = undefined,
|
|
72
82
|
onMetadata = undefined,
|
|
83
|
+
children = undefined,
|
|
73
84
|
}: Props = $props();
|
|
74
85
|
|
|
75
86
|
// ============================================================================
|
|
@@ -79,6 +90,64 @@
|
|
|
79
90
|
let isDevPanelOpen = $state(false);
|
|
80
91
|
let skipDirection: SkipDirection = $state(null);
|
|
81
92
|
|
|
93
|
+
let activeTheme = $state<FwThemePreset>(options?.theme ?? "default");
|
|
94
|
+
let activeLocale = $state<FwLocale>(options?.locale ?? "en");
|
|
95
|
+
|
|
96
|
+
// Sync locale state to i18n store and provide translator context
|
|
97
|
+
$effect(() => {
|
|
98
|
+
localeStore.set(activeLocale);
|
|
99
|
+
});
|
|
100
|
+
setContext("fw-translator", translatorStore);
|
|
101
|
+
|
|
102
|
+
// Provide context for composable controls (reactive getters)
|
|
103
|
+
setContext("fw-player-controller", {
|
|
104
|
+
get isPlaying() {
|
|
105
|
+
return storeState.isPlaying;
|
|
106
|
+
},
|
|
107
|
+
get isPaused() {
|
|
108
|
+
return storeState.isPaused;
|
|
109
|
+
},
|
|
110
|
+
get isMuted() {
|
|
111
|
+
return storeState.isMuted;
|
|
112
|
+
},
|
|
113
|
+
get volume() {
|
|
114
|
+
return storeState.volume;
|
|
115
|
+
},
|
|
116
|
+
get currentTime() {
|
|
117
|
+
return storeState.currentTime;
|
|
118
|
+
},
|
|
119
|
+
get duration() {
|
|
120
|
+
return storeState.duration;
|
|
121
|
+
},
|
|
122
|
+
get isFullscreen() {
|
|
123
|
+
return storeState.isFullscreen;
|
|
124
|
+
},
|
|
125
|
+
get isEffectivelyLive() {
|
|
126
|
+
return storeState.isEffectivelyLive;
|
|
127
|
+
},
|
|
128
|
+
get isBuffering() {
|
|
129
|
+
return storeState.isBuffering;
|
|
130
|
+
},
|
|
131
|
+
get isLoopEnabled() {
|
|
132
|
+
return storeState.isLoopEnabled;
|
|
133
|
+
},
|
|
134
|
+
get error() {
|
|
135
|
+
return storeState.error;
|
|
136
|
+
},
|
|
137
|
+
get qualities() {
|
|
138
|
+
return playerStore?.getQualities() ?? [];
|
|
139
|
+
},
|
|
140
|
+
togglePlay: () => playerStore?.togglePlay(),
|
|
141
|
+
toggleMute: () => playerStore?.toggleMute(),
|
|
142
|
+
toggleFullscreen: () => playerStore?.toggleFullscreen(),
|
|
143
|
+
toggleLoop: () => playerStore?.toggleLoop(),
|
|
144
|
+
setVolume: (v: number) => playerStore?.setVolume(v),
|
|
145
|
+
jumpToLive: () => playerStore?.jumpToLive(),
|
|
146
|
+
seek: (t: number) => playerStore?.seek(t),
|
|
147
|
+
selectQuality: (id: string) => playerStore?.selectQuality(id),
|
|
148
|
+
getQualities: () => playerStore?.getQualities() ?? [],
|
|
149
|
+
});
|
|
150
|
+
|
|
82
151
|
// Playback mode preference (persistent)
|
|
83
152
|
let devPlaybackMode: PlaybackMode = $state("auto");
|
|
84
153
|
$effect(() => {
|
|
@@ -87,6 +156,33 @@
|
|
|
87
156
|
}
|
|
88
157
|
});
|
|
89
158
|
|
|
159
|
+
// Error fade-out: keep overlay visible while it animates out
|
|
160
|
+
let displayedError: string | null = $state(null);
|
|
161
|
+
let displayedIsPassive = $state(false);
|
|
162
|
+
let isErrorDismissing = $state(false);
|
|
163
|
+
let errorDismissTimer: ReturnType<typeof setTimeout> | null = null;
|
|
164
|
+
$effect(() => {
|
|
165
|
+
const error = storeState.error;
|
|
166
|
+
const passive = storeState.isPassiveError;
|
|
167
|
+
if (error) {
|
|
168
|
+
if (errorDismissTimer) {
|
|
169
|
+
clearTimeout(errorDismissTimer);
|
|
170
|
+
errorDismissTimer = null;
|
|
171
|
+
}
|
|
172
|
+
displayedError = error;
|
|
173
|
+
displayedIsPassive = passive;
|
|
174
|
+
isErrorDismissing = false;
|
|
175
|
+
} else if (displayedError) {
|
|
176
|
+
isErrorDismissing = true;
|
|
177
|
+
errorDismissTimer = setTimeout(() => {
|
|
178
|
+
displayedError = null;
|
|
179
|
+
displayedIsPassive = false;
|
|
180
|
+
isErrorDismissing = false;
|
|
181
|
+
errorDismissTimer = null;
|
|
182
|
+
}, 300);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
90
186
|
// Container ref
|
|
91
187
|
let containerRef: HTMLElement | undefined = $state();
|
|
92
188
|
let playerRootRef: HTMLDivElement | undefined = $state();
|
|
@@ -106,7 +202,7 @@
|
|
|
106
202
|
isPlaying: false,
|
|
107
203
|
isPaused: true,
|
|
108
204
|
isBuffering: false,
|
|
109
|
-
isMuted:
|
|
205
|
+
isMuted: false,
|
|
110
206
|
volume: 1,
|
|
111
207
|
error: null as string | null,
|
|
112
208
|
isPassiveError: false,
|
|
@@ -151,7 +247,7 @@
|
|
|
151
247
|
mistUrl: options?.mistUrl,
|
|
152
248
|
authToken: options?.authToken,
|
|
153
249
|
autoplay: options?.autoplay !== false,
|
|
154
|
-
muted: options?.muted
|
|
250
|
+
muted: options?.muted === true,
|
|
155
251
|
controls: options?.stockControls === true,
|
|
156
252
|
poster: thumbnailUrl || undefined,
|
|
157
253
|
debug: options?.debug,
|
|
@@ -275,9 +371,9 @@
|
|
|
275
371
|
let waitingMessage = $derived(
|
|
276
372
|
options?.gatewayUrl
|
|
277
373
|
? storeState.state === "gateway_loading"
|
|
278
|
-
? "
|
|
279
|
-
: "
|
|
280
|
-
: "
|
|
374
|
+
? $translatorStore("resolvingEndpoint")
|
|
375
|
+
: $translatorStore("waitingForStream")
|
|
376
|
+
: $translatorStore("waitingForStream")
|
|
281
377
|
);
|
|
282
378
|
</script>
|
|
283
379
|
|
|
@@ -292,6 +388,16 @@
|
|
|
292
388
|
options?.devMode && "flex"
|
|
293
389
|
)}
|
|
294
390
|
data-player-container="true"
|
|
391
|
+
data-theme={activeTheme && activeTheme !== "default" ? activeTheme : undefined}
|
|
392
|
+
style={(() => {
|
|
393
|
+
const presetOverrides = activeTheme ? resolveTheme(activeTheme) : null;
|
|
394
|
+
const merged = { ...presetOverrides, ...options?.themeOverrides };
|
|
395
|
+
return Object.keys(merged).length > 0
|
|
396
|
+
? Object.entries(themeOverridesToStyle(merged))
|
|
397
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
398
|
+
.join("; ")
|
|
399
|
+
: undefined;
|
|
400
|
+
})()}
|
|
295
401
|
role="region"
|
|
296
402
|
aria-label="Video player"
|
|
297
403
|
onmouseenter={() => playerStore?.handleMouseEnter()}
|
|
@@ -380,7 +486,7 @@
|
|
|
380
486
|
status={storeState.isEffectivelyLive ? storeState.streamState?.status : undefined}
|
|
381
487
|
message={storeState.isEffectivelyLive
|
|
382
488
|
? storeState.streamState?.message
|
|
383
|
-
: "
|
|
489
|
+
: $translatorStore("loading")}
|
|
384
490
|
percentage={storeState.isEffectivelyLive
|
|
385
491
|
? storeState.streamState?.percentage
|
|
386
492
|
: undefined}
|
|
@@ -389,63 +495,72 @@
|
|
|
389
495
|
|
|
390
496
|
<!-- Buffering spinner -->
|
|
391
497
|
{#if showBufferingSpinner}
|
|
498
|
+
<div role="status" aria-live="polite" class="fw-buffering-overlay">
|
|
499
|
+
<div class="fw-buffering-pill">
|
|
500
|
+
<div class="fw-buffering-spinner"></div>
|
|
501
|
+
<span>{$translatorStore("buffering")}</span>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
{/if}
|
|
505
|
+
|
|
506
|
+
<!-- Passive error toast (non-blocking) -->
|
|
507
|
+
{#if displayedError && !storeState.shouldShowIdleScreen && displayedIsPassive}
|
|
392
508
|
<div
|
|
393
|
-
class=
|
|
509
|
+
class={cn(
|
|
510
|
+
"absolute bottom-20 left-1/2 -translate-x-1/2 z-30 transition-opacity duration-300",
|
|
511
|
+
isErrorDismissing
|
|
512
|
+
? "opacity-0"
|
|
513
|
+
: "animate-in fade-in slide-in-from-bottom-2 duration-200"
|
|
514
|
+
)}
|
|
515
|
+
role="status"
|
|
516
|
+
aria-live="polite"
|
|
394
517
|
>
|
|
395
518
|
<div
|
|
396
|
-
class="flex items-center gap-
|
|
519
|
+
class="flex items-center gap-2 rounded-lg border border-yellow-500/30 bg-black/80 px-4 py-2 text-sm text-white shadow-lg backdrop-blur-sm"
|
|
397
520
|
>
|
|
398
|
-
<
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
<span>
|
|
521
|
+
<span class="text-yellow-400 text-xs font-semibold uppercase"
|
|
522
|
+
>{$translatorStore("warning")}</span
|
|
523
|
+
>
|
|
524
|
+
<span>{displayedError}</span>
|
|
525
|
+
<button
|
|
526
|
+
type="button"
|
|
527
|
+
onclick={() => playerStore?.clearError()}
|
|
528
|
+
class="ml-2 text-white/60 hover:text-white"
|
|
529
|
+
aria-label={$translatorStore("dismiss")}
|
|
530
|
+
>
|
|
531
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
532
|
+
<path
|
|
533
|
+
d="M9 3L3 9M3 3L9 9"
|
|
534
|
+
stroke="currentColor"
|
|
535
|
+
stroke-width="1.5"
|
|
536
|
+
stroke-linecap="round"
|
|
537
|
+
/>
|
|
538
|
+
</svg>
|
|
539
|
+
</button>
|
|
402
540
|
</div>
|
|
403
541
|
</div>
|
|
404
542
|
{/if}
|
|
405
543
|
|
|
406
|
-
<!--
|
|
407
|
-
{#if
|
|
544
|
+
<!-- Fatal error overlay (blocking) — auto-dismisses on playback resume -->
|
|
545
|
+
{#if displayedError && !storeState.shouldShowIdleScreen && !displayedIsPassive}
|
|
408
546
|
<div
|
|
409
547
|
role="alert"
|
|
410
548
|
aria-live="assertive"
|
|
411
549
|
class={cn(
|
|
412
|
-
"fw-error-overlay",
|
|
413
|
-
|
|
414
|
-
? "fw-error-overlay--passive"
|
|
415
|
-
: "fw-error-overlay--fullscreen"
|
|
550
|
+
"fw-error-overlay fw-error-overlay--fullscreen transition-opacity duration-300",
|
|
551
|
+
isErrorDismissing && "opacity-0"
|
|
416
552
|
)}
|
|
417
553
|
>
|
|
418
|
-
<div
|
|
419
|
-
class=
|
|
420
|
-
"fw-error-
|
|
421
|
-
|
|
422
|
-
? "fw-error-popup--passive"
|
|
423
|
-
: "fw-error-popup--fullscreen"
|
|
424
|
-
)}
|
|
425
|
-
>
|
|
426
|
-
<div
|
|
427
|
-
class={cn(
|
|
428
|
-
"fw-error-header",
|
|
429
|
-
storeState.isPassiveError
|
|
430
|
-
? "fw-error-header--warning"
|
|
431
|
-
: "fw-error-header--error"
|
|
432
|
-
)}
|
|
433
|
-
>
|
|
434
|
-
<span
|
|
435
|
-
class={cn(
|
|
436
|
-
"fw-error-title",
|
|
437
|
-
storeState.isPassiveError
|
|
438
|
-
? "fw-error-title--warning"
|
|
439
|
-
: "fw-error-title--error"
|
|
440
|
-
)}
|
|
554
|
+
<div class="fw-error-popup fw-error-popup--fullscreen">
|
|
555
|
+
<div class="fw-error-header fw-error-header--error">
|
|
556
|
+
<span class="fw-error-title fw-error-title--error"
|
|
557
|
+
>{$translatorStore("error")}</span
|
|
441
558
|
>
|
|
442
|
-
{storeState.isPassiveError ? "Warning" : "Error"}
|
|
443
|
-
</span>
|
|
444
559
|
<button
|
|
445
560
|
type="button"
|
|
446
561
|
class="fw-error-close"
|
|
447
562
|
onclick={() => playerStore?.clearError()}
|
|
448
|
-
aria-label="
|
|
563
|
+
aria-label={$translatorStore("dismiss")}
|
|
449
564
|
>
|
|
450
565
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
451
566
|
<path
|
|
@@ -458,7 +573,7 @@
|
|
|
458
573
|
</button>
|
|
459
574
|
</div>
|
|
460
575
|
<div class="fw-error-body">
|
|
461
|
-
<p class="fw-error-message">
|
|
576
|
+
<p class="fw-error-message">{displayedError}</p>
|
|
462
577
|
</div>
|
|
463
578
|
<div class="fw-error-actions">
|
|
464
579
|
<button
|
|
@@ -468,10 +583,36 @@
|
|
|
468
583
|
playerStore?.clearError();
|
|
469
584
|
playerStore?.retry();
|
|
470
585
|
}}
|
|
471
|
-
aria-label="
|
|
586
|
+
aria-label={$translatorStore("retry")}
|
|
472
587
|
>
|
|
473
|
-
|
|
588
|
+
{$translatorStore("retry")}
|
|
474
589
|
</button>
|
|
590
|
+
{#if options?.devMode && playerStore?.getController()?.canAttemptFallback()}
|
|
591
|
+
<button
|
|
592
|
+
type="button"
|
|
593
|
+
class="fw-error-btn fw-error-btn--secondary"
|
|
594
|
+
onclick={() => {
|
|
595
|
+
playerStore?.clearError();
|
|
596
|
+
playerStore?.getController()?.retryWithFallback();
|
|
597
|
+
}}
|
|
598
|
+
aria-label={$translatorStore("tryNext")}
|
|
599
|
+
>
|
|
600
|
+
{$translatorStore("tryNext")}
|
|
601
|
+
</button>
|
|
602
|
+
{/if}
|
|
603
|
+
{#if options?.devMode}
|
|
604
|
+
<button
|
|
605
|
+
type="button"
|
|
606
|
+
class="fw-error-btn fw-error-btn--secondary"
|
|
607
|
+
onclick={() => {
|
|
608
|
+
playerStore?.clearError();
|
|
609
|
+
playerStore?.reload();
|
|
610
|
+
}}
|
|
611
|
+
aria-label={$translatorStore("reloadPlayer")}
|
|
612
|
+
>
|
|
613
|
+
{$translatorStore("reloadPlayer")}
|
|
614
|
+
</button>
|
|
615
|
+
{/if}
|
|
475
616
|
</div>
|
|
476
617
|
</div>
|
|
477
618
|
</div>
|
|
@@ -492,7 +633,7 @@
|
|
|
492
633
|
type="button"
|
|
493
634
|
onclick={() => playerStore?.dismissToast()}
|
|
494
635
|
class="ml-2 text-white/60 hover:text-white"
|
|
495
|
-
aria-label="
|
|
636
|
+
aria-label={$translatorStore("dismiss")}
|
|
496
637
|
>
|
|
497
638
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
498
639
|
<path
|
|
@@ -507,8 +648,10 @@
|
|
|
507
648
|
</div>
|
|
508
649
|
{/if}
|
|
509
650
|
|
|
510
|
-
<!-- Player controls -->
|
|
511
|
-
{#if
|
|
651
|
+
<!-- Player controls — custom children or default -->
|
|
652
|
+
{#if children}
|
|
653
|
+
{@render children()}
|
|
654
|
+
{:else if !useStockControls}
|
|
512
655
|
<PlayerControls
|
|
513
656
|
currentTime={storeState.currentTime}
|
|
514
657
|
duration={storeState.duration}
|
|
@@ -524,6 +667,12 @@
|
|
|
524
667
|
onStatsToggle={() => (isStatsOpen = !isStatsOpen)}
|
|
525
668
|
isContentLive={storeState.isEffectivelyLive}
|
|
526
669
|
onJumpToLive={() => playerStore?.getController()?.jumpToLive()}
|
|
670
|
+
controllerSeekableStart={playerStore?.getController()?.getSeekableStart()}
|
|
671
|
+
controllerLiveEdge={playerStore?.getController()?.getLiveEdge()}
|
|
672
|
+
{activeLocale}
|
|
673
|
+
onLocaleChange={(l) => {
|
|
674
|
+
activeLocale = l;
|
|
675
|
+
}}
|
|
527
676
|
/>
|
|
528
677
|
{/if}
|
|
529
678
|
</div>
|
|
@@ -569,7 +718,7 @@
|
|
|
569
718
|
}}
|
|
570
719
|
>
|
|
571
720
|
<StatsIcon size={14} class="opacity-70 flex-shrink-0 mr-2" />
|
|
572
|
-
{isStatsOpen ? "
|
|
721
|
+
{isStatsOpen ? $translatorStore("hideStats") : $translatorStore("showStats")}
|
|
573
722
|
</ContextMenuItem>
|
|
574
723
|
{#if options?.devMode}
|
|
575
724
|
<ContextMenuSeparator />
|
|
@@ -579,13 +728,13 @@
|
|
|
579
728
|
}}
|
|
580
729
|
>
|
|
581
730
|
<SettingsIcon size={14} class="opacity-70 flex-shrink-0 mr-2" />
|
|
582
|
-
{isDevPanelOpen ? "
|
|
731
|
+
{isDevPanelOpen ? $translatorStore("hideSettings") : $translatorStore("settings")}
|
|
583
732
|
</ContextMenuItem>
|
|
584
733
|
{/if}
|
|
585
734
|
<ContextMenuSeparator />
|
|
586
735
|
<ContextMenuItem onSelect={() => playerStore?.togglePiP()}>
|
|
587
736
|
<PictureInPictureIcon size={14} class="opacity-70 flex-shrink-0 mr-2" />
|
|
588
|
-
|
|
737
|
+
{$translatorStore("pictureInPicture")}
|
|
589
738
|
</ContextMenuItem>
|
|
590
739
|
<ContextMenuItem onSelect={() => playerStore?.toggleLoop()}>
|
|
591
740
|
<svg
|
|
@@ -604,7 +753,9 @@
|
|
|
604
753
|
<polyline points="7 23 3 19 7 15"></polyline>
|
|
605
754
|
<path d="M21 13v2a4 4 0 0 1-4 4H3"></path>
|
|
606
755
|
</svg>
|
|
607
|
-
{storeState.isLoopEnabled
|
|
756
|
+
{storeState.isLoopEnabled
|
|
757
|
+
? $translatorStore("disableLoop")
|
|
758
|
+
: $translatorStore("enableLoop")}
|
|
608
759
|
</ContextMenuItem>
|
|
609
760
|
</ContextMenuContent>
|
|
610
761
|
</ContextMenuPortal>
|
package/dist/Player.svelte.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
import { type PlaybackMode, type ContentEndpoints, type PlayerState, type PlayerStateContext, type ContentType, type PlayerMetadata, type FwThemePreset, type FwThemeOverrides, type FwLocale } from "@livepeer-frameworks/player-core";
|
|
2
3
|
interface Props {
|
|
3
4
|
contentId: string;
|
|
4
5
|
contentType?: ContentType;
|
|
@@ -18,9 +19,13 @@ interface Props {
|
|
|
18
19
|
forceType?: string;
|
|
19
20
|
forceSource?: number;
|
|
20
21
|
playbackMode?: PlaybackMode;
|
|
22
|
+
theme?: FwThemePreset;
|
|
23
|
+
themeOverrides?: FwThemeOverrides;
|
|
24
|
+
locale?: FwLocale;
|
|
21
25
|
};
|
|
22
26
|
onStateChange?: (state: PlayerState, context?: PlayerStateContext) => void;
|
|
23
27
|
onMetadata?: (metadata: PlayerMetadata) => void;
|
|
28
|
+
children?: Snippet;
|
|
24
29
|
}
|
|
25
30
|
declare const Player: import("svelte").Component<Props, {}, "">;
|
|
26
31
|
type Player = ReturnType<typeof Player>;
|