@applicaster/zapp-react-native-ui-components 14.0.0-alpha.3126393935 → 14.0.0-alpha.3140225604
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/Cell/Cell.tsx +8 -3
- package/Components/Focusable/Focusable.tsx +5 -3
- package/Components/HandlePlayable/HandlePlayable.tsx +11 -1
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -27
- package/Components/MasterCell/utils/behaviorProvider.ts +14 -82
- package/Components/MasterCell/utils/index.ts +3 -23
- package/Components/PlayerContainer/PlayerContainer.tsx +15 -6
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
- package/Components/TextInputTv/index.tsx +11 -0
- package/Components/Transitioner/Scene.tsx +0 -1
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +9 -1
- package/Components/VideoModal/PlayerDetails.tsx +24 -2
- package/Components/VideoModal/PlayerWrapper.tsx +26 -142
- package/Components/VideoModal/VideoModal.tsx +3 -17
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -7
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -240
- package/Components/VideoModal/hooks/index.ts +0 -2
- package/Components/VideoModal/hooks/useModalSize.ts +18 -2
- package/Components/VideoModal/utils.ts +6 -0
- package/Contexts/ScreenDataContext/index.tsx +0 -2
- package/Decorators/RiverFeedLoader/index.tsx +2 -8
- package/Decorators/RiverFeedLoader/utils/index.ts +2 -7
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -20
- package/package.json +5 -8
- package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -70,6 +70,8 @@ type State = {
|
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
export class CellComponent extends React.Component<Props, State> {
|
|
73
|
+
accessibilityManager: AccessibilityManager;
|
|
74
|
+
|
|
73
75
|
constructor(props) {
|
|
74
76
|
super(props);
|
|
75
77
|
this.onPress = this.onPress.bind(this);
|
|
@@ -83,6 +85,8 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
83
85
|
this.state = {
|
|
84
86
|
hasFocusableInside: props.CellRenderer.hasFocusableInside?.(props.item),
|
|
85
87
|
};
|
|
88
|
+
|
|
89
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
setScreenLayout(componentAnchorPointY, screenLayout) {
|
|
@@ -257,20 +261,21 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
257
261
|
style={styles.baseCell}
|
|
258
262
|
isFocusable={isFocusable}
|
|
259
263
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
264
|
+
{...this.accessibilityManager.getButtonAccessibilityProps(
|
|
265
|
+
item?.extensions?.accessibility?.label || item?.title
|
|
266
|
+
)}
|
|
260
267
|
>
|
|
261
268
|
{(focused, event) => {
|
|
262
269
|
const isFocused = this.isCellFocused(focused);
|
|
263
270
|
|
|
264
271
|
if (isFocused) {
|
|
265
|
-
const accessibilityManager = AccessibilityManager.getInstance();
|
|
266
|
-
|
|
267
272
|
const accessibilityTitle =
|
|
268
273
|
item?.extensions?.accessibility?.label || item?.title || "";
|
|
269
274
|
|
|
270
275
|
const accessibilityHint =
|
|
271
276
|
item?.extensions?.accessibility?.hint || "";
|
|
272
277
|
|
|
273
|
-
accessibilityManager.readText({
|
|
278
|
+
this.accessibilityManager.readText({
|
|
274
279
|
text: `${accessibilityTitle} ${accessibilityHint}`,
|
|
275
280
|
});
|
|
276
281
|
}
|
|
@@ -5,6 +5,7 @@ import { BaseFocusable } from "../BaseFocusable";
|
|
|
5
5
|
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
|
|
6
6
|
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
7
7
|
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
|
|
8
|
+
import { StyleSheet, ViewStyle } from "react-native";
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
10
11
|
initialFocus?: boolean;
|
|
@@ -21,7 +22,7 @@ type Props = {
|
|
|
21
22
|
handleFocus?: ({ mouse }: { mouse: boolean }) => void;
|
|
22
23
|
children: (boolean, string) => React.ComponentType<any>;
|
|
23
24
|
selected?: boolean;
|
|
24
|
-
style?:
|
|
25
|
+
style?: ViewStyle[] | ViewStyle;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
class Focusable extends BaseFocusable<Props> {
|
|
@@ -122,7 +123,7 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
render() {
|
|
125
|
-
const { children, style } = this.props;
|
|
126
|
+
const { children, style, ...otherProps } = this.props;
|
|
126
127
|
const { focused } = this.state;
|
|
127
128
|
|
|
128
129
|
const id = this.getId();
|
|
@@ -139,7 +140,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
139
140
|
onMouseUp={this.pressOut}
|
|
140
141
|
data-testid={focusableId}
|
|
141
142
|
focused-teststate={focused ? "focused" : "default"}
|
|
142
|
-
style={style}
|
|
143
|
+
style={StyleSheet.flatten(style) as any as React.CSSProperties}
|
|
144
|
+
{...otherProps}
|
|
143
145
|
>
|
|
144
146
|
{children(focused, { mouse: this.mouse })}
|
|
145
147
|
</div>
|
|
@@ -7,12 +7,14 @@ import {
|
|
|
7
7
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
8
8
|
import {
|
|
9
9
|
useDimensions,
|
|
10
|
+
useIsTablet as isTablet,
|
|
10
11
|
useNavigation,
|
|
11
12
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
13
|
|
|
13
14
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
14
15
|
import { PlayerContainer } from "../PlayerContainer";
|
|
15
16
|
import { useModalSize } from "../VideoModal/hooks";
|
|
17
|
+
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
16
18
|
|
|
17
19
|
type Props = {
|
|
18
20
|
item: ZappEntry;
|
|
@@ -83,6 +85,13 @@ type PlayableComponent = {
|
|
|
83
85
|
Component: React.ComponentType<any>;
|
|
84
86
|
};
|
|
85
87
|
|
|
88
|
+
const dimensionsContext: "window" | "screen" = platformSelect({
|
|
89
|
+
android_tv: "window",
|
|
90
|
+
amazon: "window",
|
|
91
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
92
|
+
default: isTablet() ? "window" : "screen", // on tablet, window represents correct values, on phone it's not as the screen could be rotated
|
|
93
|
+
});
|
|
94
|
+
|
|
86
95
|
export function HandlePlayable({
|
|
87
96
|
item,
|
|
88
97
|
isModal,
|
|
@@ -135,7 +144,8 @@ export function HandlePlayable({
|
|
|
135
144
|
});
|
|
136
145
|
}, [casting]);
|
|
137
146
|
|
|
138
|
-
const { width: screenWidth, height: screenHeight } =
|
|
147
|
+
const { width: screenWidth, height: screenHeight } =
|
|
148
|
+
useDimensions(dimensionsContext);
|
|
139
149
|
|
|
140
150
|
const modalSize = useModalSize();
|
|
141
151
|
|
|
@@ -2,7 +2,6 @@ import React, { useMemo } from "react";
|
|
|
2
2
|
import { ImageStyle } from "react-native";
|
|
3
3
|
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
|
|
4
4
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
|
-
import * as R from "ramda";
|
|
6
5
|
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
|
|
7
6
|
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
8
7
|
import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
|
|
@@ -67,32 +66,10 @@ export function FocusableView({ style, children, item, ...otherProps }: Props) {
|
|
|
67
66
|
const handleFocus = (focusable) => {
|
|
68
67
|
const focusedButtonId = getFocusedButtonId(focusable);
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const right = left + width;
|
|
75
|
-
|
|
76
|
-
const boundingRect = {
|
|
77
|
-
x,
|
|
78
|
-
y,
|
|
79
|
-
pageX,
|
|
80
|
-
pageY,
|
|
81
|
-
width,
|
|
82
|
-
height,
|
|
83
|
-
top,
|
|
84
|
-
bottom,
|
|
85
|
-
left,
|
|
86
|
-
right,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
otherProps?.onToggleFocus?.({
|
|
90
|
-
focusable: {
|
|
91
|
-
getRect: R.always(boundingRect),
|
|
92
|
-
},
|
|
93
|
-
focusedButtonId,
|
|
94
|
-
mouse: focusable.mouse,
|
|
95
|
-
});
|
|
69
|
+
otherProps?.onToggleFocus?.({
|
|
70
|
+
focusable: wrapperRef.current,
|
|
71
|
+
focusedButtonId,
|
|
72
|
+
mouse: focusable.mouse,
|
|
96
73
|
});
|
|
97
74
|
|
|
98
75
|
if (ttsLabel) {
|
|
@@ -1,58 +1,28 @@
|
|
|
1
1
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
2
|
-
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-
|
|
2
|
+
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
|
|
3
3
|
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
4
|
-
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-
|
|
4
|
+
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
5
5
|
import React, { useEffect } from "react";
|
|
6
6
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
7
7
|
import { BehaviorSubject } from "rxjs";
|
|
8
8
|
import { masterCellLogger } from "../logger";
|
|
9
9
|
import get from "lodash/get";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const parseContextKey = (
|
|
16
|
-
key: string,
|
|
17
|
-
context: string = "ctx"
|
|
18
|
-
): string | null => {
|
|
19
|
-
if (!key?.startsWith(`@{${context}/`)) return null;
|
|
20
|
-
|
|
21
|
-
return key.substring(`@{${context}/`.length, key.length - 1);
|
|
10
|
+
|
|
11
|
+
const parseContextKey = (key: string): string | null => {
|
|
12
|
+
if (!key?.startsWith("@{ctx/")) return null;
|
|
13
|
+
|
|
14
|
+
return key.substring("@{ctx/".length, key.length - 1);
|
|
22
15
|
};
|
|
23
16
|
|
|
24
17
|
const getDataSourceProvider = (
|
|
25
|
-
behavior: Behavior
|
|
26
|
-
screenRoute: string,
|
|
27
|
-
screenStateStore: ScreenStateStore
|
|
18
|
+
behavior: Behavior
|
|
28
19
|
): BehaviorSubject<string[] | string> | null => {
|
|
29
20
|
if (!behavior) return null;
|
|
30
21
|
|
|
31
22
|
const selection = String(behavior.current_selection);
|
|
32
|
-
const screenKey = parseContextKey(selection, "screen");
|
|
33
|
-
|
|
34
|
-
if (screenKey) {
|
|
35
|
-
if (behavior.select_mode === "multi") {
|
|
36
|
-
return ScreenMultiSelectProvider.getProvider(
|
|
37
|
-
screenKey,
|
|
38
|
-
screenRoute,
|
|
39
|
-
screenStateStore
|
|
40
|
-
).getObservable();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (behavior.select_mode === "single") {
|
|
44
|
-
return ScreenSingleValueProvider.getProvider(
|
|
45
|
-
screenKey,
|
|
46
|
-
screenRoute,
|
|
47
|
-
screenStateStore
|
|
48
|
-
).getObservable();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
23
|
const contextKey = parseContextKey(selection);
|
|
53
24
|
|
|
54
25
|
if (contextKey) {
|
|
55
|
-
// TODO: Add storage scope to behavior
|
|
56
26
|
if (behavior.select_mode === "multi") {
|
|
57
27
|
return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
|
|
58
28
|
}
|
|
@@ -71,8 +41,6 @@ const getDataSourceProvider = (
|
|
|
71
41
|
|
|
72
42
|
export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
73
43
|
const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
|
|
74
|
-
const screenRoute = useRoute()?.pathname || "";
|
|
75
|
-
const screenStateStore = useScreenStateStore();
|
|
76
44
|
const player = usePlayer();
|
|
77
45
|
|
|
78
46
|
const triggerUpdate = () => setLastUpdate(Date.now());
|
|
@@ -80,11 +48,7 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
80
48
|
useEffect(() => {
|
|
81
49
|
if (!behavior) return;
|
|
82
50
|
|
|
83
|
-
const dataSource = getDataSourceProvider(
|
|
84
|
-
behavior,
|
|
85
|
-
screenRoute,
|
|
86
|
-
screenStateStore
|
|
87
|
-
);
|
|
51
|
+
const dataSource = getDataSourceProvider(behavior);
|
|
88
52
|
|
|
89
53
|
if (dataSource) {
|
|
90
54
|
const subscription = dataSource.subscribe(triggerUpdate);
|
|
@@ -108,17 +72,10 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
108
72
|
|
|
109
73
|
// We cant use async in this function (its inside render),
|
|
110
74
|
// so we rely on useBehaviorUpdate to update current value and trigger re-render
|
|
111
|
-
export const isCellSelected = (
|
|
112
|
-
item,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
behavior,
|
|
116
|
-
}: {
|
|
117
|
-
item: ZappEntry;
|
|
118
|
-
screenRoute: string;
|
|
119
|
-
screenStateStore: ScreenStateStore;
|
|
120
|
-
behavior?: Behavior;
|
|
121
|
-
}): boolean => {
|
|
75
|
+
export const isCellSelected = (
|
|
76
|
+
item: ZappEntry,
|
|
77
|
+
behavior?: Behavior
|
|
78
|
+
): boolean => {
|
|
122
79
|
if (!behavior) return false;
|
|
123
80
|
|
|
124
81
|
const id = behavior.selector ? get(item, behavior.selector) : item.id;
|
|
@@ -142,32 +99,7 @@ export const isCellSelected = ({
|
|
|
142
99
|
}
|
|
143
100
|
|
|
144
101
|
const selection = String(behavior.current_selection);
|
|
145
|
-
|
|
146
|
-
const screenKey = parseContextKey(selection, "screen");
|
|
147
|
-
|
|
148
|
-
if (screenKey) {
|
|
149
|
-
if (behavior.select_mode === "single") {
|
|
150
|
-
const selectedItem = ScreenSingleValueProvider.getProvider(
|
|
151
|
-
screenKey,
|
|
152
|
-
screenRoute,
|
|
153
|
-
screenStateStore
|
|
154
|
-
).getValue();
|
|
155
|
-
|
|
156
|
-
return selectedItem === String(id);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (behavior.select_mode === "multi") {
|
|
160
|
-
const selectedItems = ScreenMultiSelectProvider.getProvider(
|
|
161
|
-
screenKey,
|
|
162
|
-
screenRoute,
|
|
163
|
-
screenStateStore
|
|
164
|
-
).getSelectedItems();
|
|
165
|
-
|
|
166
|
-
return selectedItems?.includes(String(id));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const contextKey = parseContextKey(selection, "ctx");
|
|
102
|
+
const contextKey = parseContextKey(selection);
|
|
171
103
|
|
|
172
104
|
if (contextKey) {
|
|
173
105
|
if (behavior.select_mode === "single") {
|
|
@@ -8,8 +8,6 @@ import { masterCellLogger } from "../logger";
|
|
|
8
8
|
import { getCellState } from "../../Cell/utils";
|
|
9
9
|
import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
10
|
import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
|
|
11
|
-
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
|
-
import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
|
|
13
11
|
|
|
14
12
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
15
13
|
if (R.isNil(element)) {
|
|
@@ -192,18 +190,8 @@ export const getFocusedButtonId = (focusable) => {
|
|
|
192
190
|
});
|
|
193
191
|
};
|
|
194
192
|
|
|
195
|
-
export const isSelected = ({
|
|
196
|
-
item,
|
|
197
|
-
screenRoute,
|
|
198
|
-
screenStateStore,
|
|
199
|
-
behavior,
|
|
200
|
-
}: {
|
|
201
|
-
item: ZappEntry;
|
|
202
|
-
screenRoute: string;
|
|
203
|
-
screenStateStore: ScreenStateStore;
|
|
204
|
-
behavior?: Behavior;
|
|
205
|
-
}) => {
|
|
206
|
-
return isCellSelected({ item, screenRoute, screenStateStore, behavior });
|
|
193
|
+
export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
|
|
194
|
+
return isCellSelected(item, behavior);
|
|
207
195
|
};
|
|
208
196
|
|
|
209
197
|
export const useCellState = ({
|
|
@@ -216,17 +204,9 @@ export const useCellState = ({
|
|
|
216
204
|
focused: boolean;
|
|
217
205
|
}): CellState => {
|
|
218
206
|
const lastUpdate = useBehaviorUpdate(behavior);
|
|
219
|
-
const router = useRoute();
|
|
220
|
-
const screenStateStore = useScreenStateStore();
|
|
221
207
|
|
|
222
208
|
const _isSelected = useMemo(
|
|
223
|
-
() =>
|
|
224
|
-
isSelected({
|
|
225
|
-
item,
|
|
226
|
-
screenRoute: router?.pathname,
|
|
227
|
-
screenStateStore,
|
|
228
|
-
behavior,
|
|
229
|
-
}),
|
|
209
|
+
() => isSelected(item, behavior),
|
|
230
210
|
[behavior, item, lastUpdate]
|
|
231
211
|
);
|
|
232
212
|
|
|
@@ -88,7 +88,7 @@ export const VideoModalMode = {
|
|
|
88
88
|
MAXIMIZED: "MAXIMIZED",
|
|
89
89
|
MINIMIZED: "MINIMIZED",
|
|
90
90
|
FULLSCREEN: "FULLSCREEN",
|
|
91
|
-
};
|
|
91
|
+
} as const;
|
|
92
92
|
|
|
93
93
|
export type PlayNextData = {
|
|
94
94
|
state: PlayNextState;
|
|
@@ -127,7 +127,7 @@ const webStyles = {
|
|
|
127
127
|
playerScreen: {
|
|
128
128
|
flex: 1,
|
|
129
129
|
height: "100vh",
|
|
130
|
-
|
|
130
|
+
backgroundColor: "black",
|
|
131
131
|
},
|
|
132
132
|
playerWrapper: {
|
|
133
133
|
height: "100%",
|
|
@@ -145,7 +145,6 @@ const nativeStyles = {
|
|
|
145
145
|
},
|
|
146
146
|
playerScreen: {
|
|
147
147
|
flex: 1,
|
|
148
|
-
backgroundColor: "black",
|
|
149
148
|
overflow: "hidden",
|
|
150
149
|
},
|
|
151
150
|
playerWrapper: {
|
|
@@ -565,8 +564,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
565
564
|
const isInlineTV = isInlineTVUtil(screenData);
|
|
566
565
|
|
|
567
566
|
const inline =
|
|
568
|
-
[VideoModalMode.MAXIMIZED, VideoModalMode.MINIMIZED].includes(
|
|
569
|
-
|
|
567
|
+
[VideoModalMode.MAXIMIZED, VideoModalMode.MINIMIZED].includes(
|
|
568
|
+
mode as any
|
|
569
|
+
) || isInlineTV;
|
|
570
570
|
|
|
571
571
|
const value = React.useMemo(
|
|
572
572
|
() => ({ playerId: state.playerId }),
|
|
@@ -587,7 +587,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
587
587
|
);
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
-
if (
|
|
590
|
+
if (
|
|
591
|
+
screen_background_color &&
|
|
592
|
+
mode !== VideoModalMode.FULLSCREEN &&
|
|
593
|
+
isTV()
|
|
594
|
+
) {
|
|
591
595
|
updatedStyles.playerScreen.backgroundColor = screen_background_color;
|
|
592
596
|
}
|
|
593
597
|
|
|
@@ -617,6 +621,8 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
617
621
|
playNextData,
|
|
618
622
|
};
|
|
619
623
|
|
|
624
|
+
const pointerEventsProp = mode === "MINIMIZED" ? "box-none" : "auto";
|
|
625
|
+
|
|
620
626
|
return (
|
|
621
627
|
<PlayerStateContext.Provider value={value}>
|
|
622
628
|
<PlayerContainerContextProvider
|
|
@@ -637,14 +643,17 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
637
643
|
preferredFocus
|
|
638
644
|
shouldUsePreferredFocus
|
|
639
645
|
groupId={groupId}
|
|
646
|
+
pointerEvents={pointerEventsProp}
|
|
640
647
|
>
|
|
641
648
|
{/* Video player and components */}
|
|
642
649
|
<View
|
|
643
650
|
style={styles.playerScreen}
|
|
644
651
|
testID={"player-screen-container"}
|
|
652
|
+
pointerEvents={pointerEventsProp}
|
|
645
653
|
>
|
|
646
654
|
{/* Player container */}
|
|
647
655
|
<View
|
|
656
|
+
pointerEvents={pointerEventsProp}
|
|
648
657
|
style={[
|
|
649
658
|
styles.playerWrapper,
|
|
650
659
|
// eslint-disable-next-line react-native/no-inline-styles, react-native/no-color-literals
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`<TextInputTv /> renders 1`] = `
|
|
4
4
|
<input
|
|
5
|
+
accessibilityProps={
|
|
6
|
+
{
|
|
7
|
+
"accessibilityHint": "Enter text into Search",
|
|
8
|
+
"accessibilityLabel": "Search",
|
|
9
|
+
"accessibilityRole": "textbox",
|
|
10
|
+
"accessible": true,
|
|
11
|
+
"aria-description": "Enter text into Search",
|
|
12
|
+
"aria-label": "Search",
|
|
13
|
+
"aria-role": "textbox",
|
|
14
|
+
"role": "textbox",
|
|
15
|
+
"tabindex": 0,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
testID="TextInput-tv"
|
|
6
19
|
/>
|
|
7
20
|
`;
|
|
@@ -4,6 +4,7 @@ import { Appearance, Platform, StyleSheet, TextInput } from "react-native";
|
|
|
4
4
|
import { isFunction } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
5
5
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
6
6
|
import { useIsRTL } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
7
|
+
import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
|
|
7
8
|
|
|
8
9
|
type Props = Partial<{
|
|
9
10
|
style: any;
|
|
@@ -42,6 +43,8 @@ function TextInputTV(props: Props, ref) {
|
|
|
42
43
|
const [colorScheme, setColorScheme] = useState(getInitialColorScheme());
|
|
43
44
|
const isRTL = useIsRTL();
|
|
44
45
|
|
|
46
|
+
const accessibilityManager = useAccessibilityManager({});
|
|
47
|
+
|
|
45
48
|
const onColorChange = useCallback(
|
|
46
49
|
({ colorScheme: color }) => {
|
|
47
50
|
if (color !== colorScheme) {
|
|
@@ -153,6 +156,13 @@ function TextInputTV(props: Props, ref) {
|
|
|
153
156
|
])
|
|
154
157
|
)(props);
|
|
155
158
|
|
|
159
|
+
const getAccessibilityProps = () => {
|
|
160
|
+
return {
|
|
161
|
+
accessibilityProps:
|
|
162
|
+
accessibilityManager.getInputAccessibilityProps("Search"),
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
156
166
|
const inputProps = {
|
|
157
167
|
...getProps(),
|
|
158
168
|
...getStyle(),
|
|
@@ -161,6 +171,7 @@ function TextInputTV(props: Props, ref) {
|
|
|
161
171
|
...getSecureTextEntry(),
|
|
162
172
|
...getOnEndEditing(),
|
|
163
173
|
...getOnPress(),
|
|
174
|
+
...getAccessibilityProps(),
|
|
164
175
|
};
|
|
165
176
|
|
|
166
177
|
if (
|
|
@@ -36,7 +36,6 @@ export function CurrentScreenContextProvider({
|
|
|
36
36
|
screenData: NavigationScreenData;
|
|
37
37
|
}) {
|
|
38
38
|
const { pathname, isActive = false, screenData } = props;
|
|
39
|
-
console.log("CurrentScreenContextProvider", { screenData });
|
|
40
39
|
|
|
41
40
|
const [initialScreenData, setInitialScreenData] = React.useState(screenData);
|
|
42
41
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
|
-
import { Animated } from "react-native";
|
|
2
|
+
import { Animated, Dimensions } from "react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
useSafeAreaInsets,
|
|
@@ -23,6 +23,7 @@ export enum PlayerAnimationStateEnum {
|
|
|
23
23
|
export type PlayerAnimationStateT = number | PlayerAnimationStateEnum | null;
|
|
24
24
|
|
|
25
25
|
export type ModalAnimationContextT = {
|
|
26
|
+
yTranslate: React.MutableRefObject<Animated.Value | null>;
|
|
26
27
|
isActiveGesture: boolean;
|
|
27
28
|
playerAnimationState: PlayerAnimationStateT;
|
|
28
29
|
setPlayerAnimationState: (value: PlayerAnimationStateT) => void;
|
|
@@ -48,6 +49,7 @@ export type ModalAnimationContextT = {
|
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
export const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
52
|
+
yTranslate: React.createRef<Animated.Value | null>(),
|
|
51
53
|
isActiveGesture: false,
|
|
52
54
|
playerAnimationState: null,
|
|
53
55
|
setPlayerAnimationState: () => null,
|
|
@@ -73,6 +75,10 @@ export const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
|
73
75
|
});
|
|
74
76
|
|
|
75
77
|
const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
78
|
+
const yTranslate = React.useRef(
|
|
79
|
+
new Animated.Value(Dimensions.get("window").height)
|
|
80
|
+
);
|
|
81
|
+
|
|
76
82
|
const [playerAnimationState, setPlayerAnimationState] =
|
|
77
83
|
React.useState<PlayerAnimationStateT>(null);
|
|
78
84
|
|
|
@@ -100,6 +106,7 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
100
106
|
// Reset player animation state when video modal is closed
|
|
101
107
|
if (!visible) {
|
|
102
108
|
resetPlayerAnimationState();
|
|
109
|
+
yTranslate.current?.setValue(Dimensions.get("window").height);
|
|
103
110
|
}
|
|
104
111
|
}, [visible, resetPlayerAnimationState]);
|
|
105
112
|
|
|
@@ -141,6 +148,7 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
141
148
|
return (
|
|
142
149
|
<ReactContext.Provider
|
|
143
150
|
value={{
|
|
151
|
+
yTranslate,
|
|
144
152
|
startComponentsAnimation,
|
|
145
153
|
setStartComponentsAnimation,
|
|
146
154
|
isActiveGesture: playerAnimationState !== null,
|
|
@@ -11,6 +11,8 @@ import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactH
|
|
|
11
11
|
import { ComponentsMap } from "@applicaster/zapp-react-native-ui-components/Components/River/ComponentsMap";
|
|
12
12
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
13
13
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
14
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
15
|
+
import { useDelayedPlayerDetails } from "./hooks";
|
|
14
16
|
|
|
15
17
|
const { width: SCREEN_WIDTH } = Dimensions.get("screen");
|
|
16
18
|
|
|
@@ -26,6 +28,10 @@ type Props = {
|
|
|
26
28
|
isTabletLandscape?: boolean;
|
|
27
29
|
isAudioPlayer?: boolean;
|
|
28
30
|
isTablet?: boolean;
|
|
31
|
+
inline?: any;
|
|
32
|
+
docked?: boolean;
|
|
33
|
+
isModal?: boolean;
|
|
34
|
+
pip?: boolean;
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
const containerStyle = ({
|
|
@@ -42,8 +48,24 @@ export const PlayerDetails = ({
|
|
|
42
48
|
configuration,
|
|
43
49
|
isTabletLandscape = false,
|
|
44
50
|
isAudioPlayer,
|
|
45
|
-
|
|
51
|
+
inline,
|
|
52
|
+
docked,
|
|
53
|
+
isModal,
|
|
54
|
+
pip,
|
|
46
55
|
}: Props) => {
|
|
56
|
+
const isInlineModal = inline && isModal;
|
|
57
|
+
|
|
58
|
+
// Mounting the PlayerDetails component is a resource-intensive process.
|
|
59
|
+
// Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
|
|
60
|
+
// The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
|
|
61
|
+
// This helps to avoid blocking the rotation and any animations related to the rotation.
|
|
62
|
+
const isShowPlayerDetails = useDelayedPlayerDetails({
|
|
63
|
+
isInline: isInlineModal,
|
|
64
|
+
isDocked: docked,
|
|
65
|
+
isPip: pip,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const isTablet = useIsTablet();
|
|
47
69
|
const screenData = useTargetScreenData(entry);
|
|
48
70
|
const insets = useSafeAreaInsets();
|
|
49
71
|
|
|
@@ -79,7 +101,7 @@ export const PlayerDetails = ({
|
|
|
79
101
|
}
|
|
80
102
|
}, [isAudioPlayer]);
|
|
81
103
|
|
|
82
|
-
if (isNilOrEmpty(screenData?.ui_components)) {
|
|
104
|
+
if (isNilOrEmpty(screenData?.ui_components) || !isShowPlayerDetails) {
|
|
83
105
|
return null;
|
|
84
106
|
}
|
|
85
107
|
|