@applicaster/zapp-react-native-utils 15.1.0-rc.1 → 16.0.0-alpha.9803580571

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 (144) hide show
  1. package/README.md +0 -6
  2. package/actionUtils/index.ts +7 -0
  3. package/actionsExecutor/ActionExecutorContext.tsx +43 -12
  4. package/actionsExecutor/feedDecorator.ts +6 -6
  5. package/adsUtils/__tests__/createVMAP.test.ts +419 -0
  6. package/adsUtils/index.ts +2 -2
  7. package/analyticsUtils/README.md +1 -1
  8. package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
  9. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
  10. package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
  11. package/appUtils/HooksManager/index.ts +10 -10
  12. package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
  13. package/appUtils/accessibilityManager/const.ts +4 -0
  14. package/appUtils/accessibilityManager/utils.ts +0 -1
  15. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
  16. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
  17. package/appUtils/contextKeysManager/contextResolver.ts +51 -22
  18. package/appUtils/contextKeysManager/index.ts +65 -10
  19. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +3 -0
  20. package/appUtils/focusManager/index.ios.ts +43 -4
  21. package/appUtils/focusManager/treeDataStructure/Tree/__tests__/Tree.test.js +46 -0
  22. package/appUtils/focusManager/treeDataStructure/Tree/index.js +18 -18
  23. package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
  24. package/appUtils/focusManagerAux/utils/index.ts +11 -3
  25. package/appUtils/focusManagerAux/utils/utils.ios.ts +202 -3
  26. package/appUtils/keyCodes/keys/keys.web.ts +1 -4
  27. package/appUtils/orientationHelper.ts +2 -4
  28. package/appUtils/platform/platformUtils.ts +1 -1
  29. package/appUtils/playerManager/player.ts +4 -0
  30. package/appUtils/playerManager/playerNative.ts +30 -21
  31. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  32. package/cloudEventsUtils/__tests__/index.test.ts +529 -0
  33. package/cloudEventsUtils/index.ts +65 -1
  34. package/componentsUtils/index.ts +8 -0
  35. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  36. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
  37. package/errorUtils/__tests__/GeneralError.test.ts +97 -0
  38. package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
  39. package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
  40. package/errorUtils/__tests__/NetworkError.test.ts +202 -0
  41. package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
  42. package/errorUtils/__tests__/invariant.test.ts +112 -0
  43. package/focusManager/aux/index.ts +1 -1
  44. package/headersUtils/__tests__/headersUtils.test.js +11 -1
  45. package/headersUtils/index.ts +2 -1
  46. package/manifestUtils/_internals/__tests__/index.test.js +41 -0
  47. package/manifestUtils/_internals/index.js +33 -0
  48. package/manifestUtils/defaultManifestConfigurations/player.js +59 -1
  49. package/manifestUtils/fieldUtils/__tests__/fieldUtils.test.js +49 -0
  50. package/manifestUtils/fieldUtils/index.js +54 -0
  51. package/manifestUtils/index.js +2 -0
  52. package/manifestUtils/keys.js +228 -0
  53. package/manifestUtils/mobileAction/button/__tests__/mobileActionButton.test.js +168 -0
  54. package/manifestUtils/mobileAction/button/index.js +140 -0
  55. package/manifestUtils/mobileAction/container/__tests__/mobileActionButtonsContainer.test.js +102 -0
  56. package/manifestUtils/mobileAction/container/index.js +73 -0
  57. package/manifestUtils/mobileAction/groups/__tests__/buildMobileActionButtonGroups.test.js +127 -0
  58. package/manifestUtils/mobileAction/groups/defaults.js +76 -0
  59. package/manifestUtils/mobileAction/groups/index.js +80 -0
  60. package/manifestUtils/tvAction/container/index.js +1 -1
  61. package/numberUtils/__tests__/toNumber.test.ts +27 -0
  62. package/numberUtils/__tests__/toPositiveNumber.test.ts +193 -0
  63. package/numberUtils/index.ts +23 -1
  64. package/package.json +4 -4
  65. package/pluginUtils/index.ts +4 -0
  66. package/reactHooks/advertising/index.ts +2 -2
  67. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
  68. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  69. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  70. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
  71. package/reactHooks/cell-click/__tests__/index.test.js +1 -3
  72. package/reactHooks/cell-click/index.ts +2 -1
  73. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  74. package/reactHooks/connection/__tests__/index.test.js +1 -1
  75. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  76. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
  77. package/reactHooks/device/useIsTablet.tsx +14 -19
  78. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  79. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
  80. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  81. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
  82. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
  83. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  84. package/reactHooks/feed/index.ts +0 -2
  85. package/reactHooks/feed/useBatchLoading.ts +7 -1
  86. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  87. package/reactHooks/feed/usePipesCacheReset.ts +3 -1
  88. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
  89. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  90. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  91. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
  92. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  93. package/reactHooks/navigation/__tests__/index.test.tsx +2 -4
  94. package/reactHooks/navigation/index.ts +7 -6
  95. package/reactHooks/navigation/useRoute.ts +8 -6
  96. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  97. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  98. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  99. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  100. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  101. package/reactHooks/resolvers/useCellResolver.ts +6 -2
  102. package/reactHooks/resolvers/useComponentResolver.ts +8 -2
  103. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  104. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  105. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  106. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
  107. package/reactHooks/screen/index.ts +0 -2
  108. package/reactHooks/screen/useTargetScreenData.ts +4 -2
  109. package/reactHooks/state/useRivers.ts +1 -1
  110. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
  111. package/reactHooks/usePluginConfiguration.ts +2 -2
  112. package/reactHooks/utils/__tests__/index.test.js +1 -1
  113. package/rectUtils/__tests__/index.test.ts +549 -0
  114. package/rectUtils/index.ts +2 -2
  115. package/refreshUtils/RefreshCoordinator/__tests__/refreshCoordinator.test.ts +206 -0
  116. package/refreshUtils/RefreshCoordinator/index.ts +245 -0
  117. package/refreshUtils/RefreshCoordinator/utils/__tests__/getDataRefreshConfig.test.ts +104 -0
  118. package/refreshUtils/RefreshCoordinator/utils/index.ts +29 -0
  119. package/screenPickerUtils/__tests__/index.test.ts +333 -0
  120. package/screenState/__tests__/index.test.ts +1 -1
  121. package/screenUtils/index.ts +3 -0
  122. package/searchUtils/const.ts +7 -0
  123. package/searchUtils/index.ts +3 -0
  124. package/stringUtils/index.ts +1 -1
  125. package/testUtils/index.tsx +30 -21
  126. package/time/__tests__/BackgroundTimer.test.ts +156 -0
  127. package/time/__tests__/Timer.test.ts +236 -0
  128. package/typeGuards/__tests__/isString.test.ts +21 -0
  129. package/typeGuards/index.ts +4 -0
  130. package/utils/__tests__/mergeRight.test.ts +48 -0
  131. package/utils/__tests__/path.test.ts +7 -0
  132. package/utils/__tests__/selectors.test.ts +124 -0
  133. package/utils/index.ts +13 -0
  134. package/utils/mergeRight.ts +5 -0
  135. package/utils/path.ts +6 -3
  136. package/utils/pathOr.ts +5 -1
  137. package/utils/selectors.ts +46 -0
  138. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +1 -1
  139. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  140. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  141. package/reactHooks/componentsMap/index.ts +0 -55
  142. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +0 -75
  143. package/reactHooks/feed/useFeedRefresh.tsx +0 -65
  144. package/reactHooks/screen/useIsStandaloneFullscreen.ts +0 -12
@@ -1,7 +1,9 @@
1
- import { ReplaySubject } from "rxjs";
2
- import { filter } from "rxjs/operators";
1
+ import { ReplaySubject, Subject } from "rxjs";
2
+ import { filter, switchMap, take, withLatestFrom, map } from "rxjs/operators";
3
+
3
4
  import { BUTTON_PREFIX } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const";
4
5
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
6
+ import { isPartOfMenu, isPartOfContent } from "./index.ios";
5
7
 
6
8
  type FocusableID = string;
7
9
  type RegistrationEvent = {
@@ -9,6 +11,25 @@ type RegistrationEvent = {
9
11
  registered: boolean;
10
12
  };
11
13
 
14
+ let focusableViewRegistrationSubject$ = new Subject<{
15
+ id: FocusableID;
16
+ groupId: FocusableID;
17
+ }>();
18
+
19
+ let focusableGroupRegistrationSubject$ = new ReplaySubject<{
20
+ id: FocusableID;
21
+ }>();
22
+
23
+ let focusableNativeViewRegistrationSubject$ = new Subject<{
24
+ id: FocusableID;
25
+ groupId: FocusableID;
26
+ }>();
27
+
28
+ let focusableNativeGroupRegistrationSubject$ = new ReplaySubject<{
29
+ id: FocusableID;
30
+ groupId: FocusableID;
31
+ }>();
32
+
12
33
  const isFocusableButton = (id: Option<FocusableID>): boolean =>
13
34
  id && id.includes?.(BUTTON_PREFIX);
14
35
 
@@ -22,14 +43,192 @@ export const focusableButtonsRegistration$ = (focusableGroupId: string) =>
22
43
  )
23
44
  );
24
45
 
25
- export const emitRegistered = (id: Option<FocusableID>): void => {
46
+ export const resetFocusableRegistration = () => {
47
+ // complete the old subject so subscribers are notified and resources are freed
48
+ if (!focusableViewRegistrationSubject$.closed) {
49
+ focusableViewRegistrationSubject$.complete();
50
+ }
51
+
52
+ if (!focusableGroupRegistrationSubject$.closed) {
53
+ focusableGroupRegistrationSubject$.complete();
54
+ }
55
+
56
+ if (!focusableNativeViewRegistrationSubject$.closed) {
57
+ focusableNativeViewRegistrationSubject$.complete();
58
+ }
59
+
60
+ if (!focusableNativeGroupRegistrationSubject$.closed) {
61
+ focusableNativeGroupRegistrationSubject$.complete();
62
+ }
63
+
64
+ focusableViewRegistrationSubject$ = new Subject<{
65
+ id: FocusableID;
66
+ groupId: FocusableID;
67
+ }>();
68
+
69
+ focusableGroupRegistrationSubject$ = new ReplaySubject<{
70
+ id: FocusableID;
71
+ }>();
72
+
73
+ focusableNativeViewRegistrationSubject$ = new Subject<{
74
+ id: FocusableID;
75
+ groupId: FocusableID;
76
+ }>();
77
+
78
+ focusableNativeGroupRegistrationSubject$ = new ReplaySubject<{
79
+ id: FocusableID;
80
+ groupId: FocusableID;
81
+ }>();
82
+ };
83
+
84
+ const focusableNativeViewRegistration = ({ focusableView, focusableGroup }) => {
85
+ return focusableNativeViewRegistrationSubject$.pipe(
86
+ filter(
87
+ (focusableNativeView) => focusableNativeView.id === focusableView.id
88
+ ),
89
+ take(1),
90
+ switchMap((focusableNativeView) =>
91
+ // start waiting registration of its parent FocusableNativeGroup
92
+ focusableNativeGroupRegistrationSubject$.pipe(
93
+ filter(
94
+ (focusableNativeGroup) =>
95
+ focusableNativeGroup.id === focusableNativeView.groupId
96
+ ),
97
+ take(1),
98
+ map((focusableNativeGroup) => ({
99
+ focusableNativeGroup,
100
+ focusableNativeView,
101
+ focusableView,
102
+ focusableGroup,
103
+ }))
104
+ )
105
+ )
106
+ );
107
+ };
108
+
109
+ export const firstFocusableViewInContentRegistrationFactory = () =>
110
+ focusableViewRegistrationSubject$.pipe(
111
+ switchMap((focusableView) =>
112
+ // start waiting registration of its parent FocusableGroup
113
+ focusableGroupRegistrationSubject$.pipe(
114
+ filter((focusableGroup) => focusableGroup.id === focusableView.groupId),
115
+ take(1),
116
+ map((focusableGroup) => ({
117
+ focusableView,
118
+ focusableGroup,
119
+ }))
120
+ )
121
+ ),
122
+ // start waiting registration for FocusableNativeView and its parent FocusableNativeGroup
123
+ switchMap(({ focusableView, focusableGroup }) =>
124
+ focusableNativeViewRegistration({
125
+ focusableView,
126
+ focusableGroup,
127
+ })
128
+ ),
129
+ filter(({ focusableView }) =>
130
+ isPartOfContent(focusManager.focusableTree, focusableView.id)
131
+ ),
132
+ take(1) // we care about only first FocusableView registration
133
+ );
134
+
135
+ // registration on RN level(into RN focusManager)
136
+ export const emitRegistered = ({
137
+ id,
138
+ groupId,
139
+ isGroup,
140
+ }: {
141
+ id: Option<FocusableID>;
142
+ groupId: Option<FocusableID>;
143
+ isGroup: boolean;
144
+ }): void => {
26
145
  if (isFocusableButton(id)) {
27
146
  registeredSubject$.next({ id, registered: true });
28
147
  }
148
+
149
+ if (isGroup && id) {
150
+ focusableGroupRegistrationSubject$.next({ id });
151
+ }
152
+
153
+ if (!isGroup && id && groupId) {
154
+ focusableViewRegistrationSubject$.next({ id, groupId });
155
+ }
29
156
  };
30
157
 
158
+ // unregistration on RN level(into RN focusManager)
31
159
  export const emitUnregistered = (id: Option<FocusableID>): void => {
32
160
  if (isFocusableButton(id)) {
33
161
  registeredSubject$.next({ id, registered: false });
34
162
  }
35
163
  };
164
+
165
+ // registration focusableNativeView and focusableNativeGroup
166
+ export const emitNativeRegistered = ({
167
+ id,
168
+ groupId,
169
+ isGroup,
170
+ }: {
171
+ id: Option<FocusableID>;
172
+ groupId: Option<FocusableID>;
173
+ isGroup: boolean;
174
+ }): void => {
175
+ if (!isGroup && id && groupId) {
176
+ focusableNativeViewRegistrationSubject$.next({ id, groupId });
177
+ }
178
+
179
+ if (isGroup && id && groupId) {
180
+ focusableNativeGroupRegistrationSubject$.next({ id, groupId });
181
+ }
182
+ };
183
+
184
+ // /////
185
+
186
+ const focusedSubject$ = new Subject<FocusableID>();
187
+
188
+ const focused$ = focusedSubject$.asObservable();
189
+
190
+ export const emitFocused = (id: FocusableID): void => {
191
+ focusedSubject$.next(id);
192
+ };
193
+
194
+ export const topMenuItemFocused$ = focused$.pipe(
195
+ filter((id) => id && isPartOfMenu(focusManager.focusableTree, id))
196
+ );
197
+
198
+ export const contentFocused$ = focused$.pipe(
199
+ filter((id) => {
200
+ const isContent = isPartOfContent(focusManager.focusableTree, id);
201
+
202
+ return id && isContent;
203
+ })
204
+ );
205
+
206
+ const createFocusableRegistry = () => {
207
+ const subject$ = new ReplaySubject<FocusableID | undefined>(1);
208
+
209
+ return {
210
+ observable$: subject$.asObservable(),
211
+ register: (id: FocusableID) => {
212
+ // save focusable_id on registration
213
+ subject$.next(id);
214
+ },
215
+ unregister: () => {
216
+ // reset focusable_id on unregistration
217
+ subject$.next(undefined);
218
+ },
219
+ };
220
+ };
221
+
222
+ /// HOME_TOP_MENU_ITEM
223
+ export const HomeTopMenuItemRegistry = createFocusableRegistry();
224
+
225
+ export const homeTopMenuItemFocused$ = topMenuItemFocused$.pipe(
226
+ withLatestFrom(HomeTopMenuItemRegistry.observable$),
227
+ filter(([id, homeId]) => id === homeId)
228
+ );
229
+
230
+ /// SCREEN_PICKER
231
+ export const ScreenPickerContentContainerRegistry = createFocusableRegistry();
232
+
233
+ /// SEARCH_INPUT
234
+ export const SearchInputRegistry = createFocusableRegistry();
@@ -10,10 +10,7 @@ import { Platform } from "react-native";
10
10
  * platformKeys[Platform.OS] should only include keys
11
11
  * that are unique to that platform, i.e. Exit: { keyCode: 10182 }
12
12
  */
13
- export const KEYS = Object.assign(
14
- platformKeys["web"],
15
- platformKeys[Platform.OS]
16
- );
13
+ export const KEYS = Object.assign(platformKeys.web, platformKeys[Platform.OS]);
17
14
 
18
15
  export const ARROW_KEYS = [
19
16
  KEYS.ArrowUp,
@@ -1,5 +1,5 @@
1
1
  import * as ReactNative from "react-native";
2
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import { useAppData } from "@applicaster/zapp-react-native-redux/hooks";
3
3
 
4
4
  import { isTV, platformSelect } from "../reactUtils";
5
5
  import { useIsTablet } from "../reactHooks";
@@ -184,9 +184,7 @@ export const getScreenOrientation = ({
184
184
 
185
185
  export const useGetScreenOrientation = (screenData) => {
186
186
  const isTablet = useIsTablet();
187
-
188
- const { appData } = usePickFromState(["appData"]);
189
- const isTabletPortrait = appData?.isTabletPortrait;
187
+ const { isTabletPortrait } = useAppData();
190
188
 
191
189
  return getScreenOrientation({
192
190
  screenData,
@@ -79,7 +79,7 @@ export class ClosedCaptioningManager {
79
79
  private constructor() {
80
80
  this.initialize();
81
81
 
82
- window["vizioDebug"] = {
82
+ window.vizioDebug = {
83
83
  setCCEnabled: (isCCEnabled: boolean) => {
84
84
  this.ccState$.next(isCCEnabled);
85
85
  },
@@ -250,6 +250,10 @@ export class Player {
250
250
  return false;
251
251
  }
252
252
 
253
+ if (!Number.isFinite(duration)) {
254
+ return this.getSeekableDuration() > 0;
255
+ }
256
+
253
257
  return duration > 0;
254
258
  };
255
259
 
@@ -15,6 +15,22 @@ const logger = createLogger({
15
15
 
16
16
  const { log_warning } = logger;
17
17
 
18
+ interface PlayerMethods {
19
+ seeking?: (position: number) => void;
20
+ forward?: (deltaTime: number) => void;
21
+ rewind?: (deltaTime: number) => void;
22
+ startSleepTimer?: (sleepTimestamp: number) => void;
23
+ selectTrack?: (
24
+ selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
25
+ ) => void;
26
+ setPlaybackRate?: (rate: number) => void;
27
+ appStateChange?: (appState: string, previousAppState: string) => void;
28
+ closeNativePlayer?: () => void;
29
+ togglePlayPause?: () => void;
30
+ }
31
+
32
+ type PlayerComponent = ReactComponent<PlayerRefProps> & PlayerMethods;
33
+
18
34
  type PlayerPlugnId = "QuickBrickPlayerPlugin" | "KalturaPlayerPlugin";
19
35
 
20
36
  type Props = {
@@ -62,7 +78,7 @@ export class PlayerNative extends Player {
62
78
  return this.playerState.contentPosition;
63
79
  };
64
80
 
65
- currentPlayerComponent = (): ReactComponent<PlayerRefProps> =>
81
+ currentPlayerComponent = (): PlayerComponent | null =>
66
82
  this.playerComponent?.current;
67
83
 
68
84
  getState = () => this.playerState;
@@ -121,7 +137,7 @@ export class PlayerNative extends Player {
121
137
 
122
138
  this.playerState.seekPosition = newPosition;
123
139
 
124
- this.currentPlayerComponent()?.["seeking"](this.playerState.seekPosition);
140
+ this.currentPlayerComponent()?.seeking?.(this.playerState.seekPosition);
125
141
  }
126
142
 
127
143
  this.logState(PlayerModuleFuncNames.seekTo, { position });
@@ -135,7 +151,7 @@ export class PlayerNative extends Player {
135
151
  if (!this.invokeNativeFunction(PlayerModuleFuncNames.forward, deltaTime)) {
136
152
  // Kaltura does not have yet this implementation, use legacy code
137
153
 
138
- this.currentPlayerComponent()?.["forward"](deltaTime);
154
+ this.currentPlayerComponent()?.forward?.(deltaTime);
139
155
  }
140
156
 
141
157
  this.notifyPlayHeadPositionUpdate();
@@ -151,7 +167,7 @@ export class PlayerNative extends Player {
151
167
  if (!this.invokeNativeFunction(PlayerModuleFuncNames.rewind, deltaTime)) {
152
168
  // Kaltura does not have yet this implementation, use legacy code
153
169
 
154
- this.currentPlayerComponent()?.["rewind"](deltaTime);
170
+ this.currentPlayerComponent()?.rewind?.(deltaTime);
155
171
  }
156
172
 
157
173
  this.notifyPlayHeadPositionUpdate();
@@ -178,7 +194,7 @@ export class PlayerNative extends Player {
178
194
  sleepTimestamp
179
195
  )
180
196
  ) {
181
- this.currentPlayerComponent()?.["startSleepTimer"](sleepTimestamp);
197
+ this.currentPlayerComponent()?.startSleepTimer?.(sleepTimestamp);
182
198
  }
183
199
  };
184
200
 
@@ -195,11 +211,11 @@ export class PlayerNative extends Player {
195
211
  selectTrack = (
196
212
  selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
197
213
  ) => {
198
- this.currentPlayerComponent()?.["selectTrack"]?.(selected);
214
+ this.currentPlayerComponent()?.selectTrack?.(selected);
199
215
  };
200
216
 
201
217
  setPlaybackRate = (rate: number) => {
202
- this.currentPlayerComponent()?.["setPlaybackRate"]?.(rate);
218
+ this.currentPlayerComponent()?.setPlaybackRate?.(rate);
203
219
  };
204
220
 
205
221
  getPluginConfiguration = () => {
@@ -209,24 +225,17 @@ export class PlayerNative extends Player {
209
225
  getProps = () => (this.currentPlayerComponent() as any)?.props;
210
226
 
211
227
  appStateChange = (appState, previousAppState) => {
212
- this.currentPlayerComponent()?.["appStateChange"]?.(
213
- appState,
214
- previousAppState
215
- );
228
+ this.currentPlayerComponent()?.appStateChange?.(appState, previousAppState);
216
229
  };
217
230
 
218
231
  closeNativePlayer = () => {
219
- // The player component ref may be null (for example, when the native player view is not mounted),
220
- // so calling closeNativePlayer on the component is best‑effort only. We cannot use invokeNativeFunction
221
- // here because it prepends the view id, while the native closeNativePlayer implementation does not
222
- // expect a view id argument. As a reliable fallback we always call stopBackgroundPlayback on the
223
- // native module to ensure background playback is stopped.
224
- this.currentPlayerComponent()?.["closeNativePlayer"]?.();
232
+ // TODO: Delete, does not work (component is null)
233
+ this.currentPlayerComponent()?.closeNativePlayer?.();
225
234
  this.getPlayerModule()?.stopBackgroundPlayback?.();
226
235
  };
227
236
 
228
237
  togglePlayPause = () => {
229
- this.currentPlayerComponent()?.["togglePlayPause"]?.();
238
+ this.currentPlayerComponent()?.togglePlayPause?.();
230
239
  };
231
240
 
232
241
  onVideoLoad = (event) => {
@@ -294,19 +303,19 @@ export class PlayerNative extends Player {
294
303
  isFullScreenSupported = (): boolean => {
295
304
  const config = this.getConfig();
296
305
 
297
- const disableFullScreen = config?.["disable_fullscreen"];
306
+ const disableFullScreen = config?.disable_fullscreen;
298
307
 
299
308
  if (disableFullScreen) {
300
309
  return false;
301
310
  }
302
311
 
303
- const isFullScreenAudioPlayer = config?.["full_screen_audio_player"];
312
+ const isFullScreenAudioPlayer = config?.full_screen_audio_player;
304
313
 
305
314
  return !(isFullScreenAudioPlayer && this.isAudioItem());
306
315
  };
307
316
 
308
317
  supportsNativeControls = (): boolean =>
309
- toBooleanWithDefaultFalse(this.getConfig()?.["supports_native_controls"]);
318
+ toBooleanWithDefaultFalse(this.getConfig()?.supports_native_controls);
310
319
 
311
320
  supportNativeCast = (): boolean =>
312
321
  toBooleanWithDefaultFalse(
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { Player } from "./player";
3
3
  import { usePlayer } from "./usePlayer";
4
4
 
5
- type PlayerState = {
5
+ export type PlayerState = {
6
6
  currentTime: number;
7
7
  duration: number;
8
8
  seekableDuration: number;
@@ -10,6 +10,8 @@ type PlayerState = {
10
10
  isPaused: boolean;
11
11
  isBuffering: boolean;
12
12
  isReadyToPlay: boolean;
13
+ trackState?: QuickBrickPlayer.TracksState;
14
+ isAd: boolean;
13
15
  };
14
16
 
15
17
  export const usePlayerState = (
@@ -24,6 +26,8 @@ export const usePlayerState = (
24
26
  isPaused: null,
25
27
  isBuffering: false,
26
28
  isReadyToPlay: false,
29
+ trackState: null,
30
+ isAd: false,
27
31
  });
28
32
 
29
33
  const player: Player = usePlayer(playerId);
@@ -37,6 +41,8 @@ export const usePlayerState = (
37
41
  isPaused: player.isPaused(),
38
42
  isBuffering: player.isBuffering(),
39
43
  isReadyToPlay: player.isReadyToPlay(),
44
+ trackState: player.getTracksState(),
45
+ isAd: player.isAd(),
40
46
  });
41
47
  }, [player]);
42
48
 
@@ -54,10 +60,16 @@ export const usePlayerState = (
54
60
  onPlayerPause: onPlayerChangeState,
55
61
  onPlayerResume: onPlayerChangeState,
56
62
  onPlayerSeekComplete: onPlayerChangeState,
63
+ onTracksChanged: onPlayerChangeState,
64
+ onAdBreakBegin: onPlayerChangeState,
65
+ onAdBreakEnd: onPlayerChangeState,
66
+ onAdBegin: onPlayerChangeState,
67
+ onAdEnd: onPlayerChangeState,
68
+ onAdError: onPlayerChangeState,
57
69
  },
58
70
  });
59
71
  }
60
- }, [player]);
72
+ }, [listenerId, onPlayerChangeState, player]);
61
73
 
62
74
  return state;
63
75
  };