@applicaster/quick-brick-player 13.0.0-alpha.2833001702 → 13.0.0-alpha.2957047383

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.
Files changed (33) hide show
  1. package/package.json +9 -14
  2. package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
  3. package/src/Player/AudioLayer/AudioDescription.tsx +4 -6
  4. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +67 -86
  5. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +27 -0
  6. package/src/Player/AudioLayer/Layout/Controls/index.tsx +305 -0
  7. package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +3 -13
  8. package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +30 -53
  9. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +212 -0
  10. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +83 -0
  11. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +32 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +95 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +17 -0
  14. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +214 -0
  15. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +224 -0
  16. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +102 -0
  17. package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
  18. package/src/Player/AudioLayer/Layout/const.ts +20 -0
  19. package/src/Player/AudioLayer/Layout/debug.ts +6 -0
  20. package/src/Player/AudioLayer/Layout/hooks/index.ts +3 -0
  21. package/src/Player/AudioLayer/Layout/hooks/useImageSize.ts +100 -0
  22. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
  23. package/src/Player/AudioLayer/Layout/index.tsx +21 -48
  24. package/src/Player/AudioLayer/Layout/types.ts +7 -0
  25. package/src/Player/AudioLayer/MagicBG/index.tsx +1 -1
  26. package/src/Player/AudioLayer/utils.ts +27 -0
  27. package/src/Player/Const/sleepTimerOptions.ts +10 -0
  28. package/src/Player/Const/speedOptions.ts +4 -0
  29. package/src/Player/Utils/Utils.ts +0 -5
  30. package/src/Player/Utils/index.tsx +117 -0
  31. package/src/Player/index.tsx +21 -9
  32. package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
  33. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "13.0.0-alpha.2833001702",
3
+ "version": "13.0.0-alpha.2957047383",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
- "test": "jest -w=2",
9
8
  "build": "echo 'skipping ts build for core packages'"
10
9
  },
11
10
  "files": [
@@ -36,19 +35,18 @@
36
35
  },
37
36
  "homepage": "https://github.com/applicaster/quickbrick#readme",
38
37
  "dependencies": {
39
- "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.46",
40
- "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.46",
41
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.2833001702",
42
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.2833001702",
43
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.2833001702",
44
- "keymirror": "^0.1.1",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.95",
39
+ "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
40
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.2957047383",
41
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.2957047383",
42
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.2957047383",
45
43
  "query-string": "7.1.3",
46
44
  "react-native-web-linear-gradient": "1.1.2",
47
45
  "shaka-player": "4.3.5",
48
46
  "typeface-montserrat": "^0.0.54",
49
- "video.js": "8.21.0",
50
- "videojs-contrib-eme": "^5.5.1",
51
- "videojs-contrib-quality-levels": "^4.1.0"
47
+ "video.js": "7.14.3",
48
+ "videojs-contrib-eme": "^3.8.1",
49
+ "videojs-contrib-quality-levels": "3.0.0"
52
50
  },
53
51
  "peerDependencies": {
54
52
  "@applicaster/applicaster-types": "*",
@@ -61,11 +59,8 @@
61
59
  "@applicaster/zapp-react-native-tvos-ui-components": "*",
62
60
  "@babel/runtime": "*",
63
61
  "@react-native-community/netinfo": "*",
64
- "@types/node": "*",
65
- "@types/react-native": "0.69.6",
66
62
  "immer": "*",
67
63
  "react": "*",
68
- "react-hot-loader": "*",
69
64
  "react-native": "*",
70
65
  "react-native-fs": "*",
71
66
  "react-native-gesture-handler": "*",
@@ -55,6 +55,11 @@ const useMuteUnmuteListeners = (playerId, player, asset, setImageUri) =>
55
55
  return;
56
56
  }
57
57
 
58
+ // initial state setup - show correct mute/unmute icon based on current state
59
+ if (player?.playerState?.isReadyToPlay) {
60
+ setImageUri(player.getIsMuted() ? asset.active : asset.inactive);
61
+ }
62
+
58
63
  // active action = muted, inactive = unmuted
59
64
  return player.addListener({
60
65
  id: liveImageButtonsListenerKey,
@@ -73,10 +78,17 @@ const useMuteUnmuteListeners = (playerId, player, asset, setImageUri) =>
73
78
  setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
74
79
  },
75
80
  onPlayerClose: () => {
76
- setImageUri(null);
81
+ if (isCurrentPlayer(playerId)) {
82
+ setImageUri(null);
83
+ }
77
84
  },
78
85
  onVideoEnd: () => {
79
- setImageUri(null);
86
+ if (isCurrentPlayer(playerId)) {
87
+ setImageUri(null);
88
+ }
89
+ },
90
+ onPlayerResume: () => {
91
+ setImageUri(player?.getIsMuted() ? asset.active : asset.inactive);
80
92
  },
81
93
  },
82
94
  });
@@ -93,7 +105,7 @@ const styles = StyleSheet.create({
93
105
  },
94
106
  });
95
107
 
96
- export function AssetComponent(props: CellActionAssetComponentProps) {
108
+ function AssetImage(props: CellActionAssetComponentProps) {
97
109
  const { cellUUID: playerId, asset } = props;
98
110
  const [imageUri, setImageUri] = useState<Asset>(null);
99
111
 
@@ -108,3 +120,5 @@ export function AssetComponent(props: CellActionAssetComponentProps) {
108
120
 
109
121
  return <View />;
110
122
  }
123
+
124
+ export const AssetComponent = React.memo(AssetImage);
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Text, TextStyle, View } from "react-native";
2
+ import { Text, TextStyle } from "react-native";
3
3
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
4
4
 
5
5
  type AudioDescriptionProps = {
@@ -13,8 +13,6 @@ type AudioDescriptionProps = {
13
13
  value: GetValue;
14
14
  };
15
15
 
16
- const containerStyles = { paddingTop: 32, paddingBottom: 12 };
17
-
18
16
  const titleStyles = (value: GetValue, prefix: string): TextStyle => ({
19
17
  textAlign: "left",
20
18
  color: value(`${prefix}title_color`),
@@ -83,13 +81,13 @@ export const AudioDescription = (props: AudioDescriptionProps) => {
83
81
  const prefix = layoutState.docked ? "docked_player_" : "";
84
82
 
85
83
  return (
86
- <View style={containerStyles}>
84
+ <>
87
85
  <Text style={titleStyles(value, prefix)} numberOfLines={1}>
88
86
  {title}
89
87
  </Text>
90
- <Text style={summaryStyles(value, prefix)} numberOfLines={2}>
88
+ <Text style={summaryStyles(value, prefix)} numberOfLines={1}>
91
89
  {summary}
92
90
  </Text>
93
- </View>
91
+ </>
94
92
  );
95
93
  };
@@ -1,5 +1,10 @@
1
1
  import * as React from "react";
2
- import { ViewStyle, View } from "react-native";
2
+ import {
3
+ StyleSheet,
4
+ ViewStyle,
5
+ View,
6
+ Dimensions as ScreenDimensions,
7
+ } from "react-native";
3
8
 
4
9
  import { SafeAreaView, Edge } from "react-native-safe-area-context";
5
10
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
@@ -18,28 +23,33 @@ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
23
  import { useEffect, useState } from "react";
19
24
  import { MagicBG } from "./MagicBG";
20
25
  import { formatSpeed } from "./utils";
21
- import { addQueryParam, getLiveUrl } from "../Utils";
26
+ import {
27
+ addQueryParam,
28
+ getBottomSheetModalDefaultItemIcon,
29
+ getBottomSheetModalIconProps,
30
+ getBottomSheetModalItemProps,
31
+ getBottomSheetModalLabelProps,
32
+ getBottomSheetModalSelectedItemIcon,
33
+ } from "../Utils";
22
34
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
23
35
  import {
24
36
  AnimationComponent,
25
37
  ComponentAnimationType,
26
38
  AnimatedScrollModal,
27
39
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
28
- import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
40
+ import { PADDING_HORIZONTAL } from "./Layout/const";
29
41
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
30
- import {
31
- speed_0_8,
32
- speed_1,
33
- speed_1_2,
34
- speed_1_5,
35
- speed_2,
36
- } from "@applicaster/quick-brick-mobile-transport-controls";
37
42
  import {
38
43
  SleepTimerController,
39
44
  SleepTimerState,
40
45
  SLEEP_TIMER_OFF,
41
46
  } from "./SleepTimerManager";
42
47
  import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
48
+ import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
49
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
50
+ import { openBottomSheetModal } from "@applicaster/zapp-react-native-utils/modalState";
51
+ import { sleepTimerOptions } from "../Const/sleepTimerOptions";
52
+ import { speedOptions } from "../Const/speedOptions";
43
53
 
44
54
  const { log_debug } = createLogger({
45
55
  subsystem: "UIComponent",
@@ -57,6 +67,7 @@ type Configuration = {
57
67
  [key: string]: any;
58
68
  magic_background?: boolean;
59
69
  audio_player_background_image_query?: string;
70
+ audio_player_background_image_default_color?: string;
60
71
  tablet_landscape_sidebar_width?: string;
61
72
  tablet_landscape_player_container_background_color?: string;
62
73
  };
@@ -78,54 +89,26 @@ type Props = {
78
89
  isTabletPortrait?: boolean;
79
90
  };
80
91
 
81
- export const defaultAspectRatioWidth = (height: number): number =>
82
- (height / 9) * 16;
92
+ const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
83
93
 
84
- const Styles = {
85
- mainContainer: (style: ViewStyle) => {
86
- const combinedStyle: ViewStyle = {
87
- flex: 1,
88
- };
89
-
90
- return {
91
- ...combinedStyle,
92
- ...style,
93
- };
94
- },
94
+ const Styles = StyleSheet.create({
95
95
  playerContainer: {
96
96
  flex: 1,
97
97
  },
98
98
  paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
99
-
100
- controlsMobile: {
101
- height: 50,
102
- marginHorizontal: 24,
103
- },
104
- controlsTablet: {
105
- height: 96,
106
- marginHorizontal: 24,
107
- },
108
- playerDetails: { marginTop: 60 },
109
-
110
- linearGradient: {
111
- flex: 1,
99
+ playerDetails: {
100
+ marginTop: 60,
101
+ alignSelf: "center",
102
+ width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
112
103
  },
113
- };
104
+ });
114
105
 
115
- const sleeps = [
116
- // { label: "End of episode", value: "episode" },
117
- { label: "5 minutes", value: 5 },
118
- { label: "10 minutes", value: 10 },
119
- { label: "15 minutes", value: 15 },
120
- { label: "30 minutes", value: 30 },
121
- { label: "45 minutes", value: 45 },
122
- { label: "1 hour", value: 60 },
123
- { label: "2 hours", value: 120 },
124
- ];
106
+ const edges: Edge[] = ["right", "left", "top"];
125
107
 
126
108
  export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
127
109
  const player = usePlayer();
128
110
  const playerState = usePlayerState("audio-player-wrapper");
111
+ const theme = useTheme();
129
112
 
130
113
  const {
131
114
  docked,
@@ -138,24 +121,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
138
121
  isTabletPortrait,
139
122
  } = props;
140
123
 
141
- const speeds = [
142
- { asset: configuration["speed_0_8"] || speed_0_8, value: 0.8 },
143
- { asset: configuration["speed_1"] || speed_1, value: 1.0 },
144
- { asset: configuration["speed_1_2"] || speed_1_2, value: 1.2 },
145
- { asset: configuration["speed_1_5"] || speed_1_5, value: 1.5 },
146
- { asset: configuration["speed_2"] || speed_2, value: 2.0 },
147
- ];
148
-
149
124
  const isTablet = useIsTablet();
150
125
 
151
126
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
152
127
 
153
- // TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
154
-
155
- const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
156
-
157
128
  const { title, summary } = useTitleSummaryOverlay(
158
- feedUrl,
159
129
  entry,
160
130
  playerState?.isLive,
161
131
  configuration?.audio_live_player_update_interval
@@ -193,8 +163,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
193
163
  height: 0,
194
164
  });
195
165
 
196
- const navigator = useNavigation();
197
-
198
166
  const { maximiseVideoModal } = useNavigation();
199
167
 
200
168
  const onLayout = (event: any) => {
@@ -284,44 +252,56 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
284
252
  );
285
253
 
286
254
  const onSpeedButtonPress = React.useCallback(() => {
287
- navigator.openModalBottomSheet({
255
+ openBottomSheetModal({
288
256
  modalBottomSheetContentProps: {
289
- items: speeds,
257
+ items: speedOptions,
290
258
  current_selection: playbackSpeed,
291
259
  onPress: onSpeedSelect,
292
260
  title: configuration["playback_speed_title"],
261
+ itemProps: getBottomSheetModalItemProps,
262
+ iconProps: getBottomSheetModalIconProps,
263
+ labelProps: getBottomSheetModalLabelProps,
264
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
265
+ getDefaultItemIcon: getBottomSheetModalDefaultItemIcon,
266
+ iconPlacement: "right",
293
267
  },
294
268
  options: {
295
- supportedOrientations: ["portrait"],
269
+ supportedOrientations: [
270
+ "portrait",
271
+ "landscape",
272
+ "portrait-upside-down",
273
+ ],
296
274
  },
297
275
  });
298
- }, [
299
- playbackSpeed,
300
- setPlaybackSpeed,
301
- navigator,
302
- onSpeedSelect,
303
- configuration["playback_speed_title"],
304
- ]);
276
+ }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
305
277
 
306
278
  const onSleepButtonPress = React.useCallback(() => {
307
- navigator.openModalBottomSheet({
279
+ openBottomSheetModal({
308
280
  modalBottomSheetContentProps: {
309
281
  items: [
310
282
  {
311
283
  label: configuration["playback_sleep_off_label"],
312
284
  value: 0,
313
285
  },
314
- ].concat(sleeps),
286
+ ].concat(sleepTimerOptions),
315
287
  current_selection: sleepTimerState.timer,
316
288
  onPress: onSleepSelect,
317
289
  title: configuration["playback_sleep_title"],
290
+ itemProps: getBottomSheetModalItemProps,
291
+ iconProps: getBottomSheetModalIconProps,
292
+ labelProps: getBottomSheetModalLabelProps,
293
+ getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
294
+ iconPlacement: "right",
318
295
  },
319
296
  options: {
320
- supportedOrientations: ["portrait"],
297
+ supportedOrientations: [
298
+ "portrait",
299
+ "landscape",
300
+ "portrait-upside-down",
301
+ ],
321
302
  },
322
303
  });
323
304
  }, [
324
- navigator,
325
305
  sleepTimerState.timer,
326
306
  configuration["playback_sleep_title"],
327
307
  configuration["playback_sleep_off_label"],
@@ -355,13 +335,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
355
335
  player?.seekTo(0);
356
336
  }, [player]);
357
337
 
358
- const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
359
-
360
- const ContainerView = SafeAreaView;
361
-
362
338
  const MainContent = React.useMemo(() => {
363
339
  return (
364
- <ContainerView style={Styles.mainContainer(style)} edges={edges}>
340
+ <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
365
341
  <AnimationComponent
366
342
  animationType={ComponentAnimationType.moveUpComponent}
367
343
  additionalData={{ saveArea: true }}
@@ -405,18 +381,18 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
405
381
  animationType={ComponentAnimationType.componentFade}
406
382
  >
407
383
  <PlayerDetails
384
+ isAudioPlayer
408
385
  configuration={configuration}
409
386
  style={Styles.playerDetails}
410
387
  entry={entry}
411
388
  isTabletLandscape={isTabletLandscape}
412
- isAudioPlayer={true}
413
389
  />
414
390
  </AnimationComponent>
415
391
  </View>
416
392
  </View>
417
393
  </AnimatedScrollModal>
418
394
  </AnimationComponent>
419
- </ContainerView>
395
+ </SafeAreaView>
420
396
  );
421
397
  }, [
422
398
  docked,
@@ -442,21 +418,26 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
442
418
  ]);
443
419
 
444
420
  if (configuration.magic_background) {
445
- const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
421
+ const baseUrl = imageSrcFromMediaItem(entry, null);
446
422
 
447
423
  const queryParamName =
448
424
  configuration.audio_player_background_image_query || "width";
449
425
 
426
+ const defaultBackgroundColor =
427
+ configuration.audio_player_background_image_default_color ||
428
+ theme?.app_background_color;
429
+
450
430
  const queryParamValue = 15;
451
431
 
452
- const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
432
+ const url =
433
+ baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
453
434
 
454
435
  return (
455
436
  <MagicBG
456
437
  image={url}
457
438
  fallbackUrl={baseUrl}
458
439
  colors={entry?.extensions?.backgroundColors}
459
- defaultColor="#000000"
440
+ defaultColor={defaultBackgroundColor}
460
441
  >
461
442
  {MainContent}
462
443
  </MagicBG>
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ import { View, StyleSheet } from "react-native";
3
+
4
+ import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+
6
+ import { TABLET_VERTICAL_SEPARATOR_HEIGHT } from "../const";
7
+
8
+ import { withDebug } from "../debug";
9
+
10
+ const styles = StyleSheet.create({
11
+ flexingHeight: {
12
+ flex: 1,
13
+
14
+ ...withDebug({ backgroundColor: "red" }),
15
+ },
16
+ fixedHeight: {
17
+ height: TABLET_VERTICAL_SEPARATOR_HEIGHT,
18
+
19
+ ...withDebug({ backgroundColor: "red" }),
20
+ },
21
+ });
22
+
23
+ export const VerticalGutter = () => {
24
+ const isTablet = useIsTablet();
25
+
26
+ return <View style={isTablet ? styles.fixedHeight : styles.flexingHeight} />;
27
+ };