@applicaster/quick-brick-player 12.0.0-alpha.7725319213 → 12.0.0-alpha.7754333813

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.
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
2
  import DefaultLayout from "./DefaultLayout";
3
- import DockedLayout from "./DockedLayout";
4
3
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
5
4
 
6
5
  type Dimensions = {
@@ -24,27 +23,30 @@ type LayoutProps = {
24
23
  isBuffering: boolean;
25
24
  };
26
25
  value: GetValue;
26
+ sleepTimerDate: number;
27
+ playbackSpeedName: string;
28
+ playbackSleepName: string;
27
29
  configuration: { [key: string]: any };
28
30
  onPlaybackButtonPress: () => void;
29
31
  onRewindButtonPress: () => void;
30
32
  onForwardButtonPress: () => void;
33
+ onSpeedButtonPress: () => void;
34
+ onSleepButtonPress: () => void;
31
35
  onCloseVideoModal: () => void;
36
+ cancelSleepTimer: () => void;
32
37
  onPlayerSeek: (targetTime: number) => void;
33
38
  onSkipStart: () => void;
34
39
  onSkipLive: () => void;
35
40
  maximiseVideoModal: () => void;
36
41
  dimensions: Dimensions;
42
+ defaultDimensions: Dimensions;
37
43
  playNextData: PlayNextData;
44
+ title: string | number;
45
+ summary: string | number;
38
46
  };
39
47
 
40
48
  export default function Layout(
41
49
  props: LayoutProps
42
50
  ): React.ReactElement<LayoutProps> {
43
- const { layoutState } = props;
44
-
45
- if (layoutState.docked) {
46
- return <DockedLayout {...props} />;
47
- }
48
-
49
51
  return <DefaultLayout {...props} />;
50
52
  }
@@ -4,14 +4,17 @@ import * as React from "react";
4
4
  import { StyleSheet, View } from "react-native";
5
5
  import LinearGradient from "../LinearGradient";
6
6
  import { getDominantColor, getPalettes } from "../../../utils/utils";
7
+ import { useEffect } from "react";
7
8
 
8
9
  type MagicBGProps = {
9
10
  children: React.ReactNode;
10
11
  image: string;
12
+ fallbackUrl?: string;
11
13
  defaultColor: string;
14
+ colors: string[]; // Updated to type string[] as it holds hex values
12
15
  };
13
16
 
14
- const colors = {
17
+ const defaultColors = {
15
18
  overlay: "rgba(0, 0, 0, 0.35)",
16
19
  defaultGradientStart: "rgba(0, 0, 0, 0.25)",
17
20
  defaultGradientEnd: "rgba(0, 0, 0, 0)",
@@ -23,7 +26,7 @@ const styles = StyleSheet.create({
23
26
  },
24
27
  fullScreenOverlay: {
25
28
  ...StyleSheet.absoluteFillObject,
26
- backgroundColor: colors.overlay,
29
+ backgroundColor: defaultColors.overlay,
27
30
  },
28
31
  gradientOverlay: {
29
32
  position: "absolute",
@@ -34,47 +37,81 @@ const styles = StyleSheet.create({
34
37
  },
35
38
  });
36
39
 
40
+ const fetchPaletteAndDominantColor = async (imageUrl: string) => {
41
+ const palette = await getPalettes(imageUrl);
42
+
43
+ const colors = palette.map(
44
+ (color: { r: number; g: number; b: number }) =>
45
+ `rgb(${color.r}, ${color.g}, ${color.b})`
46
+ );
47
+
48
+ const dominant = await getDominantColor(imageUrl);
49
+ const dominantColor = `rgb(${dominant.r}, ${dominant.g}, ${dominant.b})`;
50
+
51
+ return { gradientColors: colors.slice(0, 2), dominantColor };
52
+ };
53
+
37
54
  export const MagicBG: React.FC<MagicBGProps> = ({
38
55
  children,
39
56
  image,
57
+ fallbackUrl = "",
58
+ colors = [],
40
59
  defaultColor,
41
60
  }) => {
42
61
  const [dominantColor, setDominantColor] =
43
62
  React.useState<string>(defaultColor);
44
63
 
45
64
  const [gradientColors, setGradientColors] = React.useState<string[]>([
46
- colors.defaultGradientStart,
47
- colors.defaultGradientEnd,
65
+ defaultColors.defaultGradientStart,
66
+ defaultColors.defaultGradientEnd,
48
67
  ]);
49
68
 
50
- React.useEffect(() => {
69
+ useEffect(() => {
51
70
  const fetchColors = async () => {
52
- if (image) {
71
+ // Check if colors are provided and not empty
72
+ if (colors && colors.length > 0) {
73
+ // Use provided colors for gradient and dominant color
74
+ setGradientColors(colors.slice(0, 2)); // First 2 colors for gradient
75
+ setDominantColor(colors[0]); // First color as dominant
76
+ } else if (image) {
77
+ // If no colors, try fetching from image
53
78
  try {
54
- const palette = await getPalettes(image);
55
-
56
- const colors = palette.map(
57
- (color: { r: number; g: number; b: number }) =>
58
- `rgb(${color.r}, ${color.g}, ${color.b})`
59
- );
60
-
61
- setGradientColors(colors.slice(0, 2));
79
+ const { gradientColors, dominantColor } =
80
+ await fetchPaletteAndDominantColor(image);
62
81
 
63
- const dominant = await getDominantColor(image);
64
- setDominantColor(`rgb(${dominant.r}, ${dominant.g}, ${dominant.b})`);
82
+ setGradientColors(gradientColors);
83
+ setDominantColor(dominantColor);
65
84
  } catch (error) {
66
- setGradientColors([
67
- colors.defaultGradientStart,
68
- colors.defaultGradientEnd,
69
- ]);
85
+ // If image fetch fails, try fallback URL
86
+ try {
87
+ const { gradientColors, dominantColor } =
88
+ await fetchPaletteAndDominantColor(fallbackUrl);
70
89
 
71
- setDominantColor(defaultColor);
90
+ setGradientColors(gradientColors);
91
+ setDominantColor(dominantColor);
92
+ } catch {
93
+ // If everything fails, use default color
94
+ setGradientColors([
95
+ defaultColors.defaultGradientStart,
96
+ defaultColors.defaultGradientEnd,
97
+ ]);
98
+
99
+ setDominantColor(defaultColor);
100
+ }
72
101
  }
102
+ } else {
103
+ // If no image or colors, use default color
104
+ setGradientColors([
105
+ defaultColors.defaultGradientStart,
106
+ defaultColors.defaultGradientEnd,
107
+ ]);
108
+
109
+ setDominantColor(defaultColor);
73
110
  }
74
111
  };
75
112
 
76
113
  fetchColors();
77
- }, [image, defaultColor]);
114
+ }, []);
78
115
 
79
116
  return (
80
117
  <View style={[styles.container, { backgroundColor: dominantColor }]}>
@@ -0,0 +1,33 @@
1
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
+ import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
3
+
4
+ export const NAMESPACE = "audio-player";
5
+
6
+ export async function loadItemsFromStorage(key: string) {
7
+ const storedItems = await localStorage.getItem(key, NAMESPACE);
8
+
9
+ return parseJsonIfNeeded(storedItems) || null;
10
+ }
11
+
12
+ export const hasDatePassed = (timestamp: number) => {
13
+ // Get the current date and time
14
+ const currentDate = new Date();
15
+
16
+ // Compare the current date's timestamp with the given timestamp
17
+ return currentDate.getTime() > timestamp;
18
+ };
19
+
20
+ export const formatSpeed = (value: number) => {
21
+ let formattedValue = value.toString();
22
+
23
+ // If the value ends with ".0", remove it
24
+ if (formattedValue.endsWith(".0")) {
25
+ formattedValue = formattedValue.slice(0, -2);
26
+ }
27
+
28
+ // Replace "." with "_"
29
+ formattedValue = formattedValue.replace(".", "_");
30
+
31
+ // Return the formatted string with "speed_" prefix
32
+ return `speed_${formattedValue}`;
33
+ };
@@ -1,21 +1,27 @@
1
- export const toTypeString = (obj) => {
2
- switch (typeof obj) {
3
- case "object":
4
- return obj instanceof Date ? obj.toISOString() : JSON.stringify(obj); // object, null
5
- case "undefined":
6
- return "";
7
- default:
8
- // boolean, number, string
9
- return obj.toString();
10
- }
1
+ import queryString from "query-string";
2
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
3
+
4
+ export const getLiveUrl = (url: string) => {
5
+ // Use the replace method with a regular expression to replace all instances of subClass with livePage
6
+ return url.replace(new RegExp("subClass", "g"), "livePage");
11
7
  };
12
8
 
13
- export const stringsOnlyObject = (obj) => {
14
- const strObj = {};
9
+ export const addQueryParam = (
10
+ baseUrl: string,
11
+ paramName: string,
12
+ paramValue: string | number
13
+ ) => {
14
+ const [urlWithoutQuery, query] = baseUrl.split("?");
15
+
16
+ const parsedQuery = queryString.parse(query);
17
+
18
+ parsedQuery[paramName] = paramValue.toString();
15
19
 
16
- Object.keys(obj).forEach((x) => {
17
- strObj[x] = toTypeString(obj[x]);
18
- });
20
+ const updatedQueryString = queryString.stringify(parsedQuery);
21
+
22
+ return `${urlWithoutQuery}?${updatedQueryString}`;
23
+ };
19
24
 
20
- return strObj;
25
+ export const isValidDate = (dateString: string): boolean => {
26
+ return dateString.trim() !== "" && dayjs.utc(dateString).isValid();
21
27
  };
@@ -1,3 +1 @@
1
- export * from "./AssetsHelper";
2
-
3
1
  export * from "./Utils";
@@ -36,10 +36,12 @@ import { AudioPlayerWrapper } from "./AudioLayer/AudioPlayerWrapper";
36
36
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
37
37
  import { getAllAccessibilityProps } from "@applicaster/zapp-react-native-utils/configurationUtils";
38
38
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
39
- import {
40
- getTargetScreenDataFromEntry
41
- } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useTargetScreenData";
39
+ import { getTargetScreenDataFromEntry } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useTargetScreenData";
42
40
  import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
41
+ import {
42
+ AnimationComponent,
43
+ ComponentAnimationType,
44
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
43
45
 
44
46
  const RNPlayerManager = {
45
47
  QuickBrickPlayerPlugin: isApplePlatform()
@@ -59,6 +61,7 @@ const styles = StyleSheet.create({
59
61
  position: "absolute",
60
62
  zIndex: 1,
61
63
  },
64
+ playerSize: { width: "100%", height: "100%" },
62
65
  });
63
66
 
64
67
  const logger = createLogger({
@@ -91,7 +94,7 @@ export default class VideoPlayer extends React.Component<
91
94
  // TODO: Can be deleted, on controller logic
92
95
  paused: false,
93
96
  piped: false,
94
- rate: 1,
97
+ rate: 1.0,
95
98
  // TODO: Hack for analytics, must br removed
96
99
  resume: null,
97
100
 
@@ -372,6 +375,10 @@ export default class VideoPlayer extends React.Component<
372
375
  }
373
376
  };
374
377
 
378
+ setPlaybackRate = (rate = 1.0) => {
379
+ this.setState({ rate });
380
+ };
381
+
375
382
  getCurrentTime = () => {
376
383
  return this.state.currentTime;
377
384
  };
@@ -555,6 +562,26 @@ export default class VideoPlayer extends React.Component<
555
562
  this.props.listener?.onPlayerDetached?.(nativeEvent);
556
563
  };
557
564
 
565
+ onVideoFullscreenPlayerDidDismiss = () => {
566
+ this.props.listener?.onVideoFullscreenPlayerDidDismiss?.();
567
+ };
568
+
569
+ onVideoFullscreenPlayerDidPresent = () => {
570
+ this.props.listener?.onVideoFullscreenPlayerDidPresent?.();
571
+ };
572
+
573
+ onVideoFullscreenPlayerWillDismiss = () => {
574
+ this.props.listener?.onVideoFullscreenPlayerWillDismiss?.();
575
+ };
576
+
577
+ onVideoFullscreenPlayerWillPresent = () => {
578
+ this.props.listener?.onVideoFullscreenPlayerWillPresent?.();
579
+ };
580
+
581
+ onPlayerClose = () => {
582
+ this.props.listener?.onPlayerClose?.();
583
+ };
584
+
558
585
  onPiPEnter = () => {
559
586
  this.setState({ piped: true });
560
587
  this.props.openPiP();
@@ -758,7 +785,6 @@ export default class VideoPlayer extends React.Component<
758
785
 
759
786
  render() {
760
787
  const {
761
- castAction,
762
788
  docked,
763
789
  entry,
764
790
  fullscreen,
@@ -768,9 +794,15 @@ export default class VideoPlayer extends React.Component<
768
794
  isTabletPortrait,
769
795
  muted,
770
796
  style,
797
+ castAction,
798
+ controller,
799
+ startComponentsAnimation,
771
800
  } = this.props;
772
801
 
773
- const { audioTrackId, keyEvent, paused, seek, textTrackId } = this.state;
802
+ const supportNativeCast = controller.supportNativeCast();
803
+
804
+ const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
805
+ this.state;
774
806
 
775
807
  const isAudioItem =
776
808
  entry?.content?.type?.includes?.("audio") ||
@@ -822,26 +854,28 @@ export default class VideoPlayer extends React.Component<
822
854
 
823
855
  let platformSpecificProps: any = isApplePlatform()
824
856
  ? {
825
- resizeMode: nativeResizeMode,
826
- } : {};
857
+ resizeMode: nativeResizeMode,
858
+ }
859
+ : {};
827
860
 
828
- const supportsNativeControls = !!this.props.controller?.supportsNativeControls?.();
861
+ const supportsNativeControls =
862
+ !!this.props.controller?.supportsNativeControls?.();
829
863
 
830
864
  const controls = isAppleTV()
831
- ? supportsNativeControls && isInlineTV && !this.getPlayNextData()
865
+ ? supportsNativeControls && !isInlineTV && !this.getPlayNextData()
832
866
  : supportsNativeControls && !this.getPlayNextData();
833
867
 
868
+ const shouldUseNativeControls =
869
+ controls &&
870
+ !startComponentsAnimation &&
871
+ !docked &&
872
+ !castAction?.state?.connected;
873
+
834
874
  platformSpecificProps = {
835
875
  ...platformSpecificProps,
836
- controls
876
+ controls: shouldUseNativeControls,
837
877
  };
838
878
 
839
- console.log("Anton Player render2 ", {
840
- platformSpecificProps,
841
- isNotInlineTv: !isInlineTV,
842
- hasNoPlayNextData: !this.getPlayNextData()
843
- });
844
-
845
879
  const pictureInPictureEnabled =
846
880
  this.props.pluginConfiguration?.pictureInPictureEnabled;
847
881
 
@@ -857,6 +891,7 @@ export default class VideoPlayer extends React.Component<
857
891
  nowPlayingEnabled,
858
892
  paused,
859
893
  seek,
894
+ rate,
860
895
  textTrackId,
861
896
  liveSeekingEnabled,
862
897
  liveCatchUpEnabled,
@@ -902,22 +937,17 @@ export default class VideoPlayer extends React.Component<
902
937
  onVideoEnd: this.onVideoEnd, // complete
903
938
  onVideoError: this.onVideoError, // error
904
939
  onVideoProgress: this.onVideoProgress,
905
- onVideoFullscreenPlayerDidDismiss: this.unHandledEvent(
906
- "onVideoFullscreenPlayerDidPresent"
907
- ),
908
- onVideoFullscreenPlayerDidPresent: this.unHandledEvent(
909
- "onVideoFullscreenPlayerDidPresent"
910
- ),
911
- onVideoFullscreenPlayerWillDismiss: this.unHandledEvent(
912
- "onVideoFullscreenPlayerWillDismiss"
913
- ),
914
- onVideoFullscreenPlayerWillPresent: this.unHandledEvent(
915
- "onVideoFullscreenPlayerWillPresent"
916
- ),
940
+ onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
941
+ onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
942
+ onVideoFullscreenPlayerWillDismiss:
943
+ this.onVideoFullscreenPlayerWillDismiss,
944
+ onVideoFullscreenPlayerWillPresent:
945
+ this.onVideoFullscreenPlayerWillPresent,
917
946
  onVideoLoad: this.onVideoLoad,
918
947
  onVideoLoadStart: this.unHandledEvent("onVideoLoadStart"),
919
948
  onVideoBuffer: this.onVideoBuffer,
920
949
  onPlaybackStalled: this.onPlaybackStalled,
950
+ onPlayerClose: this.onPlayerClose,
921
951
  onPlayerAttached: this.onPlayerAttached,
922
952
  onPlayerDetached: this.onPlayerDetached,
923
953
  };
@@ -976,8 +1006,6 @@ export default class VideoPlayer extends React.Component<
976
1006
  ? styles.playerContainerTransparent
977
1007
  : styles.playerContainerBlack;
978
1008
 
979
- console.log("Anton Player render", {screenData, props: this.props, nativeProps});
980
-
981
1009
  const isInline = () => {
982
1010
  if (isTV()) {
983
1011
  return inline;
@@ -993,7 +1021,7 @@ export default class VideoPlayer extends React.Component<
993
1021
  !needToShowPlayNextOverlay &&
994
1022
  this.props.mode !== "PIP";
995
1023
 
996
- if (controls === true) {
1024
+ if (shouldUseNativeControls) {
997
1025
  return null;
998
1026
  }
999
1027
 
@@ -1012,6 +1040,7 @@ export default class VideoPlayer extends React.Component<
1012
1040
  extraInfoText={castAction?.state?.friendlyStatus}
1013
1041
  controlsAlwaysVisible={castAction?.state?.connected}
1014
1042
  playNextData={this.getPlayNextData()}
1043
+ nativeControls={!!controls}
1015
1044
  />
1016
1045
  ) : null;
1017
1046
  };
@@ -1046,29 +1075,14 @@ export default class VideoPlayer extends React.Component<
1046
1075
  const renderMobilePlayer = () => {
1047
1076
  return isFullScreenAudioPlayer && isAudioItem ? (
1048
1077
  <View style={containerStyle}>
1049
- {!castAction?.state?.connected && (
1078
+ {(!castAction?.state?.connected || supportNativeCast) && (
1050
1079
  <this.props.PlayerComponent
1051
1080
  ref={this._assignRoot}
1052
1081
  {...nativeEvents}
1053
1082
  {...nativeProps}
1054
1083
  />
1055
1084
  )}
1056
- <AudioPlayerWrapper {...sharedWrapperViewProps}>
1057
- <View>
1058
- {
1059
- <PlayNextOverlay
1060
- item={entry}
1061
- playerIsDocked={docked}
1062
- pluginConfiguration={this.getPluginConfiguration()}
1063
- playerId={this.props.playerId}
1064
- playNextData={this.getPlayNextData()}
1065
- setNextVideoPreloadThresholdPercentage={
1066
- this.props.setNextVideoPreloadThresholdPercentage
1067
- }
1068
- />
1069
- }
1070
- </View>
1071
- </AudioPlayerWrapper>
1085
+ <AudioPlayerWrapper {...sharedWrapperViewProps} />
1072
1086
  </View>
1073
1087
  ) : (
1074
1088
  <PlayerWrapper {...sharedWrapperViewProps}>
@@ -1083,11 +1097,20 @@ export default class VideoPlayer extends React.Component<
1083
1097
  <View style={styles.container}>
1084
1098
  <View style={[playerContainerStyles, playerDimensions]}>
1085
1099
  {isAudioItem && (
1086
- <AudioPlayer
1087
- style={playerDimensions}
1088
- audio_item={entry}
1089
- plugin_configuration={this.getPluginConfiguration()}
1090
- />
1100
+ <AnimationComponent
1101
+ animationType={ComponentAnimationType.player}
1102
+ additionalData={{
1103
+ ...playerDimensions,
1104
+ inlineAudioPlayer: true,
1105
+ }}
1106
+ style={getStyle(playerDimensions)}
1107
+ >
1108
+ <AudioPlayer
1109
+ style={styles.playerSize}
1110
+ audio_item={entry}
1111
+ plugin_configuration={this.getPluginConfiguration()}
1112
+ />
1113
+ </AnimationComponent>
1091
1114
  )}
1092
1115
 
1093
1116
  {shouldRenderBackground && (
@@ -1099,18 +1122,24 @@ export default class VideoPlayer extends React.Component<
1099
1122
  />
1100
1123
  )}
1101
1124
 
1102
- {!castAction?.state?.connected && (
1103
- <this.props.PlayerComponent
1104
- ref={this._assignRoot}
1105
- {...nativeEvents}
1106
- {...nativeProps}
1107
- listener={this.props.listener}
1125
+ {(!castAction?.state?.connected || supportNativeCast) && (
1126
+ <AnimationComponent
1127
+ animationType={ComponentAnimationType.player}
1128
+ additionalData={playerDimensions}
1108
1129
  style={getStyle(playerDimensions)}
1109
- pluginConfiguration={this.getPluginConfiguration()}
1110
- controller={this.props.controller}
1111
1130
  >
1112
- {this.childrenWithPlayNext()}
1113
- </this.props.PlayerComponent>
1131
+ <this.props.PlayerComponent
1132
+ ref={this._assignRoot}
1133
+ {...nativeEvents}
1134
+ {...nativeProps}
1135
+ listener={this.props.listener}
1136
+ style={styles.playerSize}
1137
+ pluginConfiguration={this.getPluginConfiguration()}
1138
+ controller={this.props.controller}
1139
+ >
1140
+ {this.childrenWithPlayNext()}
1141
+ </this.props.PlayerComponent>
1142
+ </AnimationComponent>
1114
1143
  )}
1115
1144
  </View>
1116
1145