@zezosoft/zezo-ott-react-native-ui-kit 1.1.2 → 1.1.3
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/lib/module/components/Auth/QrLogin/QrLogin.js +304 -138
- package/lib/module/components/Auth/QrLogin/QrLogin.js.map +1 -1
- package/lib/module/components/Auth/QrLogin/components/QrViewArea.js +193 -141
- package/lib/module/components/Auth/QrLogin/components/QrViewArea.js.map +1 -1
- package/lib/module/components/Content/Card/Category/Category.js +83 -11
- package/lib/module/components/Content/Card/Category/Category.js.map +1 -1
- package/lib/module/components/Content/Card/NowWatching/NowWatching.js +237 -108
- package/lib/module/components/Content/Card/NowWatching/NowWatching.js.map +1 -1
- package/lib/module/components/Content/Card/Sliders/Styles/One.js +185 -126
- package/lib/module/components/Content/Card/Sliders/Styles/One.js.map +1 -1
- package/lib/module/components/Content/Card/Sliders/Styles/Two.js +139 -92
- package/lib/module/components/Content/Card/Sliders/Styles/Two.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/Five.js +131 -48
- package/lib/module/components/Content/Card/Styles/Five.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/Four.js +126 -59
- package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/One.js +125 -50
- package/lib/module/components/Content/Card/Styles/One.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/RotateInOut.js +138 -53
- package/lib/module/components/Content/Card/Styles/RotateInOut.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/Six.js +207 -115
- package/lib/module/components/Content/Card/Styles/Six.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/Three.js +134 -79
- package/lib/module/components/Content/Card/Styles/Three.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/TopTen.js +186 -171
- package/lib/module/components/Content/Card/Styles/TopTen.js.map +1 -1
- package/lib/module/components/Content/Card/Styles/Two.js +144 -64
- package/lib/module/components/Content/Card/Styles/Two.js.map +1 -1
- package/lib/module/components/Content/Card/components/AdsPoster.js +162 -0
- package/lib/module/components/Content/Card/components/AdsPoster.js.map +1 -0
- package/lib/module/components/Content/Card/components/CardPoster.js +120 -136
- package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
- package/lib/module/components/Content/Card/components/index.js +4 -0
- package/lib/module/components/Content/Card/components/index.js.map +1 -0
- package/lib/module/components/Content/Content.js +67 -27
- package/lib/module/components/Content/Content.js.map +1 -1
- package/lib/module/components/Content/Sections.js +32 -11
- package/lib/module/components/Content/Sections.js.map +1 -1
- package/lib/module/constants/dummySections.js +44 -4
- package/lib/module/constants/dummySections.js.map +1 -1
- package/lib/module/hooks/Images/index.js +5 -0
- package/lib/module/hooks/Images/index.js.map +1 -0
- package/lib/module/hooks/Images/useImageLoader.js +168 -0
- package/lib/module/hooks/Images/useImageLoader.js.map +1 -0
- package/lib/module/hooks/Images/useImageValidation.js +36 -0
- package/lib/module/hooks/Images/useImageValidation.js.map +1 -0
- package/lib/module/hooks/index.js +3 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useAdTracking.js +270 -0
- package/lib/module/hooks/useAdTracking.js.map +1 -0
- package/lib/module/hooks/useCards.js +164 -0
- package/lib/module/hooks/useCards.js.map +1 -0
- package/lib/module/hooks/usePaginatedSection.js +11 -6
- package/lib/module/hooks/usePaginatedSection.js.map +1 -1
- package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts +2 -0
- package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts.map +1 -1
- package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Category/Category.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/NowWatching/NowWatching.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Sliders/Styles/One.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Sliders/Styles/Two.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts +13 -1
- package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts +13 -1
- package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/One.d.ts +15 -3
- package/lib/typescript/src/components/Content/Card/Styles/One.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts +13 -1
- package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts +1 -0
- package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts +13 -5
- package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts +1 -0
- package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts +13 -1
- package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts +26 -0
- package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts.map +1 -0
- package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts +3 -1
- package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/components/index.d.ts +2 -0
- package/lib/typescript/src/components/Content/Card/components/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Content/Card/index.d.ts +76 -6
- package/lib/typescript/src/components/Content/Card/index.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Content.d.ts +4 -3
- package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Sections.d.ts +20 -6
- package/lib/typescript/src/components/Content/Sections.d.ts.map +1 -1
- package/lib/typescript/src/constants/dummySections.d.ts +5 -0
- package/lib/typescript/src/constants/dummySections.d.ts.map +1 -1
- package/lib/typescript/src/hooks/Images/index.d.ts +3 -0
- package/lib/typescript/src/hooks/Images/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/Images/useImageLoader.d.ts +36 -0
- package/lib/typescript/src/hooks/Images/useImageLoader.d.ts.map +1 -0
- package/lib/typescript/src/hooks/Images/useImageValidation.d.ts +17 -0
- package/lib/typescript/src/hooks/Images/useImageValidation.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +3 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useAdTracking.d.ts +39 -0
- package/lib/typescript/src/hooks/useAdTracking.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useCards.d.ts +36 -0
- package/lib/typescript/src/hooks/useCards.d.ts.map +1 -0
- package/lib/typescript/src/hooks/usePaginatedSection.d.ts +12 -2
- package/lib/typescript/src/hooks/usePaginatedSection.d.ts.map +1 -1
- package/lib/typescript/src/types/sections/index.d.ts +7 -4
- package/lib/typescript/src/types/sections/index.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/components/Auth/QrLogin/QrLogin.tsx +382 -122
- package/src/components/Auth/QrLogin/components/QrViewArea.tsx +291 -197
- package/src/components/Content/Card/Category/Category.tsx +95 -8
- package/src/components/Content/Card/NowWatching/NowWatching.tsx +281 -136
- package/src/components/Content/Card/Sliders/Styles/One.tsx +244 -148
- package/src/components/Content/Card/Sliders/Styles/Two.tsx +171 -102
- package/src/components/Content/Card/Styles/Five.tsx +161 -62
- package/src/components/Content/Card/Styles/Four.tsx +164 -85
- package/src/components/Content/Card/Styles/One.tsx +161 -71
- package/src/components/Content/Card/Styles/RotateInOut.tsx +157 -60
- package/src/components/Content/Card/Styles/Six.tsx +242 -142
- package/src/components/Content/Card/Styles/Three.tsx +166 -133
- package/src/components/Content/Card/Styles/TopTen.tsx +230 -191
- package/src/components/Content/Card/Styles/Two.tsx +182 -79
- package/src/components/Content/Card/components/AdsPoster.tsx +202 -0
- package/src/components/Content/Card/components/CardPoster.tsx +134 -154
- package/src/components/Content/Card/components/index.ts +1 -0
- package/src/components/Content/Content.tsx +83 -45
- package/src/components/Content/Sections.tsx +51 -10
- package/src/constants/dummySections.ts +48 -1
- package/src/hooks/Images/index.ts +2 -0
- package/src/hooks/Images/useImageLoader.ts +206 -0
- package/src/hooks/Images/useImageValidation.ts +36 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useAdTracking.ts +349 -0
- package/src/hooks/useCards.ts +228 -0
- package/src/hooks/usePaginatedSection.ts +26 -7
- package/src/types/sections/index.ts +7 -4
|
@@ -11,64 +11,250 @@ import {
|
|
|
11
11
|
Dimensions,
|
|
12
12
|
Platform,
|
|
13
13
|
} from 'react-native';
|
|
14
|
+
import type { ViewStyle } from 'react-native';
|
|
14
15
|
import { scale } from 'react-native-size-matters';
|
|
15
16
|
import type { ThemeOverride } from '../../../../theme/themes';
|
|
16
17
|
import { useInternalTheme } from '../../../../theme/hook/useInternalTheme';
|
|
17
18
|
|
|
18
19
|
const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('window');
|
|
19
20
|
|
|
20
|
-
// Constants
|
|
21
|
+
// ==================== Constants ====================
|
|
21
22
|
const ANIMATION_DURATION = 2000;
|
|
22
23
|
const CORNER_SIZE = 18;
|
|
23
24
|
const CORNER_BORDER_WIDTH = 3;
|
|
24
25
|
const SCAN_LINE_HEIGHT = 3;
|
|
25
26
|
const SCAN_LINE_MARGIN = 12;
|
|
27
|
+
const BOX_WIDTH_RATIO = 0.7;
|
|
28
|
+
const BOX_SIZE_RATIO = 0.9;
|
|
29
|
+
const MAX_BOX_WIDTH = 320;
|
|
30
|
+
const VERTICAL_OFFSET = 40;
|
|
31
|
+
const DEFAULT_OVERLAY_COLOR = 'rgba(0, 0, 0, 0.6)';
|
|
32
|
+
const DEFAULT_SHADOW_COLOR = '#000';
|
|
26
33
|
|
|
34
|
+
// ==================== Types ====================
|
|
27
35
|
type QrViewAreaProps = {
|
|
28
36
|
scanBoxWidth?: number;
|
|
29
37
|
headerHeight?: number;
|
|
30
38
|
theme?: ThemeOverride;
|
|
31
39
|
};
|
|
32
40
|
|
|
41
|
+
type BoxDimensions = {
|
|
42
|
+
boxW: number;
|
|
43
|
+
boxH: number;
|
|
44
|
+
boxTop: number;
|
|
45
|
+
topOverlayHeight: number;
|
|
46
|
+
bottomOverlayHeight: number;
|
|
47
|
+
sideOverlayWidth: number;
|
|
48
|
+
rightOverlayWidth: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type CornerPosition = 'tl' | 'tr' | 'bl' | 'br';
|
|
52
|
+
|
|
53
|
+
// ==================== Helper Functions ====================
|
|
54
|
+
/**
|
|
55
|
+
* Calculates the scan box dimensions and overlay positions
|
|
56
|
+
*/
|
|
57
|
+
const calculateBoxDimensions = (
|
|
58
|
+
scanBoxWidth: number | undefined,
|
|
59
|
+
headerHeight: number
|
|
60
|
+
): BoxDimensions => {
|
|
61
|
+
const defaultBoxW =
|
|
62
|
+
scanBoxWidth || Math.min(SCREEN_W * BOX_WIDTH_RATIO, MAX_BOX_WIDTH);
|
|
63
|
+
const boxW = defaultBoxW * BOX_SIZE_RATIO;
|
|
64
|
+
const boxH = boxW;
|
|
65
|
+
const availableHeight = SCREEN_H - headerHeight;
|
|
66
|
+
const boxTop = Math.max(
|
|
67
|
+
headerHeight,
|
|
68
|
+
Math.floor(
|
|
69
|
+
headerHeight + (availableHeight - boxH) / 2 - scale(VERTICAL_OFFSET)
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const topOverlayHeight = Math.max(0, Math.floor(boxTop - headerHeight));
|
|
74
|
+
const bottomOverlayHeight = Math.max(
|
|
75
|
+
0,
|
|
76
|
+
Math.floor(SCREEN_H - (boxTop + boxH))
|
|
77
|
+
);
|
|
78
|
+
const leftOverlayWidth = Math.floor((SCREEN_W - boxW) / 2);
|
|
79
|
+
const scanBoxRight = leftOverlayWidth + boxW;
|
|
80
|
+
const rightOverlayWidth = Math.max(0, SCREEN_W - scanBoxRight);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
boxW,
|
|
84
|
+
boxH,
|
|
85
|
+
boxTop,
|
|
86
|
+
topOverlayHeight,
|
|
87
|
+
bottomOverlayHeight,
|
|
88
|
+
sideOverlayWidth: leftOverlayWidth,
|
|
89
|
+
rightOverlayWidth,
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Creates overlay style for a specific position
|
|
95
|
+
*/
|
|
96
|
+
const createOverlayStyle = (
|
|
97
|
+
position: 'top' | 'bottom' | 'left' | 'right',
|
|
98
|
+
dimensions: BoxDimensions,
|
|
99
|
+
headerHeight: number,
|
|
100
|
+
overlayColor: string
|
|
101
|
+
): ViewStyle[] => {
|
|
102
|
+
const baseStyleKey =
|
|
103
|
+
`overlay${position.charAt(0).toUpperCase() + position.slice(1)}` as keyof typeof styles;
|
|
104
|
+
const baseStyle = styles[baseStyleKey] || styles.overlaySide;
|
|
105
|
+
|
|
106
|
+
switch (position) {
|
|
107
|
+
case 'top':
|
|
108
|
+
return [
|
|
109
|
+
baseStyle,
|
|
110
|
+
{
|
|
111
|
+
top: headerHeight,
|
|
112
|
+
height: Math.max(0, dimensions.topOverlayHeight),
|
|
113
|
+
backgroundColor: overlayColor,
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
case 'bottom':
|
|
117
|
+
return [
|
|
118
|
+
baseStyle,
|
|
119
|
+
{
|
|
120
|
+
top: dimensions.boxTop + dimensions.boxH,
|
|
121
|
+
height: Math.max(0, dimensions.bottomOverlayHeight),
|
|
122
|
+
backgroundColor: overlayColor,
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
case 'left':
|
|
126
|
+
return [
|
|
127
|
+
baseStyle,
|
|
128
|
+
{
|
|
129
|
+
left: 0,
|
|
130
|
+
top: dimensions.boxTop,
|
|
131
|
+
height: dimensions.boxH,
|
|
132
|
+
width: Math.max(0, dimensions.sideOverlayWidth),
|
|
133
|
+
backgroundColor: overlayColor,
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
case 'right':
|
|
137
|
+
return [
|
|
138
|
+
baseStyle,
|
|
139
|
+
{
|
|
140
|
+
right: 0,
|
|
141
|
+
top: dimensions.boxTop,
|
|
142
|
+
height: dimensions.boxH,
|
|
143
|
+
width: Math.max(0, dimensions.rightOverlayWidth),
|
|
144
|
+
backgroundColor: overlayColor,
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
default:
|
|
148
|
+
return [baseStyle];
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Creates corner style based on position
|
|
154
|
+
*/
|
|
155
|
+
const createCornerStyle = (
|
|
156
|
+
position: CornerPosition,
|
|
157
|
+
borderColor: string,
|
|
158
|
+
cornerSize: number,
|
|
159
|
+
cornerBorderWidth: number
|
|
160
|
+
): ViewStyle[] => {
|
|
161
|
+
const baseStyle = [
|
|
162
|
+
styles.corner,
|
|
163
|
+
styles[`corner_${position}` as keyof typeof styles],
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
const dynamicStyle: ViewStyle = {
|
|
167
|
+
borderColor,
|
|
168
|
+
width: cornerSize,
|
|
169
|
+
height: cornerSize,
|
|
170
|
+
borderTopWidth: position.startsWith('t') ? cornerBorderWidth : 0,
|
|
171
|
+
borderBottomWidth: position.startsWith('b') ? cornerBorderWidth : 0,
|
|
172
|
+
borderLeftWidth: position.endsWith('l') ? cornerBorderWidth : 0,
|
|
173
|
+
borderRightWidth: position.endsWith('r') ? cornerBorderWidth : 0,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return [...baseStyle, dynamicStyle];
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Creates animated scan line style
|
|
181
|
+
*/
|
|
182
|
+
const createScanLineStyle = (
|
|
183
|
+
margin: number,
|
|
184
|
+
scanLineHeight: number,
|
|
185
|
+
borderColor: string,
|
|
186
|
+
shadowColor: string,
|
|
187
|
+
translateY: Animated.AnimatedInterpolation<number>
|
|
188
|
+
): ViewStyle => ({
|
|
189
|
+
position: 'absolute',
|
|
190
|
+
top: margin,
|
|
191
|
+
left: margin,
|
|
192
|
+
right: margin,
|
|
193
|
+
height: scanLineHeight,
|
|
194
|
+
borderRadius: scanLineHeight / 2,
|
|
195
|
+
backgroundColor: borderColor,
|
|
196
|
+
transform: [{ translateY }],
|
|
197
|
+
shadowColor,
|
|
198
|
+
shadowOffset: { width: 0, height: 2 },
|
|
199
|
+
shadowOpacity: 0.4,
|
|
200
|
+
shadowRadius: 4,
|
|
201
|
+
elevation: Platform.OS === 'android' ? 5 : 0,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// ==================== Custom Hooks ====================
|
|
205
|
+
/**
|
|
206
|
+
* Hook to manage scan line animation
|
|
207
|
+
*/
|
|
208
|
+
const useScanLineAnimation = (lineTravel: number) => {
|
|
209
|
+
const anim = useRef(new Animated.Value(0)).current;
|
|
210
|
+
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
const animation = Animated.loop(
|
|
213
|
+
Animated.sequence([
|
|
214
|
+
Animated.timing(anim, {
|
|
215
|
+
toValue: 1,
|
|
216
|
+
duration: ANIMATION_DURATION,
|
|
217
|
+
easing: Easing.linear,
|
|
218
|
+
useNativeDriver: true,
|
|
219
|
+
}),
|
|
220
|
+
Animated.timing(anim, {
|
|
221
|
+
toValue: 0,
|
|
222
|
+
duration: ANIMATION_DURATION,
|
|
223
|
+
easing: Easing.linear,
|
|
224
|
+
useNativeDriver: true,
|
|
225
|
+
}),
|
|
226
|
+
])
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
animation.start();
|
|
230
|
+
return () => animation.stop();
|
|
231
|
+
}, [anim]);
|
|
232
|
+
|
|
233
|
+
const translateY = useMemo(
|
|
234
|
+
() =>
|
|
235
|
+
anim.interpolate({
|
|
236
|
+
inputRange: [0, 1],
|
|
237
|
+
outputRange: [0, lineTravel],
|
|
238
|
+
}),
|
|
239
|
+
[anim, lineTravel]
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
return translateY;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// ==================== Component ====================
|
|
33
246
|
const QrViewArea: React.FC<QrViewAreaProps> = React.memo(
|
|
34
|
-
({ scanBoxWidth, headerHeight =
|
|
247
|
+
({ scanBoxWidth, headerHeight = 0, theme }) => {
|
|
35
248
|
const { theme: appliedTheme } = useInternalTheme(theme);
|
|
36
249
|
const { colors } = appliedTheme;
|
|
37
250
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const boxW = defaultBoxW * 0.9;
|
|
44
|
-
const boxH = boxW;
|
|
45
|
-
const availableHeight = SCREEN_H - headerHeight;
|
|
46
|
-
const boxTop = Math.max(
|
|
47
|
-
headerHeight,
|
|
48
|
-
Math.floor(headerHeight + (availableHeight - boxH) / 2 - scale(40))
|
|
49
|
-
);
|
|
50
|
-
const topOverlayHeight = Math.max(0, Math.floor(boxTop - headerHeight));
|
|
51
|
-
const bottomOverlayHeight = Math.max(
|
|
52
|
-
0,
|
|
53
|
-
Math.floor(SCREEN_H - (boxTop + boxH))
|
|
54
|
-
);
|
|
55
|
-
// Calculate left overlay width
|
|
56
|
-
const leftOverlayWidth = Math.floor((SCREEN_W - boxW) / 2);
|
|
57
|
-
// Calculate right overlay width to fill remaining space (fix gap)
|
|
58
|
-
const scanBoxLeft = leftOverlayWidth;
|
|
59
|
-
const scanBoxRight = scanBoxLeft + boxW;
|
|
60
|
-
const rightOverlayWidth = Math.max(0, SCREEN_W - scanBoxRight);
|
|
61
|
-
return {
|
|
62
|
-
boxW,
|
|
63
|
-
boxH,
|
|
64
|
-
boxTop,
|
|
65
|
-
topOverlayHeight,
|
|
66
|
-
bottomOverlayHeight,
|
|
67
|
-
sideOverlayWidth: leftOverlayWidth,
|
|
68
|
-
rightOverlayWidth,
|
|
69
|
-
};
|
|
70
|
-
}, [scanBoxWidth, headerHeight]);
|
|
251
|
+
// Calculate dimensions
|
|
252
|
+
const boxDimensions = useMemo(
|
|
253
|
+
() => calculateBoxDimensions(scanBoxWidth, headerHeight),
|
|
254
|
+
[scanBoxWidth, headerHeight]
|
|
255
|
+
);
|
|
71
256
|
|
|
257
|
+
// Calculate scan line properties
|
|
72
258
|
const margin = useMemo(() => scale(SCAN_LINE_MARGIN), []);
|
|
73
259
|
const lineTravel = useMemo(
|
|
74
260
|
() =>
|
|
@@ -76,116 +262,49 @@ const QrViewArea: React.FC<QrViewAreaProps> = React.memo(
|
|
|
76
262
|
[boxDimensions.boxH, margin]
|
|
77
263
|
);
|
|
78
264
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
anim.interpolate({
|
|
82
|
-
inputRange: [0, 1],
|
|
83
|
-
outputRange: [0, lineTravel],
|
|
84
|
-
}),
|
|
85
|
-
[anim, lineTravel]
|
|
86
|
-
);
|
|
265
|
+
// Animation
|
|
266
|
+
const translateY = useScanLineAnimation(lineTravel);
|
|
87
267
|
|
|
88
|
-
//
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
duration: ANIMATION_DURATION,
|
|
92
|
-
easing: Easing.linear,
|
|
93
|
-
useNativeDriver: true,
|
|
94
|
-
}),
|
|
95
|
-
[]
|
|
96
|
-
);
|
|
268
|
+
// Theme colors
|
|
269
|
+
const overlayColor = colors.overlay || DEFAULT_OVERLAY_COLOR;
|
|
270
|
+
const shadowColor = colors.shadow || DEFAULT_SHADOW_COLOR;
|
|
97
271
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Animated.timing(anim, {
|
|
102
|
-
toValue: 1,
|
|
103
|
-
...animationConfig,
|
|
104
|
-
}),
|
|
105
|
-
Animated.timing(anim, {
|
|
106
|
-
toValue: 0,
|
|
107
|
-
...animationConfig,
|
|
108
|
-
}),
|
|
109
|
-
])
|
|
110
|
-
);
|
|
111
|
-
animation.start();
|
|
112
|
-
return () => animation.stop();
|
|
113
|
-
}, [anim, animationConfig]);
|
|
114
|
-
|
|
115
|
-
// Memoize corner positions
|
|
116
|
-
const cornerPositions = useMemo(() => ['tl', 'tr', 'bl', 'br'], []);
|
|
117
|
-
|
|
118
|
-
// Memoize overlay color
|
|
119
|
-
const overlayColor = useMemo(
|
|
120
|
-
() => colors.overlay || 'rgba(0, 0, 0, 0.6)',
|
|
121
|
-
[colors.overlay]
|
|
122
|
-
);
|
|
272
|
+
// Corner properties
|
|
273
|
+
const cornerSize = useMemo(() => scale(CORNER_SIZE), []);
|
|
274
|
+
const cornerBorderWidth = useMemo(() => scale(CORNER_BORDER_WIDTH), []);
|
|
123
275
|
|
|
124
|
-
//
|
|
125
|
-
const
|
|
126
|
-
() =>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
left: 0,
|
|
155
|
-
top: boxDimensions.boxTop,
|
|
156
|
-
height: boxDimensions.boxH,
|
|
157
|
-
width: Math.max(0, boxDimensions.sideOverlayWidth),
|
|
158
|
-
backgroundColor: overlayColor,
|
|
159
|
-
},
|
|
160
|
-
],
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
key: 'right',
|
|
164
|
-
style: [
|
|
165
|
-
styles.overlaySide,
|
|
166
|
-
{
|
|
167
|
-
right: 0,
|
|
168
|
-
top: boxDimensions.boxTop,
|
|
169
|
-
height: boxDimensions.boxH,
|
|
170
|
-
width: Math.max(0, boxDimensions.rightOverlayWidth),
|
|
171
|
-
backgroundColor: overlayColor,
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
[
|
|
177
|
-
headerHeight,
|
|
178
|
-
boxDimensions.topOverlayHeight,
|
|
179
|
-
boxDimensions.boxTop,
|
|
180
|
-
boxDimensions.boxH,
|
|
181
|
-
boxDimensions.bottomOverlayHeight,
|
|
182
|
-
boxDimensions.sideOverlayWidth,
|
|
183
|
-
boxDimensions.rightOverlayWidth,
|
|
184
|
-
overlayColor,
|
|
185
|
-
]
|
|
276
|
+
// Create overlay styles
|
|
277
|
+
const overlayStyles = useMemo(
|
|
278
|
+
() => ({
|
|
279
|
+
top: createOverlayStyle(
|
|
280
|
+
'top',
|
|
281
|
+
boxDimensions,
|
|
282
|
+
headerHeight,
|
|
283
|
+
overlayColor
|
|
284
|
+
),
|
|
285
|
+
bottom: createOverlayStyle(
|
|
286
|
+
'bottom',
|
|
287
|
+
boxDimensions,
|
|
288
|
+
headerHeight,
|
|
289
|
+
overlayColor
|
|
290
|
+
),
|
|
291
|
+
left: createOverlayStyle(
|
|
292
|
+
'left',
|
|
293
|
+
boxDimensions,
|
|
294
|
+
headerHeight,
|
|
295
|
+
overlayColor
|
|
296
|
+
),
|
|
297
|
+
right: createOverlayStyle(
|
|
298
|
+
'right',
|
|
299
|
+
boxDimensions,
|
|
300
|
+
headerHeight,
|
|
301
|
+
overlayColor
|
|
302
|
+
),
|
|
303
|
+
}),
|
|
304
|
+
[boxDimensions, headerHeight, overlayColor]
|
|
186
305
|
);
|
|
187
306
|
|
|
188
|
-
//
|
|
307
|
+
// Scan box style
|
|
189
308
|
const scanBoxStyle = useMemo(
|
|
190
309
|
() => [
|
|
191
310
|
styles.scanBox,
|
|
@@ -196,80 +315,55 @@ const QrViewArea: React.FC<QrViewAreaProps> = React.memo(
|
|
|
196
315
|
height: boxDimensions.boxH,
|
|
197
316
|
},
|
|
198
317
|
],
|
|
199
|
-
[
|
|
200
|
-
boxDimensions.boxTop,
|
|
201
|
-
boxDimensions.sideOverlayWidth,
|
|
202
|
-
boxDimensions.boxW,
|
|
203
|
-
boxDimensions.boxH,
|
|
204
|
-
]
|
|
318
|
+
[boxDimensions]
|
|
205
319
|
);
|
|
206
320
|
|
|
207
|
-
//
|
|
208
|
-
const cornerSize = useMemo(() => scale(CORNER_SIZE), []);
|
|
209
|
-
const cornerBorderWidth = useMemo(() => scale(CORNER_BORDER_WIDTH), []);
|
|
210
|
-
|
|
321
|
+
// Corner style generator
|
|
211
322
|
const getCornerStyle = useCallback(
|
|
212
|
-
(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
width: cornerSize,
|
|
220
|
-
height: cornerSize,
|
|
221
|
-
borderTopWidth: c.startsWith('t') ? cornerBorderWidth : 0,
|
|
222
|
-
borderBottomWidth: c.startsWith('b') ? cornerBorderWidth : 0,
|
|
223
|
-
borderLeftWidth: c.endsWith('l') ? cornerBorderWidth : 0,
|
|
224
|
-
borderRightWidth: c.endsWith('r') ? cornerBorderWidth : 0,
|
|
225
|
-
};
|
|
226
|
-
return [...baseStyle, dynamicStyle];
|
|
227
|
-
},
|
|
323
|
+
(position: CornerPosition) =>
|
|
324
|
+
createCornerStyle(
|
|
325
|
+
position,
|
|
326
|
+
colors.button,
|
|
327
|
+
cornerSize,
|
|
328
|
+
cornerBorderWidth
|
|
329
|
+
),
|
|
228
330
|
[colors.button, cornerSize, cornerBorderWidth]
|
|
229
331
|
);
|
|
230
332
|
|
|
231
|
-
//
|
|
333
|
+
// Scan line style
|
|
232
334
|
const scanLineHeight = useMemo(() => scale(SCAN_LINE_HEIGHT), []);
|
|
233
|
-
const
|
|
234
|
-
() => ({
|
|
235
|
-
position: 'absolute' as const,
|
|
236
|
-
top: margin,
|
|
237
|
-
left: margin,
|
|
238
|
-
right: margin,
|
|
239
|
-
height: scanLineHeight,
|
|
240
|
-
borderRadius: scanLineHeight / 2,
|
|
241
|
-
backgroundColor: colors.button,
|
|
242
|
-
transform: [{ translateY }],
|
|
243
|
-
shadowColor: colors.shadow || '#000',
|
|
244
|
-
shadowOffset: { width: 0, height: 2 },
|
|
245
|
-
shadowOpacity: 0.4,
|
|
246
|
-
shadowRadius: 4,
|
|
247
|
-
elevation: Platform.OS === 'android' ? 5 : 0,
|
|
248
|
-
}),
|
|
249
|
-
[margin, scanLineHeight, colors.button, colors.shadow, translateY]
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
// Memoize corner components for better performance (used in both layouts)
|
|
253
|
-
const cornerComponents = useMemo(
|
|
335
|
+
const scanLineStyle = useMemo(
|
|
254
336
|
() =>
|
|
255
|
-
|
|
256
|
-
|
|
337
|
+
createScanLineStyle(
|
|
338
|
+
margin,
|
|
339
|
+
scanLineHeight,
|
|
340
|
+
colors.button,
|
|
341
|
+
shadowColor,
|
|
342
|
+
translateY
|
|
343
|
+
),
|
|
344
|
+
[margin, scanLineHeight, colors.button, shadowColor, translateY]
|
|
257
345
|
);
|
|
258
346
|
|
|
347
|
+
// Corner positions
|
|
348
|
+
const cornerPositions: CornerPosition[] = ['tl', 'tr', 'bl', 'br'];
|
|
349
|
+
|
|
259
350
|
return (
|
|
260
351
|
<View style={styles.container} pointerEvents="box-none">
|
|
261
|
-
{/* Overlay sections
|
|
262
|
-
{
|
|
263
|
-
|
|
264
|
-
|
|
352
|
+
{/* Overlay sections */}
|
|
353
|
+
<View style={overlayStyles.top} />
|
|
354
|
+
<View style={overlayStyles.bottom} />
|
|
355
|
+
<View style={overlayStyles.left} />
|
|
356
|
+
<View style={overlayStyles.right} />
|
|
265
357
|
|
|
266
358
|
{/* Scan box */}
|
|
267
359
|
<View style={scanBoxStyle} pointerEvents="none">
|
|
268
|
-
{/* Corner
|
|
269
|
-
{
|
|
360
|
+
{/* Corner markers */}
|
|
361
|
+
{cornerPositions.map((position) => (
|
|
362
|
+
<View key={position} style={getCornerStyle(position)} />
|
|
363
|
+
))}
|
|
270
364
|
|
|
271
365
|
{/* Animated scan line */}
|
|
272
|
-
<Animated.View style={
|
|
366
|
+
<Animated.View style={scanLineStyle} />
|
|
273
367
|
</View>
|
|
274
368
|
</View>
|
|
275
369
|
);
|