@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.
Files changed (136) hide show
  1. package/lib/module/components/Auth/QrLogin/QrLogin.js +304 -138
  2. package/lib/module/components/Auth/QrLogin/QrLogin.js.map +1 -1
  3. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js +193 -141
  4. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js.map +1 -1
  5. package/lib/module/components/Content/Card/Category/Category.js +83 -11
  6. package/lib/module/components/Content/Card/Category/Category.js.map +1 -1
  7. package/lib/module/components/Content/Card/NowWatching/NowWatching.js +237 -108
  8. package/lib/module/components/Content/Card/NowWatching/NowWatching.js.map +1 -1
  9. package/lib/module/components/Content/Card/Sliders/Styles/One.js +185 -126
  10. package/lib/module/components/Content/Card/Sliders/Styles/One.js.map +1 -1
  11. package/lib/module/components/Content/Card/Sliders/Styles/Two.js +139 -92
  12. package/lib/module/components/Content/Card/Sliders/Styles/Two.js.map +1 -1
  13. package/lib/module/components/Content/Card/Styles/Five.js +131 -48
  14. package/lib/module/components/Content/Card/Styles/Five.js.map +1 -1
  15. package/lib/module/components/Content/Card/Styles/Four.js +126 -59
  16. package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
  17. package/lib/module/components/Content/Card/Styles/One.js +125 -50
  18. package/lib/module/components/Content/Card/Styles/One.js.map +1 -1
  19. package/lib/module/components/Content/Card/Styles/RotateInOut.js +138 -53
  20. package/lib/module/components/Content/Card/Styles/RotateInOut.js.map +1 -1
  21. package/lib/module/components/Content/Card/Styles/Six.js +207 -115
  22. package/lib/module/components/Content/Card/Styles/Six.js.map +1 -1
  23. package/lib/module/components/Content/Card/Styles/Three.js +134 -79
  24. package/lib/module/components/Content/Card/Styles/Three.js.map +1 -1
  25. package/lib/module/components/Content/Card/Styles/TopTen.js +186 -171
  26. package/lib/module/components/Content/Card/Styles/TopTen.js.map +1 -1
  27. package/lib/module/components/Content/Card/Styles/Two.js +144 -64
  28. package/lib/module/components/Content/Card/Styles/Two.js.map +1 -1
  29. package/lib/module/components/Content/Card/components/AdsPoster.js +162 -0
  30. package/lib/module/components/Content/Card/components/AdsPoster.js.map +1 -0
  31. package/lib/module/components/Content/Card/components/CardPoster.js +120 -136
  32. package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
  33. package/lib/module/components/Content/Card/components/index.js +4 -0
  34. package/lib/module/components/Content/Card/components/index.js.map +1 -0
  35. package/lib/module/components/Content/Content.js +67 -27
  36. package/lib/module/components/Content/Content.js.map +1 -1
  37. package/lib/module/components/Content/Sections.js +32 -11
  38. package/lib/module/components/Content/Sections.js.map +1 -1
  39. package/lib/module/constants/dummySections.js +44 -4
  40. package/lib/module/constants/dummySections.js.map +1 -1
  41. package/lib/module/hooks/Images/index.js +5 -0
  42. package/lib/module/hooks/Images/index.js.map +1 -0
  43. package/lib/module/hooks/Images/useImageLoader.js +168 -0
  44. package/lib/module/hooks/Images/useImageLoader.js.map +1 -0
  45. package/lib/module/hooks/Images/useImageValidation.js +36 -0
  46. package/lib/module/hooks/Images/useImageValidation.js.map +1 -0
  47. package/lib/module/hooks/index.js +3 -0
  48. package/lib/module/hooks/index.js.map +1 -1
  49. package/lib/module/hooks/useAdTracking.js +270 -0
  50. package/lib/module/hooks/useAdTracking.js.map +1 -0
  51. package/lib/module/hooks/useCards.js +164 -0
  52. package/lib/module/hooks/useCards.js.map +1 -0
  53. package/lib/module/hooks/usePaginatedSection.js +11 -6
  54. package/lib/module/hooks/usePaginatedSection.js.map +1 -1
  55. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts +2 -0
  56. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts.map +1 -1
  57. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts.map +1 -1
  58. package/lib/typescript/src/components/Content/Card/Category/Category.d.ts.map +1 -1
  59. package/lib/typescript/src/components/Content/Card/NowWatching/NowWatching.d.ts.map +1 -1
  60. package/lib/typescript/src/components/Content/Card/Sliders/Styles/One.d.ts.map +1 -1
  61. package/lib/typescript/src/components/Content/Card/Sliders/Styles/Two.d.ts.map +1 -1
  62. package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts +13 -1
  63. package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts.map +1 -1
  64. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts +13 -1
  65. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
  66. package/lib/typescript/src/components/Content/Card/Styles/One.d.ts +15 -3
  67. package/lib/typescript/src/components/Content/Card/Styles/One.d.ts.map +1 -1
  68. package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts +13 -1
  69. package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts.map +1 -1
  70. package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts +1 -0
  71. package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts.map +1 -1
  72. package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts +13 -5
  73. package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts.map +1 -1
  74. package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts +1 -0
  75. package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts.map +1 -1
  76. package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts +13 -1
  77. package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts.map +1 -1
  78. package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts +26 -0
  79. package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts.map +1 -0
  80. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts +3 -1
  81. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
  82. package/lib/typescript/src/components/Content/Card/components/index.d.ts +2 -0
  83. package/lib/typescript/src/components/Content/Card/components/index.d.ts.map +1 -0
  84. package/lib/typescript/src/components/Content/Card/index.d.ts +76 -6
  85. package/lib/typescript/src/components/Content/Card/index.d.ts.map +1 -1
  86. package/lib/typescript/src/components/Content/Content.d.ts +4 -3
  87. package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
  88. package/lib/typescript/src/components/Content/Sections.d.ts +20 -6
  89. package/lib/typescript/src/components/Content/Sections.d.ts.map +1 -1
  90. package/lib/typescript/src/constants/dummySections.d.ts +5 -0
  91. package/lib/typescript/src/constants/dummySections.d.ts.map +1 -1
  92. package/lib/typescript/src/hooks/Images/index.d.ts +3 -0
  93. package/lib/typescript/src/hooks/Images/index.d.ts.map +1 -0
  94. package/lib/typescript/src/hooks/Images/useImageLoader.d.ts +36 -0
  95. package/lib/typescript/src/hooks/Images/useImageLoader.d.ts.map +1 -0
  96. package/lib/typescript/src/hooks/Images/useImageValidation.d.ts +17 -0
  97. package/lib/typescript/src/hooks/Images/useImageValidation.d.ts.map +1 -0
  98. package/lib/typescript/src/hooks/index.d.ts +3 -0
  99. package/lib/typescript/src/hooks/index.d.ts.map +1 -1
  100. package/lib/typescript/src/hooks/useAdTracking.d.ts +39 -0
  101. package/lib/typescript/src/hooks/useAdTracking.d.ts.map +1 -0
  102. package/lib/typescript/src/hooks/useCards.d.ts +36 -0
  103. package/lib/typescript/src/hooks/useCards.d.ts.map +1 -0
  104. package/lib/typescript/src/hooks/usePaginatedSection.d.ts +12 -2
  105. package/lib/typescript/src/hooks/usePaginatedSection.d.ts.map +1 -1
  106. package/lib/typescript/src/types/sections/index.d.ts +7 -4
  107. package/lib/typescript/src/types/sections/index.d.ts.map +1 -1
  108. package/package.json +6 -3
  109. package/src/components/Auth/QrLogin/QrLogin.tsx +382 -122
  110. package/src/components/Auth/QrLogin/components/QrViewArea.tsx +291 -197
  111. package/src/components/Content/Card/Category/Category.tsx +95 -8
  112. package/src/components/Content/Card/NowWatching/NowWatching.tsx +281 -136
  113. package/src/components/Content/Card/Sliders/Styles/One.tsx +244 -148
  114. package/src/components/Content/Card/Sliders/Styles/Two.tsx +171 -102
  115. package/src/components/Content/Card/Styles/Five.tsx +161 -62
  116. package/src/components/Content/Card/Styles/Four.tsx +164 -85
  117. package/src/components/Content/Card/Styles/One.tsx +161 -71
  118. package/src/components/Content/Card/Styles/RotateInOut.tsx +157 -60
  119. package/src/components/Content/Card/Styles/Six.tsx +242 -142
  120. package/src/components/Content/Card/Styles/Three.tsx +166 -133
  121. package/src/components/Content/Card/Styles/TopTen.tsx +230 -191
  122. package/src/components/Content/Card/Styles/Two.tsx +182 -79
  123. package/src/components/Content/Card/components/AdsPoster.tsx +202 -0
  124. package/src/components/Content/Card/components/CardPoster.tsx +134 -154
  125. package/src/components/Content/Card/components/index.ts +1 -0
  126. package/src/components/Content/Content.tsx +83 -45
  127. package/src/components/Content/Sections.tsx +51 -10
  128. package/src/constants/dummySections.ts +48 -1
  129. package/src/hooks/Images/index.ts +2 -0
  130. package/src/hooks/Images/useImageLoader.ts +206 -0
  131. package/src/hooks/Images/useImageValidation.ts +36 -0
  132. package/src/hooks/index.ts +3 -0
  133. package/src/hooks/useAdTracking.ts +349 -0
  134. package/src/hooks/useCards.ts +228 -0
  135. package/src/hooks/usePaginatedSection.ts +26 -7
  136. 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 = 60, theme }) => {
247
+ ({ scanBoxWidth, headerHeight = 0, theme }) => {
35
248
  const { theme: appliedTheme } = useInternalTheme(theme);
36
249
  const { colors } = appliedTheme;
37
250
 
38
- const anim = useRef(new Animated.Value(0)).current;
39
-
40
- // Memoize box dimensions with better calculations (fix gap on right side)
41
- const boxDimensions = useMemo(() => {
42
- const defaultBoxW = scanBoxWidth || Math.min(SCREEN_W * 0.7, 320);
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
- const translateY = useMemo(
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
- // Memoize animation config
89
- const animationConfig = useMemo(
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
- useEffect(() => {
99
- const animation = Animated.loop(
100
- Animated.sequence([
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
- // Memoize all overlay components in one array (optimized - created once)
125
- const overlayComponents = useMemo(
126
- () => [
127
- {
128
- key: 'top',
129
- style: [
130
- styles.overlayTop,
131
- {
132
- top: headerHeight,
133
- height: Math.max(0, boxDimensions.topOverlayHeight),
134
- backgroundColor: overlayColor,
135
- },
136
- ],
137
- },
138
- {
139
- key: 'bottom',
140
- style: [
141
- styles.overlayBottom,
142
- {
143
- top: boxDimensions.boxTop + boxDimensions.boxH,
144
- height: Math.max(0, boxDimensions.bottomOverlayHeight),
145
- backgroundColor: overlayColor,
146
- },
147
- ],
148
- },
149
- {
150
- key: 'left',
151
- style: [
152
- styles.overlaySide,
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
- // Memoize scan box style with proper positioning (ensure no gap on right)
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
- // Memoize corner styles for better performance
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
- (c: string) => {
213
- const baseStyle = [
214
- styles.corner,
215
- styles[`corner_${c}` as keyof typeof styles],
216
- ];
217
- const dynamicStyle = {
218
- borderColor: colors.button,
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
- // Memoize animated line style
333
+ // Scan line style
232
334
  const scanLineHeight = useMemo(() => scale(SCAN_LINE_HEIGHT), []);
233
- const animatedLineStyle = useMemo(
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
- cornerPositions.map((c) => <View key={c} style={getCornerStyle(c)} />),
256
- [cornerPositions, getCornerStyle]
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 - optimized single render */}
262
- {overlayComponents.map((overlay) => (
263
- <View key={overlay.key} style={overlay.style} />
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 components - shown in both layouts */}
269
- {cornerComponents}
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={animatedLineStyle} />
366
+ <Animated.View style={scanLineStyle} />
273
367
  </View>
274
368
  </View>
275
369
  );