@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,21 @@
1
+ import { combineReducers, Middleware } from '@reduxjs/toolkit'
2
+
3
+ import app from './appSlice'
4
+ import nonPersist from './nonPersistSlice'
5
+ import setting from './settingSlice'
6
+ import theme from './themeSlice'
7
+
8
+ export default combineReducers({
9
+ nonPersist,
10
+ setting,
11
+ theme,
12
+ app,
13
+ })
14
+
15
+ export const blacklist = [
16
+ 'appInit',
17
+ 'error',
18
+ 'nonPersist',
19
+ ]
20
+
21
+ export const middlewares: Middleware[] = []
@@ -0,0 +1,51 @@
1
+ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2
+
3
+ export type NonPersistState = {
4
+ initiated: boolean
5
+ loading: boolean
6
+ loadingCount: number
7
+ }
8
+
9
+ const initialState = {
10
+ initiated: false,
11
+ loading: false,
12
+ loadingCount: 0,
13
+ } as NonPersistState
14
+
15
+ export const nonPersistSlice = createSlice({
16
+ name: 'nonPersist',
17
+ initialState,
18
+ reducers: {
19
+ showLoading: (state) => {
20
+ return {
21
+ ...state,
22
+ loadingCount: state.loadingCount + 1,
23
+ loading: true,
24
+ }
25
+ },
26
+ hideLoading: (state) => {
27
+ const newLoadingCount = state.loadingCount - 1 > -1 ? state.loadingCount - 1 : 0
28
+
29
+ return {
30
+ ...state,
31
+ loadingCount: newLoadingCount,
32
+ loading: newLoadingCount > 0,
33
+ }
34
+ },
35
+ hideAllLoading: (state) => {
36
+ return {
37
+ ...state,
38
+ loadingCount: 0,
39
+ loading: false,
40
+ }
41
+ },
42
+ setInitiated: (state, action: PayloadAction<boolean>) => {
43
+ state.initiated = action.payload
44
+ },
45
+ },
46
+ })
47
+
48
+ export const {
49
+ hideAllLoading, hideLoading, setInitiated, showLoading,
50
+ } = nonPersistSlice.actions
51
+ export default nonPersistSlice.reducer
@@ -0,0 +1,48 @@
1
+ import { createSlice, PayloadAction } from '@reduxjs/toolkit'
2
+
3
+ // import { ThemeType } from '@/constants/enum/ThemeType.enum'
4
+ import { Locale, ThemeType } from '@/configs/constants/type'
5
+
6
+ export type SettingState = {
7
+ locale: Locale|undefined
8
+ isNotificationEnabled: boolean
9
+ askedLocationPermission: boolean
10
+ askedLocationPermissionAfterBlocked: boolean
11
+ }
12
+
13
+ const initialState = {
14
+ locale: undefined,
15
+ isNotificationEnabled: false,
16
+ askedLocationPermission: false,
17
+ askedLocationPermissionAfterBlocked: false,
18
+ } as SettingState
19
+
20
+ export const settingSlice = createSlice({
21
+ name: 'setting',
22
+ initialState,
23
+ reducers: {
24
+ setLocale: (state, action: PayloadAction<Locale>) => {
25
+ const locale: Locale = action.payload
26
+
27
+ return {
28
+ ...state,
29
+ locale: action.payload,
30
+ }
31
+ },
32
+ setAskedLocationPermission: (state, action: PayloadAction<boolean>) => {
33
+ return {
34
+ ...state,
35
+ askedLocationPermission: action.payload,
36
+ }
37
+ },
38
+ setAskedLocationPermissionAfterBlocked: (state, action: PayloadAction<boolean>) => {
39
+ return {
40
+ ...state,
41
+ askedLocationPermissionAfterBlocked: action.payload,
42
+ }
43
+ },
44
+ },
45
+ })
46
+
47
+ export const { setAskedLocationPermission, setAskedLocationPermissionAfterBlocked, setLocale } = settingSlice.actions
48
+ export default settingSlice.reducer
@@ -0,0 +1,55 @@
1
+ import { createSlice } from '@reduxjs/toolkit'
2
+
3
+ import { FontScale } from '@/theme/types'
4
+
5
+ type FontScaleType = keyof typeof FontScale
6
+ export type ThemeState = {
7
+ theme: 'default' | null | undefined
8
+ darkMode: boolean | null | undefined
9
+ fontScale: FontScaleType | null | undefined
10
+ }
11
+
12
+ type ThemePayload = {
13
+ payload: {
14
+ theme?: 'default' | null | undefined
15
+ darkMode?: boolean | null | undefined
16
+ fontScale?: FontScaleType | null | undefined
17
+ }
18
+ }
19
+
20
+ const slice = createSlice({
21
+ name: 'theme',
22
+ initialState: {
23
+ theme: null,
24
+ darkMode: null,
25
+ fontScale: FontScale.MEDIUM,
26
+ darkModePreference: 'light',
27
+ } as ThemeState,
28
+ reducers: {
29
+ changeTheme: (state, { payload: { darkMode, fontScale, theme } }: ThemePayload) => {
30
+ if (typeof theme !== 'undefined') {
31
+ state.theme = theme
32
+ }
33
+ if (typeof darkMode !== 'undefined') {
34
+ state.darkMode = darkMode
35
+ }
36
+ if (typeof fontScale !== 'undefined') {
37
+ state.fontScale = fontScale
38
+ }
39
+ },
40
+ setDefaultTheme: (
41
+ state,
42
+ { payload: { darkMode, fontScale, theme } }: ThemePayload,
43
+ ) => {
44
+ if (!state.theme) {
45
+ state.theme = theme
46
+ state.darkMode = darkMode
47
+ state.fontScale = fontScale
48
+ }
49
+ },
50
+ },
51
+ })
52
+
53
+ export const { changeTheme, setDefaultTheme } = slice.actions
54
+
55
+ export default slice.reducer
@@ -0,0 +1,5 @@
1
+ import { all } from 'redux-saga/effects'
2
+
3
+ export default function* rootSaga() {
4
+ yield all([]) // add watchers here
5
+ }
@@ -0,0 +1,21 @@
1
+ import {
2
+ call,
3
+ put,
4
+ select,
5
+ StrictEffect,
6
+ take,
7
+ takeLatest,
8
+ } from 'redux-saga/effects'
9
+ import { ActionType } from 'typesafe-actions'
10
+
11
+ import { Locale } from '@/configs/constants/type'
12
+
13
+ import { setLocale } from '../reducers/settingSlice'
14
+
15
+ export function* handleLocaleChange(action: ActionType<typeof setLocale>): Generator<StrictEffect, void, never> {
16
+ const locale = action.payload
17
+ }
18
+
19
+ export function* watchLocaleChange() {
20
+ yield takeLatest(setLocale.type, handleLocaleChange)
21
+ }
@@ -0,0 +1,9 @@
1
+ import { createSelector } from '@reduxjs/toolkit'
2
+
3
+ import { AppState } from '@/redux/reducers/appSlice'
4
+
5
+ import { RootState } from '../store'
6
+
7
+ export const selectState = (state: RootState): AppState => state.app
8
+
9
+ export const selectSelectedMarketId = createSelector(selectState, (state) => state.selectedMarketId)
@@ -0,0 +1,23 @@
1
+ import { createSelector, Selector } from 'reselect'
2
+
3
+ import { NonPersistState } from '@/redux/reducers/nonPersistSlice'
4
+
5
+ import { RootState } from '../store'
6
+
7
+ export const selectState = (state: RootState): NonPersistState => state.nonPersist
8
+
9
+ export const selectLoading = createSelector<[Selector<RootState, NonPersistState>], boolean>(
10
+ selectState,
11
+ (state: NonPersistState): boolean => {
12
+ const { loadingCount } = state
13
+
14
+ return loadingCount > 0
15
+ }
16
+ )
17
+
18
+ export const selectInitiated = createSelector<[Selector<RootState, NonPersistState>], boolean>(
19
+ selectState,
20
+ (state: NonPersistState): boolean => {
21
+ return state.initiated
22
+ }
23
+ )
@@ -0,0 +1,29 @@
1
+ import { createSelector } from '@reduxjs/toolkit'
2
+
3
+ import { SettingState } from '@/redux/reducers/settingSlice'
4
+
5
+ import { RootState } from '../store'
6
+
7
+ export const selectState = (state: RootState): SettingState => state.setting
8
+
9
+ export const selectLocale = createSelector(
10
+ selectState,
11
+ (state: SettingState) => state.locale
12
+ )
13
+
14
+ export const selectApiLocale = createSelector(
15
+ selectState,
16
+ (state: SettingState) => {
17
+ return state.locale?.replace('_', '-')
18
+ }
19
+ )
20
+
21
+ export const selectAskedLocationPermission = createSelector(
22
+ selectState,
23
+ (state: SettingState) => state.askedLocationPermission
24
+ )
25
+
26
+ export const selectAskedLocationPermissionAfterBlocked = createSelector(
27
+ selectState,
28
+ (state: SettingState) => state.askedLocationPermissionAfterBlocked
29
+ )
@@ -0,0 +1,13 @@
1
+ import { createSelector, Selector } from 'reselect'
2
+
3
+ import { SettingState } from '@/redux/reducers/settingSlice'
4
+ import { ThemeState } from '@/redux/reducers/themeSlice'
5
+
6
+ import { RootState } from '../store'
7
+
8
+ export const selectState = (state: RootState): ThemeState => state.theme
9
+
10
+ export const selectFontScale = createSelector(
11
+ selectState,
12
+ (state: ThemeState) => state.fontScale
13
+ )
@@ -0,0 +1,79 @@
1
+ /* eslint-disable @typescript-eslint/no-var-requires */
2
+ import 'regenerator-runtime/runtime'
3
+
4
+ import AsyncStorage from '@react-native-async-storage/async-storage'
5
+ import { combineReducers, configureStore, Middleware, StoreEnhancer } from '@reduxjs/toolkit'
6
+ import { Platform } from 'react-native'
7
+ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
8
+ // import createDebugger from 'redux-flipper'
9
+ import {
10
+ createMigrate,
11
+ FLUSH,
12
+ MigrationManifest,
13
+ PAUSE,
14
+ PERSIST,
15
+ PersistedState,
16
+ persistReducer,
17
+ persistStore,
18
+ PURGE,
19
+ REGISTER,
20
+ REHYDRATE,
21
+ } from 'redux-persist'
22
+
23
+ import rootReducer, { blacklist, middlewares } from '@/redux/reducers'
24
+
25
+ import reactotron from '../../../ReactotronConfig'
26
+
27
+ const MIGRATION_DEBUG = true
28
+ const migrations: MigrationManifest = {
29
+ // eslint-disable-next-line @typescript-eslint/naming-convention
30
+ 0: (previousVersionState: PersistedState) => {
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
32
+ return previousVersionState
33
+ },
34
+ }
35
+ const persistConfig = {
36
+ key: 'root',
37
+ version: 0,
38
+ storage: AsyncStorage,
39
+ blacklist: [...blacklist],
40
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
41
+ // transforms: [immutableTransform()],
42
+ migrate: createMigrate(migrations, { debug: MIGRATION_DEBUG }),
43
+ }
44
+ const persistedReducer = persistReducer(persistConfig, rootReducer)
45
+
46
+ const store = configureStore({
47
+ devTools: true,
48
+ reducer: persistedReducer,
49
+ middleware: (getDefaultMiddleware) => {
50
+ const debugMiddlewares: Middleware[] = []
51
+ if (__DEV__ && !process.env.JEST_WORKER_ID) {
52
+ // debugMiddlewares.push(createDebugger() as Middleware)
53
+ }
54
+
55
+ return getDefaultMiddleware({
56
+ thunk: true,
57
+ serializableCheck: {
58
+ ignoredActions: [
59
+ FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER,
60
+ ],
61
+ },
62
+ })
63
+ .concat(middlewares)
64
+ .concat(debugMiddlewares)
65
+ },
66
+ enhancers: getDefaultEnhancers => __DEV__ ? getDefaultEnhancers().concat(reactotron.createEnhancer()) : getDefaultEnhancers(),
67
+ })
68
+
69
+ const persistor = persistStore(store)
70
+
71
+ export const useAppDispatch = () => useDispatch<AppDispatch>()
72
+ export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
73
+
74
+ export { persistor, store }
75
+
76
+ // Infer the `RootState` and `AppDispatch` types from the store itself
77
+ export type RootState = ReturnType<typeof store.getState>
78
+ // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
79
+ export type AppDispatch = typeof store.dispatch
@@ -0,0 +1,5 @@
1
+ declare module 'MyStoreTypes' {
2
+ export type RootAction = ActionType<typeof import('../actions').default>;
3
+ export type RootState = StateType<typeof import('../reducers').default>;
4
+ export type Store = StateType<typeof import('./index').default>;
5
+ }
@@ -0,0 +1,146 @@
1
+ import { REACT_APP_DEBUG } from '@env'
2
+ import React from 'react'
3
+ import { Alert, ScrollView, View } from 'react-native'
4
+ import { List, TextInput } from 'react-native-paper'
5
+
6
+ import {
7
+ Body,
8
+ Button,
9
+ Container,
10
+ Content,
11
+ IconX,
12
+ MaterialTextInput,
13
+ } from '@/components/basic'
14
+ import useTheme from '@/hooks/useTheme'
15
+ import logger from '@/infrastructures/common/logger'
16
+ import { EncryptHelper } from '@/utils/encrypt-helper'
17
+
18
+ const HomeScreen = () => {
19
+ const { Layout } = useTheme()
20
+
21
+ const test = async () => {
22
+ logger.log('test start')
23
+ const result = await EncryptHelper.encryptData('test')
24
+ logger.log('test end result', result)
25
+ }
26
+
27
+ void test()
28
+
29
+ const [expanded, setExpanded] = React.useState(true)
30
+
31
+ const handlePress = () => setExpanded(!expanded)
32
+
33
+ return (
34
+ <Container insetTop>
35
+ <ScrollView
36
+ style={[Layout.fullWidth]}
37
+ >
38
+ <Body>
39
+ <Button type="text" icon={<IconX origin={IconX.IONICONS} name="home" />} text="Login" />
40
+ <Content tPadding={'tiny'}>
41
+ <IconX origin={IconX.ANT_DESIGN} name="home" />
42
+ </Content>
43
+ <Content tPadding={'small'}>
44
+ <View
45
+ style={{
46
+ width: '100%',
47
+ backgroundColor: 'yellow',
48
+ }}
49
+ >
50
+ <MaterialTextInput
51
+ mode="outlined"
52
+ label="Label"
53
+ style={{
54
+ backgroundColor: 'transparent',
55
+ }}
56
+ />
57
+ </View>
58
+ </Content>
59
+ <Content tPadding={'tiny'}>
60
+ <View
61
+ style={{
62
+ width: '100%',
63
+ }}
64
+ >
65
+ <MaterialTextInput
66
+ style={{
67
+ // backgroundColor: 'green',
68
+ }}
69
+ secureTextEntry
70
+ showEye
71
+ textContentType="password"
72
+ />
73
+ </View>
74
+ </Content>
75
+ <Content tPadding={'tiny'}>
76
+ <TextInput />
77
+ </Content>
78
+ <Content tPadding={'tiny'}>
79
+ <Button
80
+ type="icon"
81
+ icon={<IconX origin={IconX.IONICONS} name="send" />}
82
+ />
83
+ </Content>
84
+ <List.Section title="Accordions">
85
+ <List.Accordion
86
+ title="Uncontrolled Accordion"
87
+ left={props => <List.Icon {...props} icon="folder" />}
88
+ >
89
+ <List.Item title="First item" />
90
+ <List.Item title="Second item" />
91
+ </List.Accordion>
92
+ <List.Accordion
93
+ title="Uncontrolled Accordion"
94
+ left={props => <List.Icon {...props} icon="folder" />}
95
+ >
96
+ <List.Item title="First item" />
97
+ <List.Item title="Second item" />
98
+ </List.Accordion>
99
+ <List.Accordion
100
+ title="Uncontrolled Accordion"
101
+ left={props => <List.Icon {...props} icon="folder" />}
102
+ >
103
+ <List.Item title="First item" />
104
+ <List.Item title="Second item" />
105
+ </List.Accordion>
106
+
107
+ <List.Accordion
108
+ title="Controlled Accordion"
109
+ left={props => <List.Icon {...props} icon="folder" />}
110
+ expanded={expanded}
111
+ onPress={handlePress}
112
+ >
113
+ <List.Item title="First item" />
114
+ <List.Item title="Second item" />
115
+ </List.Accordion>
116
+ </List.Section>
117
+ <List.Section title="Accordions">
118
+ <List.Accordion
119
+ title="Uncontrolled Accordion"
120
+ left={props => <List.Icon {...props} icon="folder" />}
121
+ >
122
+ <List.Item title="First item" />
123
+ <List.Item title="Second item" />
124
+ </List.Accordion>
125
+ <List.Accordion
126
+ title="Uncontrolled Accordion"
127
+ left={props => <List.Icon {...props} icon="folder" />}
128
+ >
129
+ <List.Item title="First item" />
130
+ <List.Item title="Second item" />
131
+ </List.Accordion>
132
+ <List.Accordion
133
+ title="Uncontrolled Accordion"
134
+ left={props => <List.Icon {...props} icon="folder" />}
135
+ >
136
+ <List.Item title="First item" />
137
+ <List.Item title="Second item" />
138
+ </List.Accordion>
139
+ </List.Section>
140
+ </Body>
141
+ </ScrollView>
142
+ </Container>
143
+ )
144
+ }
145
+
146
+ export default HomeScreen
@@ -0,0 +1,45 @@
1
+ import React, { PropsWithChildren, useMemo } from 'react'
2
+ import { StyleSheet, TouchableOpacity, View } from 'react-native'
3
+ import { Divider, Text } from 'react-native-paper'
4
+
5
+ import { Content, PressableOpacity } from '@/components/basic'
6
+ import useTheme from '@/hooks/useTheme'
7
+ import { Theme } from '@/theme/types'
8
+
9
+ export interface IItemProps extends PropsWithChildren {
10
+ onPress?: () => void|undefined
11
+ }
12
+ const Item: React.FC<IItemProps> = ({ children, onPress }) => {
13
+ const theme = useTheme()
14
+ const { Colors, Fonts, Gutters, Layout } = theme
15
+ const styles = useMemo(() => {
16
+ return makeStyles(theme)
17
+ }, [theme])
18
+
19
+ return (
20
+ <View>
21
+ <PressableOpacity
22
+ activeOpacity={onPress !== undefined ? .6 : 1}
23
+ onPress={onPress}
24
+ >
25
+ <Content
26
+ style={[styles.Item]}
27
+ >
28
+ {children}
29
+ </Content>
30
+ </PressableOpacity>
31
+ <Divider/>
32
+ </View>
33
+ )
34
+ }
35
+
36
+ const makeStyles = (theme: Theme) => StyleSheet.create({
37
+ Item: {
38
+ minHeight: 50,
39
+ justifyContent: 'center',
40
+ // borderBottomWidth: 1,
41
+ // borderBottomColor: theme.Colors.border,
42
+ },
43
+ })
44
+
45
+ export default Item
@@ -0,0 +1,97 @@
1
+ import React from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { ScrollView, View } from 'react-native'
4
+ import DeviceInfo from 'react-native-device-info'
5
+ import { useDispatch, useSelector } from 'react-redux'
6
+
7
+ import { Body, ButtonGroup, Container, Text } from '@/components/basic'
8
+ import { Locale } from '@/configs/constants/type'
9
+ import useTheme from '@/hooks/useTheme.ts'
10
+ import { setLocale } from '@/redux/reducers/settingSlice.ts'
11
+ import { selectLocale } from '@/redux/selectors/setting.ts'
12
+ import Item from '@/screens/Settings/components/Item.tsx'
13
+ import Dialogs from '@/services/Dialogs'
14
+ import { normalize } from '@/utils'
15
+
16
+ const SettingsScreen = () => {
17
+ const buildNumber = DeviceInfo.getBuildNumber()
18
+ const version = DeviceInfo.getVersion()
19
+
20
+ const dispatch = useDispatch()
21
+ const { t } = useTranslation()
22
+ const theme = useTheme()
23
+ const { Colors, Fonts, Gutters, Layout } = theme
24
+
25
+ const lang = useSelector(selectLocale)
26
+
27
+ const onChangeLocale = (value: Locale) => {
28
+ // dispatch(setLocale(value))
29
+ Dialogs.confirm({
30
+ content: 'Are you sure you want to change language?',
31
+ onConfirm: () => {
32
+ dispatch(setLocale(value))
33
+ },
34
+ })
35
+ }
36
+
37
+ return (
38
+ <Container insetTop>
39
+ <Body>
40
+ <ScrollView overScrollMode={'never'}>
41
+ <View>
42
+ <Item>
43
+ <View style={[Layout.row, Layout.fill]} >
44
+ <View
45
+ style={[Layout.justifyContentCenter]}
46
+ >
47
+ <Text variant={'settingText'}>{t('general:version')}</Text>
48
+ </View>
49
+ <View
50
+ style={[Layout.fill, Layout.justifyContentCenter, Layout.alignItemsEnd]}
51
+ >
52
+ <Text variant={'settingText'}>{t('general:version_stringb', { version_name: version ?? '', build: buildNumber ?? '' })}</Text>
53
+ </View>
54
+ </View>
55
+ </Item>
56
+ <Item>
57
+ <View
58
+ style={[Layout.row, Layout.fill]}
59
+ >
60
+ <View
61
+ style={[Layout.justifyContentCenter]}
62
+ >
63
+ <Text variant={'settingText'}>{t('setting:language')}</Text>
64
+ </View>
65
+ <View
66
+ style={[Layout.fill, Layout.justifyContentCenter, Layout.alignItemsEnd]}
67
+ >
68
+ <ButtonGroup
69
+ value={lang}
70
+ options={[
71
+ {
72
+ label: '繁中',
73
+ value: Locale.zhTW,
74
+ },
75
+ {
76
+ label: 'EN',
77
+ value: Locale.enUS,
78
+ },
79
+ ]}
80
+ onSelect={(value) => {
81
+ onChangeLocale(value)
82
+ }}
83
+ style={{ maxWidth: 140 }}
84
+ backgroundColor={'white'}
85
+ radius={normalize(20)}
86
+ />
87
+ </View>
88
+ </View>
89
+ </Item>
90
+ </View>
91
+ </ScrollView>
92
+ </Body>
93
+ </Container>
94
+ )
95
+ }
96
+
97
+ export default SettingsScreen