@cinecrew/cinecrew-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 +31 -20
- package/package.json +1 -1
- package/src/native/InlineLivePlayer.js +7 -6
- package/src/native/MediaPlayerView.js +58 -25
- package/src/native/media/LiveChatDrawer.js +16 -25
- package/src/native/media/YouTubeVideoPlayer.web.js +2 -0
- package/src/native/media/player/PlayerBottomBar.js +4 -12
- package/src/native/media/player/playerConstants.js +3 -3
- package/src/native/media/web/useWebAc3AudioPlayback.web.js +9 -3
- package/src/native/media/web/useWebVideoAspectRatio.js +7 -2
- package/src/utils/invokePlayerAction.js +24 -0
- package/src/utils/progressBarTime.js +46 -0
- package/src/utils/webRecording.js +147 -0
- package/src/web/index.js +481 -99
- package/src/web/styles.css +129 -21
- package/types/index.d.ts +14 -1
package/src/web/styles.css
CHANGED
|
@@ -40,10 +40,9 @@
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
.cinecrew-player__title {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
right: 20px;
|
|
43
|
+
flex: 1 1 auto;
|
|
44
|
+
min-width: 0;
|
|
45
|
+
text-align: center;
|
|
47
46
|
z-index: 2;
|
|
48
47
|
overflow: hidden;
|
|
49
48
|
font-weight: 700;
|
|
@@ -70,6 +69,14 @@
|
|
|
70
69
|
opacity: 1;
|
|
71
70
|
}
|
|
72
71
|
|
|
72
|
+
.cinecrew-player__controls.is-recording { opacity: 1; }
|
|
73
|
+
.cinecrew-player__controls.is-recording > .cinecrew-player__top-controls,
|
|
74
|
+
.cinecrew-player__controls.is-recording > .cinecrew-player__center-controls,
|
|
75
|
+
.cinecrew-player__controls.is-recording > .cinecrew-player__bottom-controls {
|
|
76
|
+
visibility: hidden;
|
|
77
|
+
pointer-events: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
73
80
|
.cinecrew-player__top-controls,
|
|
74
81
|
.cinecrew-player__bottom-controls,
|
|
75
82
|
.cinecrew-player__center-controls,
|
|
@@ -103,8 +110,11 @@
|
|
|
103
110
|
|
|
104
111
|
.cinecrew-player__top-right-actions {
|
|
105
112
|
justify-content: flex-end;
|
|
113
|
+
flex: 0 0 auto;
|
|
106
114
|
}
|
|
107
115
|
|
|
116
|
+
.cinecrew-player__top-left-actions { flex: 0 0 auto; }
|
|
117
|
+
|
|
108
118
|
.cinecrew-player__bottom-controls {
|
|
109
119
|
width: 100%;
|
|
110
120
|
flex-direction: column;
|
|
@@ -128,6 +138,57 @@
|
|
|
128
138
|
justify-content: center;
|
|
129
139
|
}
|
|
130
140
|
|
|
141
|
+
.cinecrew-player__recording-overlay {
|
|
142
|
+
position: absolute;
|
|
143
|
+
top: 10px;
|
|
144
|
+
left: 50%;
|
|
145
|
+
z-index: 5;
|
|
146
|
+
display: flex;
|
|
147
|
+
min-width: 0;
|
|
148
|
+
max-width: calc(100% - 24px);
|
|
149
|
+
box-sizing: border-box;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
gap: 8px;
|
|
153
|
+
flex-wrap: wrap;
|
|
154
|
+
padding: 7px 10px;
|
|
155
|
+
border: 1px solid rgba(255,255,255,.22);
|
|
156
|
+
border-radius: 12px;
|
|
157
|
+
background: rgba(0, 0, 0, .68);
|
|
158
|
+
box-shadow: 0 6px 18px rgba(0,0,0,.28);
|
|
159
|
+
transform: translateX(-50%);
|
|
160
|
+
backdrop-filter: blur(8px);
|
|
161
|
+
font-size: .88em;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.cinecrew-player__recording-overlay.is-error { border-color: var(--cinecrew-accent); }
|
|
165
|
+
.cinecrew-player__recording-indicator { color: #ff4b63; font-size: .78em; font-weight: 800; letter-spacing: .08em; }
|
|
166
|
+
.cinecrew-player__recording-timer { font-variant-numeric: tabular-nums; font-size: 1.05em; }
|
|
167
|
+
.cinecrew-player__recording-actions { display: flex; gap: 6px; }
|
|
168
|
+
.cinecrew-player__recording-actions button,
|
|
169
|
+
.cinecrew-player__recording-overlay > button {
|
|
170
|
+
border: 1px solid rgba(255,255,255,.2);
|
|
171
|
+
border-radius: 999px;
|
|
172
|
+
padding: 6px 9px;
|
|
173
|
+
color: inherit;
|
|
174
|
+
background: rgba(255,255,255,.1);
|
|
175
|
+
cursor: pointer;
|
|
176
|
+
font: inherit;
|
|
177
|
+
}
|
|
178
|
+
.cinecrew-player__recording-download {
|
|
179
|
+
display: inline-flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
border: 1px solid rgba(255,255,255,.2);
|
|
182
|
+
border-radius: 999px;
|
|
183
|
+
padding: 6px 9px;
|
|
184
|
+
color: inherit;
|
|
185
|
+
background: rgba(255,255,255,.1);
|
|
186
|
+
text-decoration: none;
|
|
187
|
+
font: inherit;
|
|
188
|
+
}
|
|
189
|
+
.cinecrew-player__recording-actions button:last-child { border-color: #ff4b63; background: rgba(255,75,99,.2); }
|
|
190
|
+
.cinecrew-player__recording-ready { color: #70e3b1; }
|
|
191
|
+
|
|
131
192
|
.cinecrew-player__seek {
|
|
132
193
|
flex: 0 0 auto;
|
|
133
194
|
width: 100%;
|
|
@@ -431,7 +492,8 @@
|
|
|
431
492
|
grid-row: span 2;
|
|
432
493
|
place-items: center;
|
|
433
494
|
border-radius: 9px;
|
|
434
|
-
|
|
495
|
+
border: 1px solid color-mix(in srgb, var(--diagnostic-accent, #fff) 32%, transparent);
|
|
496
|
+
background: color-mix(in srgb, var(--diagnostic-accent, #fff) 14%, transparent);
|
|
435
497
|
}
|
|
436
498
|
|
|
437
499
|
.cinecrew-player__diagnostic-icon .cinecrew-player__icon { width: 18px; height: 18px; }
|
|
@@ -479,6 +541,16 @@
|
|
|
479
541
|
gap: 8px;
|
|
480
542
|
min-height: 0;
|
|
481
543
|
overflow: auto;
|
|
544
|
+
overscroll-behavior: contain;
|
|
545
|
+
scrollbar-width: thin;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.cinecrew-player__older-loading {
|
|
549
|
+
flex: 0 0 auto;
|
|
550
|
+
align-self: center;
|
|
551
|
+
padding: 6px 10px;
|
|
552
|
+
color: var(--cinecrew-accent);
|
|
553
|
+
font-size: .86em;
|
|
482
554
|
}
|
|
483
555
|
|
|
484
556
|
.cinecrew-player__chat-message,
|
|
@@ -527,6 +599,7 @@
|
|
|
527
599
|
|
|
528
600
|
.cinecrew-player__chat-composer {
|
|
529
601
|
position: relative;
|
|
602
|
+
container-type: inline-size;
|
|
530
603
|
display: flex;
|
|
531
604
|
align-items: center;
|
|
532
605
|
gap: 7px;
|
|
@@ -602,8 +675,9 @@
|
|
|
602
675
|
|
|
603
676
|
.cinecrew-player__emoji-picker {
|
|
604
677
|
position: absolute;
|
|
605
|
-
|
|
606
|
-
|
|
678
|
+
left: 0;
|
|
679
|
+
right: auto;
|
|
680
|
+
bottom: 100%;
|
|
607
681
|
z-index: 2;
|
|
608
682
|
display: flex;
|
|
609
683
|
flex-direction: column;
|
|
@@ -617,7 +691,31 @@
|
|
|
617
691
|
box-shadow: 0 10px 30px rgba(0, 0, 0, .42);
|
|
618
692
|
}
|
|
619
693
|
|
|
620
|
-
|
|
694
|
+
@supports (width: 1cqw) {
|
|
695
|
+
.cinecrew-player__emoji-picker { width: min(340px, 100cqw); }
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.cinecrew-player__emoji-anchor {
|
|
699
|
+
position: relative;
|
|
700
|
+
display: inline-flex;
|
|
701
|
+
flex: 0 0 34px;
|
|
702
|
+
width: 34px;
|
|
703
|
+
height: 34px;
|
|
704
|
+
align-self: center;
|
|
705
|
+
align-items: center;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.cinecrew-player__emoji-anchor > .cinecrew-player__emoji-toggle {
|
|
709
|
+
box-sizing: border-box;
|
|
710
|
+
width: 34px;
|
|
711
|
+
min-width: 34px;
|
|
712
|
+
height: 34px;
|
|
713
|
+
min-height: 34px;
|
|
714
|
+
padding: 0;
|
|
715
|
+
line-height: 1;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-search {
|
|
621
719
|
flex: 0 0 auto;
|
|
622
720
|
width: 100%;
|
|
623
721
|
box-sizing: border-box;
|
|
@@ -631,7 +729,7 @@
|
|
|
631
729
|
font-size: 13px;
|
|
632
730
|
}
|
|
633
731
|
|
|
634
|
-
.cinecrew-
|
|
732
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-search:focus {
|
|
635
733
|
border-color: var(--cinecrew-accent);
|
|
636
734
|
}
|
|
637
735
|
|
|
@@ -652,7 +750,7 @@
|
|
|
652
750
|
font: inherit;
|
|
653
751
|
}
|
|
654
752
|
|
|
655
|
-
.cinecrew-
|
|
753
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-categories button {
|
|
656
754
|
display: grid;
|
|
657
755
|
min-width: 0;
|
|
658
756
|
min-height: 34px;
|
|
@@ -664,8 +762,8 @@
|
|
|
664
762
|
font-size: 19px;
|
|
665
763
|
}
|
|
666
764
|
|
|
667
|
-
.cinecrew-
|
|
668
|
-
.cinecrew-
|
|
765
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-categories button:hover,
|
|
766
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-categories button.is-active {
|
|
669
767
|
border-color: var(--cinecrew-accent);
|
|
670
768
|
background: color-mix(in srgb, var(--cinecrew-accent) 14%, transparent);
|
|
671
769
|
}
|
|
@@ -682,24 +780,27 @@
|
|
|
682
780
|
scrollbar-width: thin;
|
|
683
781
|
}
|
|
684
782
|
|
|
685
|
-
.cinecrew-
|
|
783
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-grid button {
|
|
686
784
|
display: grid;
|
|
687
785
|
width: 100%;
|
|
688
786
|
min-width: 0;
|
|
689
|
-
min-height:
|
|
787
|
+
min-height: 38px;
|
|
690
788
|
place-items: center;
|
|
691
789
|
border: 0;
|
|
692
|
-
border-radius:
|
|
790
|
+
border-radius: 50%;
|
|
693
791
|
padding: 0;
|
|
694
792
|
background: transparent;
|
|
695
|
-
font-size:
|
|
793
|
+
font-size: 23px;
|
|
794
|
+
line-height: 1;
|
|
795
|
+
transition: background-color .12s ease, transform .12s ease;
|
|
696
796
|
}
|
|
697
797
|
|
|
698
|
-
.cinecrew-
|
|
798
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-grid button:hover {
|
|
699
799
|
background: rgba(255, 255, 255, .12);
|
|
800
|
+
transform: scale(1.12);
|
|
700
801
|
}
|
|
701
802
|
|
|
702
|
-
.cinecrew-
|
|
803
|
+
.cinecrew-player__emoji-picker .cinecrew-player__emoji-grid .cinecrew-player__emoji-load-more {
|
|
703
804
|
grid-column: 1 / -1;
|
|
704
805
|
min-height: 34px;
|
|
705
806
|
border: 1px solid rgba(255, 255, 255, .14);
|
|
@@ -752,6 +853,12 @@
|
|
|
752
853
|
background: rgba(255,255,255,.1);
|
|
753
854
|
}
|
|
754
855
|
|
|
856
|
+
.cinecrew-player__menu .cinecrew-player__menu-option.is-selected {
|
|
857
|
+
color: var(--cinecrew-accent);
|
|
858
|
+
background: color-mix(in srgb, var(--cinecrew-accent) 18%, transparent);
|
|
859
|
+
font-weight: 700;
|
|
860
|
+
}
|
|
861
|
+
|
|
755
862
|
.cinecrew-player__panel {
|
|
756
863
|
position: absolute;
|
|
757
864
|
inset: 0 0 0 auto;
|
|
@@ -811,9 +918,11 @@
|
|
|
811
918
|
|
|
812
919
|
@media (max-width: 640px) {
|
|
813
920
|
.cinecrew-player__controls { padding: 10px; }
|
|
814
|
-
.cinecrew-player__top-controls { align-items:
|
|
815
|
-
.cinecrew-
|
|
921
|
+
.cinecrew-player__top-controls { align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
922
|
+
.cinecrew-player__title { order: 3; flex: 0 0 100%; box-sizing: border-box; padding: 0 4px; text-align: center; }
|
|
923
|
+
.cinecrew-player__top-left-actions { order: 1; gap: 4px; }
|
|
816
924
|
.cinecrew-player__top-right-actions {
|
|
925
|
+
order: 2;
|
|
817
926
|
max-width: calc(100% - 128px);
|
|
818
927
|
flex-wrap: wrap;
|
|
819
928
|
gap: 4px;
|
|
@@ -825,7 +934,6 @@
|
|
|
825
934
|
min-height: 34px;
|
|
826
935
|
padding: 6px 8px;
|
|
827
936
|
}
|
|
828
|
-
.cinecrew-player__title { top: 96px; left: 12px; right: 12px; }
|
|
829
937
|
.cinecrew-player__bottom-actions { align-items: flex-end; gap: 6px; }
|
|
830
938
|
.cinecrew-player__bottom-right-actions { max-width: 100%; flex-wrap: wrap; justify-content: flex-end; gap: 4px; }
|
|
831
939
|
.cinecrew-player__panel { width: min(380px, 92%); }
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type * as React from 'react';
|
|
2
2
|
|
|
3
3
|
export type AspectRatio = 'FIT' | 'FILL' | 'STRETCH' | 'FILL_SCREEN' | string;
|
|
4
|
+
export interface AspectRatioOption { value: AspectRatio; label?: string }
|
|
4
5
|
export type PlayerMediaType = 'live' | 'channel' | 'movie' | 'series' | string;
|
|
5
6
|
|
|
6
7
|
export interface PlayerSource {
|
|
@@ -57,6 +58,8 @@ export interface PlayerApi {
|
|
|
57
58
|
seekBy(seconds: number): void;
|
|
58
59
|
back(): void;
|
|
59
60
|
setPlaybackRate(rate: number): void;
|
|
61
|
+
setPanel(panel: 'chat' | 'epg' | 'diagnostics' | null): void;
|
|
62
|
+
closePanel(): void;
|
|
60
63
|
getVideoElement(): unknown | null;
|
|
61
64
|
getAudioTracks(): AudioTrack[];
|
|
62
65
|
enterFullscreen?(): void | Promise<void>;
|
|
@@ -77,6 +80,7 @@ export interface PlayerActionContext {
|
|
|
77
80
|
video?: unknown | null;
|
|
78
81
|
}
|
|
79
82
|
|
|
83
|
+
/** Notification invoked after the player's built-in action has executed. */
|
|
80
84
|
export type PlayerAction = (payload?: Record<string, unknown>, context?: PlayerActionContext) => unknown;
|
|
81
85
|
|
|
82
86
|
export interface PlayerActions {
|
|
@@ -209,9 +213,14 @@ export interface CineCrewPlayerProps {
|
|
|
209
213
|
drawerMode?: PlayerDrawerMode;
|
|
210
214
|
/** Web CSS or React Native view-style overrides for the chat, EPG, and diagnostics drawer. */
|
|
211
215
|
drawerStyle?: React.CSSProperties | import('react-native').ViewStyle;
|
|
212
|
-
/** Number of chat messages fetched per page
|
|
216
|
+
/** Number of chat messages fetched per page. Older pages load automatically when scrolling to the top. Defaults to 50. */
|
|
213
217
|
messagePageSize?: number;
|
|
218
|
+
/** Available aspect-ratio choices. Items may be values or labeled { value, label } options. */
|
|
219
|
+
aspectRatios?: Array<AspectRatio | AspectRatioOption>;
|
|
220
|
+
/** Initial aspect-ratio choice. Defaults to FIT. */
|
|
221
|
+
defaultAspectRatio?: AspectRatio;
|
|
214
222
|
features?: { diagnostics?: boolean; [key: string]: boolean | undefined };
|
|
223
|
+
/** App callbacks invoked after each corresponding built-in action. */
|
|
215
224
|
actions?: PlayerActions;
|
|
216
225
|
integrations?: PlayerIntegrations;
|
|
217
226
|
theme?: PlayerTheme;
|
|
@@ -236,6 +245,8 @@ export interface CineCrewPlayerProps {
|
|
|
236
245
|
onClose?: () => void;
|
|
237
246
|
onBack?: () => void;
|
|
238
247
|
onFullscreen?: (state: { isFullscreen: boolean }) => void;
|
|
248
|
+
/** Invoked after the player applies an aspect ratio selection; actions.onAspectRatioChange takes precedence when both are supplied. */
|
|
249
|
+
onAspectRatioChange?: PlayerAction;
|
|
239
250
|
onPlayerHostRef?: (node: unknown | null) => void;
|
|
240
251
|
onInlinePreviewWheel?: (deltaY: number) => void;
|
|
241
252
|
inlinePreview?: boolean;
|
|
@@ -245,6 +256,8 @@ export interface CineCrewPlayerProps {
|
|
|
245
256
|
liveChatNonce?: number;
|
|
246
257
|
onReady?: (playerOrEvent: unknown) => void;
|
|
247
258
|
onProgress?: (event: unknown) => void;
|
|
259
|
+
/** Called once for each elapsed playback second and after a completed seek/restart with a zero-padded HH:MM:SS position. */
|
|
260
|
+
onProgressBarChange?: (time: string) => void;
|
|
248
261
|
onPlaying?: (event: unknown) => void;
|
|
249
262
|
onBuffering?: (buffering: boolean) => void;
|
|
250
263
|
onError?: (error: Error | Record<string, unknown>) => void;
|