@applicaster/zapp-react-native-ui-components 14.0.6 → 14.0.7-alpha.2341555313
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/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +107 -10
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +21 -15
- package/Components/Screen/orientationHandler.ts +7 -10
- package/Contexts/ZappHookModalContext/index.tsx +37 -61
- package/Contexts/index.ts +0 -2
- package/package.json +5 -5
|
@@ -4,7 +4,7 @@ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/nu
|
|
|
4
4
|
import { Button } from "./Button";
|
|
5
5
|
import {
|
|
6
6
|
getButtonsCount,
|
|
7
|
-
|
|
7
|
+
memoizedGetPluginIdentifier,
|
|
8
8
|
mapSelfAlignment,
|
|
9
9
|
} from "./utils";
|
|
10
10
|
|
|
@@ -80,7 +80,11 @@ export const TvActionButtons = ({
|
|
|
80
80
|
prefix: independentStyles ? prefixSpecificButton : buttonId(1),
|
|
81
81
|
value,
|
|
82
82
|
platformValue,
|
|
83
|
-
pluginIdentifier:
|
|
83
|
+
pluginIdentifier: memoizedGetPluginIdentifier(
|
|
84
|
+
configuration,
|
|
85
|
+
PREFIX,
|
|
86
|
+
index
|
|
87
|
+
),
|
|
84
88
|
suffixId: prefixSpecificButton,
|
|
85
89
|
preferredFocus: index === 0,
|
|
86
90
|
});
|
|
@@ -3,7 +3,7 @@ import { getPluginIdentifier } from "..";
|
|
|
3
3
|
describe("getPluginIdentifier", () => {
|
|
4
4
|
const prefix = "tv_buttons";
|
|
5
5
|
|
|
6
|
-
it("
|
|
6
|
+
it("returns the first valid plugin identifier", () => {
|
|
7
7
|
const configuration = {
|
|
8
8
|
tv_buttons_button_1_other: "value",
|
|
9
9
|
tv_buttons_button_1_assign_action:
|
|
@@ -13,13 +13,12 @@ describe("getPluginIdentifier", () => {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
const index = 0;
|
|
16
|
-
|
|
17
16
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
18
17
|
|
|
19
18
|
expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
|
|
20
19
|
});
|
|
21
20
|
|
|
22
|
-
it("
|
|
21
|
+
it("returns the second valid plugin identifier", () => {
|
|
23
22
|
const configuration = {
|
|
24
23
|
tv_buttons_button_1_other: "value_1",
|
|
25
24
|
tv_buttons_button_1_assign_action:
|
|
@@ -30,24 +29,124 @@ describe("getPluginIdentifier", () => {
|
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
const index = 1;
|
|
33
|
-
|
|
34
32
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
35
33
|
|
|
36
34
|
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
37
35
|
});
|
|
38
36
|
|
|
39
|
-
it("
|
|
37
|
+
it("returns undefined when there are no assign_action keys", () => {
|
|
40
38
|
const configuration = {};
|
|
39
|
+
const index = 0;
|
|
40
|
+
|
|
41
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
42
|
+
|
|
43
|
+
expect(result).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("skips undefined values and returns the correct plugin identifier", () => {
|
|
47
|
+
const configuration = {
|
|
48
|
+
tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
|
|
49
|
+
tv_buttons_button_2_assign_action: undefined,
|
|
50
|
+
tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const index = 1;
|
|
54
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
55
|
+
|
|
56
|
+
expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("handles missing intermediate keys and returns the correct plugin identifier", () => {
|
|
60
|
+
const configuration = {
|
|
61
|
+
tv_buttons_button_1_assign_action: "tv_buttons_button_1_assign_action",
|
|
62
|
+
tv_buttons_button_3_assign_action: "tv_buttons_button_3_assign_action",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const index = 1;
|
|
66
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual(configuration.tv_buttons_button_3_assign_action);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("skips empty string values and returns the first non-empty assign_action", () => {
|
|
72
|
+
const configuration = {
|
|
73
|
+
tv_buttons_button_1_assign_action: "",
|
|
74
|
+
tv_buttons_button_2_assign_action: "tv_buttons_button_2_assign_action",
|
|
75
|
+
};
|
|
41
76
|
|
|
42
77
|
const index = 0;
|
|
78
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
79
|
+
|
|
80
|
+
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("returns undefined for negative index", () => {
|
|
84
|
+
const configuration = {
|
|
85
|
+
tv_buttons_button_1_assign_action: "a",
|
|
86
|
+
tv_buttons_button_2_assign_action: "b",
|
|
87
|
+
};
|
|
43
88
|
|
|
89
|
+
const index = -1;
|
|
44
90
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
45
91
|
|
|
46
92
|
expect(result).toBeUndefined();
|
|
47
93
|
});
|
|
94
|
+
|
|
95
|
+
it("returns undefined for out-of-bounds index", () => {
|
|
96
|
+
const configuration = {
|
|
97
|
+
tv_buttons_button_1_assign_action: "a",
|
|
98
|
+
tv_buttons_button_2_assign_action: "b",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const index = 5;
|
|
102
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
103
|
+
|
|
104
|
+
expect(result).toBeUndefined();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("ignores keys with wrong prefix or format", () => {
|
|
108
|
+
const configuration = {
|
|
109
|
+
tv_buttons_button_1_assign_action: "a",
|
|
110
|
+
tv_buttons_wrongprefix_2_assign_action: "b",
|
|
111
|
+
tv_buttons_button_x_assign_action: "c",
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const index = 1;
|
|
115
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
116
|
+
|
|
117
|
+
expect(result).toBeUndefined();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("returns undefined if all assign_actions are null or empty", () => {
|
|
121
|
+
const configuration = {
|
|
122
|
+
tv_buttons_button_1_assign_action: null,
|
|
123
|
+
tv_buttons_button_2_assign_action: undefined,
|
|
124
|
+
tv_buttons_button_3_assign_action: "",
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const index = 0;
|
|
128
|
+
const result = getPluginIdentifier(configuration, prefix, index);
|
|
129
|
+
|
|
130
|
+
expect(result).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("handles non-string values correctly", () => {
|
|
134
|
+
const configuration = {
|
|
135
|
+
tv_buttons_button_1_assign_action: 123,
|
|
136
|
+
tv_buttons_button_2_assign_action: true,
|
|
137
|
+
tv_buttons_button_3_assign_action: { nested: "value" },
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
expect(getPluginIdentifier(configuration, prefix, 0)).toEqual(123);
|
|
141
|
+
expect(getPluginIdentifier(configuration, prefix, 1)).toEqual(true);
|
|
142
|
+
|
|
143
|
+
expect(getPluginIdentifier(configuration, prefix, 2)).toEqual({
|
|
144
|
+
nested: "value",
|
|
145
|
+
});
|
|
146
|
+
});
|
|
48
147
|
});
|
|
49
148
|
|
|
50
|
-
describe("getPluginIdentifier - when configuration has
|
|
149
|
+
describe("getPluginIdentifier - when configuration has duplicate values", () => {
|
|
51
150
|
const prefix = "tv_buttons";
|
|
52
151
|
|
|
53
152
|
const configuration = {
|
|
@@ -55,17 +154,15 @@ describe("getPluginIdentifier - when configuration has same values for different
|
|
|
55
154
|
tv_buttons_button_2_assign_action: "navigation_action",
|
|
56
155
|
};
|
|
57
156
|
|
|
58
|
-
it("
|
|
157
|
+
it("returns the first plugin identifier when values are identical", () => {
|
|
59
158
|
const index = 0;
|
|
60
|
-
|
|
61
159
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
62
160
|
|
|
63
161
|
expect(result).toEqual(configuration.tv_buttons_button_1_assign_action);
|
|
64
162
|
});
|
|
65
163
|
|
|
66
|
-
it("
|
|
164
|
+
it("returns the second plugin identifier when values are identical", () => {
|
|
67
165
|
const index = 1;
|
|
68
|
-
|
|
69
166
|
const result = getPluginIdentifier(configuration, prefix, index);
|
|
70
167
|
|
|
71
168
|
expect(result).toEqual(configuration.tv_buttons_button_2_assign_action);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
|
+
import memoizee from "memoizee";
|
|
2
3
|
|
|
3
4
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
-
import { isNotNil } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
5
5
|
|
|
6
6
|
export const getButtonsCount = (
|
|
7
7
|
configuration: Record<string, unknown>,
|
|
@@ -21,23 +21,29 @@ export const getPluginIdentifier = (
|
|
|
21
21
|
configuration: Record<string, unknown>,
|
|
22
22
|
prefix: string,
|
|
23
23
|
index: number
|
|
24
|
-
): string => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
): string | undefined => {
|
|
25
|
+
const re = new RegExp(`${prefix}_button_\\d_assign_action`);
|
|
26
|
+
let count = 0;
|
|
27
|
+
|
|
28
|
+
for (const [key, value] of Object.entries(configuration)) {
|
|
29
|
+
if (
|
|
30
|
+
key.startsWith(`${prefix}_button`) &&
|
|
31
|
+
re.test(key) &&
|
|
32
|
+
value != null &&
|
|
33
|
+
value !== ""
|
|
34
|
+
) {
|
|
35
|
+
if (count === index) return value as string;
|
|
36
|
+
count++;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
})
|
|
38
|
-
);
|
|
40
|
+
return undefined;
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
export const memoizedGetPluginIdentifier = memoizee(getPluginIdentifier, {
|
|
44
|
+
primitive: true,
|
|
45
|
+
});
|
|
46
|
+
|
|
41
47
|
type Label = {
|
|
42
48
|
name: string;
|
|
43
49
|
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
allowedOrientationsForScreen,
|
|
5
|
-
ORIENTATIONS,
|
|
6
5
|
getOrientation,
|
|
6
|
+
ORIENTATIONS,
|
|
7
7
|
useGetScreenOrientation,
|
|
8
8
|
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
|
|
9
9
|
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
|
|
10
10
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
11
11
|
import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
12
12
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
|
-
|
|
14
|
-
import { ZappHookModalContext } from "../../Contexts";
|
|
15
|
-
import { HookModalContextT } from "../../Contexts/ZappHookModalContext";
|
|
13
|
+
import { zappHookModalStore } from "../../Contexts/ZappHookModalContext";
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* This function calls the native module needed to set orientation
|
|
@@ -89,10 +87,6 @@ type Props = {
|
|
|
89
87
|
};
|
|
90
88
|
|
|
91
89
|
export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
92
|
-
const { isHooksExecutionInProgress } = React.useContext<HookModalContextT>(
|
|
93
|
-
ZappHookModalContext.ReactContext
|
|
94
|
-
);
|
|
95
|
-
|
|
96
90
|
const prevIsActive = usePrevious(isActive);
|
|
97
91
|
|
|
98
92
|
const newOrientation = useNewOrientationForScreenData({
|
|
@@ -105,6 +99,9 @@ export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
|
105
99
|
return;
|
|
106
100
|
}
|
|
107
101
|
|
|
102
|
+
// TODO: make sure it can be static getter and subscription is not needed
|
|
103
|
+
const { isHooksExecutionInProgress } = zappHookModalStore.getState();
|
|
104
|
+
|
|
108
105
|
// If modal hook presented we need to skip
|
|
109
106
|
// Change orientation for presenter screen
|
|
110
107
|
if (isHooksExecutionInProgress) {
|
|
@@ -116,7 +113,7 @@ export function useScreenOrientationHandler({ screenData, isActive }: Props) {
|
|
|
116
113
|
|
|
117
114
|
setOrientation(newOrientation);
|
|
118
115
|
}
|
|
119
|
-
}, [newOrientation,
|
|
116
|
+
}, [newOrientation, prevIsActive, isActive]);
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
export function useOrientationHandler({ screenData }: OrientationHookArgs) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { create } from "zustand";
|
|
2
2
|
|
|
3
3
|
type HookModalState = {
|
|
4
4
|
path: string;
|
|
@@ -10,11 +10,12 @@ export type HookModalContextT = {
|
|
|
10
10
|
setIsHooksExecutionInProgress: (hookExecutionState?: boolean) => void;
|
|
11
11
|
isRunningInBackground: boolean;
|
|
12
12
|
isPresentationFullScreen: boolean;
|
|
13
|
-
setIsRunningInBackground: (
|
|
14
|
-
setIsPresentingFullScreen: (
|
|
13
|
+
setIsRunningInBackground: () => void;
|
|
14
|
+
setIsPresentingFullScreen: () => void;
|
|
15
15
|
state: HookModalState;
|
|
16
16
|
setState: (state: HookModalState) => void;
|
|
17
17
|
resetState: () => void;
|
|
18
|
+
hookPresentationMode: HookPresentationMode;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const initialState = {
|
|
@@ -24,68 +25,43 @@ const initialState = {
|
|
|
24
25
|
|
|
25
26
|
type HookPresentationMode = "background" | "fullScreen";
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isRunningInBackground: null,
|
|
31
|
-
setIsRunningInBackground: () => {},
|
|
32
|
-
setIsPresentingFullScreen: () => {},
|
|
33
|
-
isPresentationFullScreen: null,
|
|
28
|
+
// Use useZappHookModalStore() in React components (hooks)
|
|
29
|
+
// Use zappHookModalStore.getState() in non-React functions (utility functions, etc.)
|
|
30
|
+
export const useZappHookModalStore = create<HookModalContextT>()((set) => ({
|
|
34
31
|
state: initialState,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
40
|
-
const [state, setState] = React.useState<HookModalState>(initialState);
|
|
41
|
-
|
|
42
|
-
const [hookPresentationMode, setHookPresentationMode] =
|
|
43
|
-
React.useState<HookPresentationMode>(null);
|
|
44
|
-
|
|
45
|
-
const resetState = useCallback(() => {
|
|
46
|
-
setState(initialState);
|
|
47
|
-
}, [setState]);
|
|
48
|
-
|
|
49
|
-
const [isHooksExecutionInProgress, setIsHooksExecutionInProgress] =
|
|
50
|
-
React.useState(false);
|
|
32
|
+
isHooksExecutionInProgress: false,
|
|
33
|
+
hookPresentationMode: null as HookPresentationMode,
|
|
34
|
+
isRunningInBackground: false,
|
|
35
|
+
isPresentationFullScreen: false,
|
|
51
36
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
37
|
+
setState: (newState: HookModalState) => {
|
|
38
|
+
set({ state: newState });
|
|
39
|
+
},
|
|
55
40
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
41
|
+
setIsHooksExecutionInProgress: (hookExecutionState?: boolean) => {
|
|
42
|
+
set({ isHooksExecutionInProgress: hookExecutionState ?? false });
|
|
43
|
+
},
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
isHooksExecutionInProgress,
|
|
68
|
-
setIsHooksExecutionInProgress,
|
|
69
|
-
state,
|
|
70
|
-
setState,
|
|
71
|
-
resetState,
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
</ReactContext.Provider>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
45
|
+
setIsRunningInBackground: () => {
|
|
46
|
+
set({
|
|
47
|
+
hookPresentationMode: "background",
|
|
48
|
+
isRunningInBackground: true,
|
|
49
|
+
isPresentationFullScreen: false,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
78
52
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
53
|
+
setIsPresentingFullScreen: () => {
|
|
54
|
+
set({
|
|
55
|
+
hookPresentationMode: "fullScreen",
|
|
56
|
+
isRunningInBackground: false,
|
|
57
|
+
isPresentationFullScreen: true,
|
|
58
|
+
});
|
|
59
|
+
},
|
|
87
60
|
|
|
88
|
-
|
|
89
|
-
};
|
|
61
|
+
resetState: () => {
|
|
62
|
+
set({ state: initialState });
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
90
65
|
|
|
91
|
-
|
|
66
|
+
// Export an alias for clearer non-React usage (utility functions, etc.)
|
|
67
|
+
export const zappHookModalStore = useZappHookModalStore;
|
package/Contexts/index.ts
CHANGED
|
@@ -12,8 +12,6 @@ export { HorizontalScrollContext } from "./HorizontalScrollContext";
|
|
|
12
12
|
|
|
13
13
|
export { RiverOffsetContext } from "./RiverOffsetContext";
|
|
14
14
|
|
|
15
|
-
export { ZappHookModalContext } from "./ZappHookModalContext";
|
|
16
|
-
|
|
17
15
|
export { MeasurementContext } from "./MeasurementContext";
|
|
18
16
|
|
|
19
17
|
export * from "./ZappPipesContext";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.7-alpha.2341555313",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "14.0.
|
|
32
|
-
"@applicaster/zapp-react-native-bridge": "14.0.
|
|
33
|
-
"@applicaster/zapp-react-native-redux": "14.0.
|
|
34
|
-
"@applicaster/zapp-react-native-utils": "14.0.
|
|
31
|
+
"@applicaster/applicaster-types": "14.0.7-alpha.2341555313",
|
|
32
|
+
"@applicaster/zapp-react-native-bridge": "14.0.7-alpha.2341555313",
|
|
33
|
+
"@applicaster/zapp-react-native-redux": "14.0.7-alpha.2341555313",
|
|
34
|
+
"@applicaster/zapp-react-native-utils": "14.0.7-alpha.2341555313",
|
|
35
35
|
"fast-json-stable-stringify": "^2.1.0",
|
|
36
36
|
"promise": "^8.3.0",
|
|
37
37
|
"url": "^0.11.0",
|