@applicaster/quick-brick-player 13.0.0-alpha.4454978740 → 13.0.0-alpha.4514355105

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "13.0.0-alpha.4454978740",
3
+ "version": "13.0.0-alpha.4514355105",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -36,11 +36,11 @@
36
36
  },
37
37
  "homepage": "https://github.com/applicaster/quickbrick#readme",
38
38
  "dependencies": {
39
- "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.28",
40
- "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.31",
41
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.4454978740",
42
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.4454978740",
43
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.4454978740",
39
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.69",
40
+ "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
41
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.4514355105",
42
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.4514355105",
43
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.4514355105",
44
44
  "keymirror": "^0.1.1",
45
45
  "query-string": "7.1.3",
46
46
  "react-native-web-linear-gradient": "1.1.2",
@@ -61,12 +61,9 @@
61
61
  "@applicaster/zapp-react-native-tvos-ui-components": "*",
62
62
  "@babel/runtime": "*",
63
63
  "@react-native-community/netinfo": "*",
64
- "@types/node": "*",
65
- "@types/react-native": "0.69.6",
66
64
  "immer": "*",
67
- "react": "17.0.2",
68
- "react-hot-loader": "*",
69
- "react-native": "0.68.6",
65
+ "react": "*",
66
+ "react-native": "*",
70
67
  "react-native-fs": "*",
71
68
  "react-native-gesture-handler": "*",
72
69
  "react-native-linear-gradient": "*",
@@ -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 * as React from "react";
2
- import { ViewStyle, View } from "react-native";
2
+ import { ViewStyle, View, Dimensions as ScreenDimensions } from "react-native";
3
3
 
4
4
  import { SafeAreaView, Edge } from "react-native-safe-area-context";
5
5
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
@@ -40,6 +40,8 @@ import {
40
40
  SLEEP_TIMER_OFF,
41
41
  } from "./SleepTimerManager";
42
42
  import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
43
+ import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
44
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
43
45
 
44
46
  const { log_debug } = createLogger({
45
47
  subsystem: "UIComponent",
@@ -57,6 +59,7 @@ type Configuration = {
57
59
  [key: string]: any;
58
60
  magic_background?: boolean;
59
61
  audio_player_background_image_query?: string;
62
+ audio_player_background_image_default_color?: string;
60
63
  tablet_landscape_sidebar_width?: string;
61
64
  tablet_landscape_player_container_background_color?: string;
62
65
  };
@@ -78,8 +81,7 @@ type Props = {
78
81
  isTabletPortrait?: boolean;
79
82
  };
80
83
 
81
- export const defaultAspectRatioWidth = (height: number): number =>
82
- (height / 9) * 16;
84
+ const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
83
85
 
84
86
  const Styles = {
85
87
  mainContainer: (style: ViewStyle) => {
@@ -105,7 +107,11 @@ const Styles = {
105
107
  height: 96,
106
108
  marginHorizontal: 24,
107
109
  },
108
- playerDetails: { marginTop: 60 },
110
+ playerDetails: {
111
+ marginTop: 60,
112
+ alignSelf: "center",
113
+ width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
114
+ },
109
115
 
110
116
  linearGradient: {
111
117
  flex: 1,
@@ -123,9 +129,12 @@ const sleeps = [
123
129
  { label: "2 hours", value: 120 },
124
130
  ];
125
131
 
132
+ const edges: Edge[] = ["right", "left", "top"];
133
+
126
134
  export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
127
135
  const player = usePlayer();
128
136
  const playerState = usePlayerState("audio-player-wrapper");
137
+ const theme = useTheme();
129
138
 
130
139
  const {
131
140
  docked,
@@ -355,8 +364,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
355
364
  player?.seekTo(0);
356
365
  }, [player]);
357
366
 
358
- const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
359
-
360
367
  const ContainerView = SafeAreaView;
361
368
 
362
369
  const MainContent = React.useMemo(() => {
@@ -442,21 +449,26 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
442
449
  ]);
443
450
 
444
451
  if (configuration.magic_background) {
445
- const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
452
+ const baseUrl = imageSrcFromMediaItem(entry, null);
446
453
 
447
454
  const queryParamName =
448
455
  configuration.audio_player_background_image_query || "width";
449
456
 
457
+ const defaultBackgroundColor =
458
+ configuration.audio_player_background_image_default_color ||
459
+ theme?.app_background_color;
460
+
450
461
  const queryParamValue = 15;
451
462
 
452
- const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
463
+ const url =
464
+ baseUrl && addQueryParam(baseUrl, queryParamName, queryParamValue);
453
465
 
454
466
  return (
455
467
  <MagicBG
456
468
  image={url}
457
469
  fallbackUrl={baseUrl}
458
470
  colors={entry?.extensions?.backgroundColors}
459
- defaultColor="#000000"
471
+ defaultColor={defaultBackgroundColor}
460
472
  >
461
473
  {MainContent}
462
474
  </MagicBG>
@@ -1,13 +1,14 @@
1
1
  import * as React from "react";
2
+ import { useEffect, useMemo, useState } from "react";
2
3
  import * as R from "ramda";
3
- import { View } from "react-native";
4
+ import { View, Dimensions as ScreenDimensions } from "react-native";
4
5
  import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
5
6
 
6
7
  import {
7
- ProgressBar,
8
8
  Controls,
9
- TransportInfo,
10
9
  CountDown,
10
+ ProgressBar,
11
+ TransportInfo,
11
12
  } from "@applicaster/quick-brick-mobile-transport-controls";
12
13
 
13
14
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
@@ -15,26 +16,30 @@ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
15
16
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
16
17
  import {
17
18
  forwardButton,
19
+ PADDING_HORIZONTAL,
18
20
  playbackButton,
19
21
  rewindButton,
20
- skipToStartButton,
21
22
  skipToLiveButton,
22
- PADDING_HORIZONTAL,
23
- speedButton,
23
+ skipToStartButton,
24
24
  sleepButton,
25
+ speedButton,
25
26
  } from "./defaultLayoutsConts";
26
27
  import { AudioDescription } from "../AudioDescription";
27
28
  import { PlayerImageBackground } from "@applicaster/zapp-react-native-ui-components/Components/PlayerImageBackground";
28
29
  import { useLanguageData } from "@applicaster/zapp-react-native-utils/reactHooks/player";
29
30
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
30
- import { useEffect, useMemo, useState } from "react";
31
31
  import {
32
- useModalAnimationContext,
33
32
  AnimationComponent,
34
33
  ComponentAnimationType,
34
+ useModalAnimationContext,
35
35
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
36
+ import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
36
37
  import DockedLayout from "./DockedLayout";
37
38
  import { isValidDate } from "../../Utils";
39
+ import { calculateBorderRadius } from "../utils";
40
+
41
+ const getAudioPlayerWidthForTablet = (isPortraitMode: boolean) =>
42
+ isPortraitMode ? 463 : 350;
38
43
 
39
44
  type Dimensions = {
40
45
  width: number;
@@ -79,6 +84,9 @@ type LayoutProps = {
79
84
  defaultDimensions: Dimensions;
80
85
  };
81
86
 
87
+ const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } =
88
+ ScreenDimensions.get("screen");
89
+
82
90
  const Styles = {
83
91
  container: { flex: 1 },
84
92
  tabletContainer: (isPortraitMode: boolean) => ({
@@ -86,42 +94,63 @@ const Styles = {
86
94
  alignItems: "center",
87
95
  justifyContent: isPortraitMode ? "center" : "flex-start",
88
96
  }),
89
- playerImageWrapper: {
97
+ playerImageWrapper: (docked: boolean) => ({
90
98
  width: "100%",
91
99
  maxHeight: 750,
92
- marginTop: 80,
100
+ marginTop: docked ? 80 : 20,
101
+ }),
102
+ playerInfoWrapper: {
103
+ flex: 1,
104
+ alignItems: "center",
105
+ justifyContent: "space-between",
93
106
  },
94
- tabletLayout: {
95
- width: 463,
107
+ tabletLayout: (isPortraitMode: boolean) => ({
108
+ width: getAudioPlayerWidthForTablet(isPortraitMode),
96
109
  marginBottom: 80,
97
- },
110
+ paddingHorizontal: undefined, // override paddingHorizontal
111
+ }),
98
112
  controls: (isTablet: boolean, isLiveShowFullControls: boolean) => ({
99
113
  height: isTablet ? 64 : 50,
100
- marginHorizontal: 10,
114
+ marginHorizontal: isTablet ? undefined : 10,
101
115
  justifyContent: isLiveShowFullControls ? "space-between" : "space-evenly",
102
116
  }),
103
- backgroundImageContainer: (dimensions: Dimensions, isTablet: boolean) => {
104
- const mobileValue = dimensions.width
117
+ backgroundImageContainer: (
118
+ dimensions: Dimensions,
119
+ isTablet: boolean,
120
+ isPortraitMode: boolean
121
+ ) => {
122
+ if (isTablet) {
123
+ const size = getAudioPlayerWidthForTablet(isPortraitMode);
124
+
125
+ return {
126
+ width: size,
127
+ height: size,
128
+ };
129
+ }
130
+
131
+ const mobileValue = dimensions?.width
105
132
  ? dimensions.width - PADDING_HORIZONTAL * 2
106
- : 330;
133
+ : SCREEN_WIDTH - PADDING_HORIZONTAL * 2;
107
134
 
108
135
  return {
109
- width: isTablet ? 463 : mobileValue,
110
- height: isTablet ? 463 : mobileValue,
136
+ width: mobileValue,
137
+ height: mobileValue,
111
138
  };
112
139
  },
113
140
  backgroundImageContainerImageStyle: (
114
141
  isTablet: boolean,
115
142
  docked: boolean,
116
143
  startComponentsAnimation: boolean,
117
- isActiveGesture: boolean
144
+ isActiveGesture: boolean,
145
+ playerAnimationState: PlayerAnimationStateT
118
146
  ) => ({
119
- borderRadius:
120
- (startComponentsAnimation && isActiveGesture) || docked
121
- ? 0
122
- : isTablet
123
- ? 24
124
- : 10,
147
+ borderRadius: calculateBorderRadius(
148
+ isTablet,
149
+ docked,
150
+ startComponentsAnimation,
151
+ isActiveGesture,
152
+ playerAnimationState
153
+ ),
125
154
  }),
126
155
 
127
156
  paddingHorizontal: {
@@ -173,8 +202,7 @@ export default function DefaultLayout(props: LayoutProps) {
173
202
  } = props;
174
203
 
175
204
  const isTablet = useIsTablet();
176
- const { width, height } = dimensions;
177
- const isPortraitMode = width < height;
205
+ const isPortraitMode = SCREEN_WIDTH < SCREEN_HEIGHT;
178
206
  const isLiveContent = playerState.isLive;
179
207
  const docked = layoutState.docked;
180
208
 
@@ -330,12 +358,15 @@ export default function DefaultLayout(props: LayoutProps) {
330
358
 
331
359
  const defaultImageDimensions = React.useMemo(
332
360
  () =>
333
- defaultDimensions &&
334
- Styles.backgroundImageContainer(defaultDimensions, isTablet),
335
- [defaultDimensions, isTablet]
361
+ Styles.backgroundImageContainer(
362
+ defaultDimensions,
363
+ isTablet,
364
+ isPortraitMode
365
+ ),
366
+ [defaultDimensions, isTablet, isPortraitMode]
336
367
  );
337
368
 
338
- const { isActiveGesture, startComponentsAnimation } =
369
+ const { isActiveGesture, startComponentsAnimation, playerAnimationState } =
339
370
  useModalAnimationContext();
340
371
 
341
372
  return (
@@ -344,7 +375,10 @@ export default function DefaultLayout(props: LayoutProps) {
344
375
  isTablet ? Styles.tabletContainer(isPortraitMode) : Styles.container
345
376
  }
346
377
  >
347
- <AnimationComponent animationType={ComponentAnimationType.componentFade}>
378
+ <AnimationComponent
379
+ animationType={ComponentAnimationType.componentFade}
380
+ style={isTablet ? Styles.playerInfoWrapper : undefined}
381
+ >
348
382
  <TransportInfo
349
383
  content={entry}
350
384
  value={value}
@@ -356,13 +390,16 @@ export default function DefaultLayout(props: LayoutProps) {
356
390
  </AnimationComponent>
357
391
  <AnimationComponent
358
392
  animationType={ComponentAnimationType.moveUpComponent}
359
- style={isTablet ? Styles.playerImageWrapper : undefined}
393
+ style={isTablet ? Styles.playerImageWrapper(docked) : undefined}
360
394
  >
361
395
  <AnimationComponent
362
396
  animationType={ComponentAnimationType.moveComponentHorizontal}
363
397
  additionalData={{
364
398
  disableAnimatedComponent: !isTablet,
365
- moveValue: (dimensions.width - 463) / 2,
399
+ moveValue:
400
+ (dimensions.width -
401
+ getAudioPlayerWidthForTablet(isPortraitMode)) /
402
+ 2,
366
403
  extraAnimation: !isTablet
367
404
  ? {
368
405
  [ComponentAnimationType.audioPlayerPaddingHorizontal]: {
@@ -375,12 +412,17 @@ export default function DefaultLayout(props: LayoutProps) {
375
412
  >
376
413
  <PlayerImageBackground
377
414
  entry={entry}
378
- style={Styles.backgroundImageContainer(dimensions, isTablet)}
415
+ style={Styles.backgroundImageContainer(
416
+ dimensions,
417
+ isTablet,
418
+ isPortraitMode
419
+ )}
379
420
  imageStyle={Styles.backgroundImageContainerImageStyle(
380
421
  isTablet,
381
422
  docked,
382
423
  startComponentsAnimation,
383
- isActiveGesture
424
+ isActiveGesture,
425
+ playerAnimationState
384
426
  )}
385
427
  defaultImageDimensions={defaultImageDimensions}
386
428
  />
@@ -391,7 +433,7 @@ export default function DefaultLayout(props: LayoutProps) {
391
433
  <View
392
434
  style={[
393
435
  Styles.paddingHorizontal,
394
- isTablet ? Styles.tabletLayout : undefined,
436
+ isTablet ? Styles.tabletLayout(isPortraitMode) : undefined,
395
437
  ]}
396
438
  >
397
439
  {!docked && (
@@ -405,9 +447,10 @@ export default function DefaultLayout(props: LayoutProps) {
405
447
  layoutState={layoutState}
406
448
  />
407
449
  <Separator />
408
- {needsToShowProgressBar && (
450
+ {needsToShowProgressBar ? (
409
451
  <View>
410
452
  <ProgressBar
453
+ name={"audio-default-layout"}
411
454
  content={entry}
412
455
  value={value}
413
456
  visible={true}
@@ -422,17 +465,17 @@ export default function DefaultLayout(props: LayoutProps) {
422
465
  onSkipLive={onSkipLive}
423
466
  />
424
467
 
425
- {showCounter && timeLeft >= 0 && (
468
+ {showCounter && timeLeft >= 0 ? (
426
469
  <CountDown
427
470
  timeLeft={timeLeft}
428
471
  value={value}
429
472
  title={sleepTitle}
430
473
  />
431
- )}
474
+ ) : null}
432
475
 
433
476
  <Separator />
434
477
  </View>
435
- )}
478
+ ) : null}
436
479
  <Controls
437
480
  value={value}
438
481
  visible={true}
@@ -9,18 +9,18 @@ import * as R from "ramda";
9
9
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
10
10
 
11
11
  import {
12
+ Button,
12
13
  ContentInfo,
13
- ProgressBar,
14
14
  Controls,
15
- Button,
15
+ ProgressBar,
16
16
  } from "@applicaster/quick-brick-mobile-transport-controls";
17
17
 
18
18
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
19
19
  import {
20
- useModalAnimationContext,
21
20
  AnimationComponent,
22
21
  ComponentAnimationType,
23
22
  PlayerAnimationStateEnum,
23
+ useModalAnimationContext,
24
24
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
25
25
 
26
26
  type Dimensions = {
@@ -230,7 +230,7 @@ export default function DockedLayout(props: LayoutProps) {
230
230
  } = useModalAnimationContext();
231
231
 
232
232
  const maximazeVideoModal = React.useCallback(
233
- () => setPlayerAnimationState(PlayerAnimationStateEnum.maximaze),
233
+ () => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
234
234
  []
235
235
  );
236
236
 
@@ -245,18 +245,19 @@ export default function DockedLayout(props: LayoutProps) {
245
245
  ]}
246
246
  >
247
247
  {!playerState.isLive &&
248
- (layoutState.docked || startComponentsAnimation) && (
249
- <ProgressBar
250
- content={entry}
251
- value={value}
252
- visible={visible}
253
- layoutState={layoutState}
254
- onPlayerSeek={onPlayerSeek}
255
- playerState={playerState}
256
- startComponentsAnimation={startComponentsAnimation}
257
- docked
258
- />
259
- )}
248
+ (layoutState.docked || startComponentsAnimation) ? (
249
+ <ProgressBar
250
+ name={"audio-docked-layout"}
251
+ content={entry}
252
+ value={value}
253
+ visible={visible}
254
+ layoutState={layoutState}
255
+ onPlayerSeek={onPlayerSeek}
256
+ playerState={playerState}
257
+ startComponentsAnimation={startComponentsAnimation}
258
+ docked
259
+ />
260
+ ) : null}
260
261
 
261
262
  <View style={styles.content}>
262
263
  <View
@@ -17,7 +17,7 @@ const playbackButtonMargins = (
17
17
  isTablet: boolean,
18
18
  isLiveShowFullControls: boolean
19
19
  ): number =>
20
- isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? 95 : 40;
20
+ isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? undefined : 40;
21
21
 
22
22
  export const PADDING_HORIZONTAL = 15;
23
23
 
@@ -47,7 +47,7 @@ const fetchPaletteAndDominantColor = async (imageUrl: string) => {
47
47
  const dominant = await getDominantColor(imageUrl);
48
48
  const dominantColor = `rgb(${dominant.r}, ${dominant.g}, ${dominant.b})`;
49
49
 
50
- return { gradientColors: colors.slice(0, 2), dominantColor };
50
+ return { gradientColors: colors.slice(0, 2).reverse(), dominantColor };
51
51
  };
52
52
 
53
53
  export const MagicBG: React.FC<MagicBGProps> = ({
@@ -1,4 +1,8 @@
1
1
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
+ import {
3
+ PlayerAnimationStateEnum,
4
+ PlayerAnimationStateT,
5
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
2
6
  import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
3
7
 
4
8
  export const NAMESPACE = "audio-player";
@@ -31,3 +35,23 @@ export const formatSpeed = (value: number) => {
31
35
  // Return the formatted string with "speed_" prefix
32
36
  return `speed_${formattedValue}`;
33
37
  };
38
+
39
+ export const calculateBorderRadius = (
40
+ isTablet: boolean,
41
+ docked: boolean,
42
+ startComponentsAnimation: boolean,
43
+ isActiveGesture: boolean,
44
+ playerAnimationState: PlayerAnimationStateT
45
+ ): number => {
46
+ const shouldRemoveBorderRadius =
47
+ (startComponentsAnimation &&
48
+ isActiveGesture &&
49
+ playerAnimationState !== PlayerAnimationStateEnum.maximize) ||
50
+ docked;
51
+
52
+ if (shouldRemoveBorderRadius) {
53
+ return 0;
54
+ }
55
+
56
+ return isTablet ? 24 : 10;
57
+ };
@@ -721,7 +721,7 @@ export default class VideoPlayer extends React.Component<
721
721
 
722
722
  const isAudioItem =
723
723
  entry?.content?.type?.includes?.("audio") ||
724
- entry?.type?.value === "audio";
724
+ entry?.type?.value?.includes?.("audio");
725
725
 
726
726
  const getStyle = (dimensions) => {
727
727
  const generalStyles = isAudioItem ? styles.audio : styles.video;
@@ -806,7 +806,6 @@ export default class VideoPlayer extends React.Component<
806
806
  nowPlayingEnabled,
807
807
  paused,
808
808
  seek,
809
- rate,
810
809
  textTrackId,
811
810
  liveSeekingEnabled,
812
811
  liveCatchUpEnabled,
@@ -817,7 +816,14 @@ export default class VideoPlayer extends React.Component<
817
816
  accessibilityProps: getAllAccessibilityProps(
818
817
  this.getPluginConfiguration()
819
818
  ),
820
- }; // rate temporary removed, because of bug with subtitles
819
+ };
820
+
821
+ if (!isAppleTV()) {
822
+ // TODO: Move to RN method and remove from props.
823
+ // Causes tvOS bug: native player passes rate on fast seek,
824
+ // RN returns it and it breaks playback.
825
+ nativeProps.rate = rate;
826
+ }
821
827
 
822
828
  if (
823
829
  this.isReactNativeMethodsSupported() &&
@@ -990,14 +996,14 @@ export default class VideoPlayer extends React.Component<
990
996
  const renderMobilePlayer = () => {
991
997
  return isFullScreenAudioPlayer && isAudioItem ? (
992
998
  <View style={containerStyle}>
993
- {(!castAction?.state?.connected || supportNativeCast) && (
999
+ {!castAction?.state?.connected || supportNativeCast ? (
994
1000
  <this.props.PlayerComponent
995
1001
  ref={this._assignRoot}
996
1002
  {...nativeEvents}
997
1003
  {...nativeProps}
998
1004
  listener={this.props.listener}
999
1005
  />
1000
- )}
1006
+ ) : null}
1001
1007
  <AudioPlayerWrapper {...sharedWrapperViewProps} />
1002
1008
  </View>
1003
1009
  ) : (
@@ -1012,7 +1018,7 @@ export default class VideoPlayer extends React.Component<
1012
1018
  return (
1013
1019
  <View style={styles.container}>
1014
1020
  <View style={[playerContainerStyles, playerDimensions]}>
1015
- {isAudioItem && (
1021
+ {isAudioItem ? (
1016
1022
  <AnimationComponent
1017
1023
  animationType={ComponentAnimationType.player}
1018
1024
  additionalData={{
@@ -1031,18 +1037,18 @@ export default class VideoPlayer extends React.Component<
1031
1037
  plugin_configuration={this.getPluginConfiguration()}
1032
1038
  />
1033
1039
  </AnimationComponent>
1034
- )}
1040
+ ) : null}
1035
1041
 
1036
- {shouldRenderBackground && (
1042
+ {shouldRenderBackground ? (
1037
1043
  <PlayerImageBackground
1038
1044
  imageKey={backgroundImageKey}
1039
1045
  configuration={this.getPluginConfiguration()}
1040
1046
  entry={entry}
1041
1047
  style={getBackgroundImageStyle(playerDimensions)}
1042
1048
  />
1043
- )}
1049
+ ) : null}
1044
1050
 
1045
- {(!castAction?.state?.connected || supportNativeCast) && (
1051
+ {!castAction?.state?.connected || supportNativeCast ? (
1046
1052
  <AnimationComponent
1047
1053
  animationType={ComponentAnimationType.player}
1048
1054
  additionalData={playerDimensions}
@@ -1064,7 +1070,7 @@ export default class VideoPlayer extends React.Component<
1064
1070
  {this.childrenWithPlayNext()}
1065
1071
  </this.props.PlayerComponent>
1066
1072
  </AnimationComponent>
1067
- )}
1073
+ ) : null}
1068
1074
  </View>
1069
1075
 
1070
1076
  {renderTransportControls(playerDimensions)}