@ccrf01/react-native-template 0.0.16

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 (233) hide show
  1. package/.github/workflows/npm-publish.yml +28 -0
  2. package/.vscode/settings.json +15 -0
  3. package/README.md +58 -0
  4. package/package.json +16 -0
  5. package/template/.bundle/config +2 -0
  6. package/template/.env.development +1 -0
  7. package/template/.env.production +1 -0
  8. package/template/.eslintrc.js +392 -0
  9. package/template/.java-version +1 -0
  10. package/template/.prettierrc.js +5 -0
  11. package/template/.ruby-version +1 -0
  12. package/template/.watchmanconfig +1 -0
  13. package/template/Gemfile +23 -0
  14. package/template/Gemfile.lock +330 -0
  15. package/template/README.md +97 -0
  16. package/template/ReactotronConfig.js +17 -0
  17. package/template/__tests__/App.test.tsx +13 -0
  18. package/template/_gitignore +75 -0
  19. package/template/_node-version +1 -0
  20. package/template/android/app/build.gradle +162 -0
  21. package/template/android/app/debug.keystore +0 -0
  22. package/template/android/app/proguard-rules.pro +10 -0
  23. package/template/android/app/src/debug/AndroidManifest.xml +9 -0
  24. package/template/android/app/src/main/AndroidManifest.xml +26 -0
  25. package/template/android/app/src/main/java/com/projectname/MainActivity.kt +30 -0
  26. package/template/android/app/src/main/java/com/projectname/MainApplication.kt +27 -0
  27. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  28. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  29. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  30. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  31. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  32. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  33. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  34. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  35. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  36. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  37. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  38. package/template/android/app/src/main/res/values/strings.xml +3 -0
  39. package/template/android/app/src/main/res/values/styles.xml +9 -0
  40. package/template/android/build.gradle +37 -0
  41. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  42. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  43. package/template/android/gradle.properties +48 -0
  44. package/template/android/gradlew +251 -0
  45. package/template/android/gradlew.bat +99 -0
  46. package/template/android/keystore/keystore.properties +4 -0
  47. package/template/android/settings.gradle +6 -0
  48. package/template/android/version.properties +2 -0
  49. package/template/app.json +4 -0
  50. package/template/babel.config.js +38 -0
  51. package/template/fastlane/Fastfile +136 -0
  52. package/template/fastlane/Pluginfile +9 -0
  53. package/template/fastlane/README.md +46 -0
  54. package/template/index.js +9 -0
  55. package/template/ios/.xcode.env +11 -0
  56. package/template/ios/Podfile +35 -0
  57. package/template/ios/Podfile.lock +3669 -0
  58. package/template/ios/ProjectName/AppDelegate.swift +48 -0
  59. package/template/ios/ProjectName/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  60. package/template/ios/ProjectName/Images.xcassets/Contents.json +6 -0
  61. package/template/ios/ProjectName/Info.plist +66 -0
  62. package/template/ios/ProjectName/LaunchScreen.storyboard +47 -0
  63. package/template/ios/ProjectName/PrivacyInfo.xcprivacy +47 -0
  64. package/template/ios/ProjectName.xcodeproj/project.pbxproj +482 -0
  65. package/template/ios/ProjectName.xcodeproj/xcshareddata/xcschemes/ProjectName.xcscheme +88 -0
  66. package/template/ios/ProjectName.xcworkspace/contents.xcworkspacedata +10 -0
  67. package/template/jest.config.js +3 -0
  68. package/template/metro.config.js +20 -0
  69. package/template/package-lock.json +17073 -0
  70. package/template/package.json +156 -0
  71. package/template/src/@types/emotion.d.ts +12 -0
  72. package/template/src/@types/env.d.ts +3 -0
  73. package/template/src/@types/redux-persist-transform-immutable.d.ts +1 -0
  74. package/template/src/@types/typing.d.ts +17 -0
  75. package/template/src/AppContainer.tsx +109 -0
  76. package/template/src/assets/images/143.png +0 -0
  77. package/template/src/assets/index.ts +13 -0
  78. package/template/src/components/basic/BackButton/index.tsx +34 -0
  79. package/template/src/components/basic/Body/index.tsx +68 -0
  80. package/template/src/components/basic/Button/index.tsx +181 -0
  81. package/template/src/components/basic/Button/utils.ts +78 -0
  82. package/template/src/components/basic/ButtonGroup/index.tsx +182 -0
  83. package/template/src/components/basic/Card/index.tsx +3 -0
  84. package/template/src/components/basic/Container/index.tsx +38 -0
  85. package/template/src/components/basic/Content/index.tsx +87 -0
  86. package/template/src/components/basic/DropDown/index.tsx +354 -0
  87. package/template/src/components/basic/ExpandableOverlay/index.tsx +113 -0
  88. package/template/src/components/basic/Header/index.tsx +216 -0
  89. package/template/src/components/basic/Header/styles.ts +0 -0
  90. package/template/src/components/basic/Icons/index.tsx +131 -0
  91. package/template/src/components/basic/InputLabel/index.tsx +19 -0
  92. package/template/src/components/basic/LoadingOverlay/index.tsx +68 -0
  93. package/template/src/components/basic/MaterialTextInput/index.tsx +153 -0
  94. package/template/src/components/basic/NumberInput/index.tsx +53 -0
  95. package/template/src/components/basic/Picker/PickerContext.ts +7 -0
  96. package/template/src/components/basic/Picker/PickerHeader.tsx +130 -0
  97. package/template/src/components/basic/Picker/PickerItem.tsx +105 -0
  98. package/template/src/components/basic/Picker/PickerItemsList.tsx +135 -0
  99. package/template/src/components/basic/Picker/PickerPresenter.ts +54 -0
  100. package/template/src/components/basic/Picker/hooks/useImperativePickerHandle.ts +27 -0
  101. package/template/src/components/basic/Picker/hooks/usePickerLabel.ts +74 -0
  102. package/template/src/components/basic/Picker/hooks/usePickerSearch.ts +37 -0
  103. package/template/src/components/basic/Picker/hooks/usePickerSelection.ts +57 -0
  104. package/template/src/components/basic/Picker/index.tsx +284 -0
  105. package/template/src/components/basic/Picker/types.tsx +229 -0
  106. package/template/src/components/basic/PressableOpacity/index.tsx +20 -0
  107. package/template/src/components/basic/RootDialog/Dialog.tsx +246 -0
  108. package/template/src/components/basic/RootDialog/Manager.tsx +110 -0
  109. package/template/src/components/basic/RootDialog/animations/Animation.ts +29 -0
  110. package/template/src/components/basic/RootDialog/animations/FadeAnimation.ts +40 -0
  111. package/template/src/components/basic/RootDialog/animations/ScaleAnimation.ts +37 -0
  112. package/template/src/components/basic/RootDialog/animations/SlideAnimation.ts +89 -0
  113. package/template/src/components/basic/RootDialog/components/Backdrop.tsx +60 -0
  114. package/template/src/components/basic/RootDialog/components/BaseDialog.tsx +564 -0
  115. package/template/src/components/basic/RootDialog/components/BottomDialog.tsx +32 -0
  116. package/template/src/components/basic/RootDialog/components/DialogButton.tsx +87 -0
  117. package/template/src/components/basic/RootDialog/components/DialogContent.tsx +26 -0
  118. package/template/src/components/basic/RootDialog/components/DialogContext.tsx +8 -0
  119. package/template/src/components/basic/RootDialog/components/DialogFooter.tsx +42 -0
  120. package/template/src/components/basic/RootDialog/components/DialogTitle.tsx +53 -0
  121. package/template/src/components/basic/RootDialog/components/DraggableView.tsx +271 -0
  122. package/template/src/components/basic/RootDialog/index.ts +21 -0
  123. package/template/src/components/basic/RootDialog/type.ts +102 -0
  124. package/template/src/components/basic/Text/index.tsx +8 -0
  125. package/template/src/components/basic/index.ts +35 -0
  126. package/template/src/configs/constants/type/APIStatus.type.ts +8 -0
  127. package/template/src/configs/constants/type/Locale.type.ts +7 -0
  128. package/template/src/configs/constants/type/StorageKey.type.ts +7 -0
  129. package/template/src/configs/constants/type/ThemeType.type.ts +6 -0
  130. package/template/src/configs/constants/type/index.ts +11 -0
  131. package/template/src/configs/index.ts +22 -0
  132. package/template/src/contexts/ThemeContext.ts +6 -0
  133. package/template/src/hooks/useAppLoading.ts +26 -0
  134. package/template/src/hooks/useAppState.ts +36 -0
  135. package/template/src/hooks/useArray.ts +47 -0
  136. package/template/src/hooks/useAsync.ts +42 -0
  137. package/template/src/hooks/useAsyncStorage.ts +41 -0
  138. package/template/src/hooks/useBoolean.ts +21 -0
  139. package/template/src/hooks/useBuildTheme.ts +249 -0
  140. package/template/src/hooks/useCountDown.ts +111 -0
  141. package/template/src/hooks/useCounter.ts +27 -0
  142. package/template/src/hooks/useDebounce.ts +25 -0
  143. package/template/src/hooks/useDebouncedValidate.ts +32 -0
  144. package/template/src/hooks/useDebugInformation.ts +38 -0
  145. package/template/src/hooks/useDeviceToken.ts +20 -0
  146. package/template/src/hooks/useEncryptedStorage.ts +41 -0
  147. package/template/src/hooks/useFontFamily.ts +13 -0
  148. package/template/src/hooks/useHttp.ts +18 -0
  149. package/template/src/hooks/useInterval.ts +24 -0
  150. package/template/src/hooks/useIsForeground.ts +17 -0
  151. package/template/src/hooks/useMMKVStorage.ts +0 -0
  152. package/template/src/hooks/usePrevious.ts +12 -0
  153. package/template/src/hooks/useRenderCount.ts +10 -0
  154. package/template/src/hooks/useTheme.ts +17 -0
  155. package/template/src/hooks/useTimeCountDown.ts +91 -0
  156. package/template/src/index.tsx +65 -0
  157. package/template/src/infrastructures/NetClient/AbstractClient.ts +66 -0
  158. package/template/src/infrastructures/NetClient/ApiResponse.ts +16 -0
  159. package/template/src/infrastructures/NetClient/ApisauceClient.ts +76 -0
  160. package/template/src/infrastructures/NetClient/AxiosClient.ts +80 -0
  161. package/template/src/infrastructures/NetClient/FetchNetClient.ts +120 -0
  162. package/template/src/infrastructures/NetClient/config.ts +3 -0
  163. package/template/src/infrastructures/NetClient/interfaces/INetClient.ts +6 -0
  164. package/template/src/infrastructures/Storage/IStorage.ts +7 -0
  165. package/template/src/infrastructures/Storage/MMKVStorage.ts +41 -0
  166. package/template/src/infrastructures/common/Timeout.ts +27 -0
  167. package/template/src/infrastructures/common/colorUtils.ts +82 -0
  168. package/template/src/infrastructures/common/dateUtils.ts +39 -0
  169. package/template/src/infrastructures/common/logger.ts +115 -0
  170. package/template/src/locales/en-US/general.json +26 -0
  171. package/template/src/locales/en-US/index.ts +9 -0
  172. package/template/src/locales/en-US/screens.json +4 -0
  173. package/template/src/locales/en-US/setting.json +3 -0
  174. package/template/src/locales/i18n.ts +109 -0
  175. package/template/src/locales/zh-TW/general.json +26 -0
  176. package/template/src/locales/zh-TW/index.ts +9 -0
  177. package/template/src/locales/zh-TW/screens.json +4 -0
  178. package/template/src/locales/zh-TW/setting.json +3 -0
  179. package/template/src/models/index.ts +5 -0
  180. package/template/src/models/request.model.ts +50 -0
  181. package/template/src/navigators/DrawerNav/DrawerContent.tsx +66 -0
  182. package/template/src/navigators/DrawerNav/DrawerItem.tsx +261 -0
  183. package/template/src/navigators/DrawerNav/index.tsx +39 -0
  184. package/template/src/navigators/DrawerNav/props.ts +12 -0
  185. package/template/src/navigators/DrawerNav/types.ts +8 -0
  186. package/template/src/navigators/MainBottomTabNav/index.tsx +83 -0
  187. package/template/src/navigators/MainBottomTabNav/props.ts +16 -0
  188. package/template/src/navigators/MainBottomTabNav/types.ts +6 -0
  189. package/template/src/navigators/RootStack.tsx +43 -0
  190. package/template/src/navigators/index.tsx +40 -0
  191. package/template/src/navigators/props.ts +14 -0
  192. package/template/src/navigators/types.ts +18 -0
  193. package/template/src/navigators/utils.ts +68 -0
  194. package/template/src/redux/api/api.ts +41 -0
  195. package/template/src/redux/reducers/appSlice.ts +26 -0
  196. package/template/src/redux/reducers/index.ts +21 -0
  197. package/template/src/redux/reducers/nonPersistSlice.ts +51 -0
  198. package/template/src/redux/reducers/settingSlice.ts +48 -0
  199. package/template/src/redux/reducers/themeSlice.ts +55 -0
  200. package/template/src/redux/saga/index.ts +5 -0
  201. package/template/src/redux/saga/settingSaga.ts +21 -0
  202. package/template/src/redux/selectors/app.ts +9 -0
  203. package/template/src/redux/selectors/nonPersist.ts +23 -0
  204. package/template/src/redux/selectors/setting.ts +29 -0
  205. package/template/src/redux/selectors/theme.ts +13 -0
  206. package/template/src/redux/store/index.ts +79 -0
  207. package/template/src/redux/store/types.d.ts +5 -0
  208. package/template/src/screens/Home/index.tsx +146 -0
  209. package/template/src/screens/Settings/components/Item.tsx +45 -0
  210. package/template/src/screens/Settings/index.tsx +97 -0
  211. package/template/src/screens/Splash/index.tsx +53 -0
  212. package/template/src/services/Dialogs.tsx +226 -0
  213. package/template/src/services/PermissionCheck.ts +257 -0
  214. package/template/src/theme/Common.ts +48 -0
  215. package/template/src/theme/Fonts.ts +196 -0
  216. package/template/src/theme/Gutters.ts +63 -0
  217. package/template/src/theme/Icons.ts +28 -0
  218. package/template/src/theme/Images.ts +13 -0
  219. package/template/src/theme/Layout.ts +106 -0
  220. package/template/src/theme/Variables.ts +167 -0
  221. package/template/src/theme/components/Buttons.ts +37 -0
  222. package/template/src/theme/index.ts +8 -0
  223. package/template/src/theme/metrics.ts +57 -0
  224. package/template/src/theme/themes/default_dark/Images.ts +7 -0
  225. package/template/src/theme/themes/default_dark/Variables.ts +84 -0
  226. package/template/src/theme/themes/default_dark/index.ts +2 -0
  227. package/template/src/theme/themes/index.ts +8 -0
  228. package/template/src/theme/types.ts +152 -0
  229. package/template/src/utils/encrypt-helper.ts +118 -0
  230. package/template/src/utils/index.ts +76 -0
  231. package/template/src/utils/sys-info-data.ts +17 -0
  232. package/template/tsconfig.json +44 -0
  233. package/template.config.js +8 -0
@@ -0,0 +1,261 @@
1
+ import { PlatformPressable } from '@react-navigation/elements'
2
+ import { Link, useTheme } from '@react-navigation/native'
3
+ import * as React from 'react'
4
+ import {
5
+ Platform,
6
+ StyleProp,
7
+ StyleSheet,
8
+ Text,
9
+ TextStyle,
10
+ View,
11
+ ViewStyle,
12
+ } from 'react-native'
13
+ import Color from 'tinycolor2'
14
+
15
+ type Props = {
16
+ /**
17
+ * The label text of the item.
18
+ */
19
+ label:
20
+ | string
21
+ | ((props: { focused: boolean; color: string }) => React.ReactNode)
22
+ /**
23
+ * Icon to display for the `DrawerItem`.
24
+ */
25
+ icon?: (props: {
26
+ focused: boolean
27
+ size: number
28
+ color: string
29
+ }) => React.ReactNode
30
+ /**
31
+ * URL to use for the link to the tab.
32
+ */
33
+ to?: string
34
+ /**
35
+ * Whether to highlight the drawer item as active.
36
+ */
37
+ focused?: boolean
38
+ /**
39
+ * Function to execute on press.
40
+ */
41
+ onPress: () => void
42
+ /**
43
+ * Color for the icon and label when the item is active.
44
+ */
45
+ activeTintColor?: string
46
+ /**
47
+ * Color for the icon and label when the item is inactive.
48
+ */
49
+ inactiveTintColor?: string
50
+ /**
51
+ * Background color for item when its active.
52
+ */
53
+ activeBackgroundColor?: string
54
+ /**
55
+ * Background color for item when it's inactive.
56
+ */
57
+ inactiveBackgroundColor?: string
58
+ /**
59
+ * Color of the touchable effect on press.
60
+ * Only supported on Android.
61
+ *
62
+ * @platform android
63
+ */
64
+ pressColor?: string
65
+ /**
66
+ * Opacity of the touchable effect on press.
67
+ * Only supported on iOS.
68
+ *
69
+ * @platform ios
70
+ */
71
+ pressOpacity?: number
72
+ /**
73
+ * Style object for the label element.
74
+ */
75
+ labelStyle?: StyleProp<TextStyle>
76
+ /**
77
+ * Style object for the wrapper element.
78
+ */
79
+ style?: StyleProp<ViewStyle>
80
+ /**
81
+ * Whether label font should scale to respect Text Size accessibility settings.
82
+ */
83
+ allowFontScaling?: boolean
84
+
85
+ /**
86
+ * Accessibility label for drawer item.
87
+ */
88
+ accessibilityLabel?: string
89
+ /**
90
+ * ID to locate this drawer item in tests.
91
+ */
92
+ testID?: string
93
+ linkParams?: Record<string, any>
94
+ }
95
+
96
+ const LinkPressable = ({
97
+ accessibilityRole,
98
+ children,
99
+ linkParams,
100
+ onLongPress,
101
+ onPress,
102
+ onPressIn,
103
+ onPressOut,
104
+ style,
105
+ to,
106
+ ...rest
107
+ }: Omit<React.ComponentProps<typeof PlatformPressable>, 'style' | 'pressRetentionOffset'> & {
108
+ style: StyleProp<ViewStyle>
109
+ } & {
110
+ to?: string
111
+ children: React.ReactNode
112
+ onPress?: () => void
113
+ linkParams?: Record<string, any>
114
+ }) => {
115
+ if (Platform.OS === 'web' && to) {
116
+ // React Native Web doesn't forward `onClick` if we use `TouchableWithoutFeedback`.
117
+ // We need to use `onClick` to be able to prevent default browser handling of links.
118
+ return (
119
+ <Link
120
+ {...rest}
121
+ screen={to}
122
+ params={linkParams ?? {}}
123
+ disabled={false}
124
+ style={[styles.button, style]}
125
+ onPress={(e: any) => {
126
+ if (
127
+ !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) && // ignore clicks with modifier keys
128
+ (e.button == null || e.button === 0) // ignore everything but left clicks
129
+ ) {
130
+ e.preventDefault()
131
+ onPress?.(e)
132
+ }
133
+ }}
134
+ // types for PressableProps and TextProps are incompatible with each other by `null` so we
135
+ // can't use {...rest} for these 3 props
136
+ onLongPress={onLongPress ?? undefined}
137
+ onPressIn={onPressIn ?? undefined}
138
+ onPressOut={onPressOut ?? undefined}
139
+ >
140
+ {children}
141
+ </Link>
142
+ )
143
+ } else {
144
+ return (
145
+ <PlatformPressable
146
+ {...rest}
147
+ accessibilityRole={accessibilityRole}
148
+ onPress={onPress}
149
+ >
150
+ <View style={style}>{children}</View>
151
+ </PlatformPressable>
152
+ )
153
+ }
154
+ }
155
+
156
+ /**
157
+ * A component used to show an action item with an icon and a label in a navigation drawer.
158
+ */
159
+ const DrawerItem = (props: Props) => {
160
+ const { colors } = useTheme()
161
+
162
+ const {
163
+ icon,
164
+ label,
165
+ labelStyle,
166
+ to,
167
+ focused = false,
168
+ allowFontScaling,
169
+ activeTintColor = colors.primary,
170
+ inactiveTintColor = Color(colors.text).setAlpha(0.68)
171
+ .toPercentageRgbString(),
172
+ activeBackgroundColor = Color(activeTintColor).setAlpha(0.12)
173
+ .toPercentageRgbString(),
174
+ inactiveBackgroundColor = 'transparent',
175
+ style,
176
+ onPress,
177
+ pressColor,
178
+ pressOpacity,
179
+ testID,
180
+ accessibilityLabel,
181
+ ...rest
182
+ } = props
183
+
184
+ const { borderRadius = 4 } = StyleSheet.flatten(style || {})
185
+ const color = focused ? activeTintColor : inactiveTintColor
186
+ const backgroundColor = focused
187
+ ? activeBackgroundColor
188
+ : inactiveBackgroundColor
189
+
190
+ const iconNode = icon ? icon({ size: 24, focused, color }) : null
191
+
192
+ return (
193
+ <View
194
+ collapsable={false}
195
+ {...rest}
196
+ style={[styles.container, { borderRadius, backgroundColor }, style]}
197
+ >
198
+ <LinkPressable
199
+ testID={testID}
200
+ onPress={onPress}
201
+ style={[styles.wrapper, { borderRadius }]}
202
+ accessibilityLabel={accessibilityLabel}
203
+ accessibilityRole="button"
204
+ accessibilityState={{ selected: focused }}
205
+ pressColor={pressColor}
206
+ pressOpacity={pressOpacity}
207
+ to={to}
208
+ >
209
+ <React.Fragment>
210
+ {iconNode}
211
+ <View
212
+ style={[
213
+ styles.label,
214
+ { marginLeft: iconNode ? 12 : 0, marginVertical: 5 },
215
+ ]}
216
+ >
217
+ {typeof label === 'string' ? (
218
+ <Text
219
+ numberOfLines={1}
220
+ allowFontScaling={allowFontScaling}
221
+ style={[
222
+ {
223
+ color,
224
+ fontWeight: '500',
225
+ },
226
+ labelStyle,
227
+ ]}
228
+ >
229
+ {label}
230
+ </Text>
231
+ ) : (
232
+ label({ color, focused })
233
+ )}
234
+ </View>
235
+ </React.Fragment>
236
+ </LinkPressable>
237
+ </View>
238
+ )
239
+ }
240
+
241
+ const styles = StyleSheet.create({
242
+ container: {
243
+ marginHorizontal: 10,
244
+ marginVertical: 4,
245
+ overflow: 'hidden',
246
+ },
247
+ wrapper: {
248
+ flexDirection: 'row',
249
+ alignItems: 'center',
250
+ padding: 8,
251
+ },
252
+ label: {
253
+ marginRight: 24,
254
+ flex: 1,
255
+ },
256
+ button: {
257
+ display: 'flex',
258
+ },
259
+ })
260
+
261
+ export default DrawerItem
@@ -0,0 +1,39 @@
1
+ import { createDrawerNavigator } from '@react-navigation/drawer'
2
+ import React from 'react'
3
+ import { useTranslation } from 'react-i18next'
4
+
5
+ import useTheme from '@/hooks/useTheme'
6
+ import DrawerContent from '@/navigators/DrawerNav/DrawerContent'
7
+ import { MainDrawerNavigationParamList } from '@/navigators/DrawerNav/types'
8
+ import MainBottomTabNav from '@/navigators/MainBottomTabNav'
9
+ import { AppRoutes } from '@/navigators/types'
10
+
11
+ const Drawer = createDrawerNavigator<MainDrawerNavigationParamList>()
12
+
13
+ const DrawerNav = (): React.ReactElement => {
14
+ const { Colors } = useTheme()
15
+ const { t } = useTranslation()
16
+
17
+ return (
18
+ <Drawer.Navigator
19
+ drawerContent={(props) => <DrawerContent {...props} />}
20
+ screenOptions={{
21
+ headerShown: false,
22
+ drawerPosition: 'right',
23
+ drawerType: 'front',
24
+ drawerStyle: {
25
+ backgroundColor: Colors.background,
26
+ width: '80%',
27
+ },
28
+ swipeEnabled: true,
29
+ }}
30
+ >
31
+ <Drawer.Screen
32
+ name={AppRoutes.MainBottomTabNav}
33
+ component={MainBottomTabNav}
34
+ />
35
+ </Drawer.Navigator>
36
+ )
37
+ }
38
+
39
+ export default DrawerNav
@@ -0,0 +1,12 @@
1
+ import { DrawerScreenProps } from '@react-navigation/drawer'
2
+ import { CompositeScreenProps } from '@react-navigation/native'
3
+
4
+ import { MainDrawerNavigationParamList } from '@/navigators/DrawerNav/types'
5
+ import { RootScreenProps } from '@/navigators/props'
6
+ import { AppRoutes } from '@/navigators/types'
7
+
8
+ export type MainBottomTabNavScreenProps = CompositeScreenProps<
9
+ DrawerScreenProps<MainDrawerNavigationParamList, AppRoutes.MainBottomTabNav>,
10
+ RootScreenProps
11
+ >
12
+
@@ -0,0 +1,8 @@
1
+ import { NavigatorScreenParams } from '@react-navigation/native'
2
+
3
+ import { MainBottomTabNavigationParamList } from '@/navigators/MainBottomTabNav/types'
4
+ import { AppRoutes } from '@/navigators/types'
5
+
6
+ export type MainDrawerNavigationParamList = {
7
+ [AppRoutes.MainBottomTabNav]: NavigatorScreenParams<MainBottomTabNavigationParamList>
8
+ }
@@ -0,0 +1,83 @@
1
+ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
2
+ import React, { useCallback } from 'react'
3
+ import { useTranslation } from 'react-i18next'
4
+ import LinearGradient from 'react-native-linear-gradient'
5
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
+
7
+ import { IconX } from '@/components/basic'
8
+ import useTheme from '@/hooks/useTheme'
9
+ import { MainBottomTabNavigationParamList } from '@/navigators/MainBottomTabNav/types'
10
+ import { AppRoutes } from '@/navigators/types'
11
+ import HomeScreen from '@/screens/Home'
12
+ import SettingsScreen from '@/screens/Settings'
13
+
14
+ const Tab = createBottomTabNavigator<MainBottomTabNavigationParamList>()
15
+
16
+ const MainBottomTabNav = () => {
17
+ const { t } = useTranslation()
18
+ const insets = useSafeAreaInsets()
19
+ const { Colors } = useTheme()
20
+
21
+ const tabBarHeight = 60 + insets.bottom
22
+
23
+ const renderTabIcon = useCallback((iconName: string) => {
24
+ const renderNamedTabIcon = ({ color, focused }: { color?: string; focused: boolean }) => {
25
+ return <IconX origin={IconX.ANT_DESIGN} name={iconName} size={26} color={color} />
26
+ }
27
+
28
+ return renderNamedTabIcon
29
+ }, [])
30
+
31
+ return (
32
+ <Tab.Navigator
33
+ initialRouteName={AppRoutes.HomeScreen}
34
+ backBehavior={'initialRoute'}
35
+ screenOptions={{
36
+ headerShown: false,
37
+ tabBarActiveTintColor: Colors.primary,
38
+ tabBarBackground: () => {
39
+ return (
40
+ <LinearGradient
41
+ colors={[
42
+ '#E8E8E8', '#E8E8E8', '#fff', '#fff', '#FAFAFA', '#E8E8E8',
43
+ ]}
44
+ start={{ x: 0.0, y: 1.0 }}
45
+ end={{ x: 0.0, y: 0.0 }}
46
+ style={{ height: tabBarHeight }}
47
+ />
48
+ )
49
+ },
50
+ tabBarStyle: {
51
+ height: tabBarHeight,
52
+ },
53
+ }}
54
+ >
55
+ <Tab.Screen
56
+ name={AppRoutes.HomeScreen}
57
+ component={HomeScreen}
58
+ options={{
59
+ tabBarLabel: `${t('screens:home')}`,
60
+ tabBarIcon: renderTabIcon('home'),
61
+ tabBarLabelStyle: {
62
+ fontSize: 12,
63
+ fontWeight: '500',
64
+ },
65
+ }}
66
+ />
67
+ <Tab.Screen
68
+ name={AppRoutes.SettingsScreen}
69
+ component={SettingsScreen}
70
+ options={{
71
+ tabBarLabel: `${t('screens:settings')}`,
72
+ tabBarIcon: renderTabIcon('setting'),
73
+ tabBarLabelStyle: {
74
+ fontSize: 12,
75
+ fontWeight: '500',
76
+ },
77
+ }}
78
+ />
79
+ </Tab.Navigator>
80
+ )
81
+ }
82
+
83
+ export default MainBottomTabNav
@@ -0,0 +1,16 @@
1
+ import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
2
+ import { CompositeScreenProps } from '@react-navigation/native'
3
+
4
+ import { MainBottomTabNavigationParamList } from '@/navigators/MainBottomTabNav/types'
5
+ import { MainDrawerNavScreenProps } from '@/navigators/props'
6
+ import { AppRoutes } from '@/navigators/types'
7
+
8
+ export type HomeScreenProps = CompositeScreenProps<
9
+ BottomTabScreenProps<MainBottomTabNavigationParamList, AppRoutes.HomeScreen>,
10
+ MainDrawerNavScreenProps
11
+ >
12
+
13
+ export type SettingsScreenProps = CompositeScreenProps<
14
+ BottomTabScreenProps<MainBottomTabNavigationParamList, AppRoutes.SettingsScreen>,
15
+ MainDrawerNavScreenProps
16
+ >
@@ -0,0 +1,6 @@
1
+ import { AppRoutes } from '@/navigators/types'
2
+
3
+ export type MainBottomTabNavigationParamList = {
4
+ [AppRoutes.HomeScreen]: undefined
5
+ [AppRoutes.SettingsScreen]: undefined
6
+ }
@@ -0,0 +1,43 @@
1
+ import { createStackNavigator } from '@react-navigation/stack'
2
+ import React from 'react'
3
+ import { useTranslation } from 'react-i18next'
4
+
5
+ import Header, { HeaderProps } from '@/components/basic/Header'
6
+ import DrawerNav from '@/navigators/DrawerNav'
7
+ import SplashScreen from '@/screens/Splash'
8
+
9
+ import { AppRoutes, RootStackNavigationParamList } from './types'
10
+
11
+ const Stack = createStackNavigator<RootStackNavigationParamList>()
12
+
13
+ const RootStack = (): React.ReactElement => {
14
+ const renderHeader = (props: HeaderProps) => {
15
+ return (
16
+ <>
17
+ <Header {...props} />
18
+ </>
19
+ )
20
+ }
21
+
22
+ return (
23
+ <Stack.Navigator
24
+ // headerMode="none"
25
+ // headerMode={'float'}
26
+ id={'Root'}
27
+ initialRouteName={AppRoutes.SplashScreen}
28
+ >
29
+ <Stack.Screen
30
+ name={AppRoutes.SplashScreen}
31
+ component={SplashScreen}
32
+ options={{ headerShown: false }}
33
+ />
34
+ <Stack.Screen
35
+ name={AppRoutes.MainDrawerNav}
36
+ component={DrawerNav}
37
+ options={{ headerShown: false }}
38
+ />
39
+ </Stack.Navigator>
40
+ )
41
+ }
42
+
43
+ export default RootStack
@@ -0,0 +1,40 @@
1
+ import { useBackHandler } from '@react-native-community/hooks'
2
+ import { NavigationContainer, Theme as NavigationThemeType } from '@react-navigation/native'
3
+ import React, { FunctionComponent, useCallback } from 'react'
4
+ import { BackHandler, StatusBar } from 'react-native'
5
+ import { useSelector } from 'react-redux'
6
+
7
+ import useTheme from '@/hooks/useTheme'
8
+ import logger from '@/infrastructures/common/logger'
9
+ import { selectLoading } from '@/redux/selectors/nonPersist'
10
+ import { ThemeNavigationTheme } from '@/theme/types'
11
+
12
+ import RootStack from './RootStack'
13
+ import { navigationRef } from './utils'
14
+
15
+ interface IAppContainerProps {
16
+ theme: NavigationThemeType
17
+ }
18
+ const AppNavigationContainer: FunctionComponent<IAppContainerProps> = ({ theme }: IAppContainerProps) => {
19
+ const { Colors, darkMode } = useTheme()
20
+ const { statusBarBackgroundColor } = Colors
21
+
22
+
23
+ const loading = useSelector(selectLoading)
24
+ const onBackPress = useCallback(() => {
25
+ logger.log('onBackPress', loading)
26
+
27
+ return loading
28
+ }, [loading])
29
+ useBackHandler(onBackPress)
30
+
31
+
32
+ return (
33
+ <NavigationContainer ref={navigationRef} theme={theme}>
34
+ <StatusBar barStyle={darkMode ? 'light-content' : 'dark-content'} translucent backgroundColor={statusBarBackgroundColor} />
35
+ <RootStack />
36
+ </NavigationContainer>
37
+ )
38
+ }
39
+
40
+ export default AppNavigationContainer
@@ -0,0 +1,14 @@
1
+ import { BottomTabNavigationProp, BottomTabScreenProps } from '@react-navigation/bottom-tabs'
2
+ import { DrawerScreenProps } from '@react-navigation/drawer'
3
+ import { MaterialTopTabScreenProps } from '@react-navigation/material-top-tabs'
4
+ import { CompositeNavigationProp, CompositeScreenProps, RouteProp } from '@react-navigation/native'
5
+ import { StackNavigationProp, StackScreenProps } from '@react-navigation/stack'
6
+
7
+ import { AppRoutes, RootStackNavigationParamList } from '@/navigators/types'
8
+
9
+ export type RootScreenProps = StackScreenProps<RootStackNavigationParamList>
10
+ export type RootScreenNavigationProp = RootScreenProps['navigation']
11
+
12
+ export type MainDrawerNavScreenProps = StackScreenProps<RootStackNavigationParamList, AppRoutes.MainDrawerNav>
13
+
14
+
@@ -0,0 +1,18 @@
1
+ import { NavigatorScreenParams } from '@react-navigation/native'
2
+
3
+ import { MainDrawerNavigationParamList } from '@/navigators/DrawerNav/types'
4
+
5
+ export enum AppRoutes {
6
+ SplashScreen = 'SplashScreen',
7
+ MainDrawerNav = 'MainDrawerNav',
8
+ MainBottomTabNav = 'MainBottomTabNav',
9
+ HomeScreen = 'HomeScreen',
10
+ SettingsScreen = 'SettingsScreen',
11
+ }
12
+
13
+ export type RootStackNavigationParamList = {
14
+ [AppRoutes.SplashScreen]: undefined
15
+ [AppRoutes.MainDrawerNav]: NavigatorScreenParams<MainDrawerNavigationParamList>|undefined
16
+ }
17
+
18
+
@@ -0,0 +1,68 @@
1
+ import {
2
+ CommonActions,
3
+ createNavigationContainerRef,
4
+ NavigationState,
5
+ PartialRoute,
6
+ PartialState,
7
+ Route,
8
+ } from '@react-navigation/native'
9
+
10
+ // import { NavigationState, PartialState, Route } from '@react-navigation/routers'
11
+ import logger from '@/infrastructures/common/logger'
12
+
13
+ import { RootStackNavigationParamList } from './types'
14
+
15
+ export const navigationRef = createNavigationContainerRef<RootStackNavigationParamList>()
16
+ export const navigate = (name: keyof RootStackNavigationParamList, params: any) => {
17
+ if (navigationRef.isReady()) {
18
+ logger.log('navigate navigationRef ready')
19
+ navigationRef.navigate(name, params)
20
+ } else {
21
+ logger.log('navigate navigationRef not ready')
22
+ }
23
+ }
24
+
25
+ type ResetState =
26
+ | PartialState<NavigationState<RootStackNavigationParamList>>
27
+ | NavigationState<RootStackNavigationParamList>
28
+ | (Omit<NavigationState<RootStackNavigationParamList>, 'routes'> & {
29
+ routes: Omit<Route<string>, 'key'>[]
30
+ })
31
+ export type ResetRoutes = ResetState['routes']
32
+
33
+ export const navigateAndReset = (routes: PartialRoute<Route<NavigationState<RootStackNavigationParamList>['routeNames'][number]>>[] | Omit<Route<string>, 'key'>[], index = 0) => {
34
+ if (navigationRef.isReady()) {
35
+
36
+ navigationRef.dispatch(
37
+ CommonActions.reset({
38
+ index,
39
+ routes,
40
+ }),
41
+ )
42
+ }
43
+ }
44
+
45
+ export const navigateAndSimpleReset = (name: string, params: any = {}, index = 0) => {
46
+ if (navigationRef.isReady()) {
47
+ navigationRef.dispatch(
48
+ CommonActions.reset({
49
+ index,
50
+ routes: [
51
+ {
52
+ name,
53
+ params,
54
+ },
55
+ ],
56
+ }),
57
+ )
58
+ }
59
+ }
60
+
61
+ export const getCurrentRouteName = () => {
62
+ if (navigationRef.isReady()) {
63
+ return navigationRef.current?.getCurrentRoute()?.name
64
+ }
65
+
66
+ return undefined
67
+ }
68
+
@@ -0,0 +1,41 @@
1
+ import type { BaseQueryFn, FetchArgs, FetchBaseQueryError } from '@reduxjs/toolkit/query'
2
+ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
3
+
4
+ import { API_ENDPOINT, API_TIMEOUT } from '@/configs'
5
+ import logger from '@/infrastructures/common/logger'
6
+ import { IBaseResponse } from '@/models/request.model'
7
+
8
+ export const baseQuery = fetchBaseQuery({
9
+ baseUrl: API_ENDPOINT,
10
+ timeout: API_TIMEOUT,
11
+ })
12
+ export const baseQueryWithErrorHandle: BaseQueryFn<
13
+ string | FetchArgs,
14
+ unknown,
15
+ FetchBaseQueryError
16
+ > = async (args, api, extraOptions) => {
17
+ logger.log('baseQueryWithErrorHandle args', args)
18
+ const result = await baseQuery(args, api, extraOptions)
19
+ if (result.data) {
20
+ const data = result.data as IBaseResponse<unknown>
21
+ logger.log('baseQueryWithErrorHandle data', data)
22
+
23
+ if (!data.success) {
24
+ return {
25
+ error: {
26
+ status: result?.meta?.response?.status || 0,
27
+ data: {
28
+ success: false,
29
+ code: data.code,
30
+ message: data.message,
31
+ },
32
+ message: data.message,
33
+ },
34
+ }
35
+ }
36
+
37
+ return result
38
+ }
39
+
40
+ return result
41
+ }
@@ -0,0 +1,26 @@
1
+ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2
+
3
+ import logger from '@/infrastructures/common/logger'
4
+
5
+ export type AppState = {
6
+ selectedMarketId: string|undefined
7
+ }
8
+
9
+ const initialState = { selectedMarketId: undefined } as AppState
10
+ export const appSlice = createSlice({
11
+ name: 'app',
12
+ initialState,
13
+ reducers: {
14
+ setSelectedMarket: (state, action: PayloadAction<{ marketId: string}>) => {
15
+ logger.log('appSlice: setSelectedMarket: action.payload.marketId', action.payload.marketId)
16
+
17
+ return {
18
+ ...state,
19
+ selectedMarketId: action.payload.marketId,
20
+ }
21
+ },
22
+ },
23
+ })
24
+
25
+ export const { setSelectedMarket } = appSlice.actions
26
+ export default appSlice.reducer