@applicaster/zapp-react-native-ui-components 12.0.0-alpha.5882013252 → 12.0.0-alpha.5895113034
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/Components/AnimatedInOut/index.tsx +18 -10
- package/Components/AudioPlayer/AudioPlayer.tsx +9 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/Cell/Cell.tsx +2 -2
- package/Components/Cell/CellWithFocusable.tsx +21 -14
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableList/FocusableChild.ts +24 -14
- package/Components/FocusableList/FocusableItem.tsx +1 -1
- package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
- package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
- package/Components/FocusableList/index.tsx +26 -25
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +11 -8
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HandlePlayable/HandlePlayable.tsx +1 -1
- package/Components/HookRenderer/index.tsx +1 -6
- package/Components/Image/Image.android.tsx +3 -22
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/__tests__/index.test.tsx +1 -34
- package/Components/Layout/TV/index.tsx +28 -41
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -110
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +21 -8
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +17 -2
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -10
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/utils/index.ts +16 -5
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
- package/Components/ModalComponent/Button/Item.tsx +82 -0
- package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
- package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
- package/Components/ModalComponent/Button/assets.ts +4 -0
- package/Components/ModalComponent/Button/index.tsx +111 -0
- package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
- package/Components/ModalComponent/Header/Title.tsx +70 -0
- package/Components/ModalComponent/Header/assets.ts +4 -0
- package/Components/ModalComponent/Header/index.tsx +71 -0
- package/Components/ModalComponent/Header/utils.ts +79 -0
- package/Components/ModalComponent/index.tsx +38 -0
- package/Components/ModalComponent/utils.ts +126 -0
- package/Components/PlayerContainer/ErrorDisplay/ErrorDisplay.tsx +4 -7
- package/Components/PlayerContainer/PlayerContainer.tsx +61 -30
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +97 -2
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/River.tsx +8 -5
- package/Components/River/TV/River.tsx +2 -2
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/River/useScreenConfiguration.ts +5 -6
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
- package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
- package/Components/RouteManager/index.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +48 -36
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
- package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
- package/Components/Screen/index.tsx +103 -44
- package/Components/Screen/navigationHandler.ts +0 -82
- package/Components/Screen/orientationHandler.ts +1 -1
- package/Components/ScreenResolver/index.tsx +1 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/TrackedView/index.tsx +6 -3
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +9 -2
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +45 -13
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +81 -72
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
- package/Components/VideoModal/PlayerDetails.tsx +6 -3
- package/Components/VideoModal/PlayerWrapper.tsx +134 -103
- package/Components/VideoModal/VideoModal.tsx +25 -42
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +15 -3
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +242 -166
- package/Components/VideoModal/hooks/useModalSize.ts +13 -4
- package/Components/VideoModal/utils.ts +3 -3
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Components/ZappUIComponent/index.tsx +22 -12
- package/Components/index.js +2 -0
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +95 -29
- package/Contexts/ScreenDataContext/index.ts +3 -0
- package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/Decorators/RiverResolver/index.tsx +0 -4
- package/Decorators/index.tsx +0 -4
- package/events/index.ts +1 -0
- package/package.json +5 -6
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
10
10
|
import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
11
|
-
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks
|
|
11
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
import { ZappHookModalContext } from "../../Contexts";
|
|
13
13
|
import { HookModalContextT } from "../../Contexts/ZappHookModalContext";
|
|
14
14
|
|
|
@@ -17,9 +17,12 @@ type TrackedViewProps = {
|
|
|
17
17
|
export const TrackedView = memo(function TrackedView(props: TrackedViewProps) {
|
|
18
18
|
const children = props.children;
|
|
19
19
|
|
|
20
|
-
const onPositionUpdated = useCallback(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const onPositionUpdated = useCallback(
|
|
21
|
+
(event: TrackedViewNativeProps) => {
|
|
22
|
+
props.onPositionUpdated(event.nativeEvent);
|
|
23
|
+
},
|
|
24
|
+
[props.onPositionUpdated]
|
|
25
|
+
);
|
|
23
26
|
|
|
24
27
|
if (isTV()) {
|
|
25
28
|
return <View {...(props as any)}>{children}</View>;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "react-native";
|
|
8
8
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
9
9
|
import { PathnameContext } from "../../Contexts/PathnameContext";
|
|
10
|
+
import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
|
|
10
11
|
|
|
11
12
|
type Props = {
|
|
12
13
|
children: any;
|
|
@@ -16,6 +17,8 @@ type Props = {
|
|
|
16
17
|
animating: boolean;
|
|
17
18
|
contentStyle: ViewStyle;
|
|
18
19
|
pathname: string;
|
|
20
|
+
isActive: boolean;
|
|
21
|
+
screenData: NavigationScreenData;
|
|
19
22
|
};
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -38,34 +41,36 @@ export function Scene({
|
|
|
38
41
|
animating,
|
|
39
42
|
contentStyle,
|
|
40
43
|
pathname,
|
|
44
|
+
isActive = false,
|
|
45
|
+
screenData,
|
|
41
46
|
}: Props) {
|
|
47
|
+
const [initialScreenData, setInitialScreenData] = React.useState(screenData);
|
|
48
|
+
|
|
49
|
+
React.useLayoutEffect(() => {
|
|
50
|
+
if (isActive) {
|
|
51
|
+
setInitialScreenData(screenData);
|
|
52
|
+
}
|
|
53
|
+
}, [screenData, isActive]);
|
|
54
|
+
|
|
42
55
|
const frame = useSafeAreaFrame();
|
|
43
56
|
const { height, width } = useWindowDimensions();
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<Animated.View
|
|
50
|
-
pointerEvents={pointerEvents}
|
|
51
|
-
style={[style, contentStyle, { height, width }]}
|
|
52
|
-
>
|
|
53
|
-
<PathnameContext.Provider value={pathname}>
|
|
54
|
-
{children}
|
|
55
|
-
</PathnameContext.Provider>
|
|
56
|
-
<Animated.View style={overlayStyle} />
|
|
57
|
-
</Animated.View>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
58
|
+
// Safe frame takes too long to update,
|
|
59
|
+
// so we can not rely on it there, and use height and width instead.
|
|
60
|
+
const isAnimating = animating && overlayStyle;
|
|
61
|
+
const dimensions = isAnimating ? { height, width } : frame;
|
|
60
62
|
|
|
61
63
|
return (
|
|
62
64
|
<Animated.View
|
|
63
65
|
pointerEvents={pointerEvents}
|
|
64
|
-
style={[style, contentStyle,
|
|
66
|
+
style={[style, contentStyle, dimensions]}
|
|
65
67
|
>
|
|
66
|
-
<
|
|
67
|
-
{
|
|
68
|
-
|
|
68
|
+
<ScreenDataContext.Provider value={initialScreenData}>
|
|
69
|
+
<PathnameContext.Provider value={pathname}>
|
|
70
|
+
{children}
|
|
71
|
+
</PathnameContext.Provider>
|
|
72
|
+
</ScreenDataContext.Provider>
|
|
73
|
+
{isAnimating && <Animated.View style={overlayStyle} />}
|
|
69
74
|
</Animated.View>
|
|
70
75
|
);
|
|
71
76
|
}
|
|
@@ -278,7 +278,8 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
278
278
|
// instead of dangerous nulls or duplicates.
|
|
279
279
|
renderSingleScene({ scenes, to }) {
|
|
280
280
|
const { contentStyle, layoutData } = this.props;
|
|
281
|
-
const screenData =
|
|
281
|
+
const screenData = this.props.children.props.screenData;
|
|
282
|
+
const pathname = scenes[to.index].key;
|
|
282
283
|
|
|
283
284
|
const orientation = getScreenOrientation({
|
|
284
285
|
screenData,
|
|
@@ -296,10 +297,12 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
296
297
|
}) && (
|
|
297
298
|
<Scene
|
|
298
299
|
{...{ style: to.style }}
|
|
299
|
-
pathname={
|
|
300
|
+
pathname={pathname}
|
|
301
|
+
isActive={pathname === this.props.navigator.currentRoute}
|
|
300
302
|
contentStyle={contentStyle}
|
|
301
303
|
key={scenes[to.index].key}
|
|
302
304
|
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
305
|
+
screenData={screenData}
|
|
303
306
|
>
|
|
304
307
|
{scenes[to.index].children}
|
|
305
308
|
</Scene>
|
|
@@ -319,12 +322,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
319
322
|
<Scene
|
|
320
323
|
key={scenes[from.index].key}
|
|
321
324
|
pathname={scenes[from.index].key}
|
|
325
|
+
isActive={scenes[from.index].key === this.props.navigator.currentRoute}
|
|
322
326
|
style={from.style}
|
|
323
327
|
pointerEvents="none"
|
|
324
328
|
overlayStyle={from.overlayStyle}
|
|
325
329
|
animating={this.state.animating}
|
|
326
330
|
contentStyle={contentStyle}
|
|
327
331
|
screenUniqueId={scenes[from.index].screenUniqueId}
|
|
332
|
+
screenData={scenes[from.index].children.props.screenData}
|
|
328
333
|
>
|
|
329
334
|
{scenes[from.index].children}
|
|
330
335
|
</Scene>
|
|
@@ -333,12 +338,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
333
338
|
const toScene = scenes[to.index] && (
|
|
334
339
|
<Scene
|
|
335
340
|
pathname={scenes[to.index].key}
|
|
341
|
+
isActive={scenes[to.index].key === this.props.navigator.currentRoute}
|
|
336
342
|
key={scenes[to.index].key}
|
|
337
343
|
style={to.style}
|
|
338
344
|
overlayStyle={to.overlayStyle}
|
|
339
345
|
animating={this.state.animating}
|
|
340
346
|
contentStyle={contentStyle}
|
|
341
347
|
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
348
|
+
screenData={this.props.children.props.screenData}
|
|
342
349
|
>
|
|
343
350
|
{scenes[to.index].children}
|
|
344
351
|
</Scene>
|
|
@@ -21,7 +21,9 @@ exports[`<Scene /> renders correctly 1`] = `
|
|
|
21
21
|
]
|
|
22
22
|
}
|
|
23
23
|
>
|
|
24
|
-
<ContextProvider
|
|
24
|
+
<ContextProvider>
|
|
25
|
+
<ContextProvider />
|
|
26
|
+
</ContextProvider>
|
|
25
27
|
</ForwardRef(AnimatedComponentWrapper)>
|
|
26
28
|
`;
|
|
27
29
|
|
|
@@ -43,7 +45,9 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
|
|
|
43
45
|
]
|
|
44
46
|
}
|
|
45
47
|
>
|
|
46
|
-
<ContextProvider
|
|
48
|
+
<ContextProvider>
|
|
49
|
+
<ContextProvider />
|
|
50
|
+
</ContextProvider>
|
|
47
51
|
<ForwardRef(AnimatedComponentWrapper)
|
|
48
52
|
style={
|
|
49
53
|
Object {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { setUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
|
|
7
7
|
import { loggerLiveImageManager } from "./loggerHelper";
|
|
8
8
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
9
|
+
import { Component } from "react";
|
|
9
10
|
|
|
10
11
|
const { log_debug, log_info, log_error } = loggerLiveImageManager;
|
|
11
12
|
|
|
@@ -36,7 +37,8 @@ type Position = {
|
|
|
36
37
|
type LiveImageProps = {
|
|
37
38
|
player: Player;
|
|
38
39
|
playerId: string;
|
|
39
|
-
setMode
|
|
40
|
+
setMode?: (type: LiveImageType) => void;
|
|
41
|
+
component: Component;
|
|
40
42
|
// TODO: ...primary, powerCell, tvGallery, etc.
|
|
41
43
|
// type: string;
|
|
42
44
|
};
|
|
@@ -164,7 +166,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
164
166
|
|
|
165
167
|
// Fake close event, because we unmount native view
|
|
166
168
|
item.player?.onPlayerClose();
|
|
167
|
-
item.setMode(LiveImageType.Image);
|
|
169
|
+
item.setMode?.(LiveImageType.Image);
|
|
168
170
|
|
|
169
171
|
if (item === this.currentlyPlaying) {
|
|
170
172
|
this.currentlyPlaying = null;
|
|
@@ -191,8 +193,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
this.currentlyPlaying = item;
|
|
194
|
-
|
|
195
|
-
item.setMode(LiveImageType.Video);
|
|
196
|
+
item.setMode?.(LiveImageType.Video);
|
|
196
197
|
|
|
197
198
|
if (item.player.playerState.isReadyToPlay) {
|
|
198
199
|
item.player.play();
|
|
@@ -209,6 +210,11 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
209
210
|
this.pauseItem(item);
|
|
210
211
|
};
|
|
211
212
|
|
|
213
|
+
public onLiveImageCompleted = (_item: LiveImage) => {
|
|
214
|
+
// TODO: Notify listeners that player has died
|
|
215
|
+
// Do not try look for new playable, otherwise you will restart video finish to play
|
|
216
|
+
};
|
|
217
|
+
|
|
212
218
|
public muteAll = () => {
|
|
213
219
|
log_debug("muteAll");
|
|
214
220
|
|
|
@@ -235,6 +241,14 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
235
241
|
const playerItem = this.findNextPlayableItem();
|
|
236
242
|
|
|
237
243
|
if (playerItem) {
|
|
244
|
+
if (!playerItem.isFullyVisible) {
|
|
245
|
+
log_error(
|
|
246
|
+
`checkPlayerPosition: trying to start playback currently invisible item: ${playerInfo(
|
|
247
|
+
playerItem.player
|
|
248
|
+
)}`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
238
252
|
// Will also check if it's item that already playing
|
|
239
253
|
this.playLiveImage(playerItem);
|
|
240
254
|
}
|
|
@@ -242,7 +256,6 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
242
256
|
|
|
243
257
|
onPrimaryPlayerClosed = () => {
|
|
244
258
|
const playerItem = this.findNextPlayableItem();
|
|
245
|
-
|
|
246
259
|
log_info("onPrimaryPlayerClosed: starting to play visible live-image");
|
|
247
260
|
|
|
248
261
|
this.currentlyPlaying = null;
|
|
@@ -338,6 +351,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
338
351
|
item,
|
|
339
352
|
playerId: this.currentlyPlaying?.playerId,
|
|
340
353
|
primaryPlayerId: this.primaryPlayer?.playerId,
|
|
354
|
+
entry: item.getPlayer().getEntry(),
|
|
341
355
|
},
|
|
342
356
|
});
|
|
343
357
|
};
|
|
@@ -356,12 +370,12 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
356
370
|
// TODO: This branch was used when we had play button to toggle replay.
|
|
357
371
|
// Now we mute button instead but we keep it just in case.
|
|
358
372
|
if (IS_ALLOWED_REPLAY && !isTV() && isCurrentItemEnded) {
|
|
359
|
-
this.currentlyPlaying
|
|
360
|
-
this.currentlyPlaying
|
|
373
|
+
this.currentlyPlaying?.player.seekTo(0);
|
|
374
|
+
this.currentlyPlaying?.player.pause();
|
|
361
375
|
|
|
362
376
|
// TODO: ...Maybe player some other item
|
|
363
377
|
} else {
|
|
364
|
-
item.setMode(LiveImageType.Image);
|
|
378
|
+
item.setMode?.(LiveImageType.Image);
|
|
365
379
|
}
|
|
366
380
|
|
|
367
381
|
// Prevent receiving onEnd event from both `close` and `end` player events
|
|
@@ -372,15 +386,31 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
372
386
|
item,
|
|
373
387
|
playerId: this.currentlyPlaying?.playerId,
|
|
374
388
|
primaryPlayerId: this.primaryPlayer?.playerId,
|
|
389
|
+
entry: item.getPlayer().getEntry(),
|
|
375
390
|
},
|
|
376
391
|
});
|
|
377
392
|
};
|
|
378
393
|
|
|
379
394
|
onLiveImageError = (item: LiveImage, error: Error) => {
|
|
380
|
-
item.setMode(LiveImageType.Image);
|
|
395
|
+
item.setMode?.(LiveImageType.Image);
|
|
381
396
|
|
|
382
|
-
|
|
397
|
+
const currentItem = this.currentlyPlaying;
|
|
398
|
+
|
|
399
|
+
log_debug(
|
|
400
|
+
`onLiveImageError: error: ${error.message}, live-image ${playerInfo(
|
|
401
|
+
item.player
|
|
402
|
+
)}, currentPlayingId: ${
|
|
403
|
+
this.currentlyPlaying?.playerId
|
|
404
|
+
}, primaryPlayerId: ${this.primaryPlayer?.playerId}`
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
if (currentItem === item) {
|
|
383
408
|
this.currentlyPlaying = null;
|
|
409
|
+
|
|
410
|
+
log_debug(
|
|
411
|
+
`onLiveImageError: currentitem: ${currentItem.playerId} was removed`
|
|
412
|
+
);
|
|
413
|
+
|
|
384
414
|
// TODO: ...Maybe player some other item
|
|
385
415
|
}
|
|
386
416
|
|
|
@@ -389,8 +419,9 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
389
419
|
event: {
|
|
390
420
|
item,
|
|
391
421
|
error,
|
|
392
|
-
playerId:
|
|
393
|
-
primaryPlayerId:
|
|
422
|
+
playerId: currentItem?.playerId,
|
|
423
|
+
primaryPlayerId: currentItem?.playerId,
|
|
424
|
+
entry: item.getPlayer().getEntry(),
|
|
394
425
|
},
|
|
395
426
|
});
|
|
396
427
|
};
|
|
@@ -446,12 +477,13 @@ export class LiveImage implements QuickBrickPlayer.SharedPlayerCallBacks {
|
|
|
446
477
|
};
|
|
447
478
|
|
|
448
479
|
readonly playerId: string;
|
|
480
|
+
readonly component: Component;
|
|
449
481
|
|
|
450
482
|
constructor(props: LiveImageProps) {
|
|
451
483
|
this.player = props.player;
|
|
452
484
|
this.setMode = props.setMode;
|
|
453
485
|
this.playerId = this.player.playerId;
|
|
454
|
-
|
|
486
|
+
this.component = props.component;
|
|
455
487
|
this.player.addListener({ id: "live-image", listener: this });
|
|
456
488
|
}
|
|
457
489
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// /// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
//
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import * as R from "ramda";
|
|
5
4
|
|
|
6
5
|
import { AppState, AppStateStatus } from "react-native";
|
|
7
6
|
import { TrackedView } from "../TrackedView";
|
|
@@ -9,14 +8,13 @@ import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/l
|
|
|
9
8
|
|
|
10
9
|
import { playerFactory } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
|
|
11
10
|
|
|
12
|
-
import { BufferAnimation } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/BufferAnimation";
|
|
13
11
|
import {
|
|
14
12
|
isApplePlatform,
|
|
15
13
|
isTV,
|
|
16
14
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
17
15
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
|
|
18
16
|
import { getUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
|
|
19
|
-
import
|
|
17
|
+
import Image from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/Image";
|
|
20
18
|
import { LiveImage, LiveImageManager, LiveImageType } from "./LiveImageManager";
|
|
21
19
|
|
|
22
20
|
import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
|
|
@@ -25,12 +23,13 @@ import { loggerLiveImageComponent } from "./loggerHelper";
|
|
|
25
23
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
26
24
|
import { PlayerRole } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/conts";
|
|
27
25
|
import { getAutoplaySettings } from "./utils";
|
|
26
|
+
import { isString } from "@applicaster/zapp-react-native-utils/stringUtils";
|
|
27
|
+
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
28
28
|
|
|
29
29
|
const { log_error } = loggerLiveImageComponent;
|
|
30
30
|
|
|
31
|
-
const isMeasurement = (item) =>
|
|
32
|
-
|
|
33
|
-
};
|
|
31
|
+
const isMeasurement = (item: ZappEntry) =>
|
|
32
|
+
isString(item.id) && item.id.startsWith("pre-measurement-");
|
|
34
33
|
|
|
35
34
|
type Props = {
|
|
36
35
|
item: ZappEntry;
|
|
@@ -40,12 +39,13 @@ type Props = {
|
|
|
40
39
|
imageKey?: string;
|
|
41
40
|
screenConfig: Record<string, any>;
|
|
42
41
|
audioMutedByDefault?: boolean;
|
|
42
|
+
uri: string; // cover image url
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const PlayerLiveImageComponent = (props: Props) => {
|
|
46
46
|
const dimensions = useDimensions("screen", { fullDimensions: true });
|
|
47
47
|
|
|
48
|
-
const { item, style, playerId
|
|
48
|
+
const { item, style, playerId } = props;
|
|
49
49
|
|
|
50
50
|
const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
|
|
51
51
|
const [mode, setMode] = React.useState(LiveImageType.Image);
|
|
@@ -55,20 +55,17 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
55
55
|
isTV() ? false : getUserCellPlayerMutedPreference(props.audioMutedByDefault)
|
|
56
56
|
);
|
|
57
57
|
|
|
58
|
-
const [PlayerViewComponent, setPlayerViewComponent] = React.useState(null);
|
|
59
|
-
const Player: any = PlayerViewComponent || BufferAnimation;
|
|
60
|
-
|
|
61
58
|
const ref = React.useRef(null);
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Debounced setMode function.
|
|
62
|
+
*
|
|
63
|
+
* Sets to video with a 1sec delay. Set to image happens immediately and cancels the timeout.
|
|
64
|
+
*
|
|
65
|
+
* @param type video or image
|
|
66
|
+
*/
|
|
67
|
+
const setModeDebounced = React.useCallback(
|
|
68
|
+
(type: LiveImageType) => {
|
|
72
69
|
if (type === LiveImageType.Video) {
|
|
73
70
|
if (type === mode) {
|
|
74
71
|
return;
|
|
@@ -80,45 +77,45 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
80
77
|
} else {
|
|
81
78
|
if (timeoutRef.current) {
|
|
82
79
|
clearTimeout(timeoutRef.current);
|
|
80
|
+
timeoutRef.current = null;
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
setMode(type);
|
|
86
84
|
}
|
|
87
|
-
}
|
|
85
|
+
},
|
|
86
|
+
[mode]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const { screenConfig, playerPluginId } = props;
|
|
88
90
|
|
|
91
|
+
const liveImageItem: LiveImage = React.useMemo(() => {
|
|
89
92
|
const playerFactoryItem = playerFactory({
|
|
90
93
|
player: ref,
|
|
91
|
-
listener: props as Record<string, any>,
|
|
92
94
|
playerId,
|
|
93
95
|
autoplay: false,
|
|
94
96
|
entry: item,
|
|
95
|
-
muted,
|
|
96
|
-
playerPluginId:
|
|
97
|
-
screenConfig:
|
|
97
|
+
muted, // Initial muted state, not needed in dependencies
|
|
98
|
+
playerPluginId: playerPluginId,
|
|
99
|
+
screenConfig: screenConfig,
|
|
98
100
|
playerRole: PlayerRole.Cell,
|
|
99
101
|
});
|
|
100
102
|
|
|
101
|
-
const Component = playerFactoryItem?.Component;
|
|
102
|
-
|
|
103
|
-
if (!R.isNil(Component) && Component !== PlayerViewComponent) {
|
|
104
|
-
setPlayerViewComponent(Component);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
103
|
if (playerFactoryItem) {
|
|
108
104
|
return new LiveImage({
|
|
109
105
|
playerId,
|
|
110
106
|
player: playerFactoryItem.controller,
|
|
111
|
-
|
|
107
|
+
component: playerFactoryItem?.Component,
|
|
112
108
|
});
|
|
113
109
|
} else {
|
|
114
110
|
throw new Error("Player factory item is null");
|
|
115
111
|
}
|
|
116
|
-
}, [playerId, item
|
|
112
|
+
}, [playerId, item, playerPluginId, screenConfig]);
|
|
117
113
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
React.useEffect(() => {
|
|
115
|
+
liveImageItem.setMode = setModeDebounced;
|
|
116
|
+
}, [setModeDebounced, liveImageItem]);
|
|
117
|
+
|
|
118
|
+
const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
|
|
122
119
|
|
|
123
120
|
const controller = liveImageItem.getPlayer();
|
|
124
121
|
const player = usePlayer(playerId);
|
|
@@ -127,6 +124,10 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
127
124
|
ref.current = component;
|
|
128
125
|
};
|
|
129
126
|
|
|
127
|
+
const onLiveImageCompleted = React.useCallback(() => {
|
|
128
|
+
LiveImageManager.instance.onLiveImageCompleted(liveImageItem);
|
|
129
|
+
}, [liveImageItem]);
|
|
130
|
+
|
|
130
131
|
const onStop = React.useCallback(() => {
|
|
131
132
|
LiveImageManager.instance.pauseLiveImage(liveImageItem);
|
|
132
133
|
}, [liveImageItem]);
|
|
@@ -140,13 +141,14 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
140
141
|
const unregister = LiveImageManager.instance.register(liveImageItem);
|
|
141
142
|
|
|
142
143
|
return () => {
|
|
143
|
-
unregister();
|
|
144
|
-
|
|
145
144
|
if (timeoutRef.current) {
|
|
146
145
|
clearTimeout(timeoutRef.current);
|
|
146
|
+
timeoutRef.current = null;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
unregister();
|
|
148
150
|
};
|
|
149
|
-
}, [
|
|
151
|
+
}, [item, liveImageItem]);
|
|
150
152
|
|
|
151
153
|
React.useEffect(() => {
|
|
152
154
|
if (!player) {
|
|
@@ -178,11 +180,12 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
178
180
|
setMuted(false);
|
|
179
181
|
},
|
|
180
182
|
onPlayerClose: () => {
|
|
183
|
+
onLiveImageCompleted();
|
|
181
184
|
setIsReady(false);
|
|
182
185
|
},
|
|
183
186
|
},
|
|
184
187
|
});
|
|
185
|
-
}, [player, onStop]);
|
|
188
|
+
}, [player, onStop, onLiveImageCompleted, start, end]);
|
|
186
189
|
|
|
187
190
|
React.useEffect(() => {
|
|
188
191
|
const subscription = AppState.addEventListener(
|
|
@@ -233,40 +236,48 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
233
236
|
};
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
|
-
}, [liveImageItem]);
|
|
237
|
-
|
|
238
|
-
const onPositionUpdated = (
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
}, [liveImageItem, playerId, controller]);
|
|
240
|
+
|
|
241
|
+
const onPositionUpdated = React.useCallback(
|
|
242
|
+
(data) => {
|
|
243
|
+
const normalizedRect = (rect: {
|
|
244
|
+
left: number;
|
|
245
|
+
right: number;
|
|
246
|
+
top: number;
|
|
247
|
+
bottom: number;
|
|
248
|
+
}) => {
|
|
249
|
+
if (!rect) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
243
252
|
|
|
244
|
-
|
|
253
|
+
const { left, right, top, bottom } = rect;
|
|
245
254
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
255
|
+
return {
|
|
256
|
+
left: left / dimensions.width,
|
|
257
|
+
right: right / dimensions.width,
|
|
258
|
+
top: top / dimensions.height,
|
|
259
|
+
bottom: bottom / dimensions.height,
|
|
260
|
+
centerX: (left + right) / 2 / dimensions.width,
|
|
261
|
+
centerY: (top + bottom) / 2 / dimensions.height,
|
|
262
|
+
};
|
|
253
263
|
};
|
|
254
|
-
};
|
|
255
264
|
|
|
256
|
-
|
|
265
|
+
liveImageItem.position = normalizedRect(data.rect);
|
|
257
266
|
|
|
258
|
-
|
|
267
|
+
const newIsFullyVisible = !!data.rect;
|
|
259
268
|
|
|
260
|
-
|
|
261
|
-
|
|
269
|
+
if (liveImageItem.isFullyVisible !== newIsFullyVisible) {
|
|
270
|
+
liveImageItem.isFullyVisible = newIsFullyVisible;
|
|
262
271
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
272
|
+
liveImageItem.isFullyVisible
|
|
273
|
+
? LiveImageManager.instance.onViewportEnter(liveImageItem)
|
|
274
|
+
: LiveImageManager.instance.onViewportLeave(liveImageItem);
|
|
275
|
+
} else {
|
|
276
|
+
LiveImageManager.instance.checkPlayerPosition(liveImageItem);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
[liveImageItem, dimensions]
|
|
280
|
+
);
|
|
270
281
|
|
|
271
282
|
const platformSpecificProps = isApplePlatform()
|
|
272
283
|
? { hideNativeControls: true, controls: false }
|
|
@@ -276,7 +287,9 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
276
287
|
const isVideoMode = mode === LiveImageType.Video;
|
|
277
288
|
const isBackgroundImageVisible = isImageMode || !isReadyToPlay;
|
|
278
289
|
const videoStyles = { ...style, position: "absolute", zIndex: -100 };
|
|
290
|
+
const Player: any = liveImageItem.component || BufferAnimation;
|
|
279
291
|
|
|
292
|
+
// TODO: nice to have - resolve imageKey when imageUrl is not provided
|
|
280
293
|
return (
|
|
281
294
|
<TrackedView
|
|
282
295
|
testId={`tracked-view-${playerId}-${item.title}`}
|
|
@@ -301,11 +314,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
301
314
|
animationConfig={overlayFadeIn}
|
|
302
315
|
staticStyles={style}
|
|
303
316
|
>
|
|
304
|
-
<
|
|
305
|
-
entry={item}
|
|
306
|
-
style={style}
|
|
307
|
-
imageKey={imageKey}
|
|
308
|
-
/>
|
|
317
|
+
<Image {...props} resizeMode="cover" style={style} applyMaxSize />
|
|
309
318
|
</AnimatedInOut>
|
|
310
319
|
}
|
|
311
320
|
</TrackedView>
|