@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.
- package/.github/workflows/npm-publish.yml +28 -0
- package/.vscode/settings.json +15 -0
- package/README.md +58 -0
- package/package.json +16 -0
- package/template/.bundle/config +2 -0
- package/template/.env.development +1 -0
- package/template/.env.production +1 -0
- package/template/.eslintrc.js +392 -0
- package/template/.java-version +1 -0
- package/template/.prettierrc.js +5 -0
- package/template/.ruby-version +1 -0
- package/template/.watchmanconfig +1 -0
- package/template/Gemfile +23 -0
- package/template/Gemfile.lock +330 -0
- package/template/README.md +97 -0
- package/template/ReactotronConfig.js +17 -0
- package/template/__tests__/App.test.tsx +13 -0
- package/template/_gitignore +75 -0
- package/template/_node-version +1 -0
- package/template/android/app/build.gradle +162 -0
- package/template/android/app/debug.keystore +0 -0
- package/template/android/app/proguard-rules.pro +10 -0
- package/template/android/app/src/debug/AndroidManifest.xml +9 -0
- package/template/android/app/src/main/AndroidManifest.xml +26 -0
- package/template/android/app/src/main/java/com/projectname/MainActivity.kt +30 -0
- package/template/android/app/src/main/java/com/projectname/MainApplication.kt +27 -0
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/values/strings.xml +3 -0
- package/template/android/app/src/main/res/values/styles.xml +9 -0
- package/template/android/build.gradle +37 -0
- package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/template/android/gradle.properties +48 -0
- package/template/android/gradlew +251 -0
- package/template/android/gradlew.bat +99 -0
- package/template/android/keystore/keystore.properties +4 -0
- package/template/android/settings.gradle +6 -0
- package/template/android/version.properties +2 -0
- package/template/app.json +4 -0
- package/template/babel.config.js +38 -0
- package/template/fastlane/Fastfile +136 -0
- package/template/fastlane/Pluginfile +9 -0
- package/template/fastlane/README.md +46 -0
- package/template/index.js +9 -0
- package/template/ios/.xcode.env +11 -0
- package/template/ios/Podfile +35 -0
- package/template/ios/Podfile.lock +3669 -0
- package/template/ios/ProjectName/AppDelegate.swift +48 -0
- package/template/ios/ProjectName/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/template/ios/ProjectName/Images.xcassets/Contents.json +6 -0
- package/template/ios/ProjectName/Info.plist +66 -0
- package/template/ios/ProjectName/LaunchScreen.storyboard +47 -0
- package/template/ios/ProjectName/PrivacyInfo.xcprivacy +47 -0
- package/template/ios/ProjectName.xcodeproj/project.pbxproj +482 -0
- package/template/ios/ProjectName.xcodeproj/xcshareddata/xcschemes/ProjectName.xcscheme +88 -0
- package/template/ios/ProjectName.xcworkspace/contents.xcworkspacedata +10 -0
- package/template/jest.config.js +3 -0
- package/template/metro.config.js +20 -0
- package/template/package-lock.json +17073 -0
- package/template/package.json +156 -0
- package/template/src/@types/emotion.d.ts +12 -0
- package/template/src/@types/env.d.ts +3 -0
- package/template/src/@types/redux-persist-transform-immutable.d.ts +1 -0
- package/template/src/@types/typing.d.ts +17 -0
- package/template/src/AppContainer.tsx +109 -0
- package/template/src/assets/images/143.png +0 -0
- package/template/src/assets/index.ts +13 -0
- package/template/src/components/basic/BackButton/index.tsx +34 -0
- package/template/src/components/basic/Body/index.tsx +68 -0
- package/template/src/components/basic/Button/index.tsx +181 -0
- package/template/src/components/basic/Button/utils.ts +78 -0
- package/template/src/components/basic/ButtonGroup/index.tsx +182 -0
- package/template/src/components/basic/Card/index.tsx +3 -0
- package/template/src/components/basic/Container/index.tsx +38 -0
- package/template/src/components/basic/Content/index.tsx +87 -0
- package/template/src/components/basic/DropDown/index.tsx +354 -0
- package/template/src/components/basic/ExpandableOverlay/index.tsx +113 -0
- package/template/src/components/basic/Header/index.tsx +216 -0
- package/template/src/components/basic/Header/styles.ts +0 -0
- package/template/src/components/basic/Icons/index.tsx +131 -0
- package/template/src/components/basic/InputLabel/index.tsx +19 -0
- package/template/src/components/basic/LoadingOverlay/index.tsx +68 -0
- package/template/src/components/basic/MaterialTextInput/index.tsx +153 -0
- package/template/src/components/basic/NumberInput/index.tsx +53 -0
- package/template/src/components/basic/Picker/PickerContext.ts +7 -0
- package/template/src/components/basic/Picker/PickerHeader.tsx +130 -0
- package/template/src/components/basic/Picker/PickerItem.tsx +105 -0
- package/template/src/components/basic/Picker/PickerItemsList.tsx +135 -0
- package/template/src/components/basic/Picker/PickerPresenter.ts +54 -0
- package/template/src/components/basic/Picker/hooks/useImperativePickerHandle.ts +27 -0
- package/template/src/components/basic/Picker/hooks/usePickerLabel.ts +74 -0
- package/template/src/components/basic/Picker/hooks/usePickerSearch.ts +37 -0
- package/template/src/components/basic/Picker/hooks/usePickerSelection.ts +57 -0
- package/template/src/components/basic/Picker/index.tsx +284 -0
- package/template/src/components/basic/Picker/types.tsx +229 -0
- package/template/src/components/basic/PressableOpacity/index.tsx +20 -0
- package/template/src/components/basic/RootDialog/Dialog.tsx +246 -0
- package/template/src/components/basic/RootDialog/Manager.tsx +110 -0
- package/template/src/components/basic/RootDialog/animations/Animation.ts +29 -0
- package/template/src/components/basic/RootDialog/animations/FadeAnimation.ts +40 -0
- package/template/src/components/basic/RootDialog/animations/ScaleAnimation.ts +37 -0
- package/template/src/components/basic/RootDialog/animations/SlideAnimation.ts +89 -0
- package/template/src/components/basic/RootDialog/components/Backdrop.tsx +60 -0
- package/template/src/components/basic/RootDialog/components/BaseDialog.tsx +564 -0
- package/template/src/components/basic/RootDialog/components/BottomDialog.tsx +32 -0
- package/template/src/components/basic/RootDialog/components/DialogButton.tsx +87 -0
- package/template/src/components/basic/RootDialog/components/DialogContent.tsx +26 -0
- package/template/src/components/basic/RootDialog/components/DialogContext.tsx +8 -0
- package/template/src/components/basic/RootDialog/components/DialogFooter.tsx +42 -0
- package/template/src/components/basic/RootDialog/components/DialogTitle.tsx +53 -0
- package/template/src/components/basic/RootDialog/components/DraggableView.tsx +271 -0
- package/template/src/components/basic/RootDialog/index.ts +21 -0
- package/template/src/components/basic/RootDialog/type.ts +102 -0
- package/template/src/components/basic/Text/index.tsx +8 -0
- package/template/src/components/basic/index.ts +35 -0
- package/template/src/configs/constants/type/APIStatus.type.ts +8 -0
- package/template/src/configs/constants/type/Locale.type.ts +7 -0
- package/template/src/configs/constants/type/StorageKey.type.ts +7 -0
- package/template/src/configs/constants/type/ThemeType.type.ts +6 -0
- package/template/src/configs/constants/type/index.ts +11 -0
- package/template/src/configs/index.ts +22 -0
- package/template/src/contexts/ThemeContext.ts +6 -0
- package/template/src/hooks/useAppLoading.ts +26 -0
- package/template/src/hooks/useAppState.ts +36 -0
- package/template/src/hooks/useArray.ts +47 -0
- package/template/src/hooks/useAsync.ts +42 -0
- package/template/src/hooks/useAsyncStorage.ts +41 -0
- package/template/src/hooks/useBoolean.ts +21 -0
- package/template/src/hooks/useBuildTheme.ts +249 -0
- package/template/src/hooks/useCountDown.ts +111 -0
- package/template/src/hooks/useCounter.ts +27 -0
- package/template/src/hooks/useDebounce.ts +25 -0
- package/template/src/hooks/useDebouncedValidate.ts +32 -0
- package/template/src/hooks/useDebugInformation.ts +38 -0
- package/template/src/hooks/useDeviceToken.ts +20 -0
- package/template/src/hooks/useEncryptedStorage.ts +41 -0
- package/template/src/hooks/useFontFamily.ts +13 -0
- package/template/src/hooks/useHttp.ts +18 -0
- package/template/src/hooks/useInterval.ts +24 -0
- package/template/src/hooks/useIsForeground.ts +17 -0
- package/template/src/hooks/useMMKVStorage.ts +0 -0
- package/template/src/hooks/usePrevious.ts +12 -0
- package/template/src/hooks/useRenderCount.ts +10 -0
- package/template/src/hooks/useTheme.ts +17 -0
- package/template/src/hooks/useTimeCountDown.ts +91 -0
- package/template/src/index.tsx +65 -0
- package/template/src/infrastructures/NetClient/AbstractClient.ts +66 -0
- package/template/src/infrastructures/NetClient/ApiResponse.ts +16 -0
- package/template/src/infrastructures/NetClient/ApisauceClient.ts +76 -0
- package/template/src/infrastructures/NetClient/AxiosClient.ts +80 -0
- package/template/src/infrastructures/NetClient/FetchNetClient.ts +120 -0
- package/template/src/infrastructures/NetClient/config.ts +3 -0
- package/template/src/infrastructures/NetClient/interfaces/INetClient.ts +6 -0
- package/template/src/infrastructures/Storage/IStorage.ts +7 -0
- package/template/src/infrastructures/Storage/MMKVStorage.ts +41 -0
- package/template/src/infrastructures/common/Timeout.ts +27 -0
- package/template/src/infrastructures/common/colorUtils.ts +82 -0
- package/template/src/infrastructures/common/dateUtils.ts +39 -0
- package/template/src/infrastructures/common/logger.ts +115 -0
- package/template/src/locales/en-US/general.json +26 -0
- package/template/src/locales/en-US/index.ts +9 -0
- package/template/src/locales/en-US/screens.json +4 -0
- package/template/src/locales/en-US/setting.json +3 -0
- package/template/src/locales/i18n.ts +109 -0
- package/template/src/locales/zh-TW/general.json +26 -0
- package/template/src/locales/zh-TW/index.ts +9 -0
- package/template/src/locales/zh-TW/screens.json +4 -0
- package/template/src/locales/zh-TW/setting.json +3 -0
- package/template/src/models/index.ts +5 -0
- package/template/src/models/request.model.ts +50 -0
- package/template/src/navigators/DrawerNav/DrawerContent.tsx +66 -0
- package/template/src/navigators/DrawerNav/DrawerItem.tsx +261 -0
- package/template/src/navigators/DrawerNav/index.tsx +39 -0
- package/template/src/navigators/DrawerNav/props.ts +12 -0
- package/template/src/navigators/DrawerNav/types.ts +8 -0
- package/template/src/navigators/MainBottomTabNav/index.tsx +83 -0
- package/template/src/navigators/MainBottomTabNav/props.ts +16 -0
- package/template/src/navigators/MainBottomTabNav/types.ts +6 -0
- package/template/src/navigators/RootStack.tsx +43 -0
- package/template/src/navigators/index.tsx +40 -0
- package/template/src/navigators/props.ts +14 -0
- package/template/src/navigators/types.ts +18 -0
- package/template/src/navigators/utils.ts +68 -0
- package/template/src/redux/api/api.ts +41 -0
- package/template/src/redux/reducers/appSlice.ts +26 -0
- package/template/src/redux/reducers/index.ts +21 -0
- package/template/src/redux/reducers/nonPersistSlice.ts +51 -0
- package/template/src/redux/reducers/settingSlice.ts +48 -0
- package/template/src/redux/reducers/themeSlice.ts +55 -0
- package/template/src/redux/saga/index.ts +5 -0
- package/template/src/redux/saga/settingSaga.ts +21 -0
- package/template/src/redux/selectors/app.ts +9 -0
- package/template/src/redux/selectors/nonPersist.ts +23 -0
- package/template/src/redux/selectors/setting.ts +29 -0
- package/template/src/redux/selectors/theme.ts +13 -0
- package/template/src/redux/store/index.ts +79 -0
- package/template/src/redux/store/types.d.ts +5 -0
- package/template/src/screens/Home/index.tsx +146 -0
- package/template/src/screens/Settings/components/Item.tsx +45 -0
- package/template/src/screens/Settings/index.tsx +97 -0
- package/template/src/screens/Splash/index.tsx +53 -0
- package/template/src/services/Dialogs.tsx +226 -0
- package/template/src/services/PermissionCheck.ts +257 -0
- package/template/src/theme/Common.ts +48 -0
- package/template/src/theme/Fonts.ts +196 -0
- package/template/src/theme/Gutters.ts +63 -0
- package/template/src/theme/Icons.ts +28 -0
- package/template/src/theme/Images.ts +13 -0
- package/template/src/theme/Layout.ts +106 -0
- package/template/src/theme/Variables.ts +167 -0
- package/template/src/theme/components/Buttons.ts +37 -0
- package/template/src/theme/index.ts +8 -0
- package/template/src/theme/metrics.ts +57 -0
- package/template/src/theme/themes/default_dark/Images.ts +7 -0
- package/template/src/theme/themes/default_dark/Variables.ts +84 -0
- package/template/src/theme/themes/default_dark/index.ts +2 -0
- package/template/src/theme/themes/index.ts +8 -0
- package/template/src/theme/types.ts +152 -0
- package/template/src/utils/encrypt-helper.ts +118 -0
- package/template/src/utils/index.ts +76 -0
- package/template/src/utils/sys-info-data.ts +17 -0
- package/template/tsconfig.json +44 -0
- package/template.config.js +8 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import APIResponse from '../ApiResponse'
|
|
2
|
+
|
|
3
|
+
export interface INetClient {
|
|
4
|
+
get<T>(path: string, params: Record<string, any>, headerParams: Record<string, string>): Promise<APIResponse<T>>
|
|
5
|
+
postJson<T>(path: string, json: Record<string, any>, headerParams: Record<string, string>): Promise<APIResponse<T>>
|
|
6
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MMKV } from 'react-native-mmkv'
|
|
2
|
+
|
|
3
|
+
import { IStorage } from '@/infrastructures/Storage/IStorage'
|
|
4
|
+
|
|
5
|
+
const storage = new MMKV()
|
|
6
|
+
|
|
7
|
+
export class MMKVStorage implements IStorage {
|
|
8
|
+
getItem = async (key: string) => {
|
|
9
|
+
const value = storage.getString(key)
|
|
10
|
+
|
|
11
|
+
return Promise.resolve(value ?? null)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
setItem = async (key: string, value: string) => {
|
|
15
|
+
return new Promise<boolean>((resolve) => {
|
|
16
|
+
storage.set(key, value)
|
|
17
|
+
|
|
18
|
+
return resolve(true)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
removeItem = async (key: string) => {
|
|
23
|
+
storage.delete(key)
|
|
24
|
+
|
|
25
|
+
return Promise.resolve()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getAllKeys = async () => {
|
|
29
|
+
const value = storage.getAllKeys()
|
|
30
|
+
|
|
31
|
+
return Promise.resolve(value)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
clear = async () => {
|
|
35
|
+
storage.clearAll()
|
|
36
|
+
|
|
37
|
+
return Promise.resolve()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { storage }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class Timeout<T> {
|
|
2
|
+
timeout: number
|
|
3
|
+
timeoutID: NodeJS.Timeout|undefined
|
|
4
|
+
constructor(config: { ms?: number } = {}) {
|
|
5
|
+
this.timeout = config.ms || 10000
|
|
6
|
+
this.timeoutID = undefined
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public start() {
|
|
10
|
+
return new Promise<T>((resolve, reject) => {
|
|
11
|
+
this.timeoutID = setTimeout(() => {
|
|
12
|
+
reject('timeout')
|
|
13
|
+
// this.clear();
|
|
14
|
+
}, this.timeout)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public clear() {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
20
|
+
if (this.timeoutID !== undefined) {
|
|
21
|
+
clearTimeout(this.timeoutID)
|
|
22
|
+
this.timeoutID = undefined
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default Timeout
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import color from 'tinycolor2'
|
|
2
|
+
|
|
3
|
+
const hex2RGB = (hex: string): number[] => {
|
|
4
|
+
if (hex.charAt(0) === '#') {
|
|
5
|
+
hex = hex.substring(1)
|
|
6
|
+
}
|
|
7
|
+
if ((hex.length < 2) || (hex.length > 6)) {
|
|
8
|
+
return []
|
|
9
|
+
}
|
|
10
|
+
const values = hex.split('')
|
|
11
|
+
let r
|
|
12
|
+
let g
|
|
13
|
+
let b
|
|
14
|
+
|
|
15
|
+
if (hex.length === 2) {
|
|
16
|
+
r = parseInt(values[0].toString() + values[1].toString(), 16)
|
|
17
|
+
g = r
|
|
18
|
+
b = r
|
|
19
|
+
} else if (hex.length === 3) {
|
|
20
|
+
r = parseInt(values[0].toString() + values[0].toString(), 16)
|
|
21
|
+
g = parseInt(values[1].toString() + values[1].toString(), 16)
|
|
22
|
+
b = parseInt(values[2].toString() + values[2].toString(), 16)
|
|
23
|
+
} else if (hex.length === 6) {
|
|
24
|
+
r = parseInt(values[0].toString() + values[1].toString(), 16)
|
|
25
|
+
g = parseInt(values[2].toString() + values[3].toString(), 16)
|
|
26
|
+
b = parseInt(values[4].toString() + values[5].toString(), 16)
|
|
27
|
+
} else {
|
|
28
|
+
return []
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return [r, g, b]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const hex2RGBColor = (hex: string, opacity: number = 1.0) => {
|
|
35
|
+
const rgb: number[] = hex2RGB(hex)
|
|
36
|
+
if (rgb.length === 3) {
|
|
37
|
+
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${opacity})`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const isDark = ({ backgroundColor, dark }: {
|
|
44
|
+
dark?: boolean
|
|
45
|
+
backgroundColor?: string
|
|
46
|
+
}) => {
|
|
47
|
+
if (typeof dark === 'boolean') {
|
|
48
|
+
return dark
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (backgroundColor === 'transparent') {
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (backgroundColor !== 'transparent') {
|
|
56
|
+
return !color(backgroundColor)
|
|
57
|
+
.isLight()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const rgbToHex = (rgb: string, forceRemoveAlpha = false) => {
|
|
64
|
+
const rgbArray = rgb.split(',')
|
|
65
|
+
const r = parseInt(rgbArray[0].split('(')[1], 10)
|
|
66
|
+
const g = parseInt(rgbArray[1], 10)
|
|
67
|
+
const b = parseInt(rgbArray[2], 10)
|
|
68
|
+
const a = forceRemoveAlpha ? 1 : parseFloat(rgbArray[3])
|
|
69
|
+
const alpha = parseFloat(rgbArray[3])
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
hex: color({ r, g, b }).toHex(),
|
|
73
|
+
alpha,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
hex2RGB,
|
|
79
|
+
hex2RGBColor,
|
|
80
|
+
isDark,
|
|
81
|
+
rgbToHex,
|
|
82
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import moment from 'moment'
|
|
2
|
+
|
|
3
|
+
import { Locale } from '@/configs/constants/type'
|
|
4
|
+
|
|
5
|
+
const formatDate = (date: Date, format: string = 'YYYY-MM-DD HH:mm:ss') => {
|
|
6
|
+
const momentDate = moment(date)
|
|
7
|
+
|
|
8
|
+
return momentDate.format(format)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const parseDate = (dateText?: string, format: string = 'YYYY-MM-DD') => {
|
|
12
|
+
if (dateText === undefined) {
|
|
13
|
+
return undefined
|
|
14
|
+
}
|
|
15
|
+
const momentDate = moment(dateText, format)
|
|
16
|
+
|
|
17
|
+
return momentDate.toDate()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const convertDateTextObject = (dateText?: string, fromFormat: string = 'YYYY-MM-DD', lang: Locale = Locale.enUS, toEnMonthFormat = 'MMM') => {
|
|
22
|
+
if (dateText === undefined) {
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
const momentDate = moment(dateText, fromFormat)
|
|
26
|
+
const monthFormat = lang === Locale.enUS ? toEnMonthFormat : 'M'
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
year: momentDate.format('YYYY'),
|
|
30
|
+
month: momentDate.format(monthFormat),
|
|
31
|
+
day: momentDate.format('D'),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
convertDateTextObject,
|
|
37
|
+
formatDate,
|
|
38
|
+
parseDate,
|
|
39
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
import { REACT_APP_DEBUG } from '@env'
|
|
5
|
+
import { ApiResponse } from 'apisauce'
|
|
6
|
+
import { AxiosResponse } from 'axios'
|
|
7
|
+
import clc from 'cli-color'
|
|
8
|
+
|
|
9
|
+
import { ITypedMap } from '@/models'
|
|
10
|
+
|
|
11
|
+
import APIResponse from '../NetClient/ApiResponse'
|
|
12
|
+
|
|
13
|
+
const log = (message?: any, ...para: any[]) => {
|
|
14
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
15
|
+
if (para === undefined || para === null || para.length === 0) {
|
|
16
|
+
console.log(`${clc.greenBright(message)}`)
|
|
17
|
+
} else if (para && para.length === 1) {
|
|
18
|
+
console.log(`${clc.greenBright(message)}`, para[0])
|
|
19
|
+
} else {
|
|
20
|
+
console.log(`${clc.greenBright(message)}`, para)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const debug = (message?: any, ...para: any[]): void => {
|
|
25
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
26
|
+
if (para === undefined || para === null || para.length === 0) {
|
|
27
|
+
console.debug(`${clc.green(message)}`)
|
|
28
|
+
} else if (para && para.length === 1) {
|
|
29
|
+
console.debug(`${clc.green(message)}`, para[0])
|
|
30
|
+
} else {
|
|
31
|
+
console.debug(`${clc.green(message)}`, para)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const info = (message: string): void => {
|
|
36
|
+
if (REACT_APP_DEBUG === 'true') console.log(clc.greenBright(message))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const warn = (message: string): void => {
|
|
40
|
+
if (REACT_APP_DEBUG === 'true') console.log(clc.yellow(message))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const error = (message: string, errorObj?: any): void => {
|
|
44
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
45
|
+
console.log(clc.red(message))
|
|
46
|
+
if (errorObj) {
|
|
47
|
+
console.log(errorObj)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const request = (method: string, headerParams: Record<string, unknown>, url: string, formBody?: string): void => {
|
|
53
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
54
|
+
const bodyString = method !== 'GET' ? `${clc.greenBright('\nRequest [Body]')}${!formBody ? clc.greenBright(' <Empty>') : clc.greenBright(`\n${JSON.stringify(JSON.parse(formBody), [''], 2)}`)}` : ''
|
|
55
|
+
const requestSymbol = `${clc.greenBright('Request ==> ')}`
|
|
56
|
+
|
|
57
|
+
console.log(`\n
|
|
58
|
+
${clc.blackBright('=============================< ')}${requestSymbol}${(clc.blackBright('>=================================\n'))}
|
|
59
|
+
${clc.xterm(132)(`Request [Method]: ${method}`)}
|
|
60
|
+
${clc.green(`Request [Url]: ${url}`)}
|
|
61
|
+
${clc.cyan('Request [Header]')}${!headerParams ? clc.cyan(' <Empty>') : clc.cyan(`\n${JSON.stringify(headerParams, null, 2)}\n`)}${bodyString}
|
|
62
|
+
${clc.blackBright('\n========================================================================')}
|
|
63
|
+
`)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const resp = (response: Response | AxiosResponse | ApiResponse<any>): void => {
|
|
68
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
69
|
+
const responseSymbol = `${clc.greenBright('<== Response ')}`
|
|
70
|
+
|
|
71
|
+
const url = response instanceof Response ? response.url : response.config?.url
|
|
72
|
+
|
|
73
|
+
console.log(`\n
|
|
74
|
+
${clc.blackBright('=============================< ')}${responseSymbol}${(clc.blackBright('>=================================\n'))}
|
|
75
|
+
${clc.green(`Response [Url]: ${url}`)}
|
|
76
|
+
${clc.yellow(`Response [Status Code]: ${response.status}`)}
|
|
77
|
+
${clc.cyan('Response [Header]')}
|
|
78
|
+
${clc.cyan(response.headers ? JSON.stringify(response.headers, null, 2) : '')} \n
|
|
79
|
+
${clc.blackBright('========================================================================')}
|
|
80
|
+
`)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const responseBody = (respBody: Record<string, unknown>): void => {
|
|
85
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
86
|
+
console.log(`\n
|
|
87
|
+
${clc.greenBright('Response [Body]:')}
|
|
88
|
+
${clc.greenBright(JSON.stringify(respBody, null, 2))} \n
|
|
89
|
+
${clc.blackBright('========================================================================')}
|
|
90
|
+
`)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const object = (message: string, obj: Record<string, unknown> | ITypedMap<any>): void => {
|
|
95
|
+
if (REACT_APP_DEBUG === 'true') {
|
|
96
|
+
console.log(`\n
|
|
97
|
+
${clc.blackBright('=============================< ')}${message}${(clc.blackBright('>=================================\n'))}
|
|
98
|
+
${clc.greenBright(JSON.stringify(obj, null, 2))} \n
|
|
99
|
+
${clc.blackBright('========================================================================')}
|
|
100
|
+
`)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
log,
|
|
106
|
+
info,
|
|
107
|
+
debug,
|
|
108
|
+
warn,
|
|
109
|
+
error,
|
|
110
|
+
request,
|
|
111
|
+
resp,
|
|
112
|
+
responseBody,
|
|
113
|
+
object,
|
|
114
|
+
}
|
|
115
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_name": "ProjectName",
|
|
3
|
+
"button": {
|
|
4
|
+
"cancel": "Cancel",
|
|
5
|
+
"choose": "Choose",
|
|
6
|
+
"confirm": "Confirm",
|
|
7
|
+
"done": "Done",
|
|
8
|
+
"edit": "Edit",
|
|
9
|
+
"learn_more": "Learn More",
|
|
10
|
+
"ok": "OK",
|
|
11
|
+
"redeem": "Redeem",
|
|
12
|
+
"reset": "Reset",
|
|
13
|
+
"retry": "Retry",
|
|
14
|
+
"show_more": "Show More",
|
|
15
|
+
"submit": "Submit",
|
|
16
|
+
"save": "Save"
|
|
17
|
+
},
|
|
18
|
+
"date_display": "{{day}} {{month}} {{year}}",
|
|
19
|
+
"loading": "Loading...",
|
|
20
|
+
"placeholder": {
|
|
21
|
+
"search": "Search"
|
|
22
|
+
},
|
|
23
|
+
"version": "App Version",
|
|
24
|
+
"version_string": "{{version_name}}",
|
|
25
|
+
"version_stringb": "{{version_name}} (Build {{build}})"
|
|
26
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
3
|
+
import 'intl-pluralrules'
|
|
4
|
+
|
|
5
|
+
import { REACT_APP_DEBUG as DEBUG } from '@env'
|
|
6
|
+
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
7
|
+
import i18n, { LanguageDetectorAsyncModule, Services } from 'i18next'
|
|
8
|
+
import { initReactI18next } from 'react-i18next'
|
|
9
|
+
import * as RNLocalize from 'react-native-localize'
|
|
10
|
+
|
|
11
|
+
import { Locale } from '@/configs/constants/type'
|
|
12
|
+
import { StorageKey } from '@/configs/constants/type/StorageKey.type'
|
|
13
|
+
import logger from '@/infrastructures/common/logger'
|
|
14
|
+
|
|
15
|
+
import en_US from './en-US/index'
|
|
16
|
+
// import zh_CN from './zh-CN/index'
|
|
17
|
+
import zh_TW from './zh-TW/index'
|
|
18
|
+
|
|
19
|
+
const i18nOptions: Record<any, any> = {
|
|
20
|
+
compatibilityJSON: 'v4',
|
|
21
|
+
lng: 'zh_TW',
|
|
22
|
+
fallbackLng: 'zh_TW',
|
|
23
|
+
debug: DEBUG === 'true',
|
|
24
|
+
keySeparator: '.',
|
|
25
|
+
nsSeparator: ':',
|
|
26
|
+
interpolation: { escapeValue: false }, // not needed for react as it escapes by default
|
|
27
|
+
resources: {
|
|
28
|
+
en_US: en_US,
|
|
29
|
+
// zh_CN: zh_CN,
|
|
30
|
+
zh_TW: zh_TW,
|
|
31
|
+
},
|
|
32
|
+
react: {
|
|
33
|
+
// wait: true,
|
|
34
|
+
useSuspense: true,
|
|
35
|
+
bindI18n: 'languageChanged loaded',
|
|
36
|
+
bindI18nStore: 'added removed',
|
|
37
|
+
nsMode: 'default',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const findBestMatchedDeviceLanguage = (deviceLocale: string) => {
|
|
42
|
+
let appLang = Locale.enUS
|
|
43
|
+
switch (deviceLocale) {
|
|
44
|
+
case (new RegExp(/^en/).exec(deviceLocale) || {}).input:
|
|
45
|
+
appLang = Locale.enUS
|
|
46
|
+
break
|
|
47
|
+
case (new RegExp(/^zh-HK/).exec(deviceLocale) || new RegExp(/^zh-Hant/).exec(deviceLocale) || {}).input:
|
|
48
|
+
appLang = Locale.zhTW
|
|
49
|
+
break
|
|
50
|
+
// case (new RegExp(/^zh-CN/).exec(deviceLocale) || new RegExp(/^zh-Hans/).exec(deviceLocale) || {}).input:
|
|
51
|
+
// appLang = Locale.zhCN
|
|
52
|
+
// break
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return appLang
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const languageDetector: LanguageDetectorAsyncModule = {
|
|
59
|
+
type: 'languageDetector',
|
|
60
|
+
// If this is set to true, your detect function receives a callback function that you should call with your language,
|
|
61
|
+
// useful to retrieve your language stored in AsyncStorage for example
|
|
62
|
+
async: true,
|
|
63
|
+
init: (
|
|
64
|
+
_services: Services,
|
|
65
|
+
_detectorOptions: object,
|
|
66
|
+
_i18nextOptions: object,
|
|
67
|
+
) => {
|
|
68
|
+
/* use services and options */
|
|
69
|
+
},
|
|
70
|
+
detect: (callback: (lng: string) => void) => {
|
|
71
|
+
void AsyncStorage.getItem(StorageKey.appLang)
|
|
72
|
+
.then((value: string | null) => {
|
|
73
|
+
if (value === undefined || value === null) {
|
|
74
|
+
const preferredLocale = RNLocalize.getLocales()[0]
|
|
75
|
+
const deviceLocale = preferredLocale.languageTag
|
|
76
|
+
const bestLng = findBestMatchedDeviceLanguage(deviceLocale)
|
|
77
|
+
|
|
78
|
+
logger.log('i18n detector bestLng', bestLng)
|
|
79
|
+
callback(bestLng)
|
|
80
|
+
|
|
81
|
+
return
|
|
82
|
+
} else {
|
|
83
|
+
logger.log('i18n detector AsyncStorage APP_LANG', value)
|
|
84
|
+
callback(value)
|
|
85
|
+
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
cacheUserLanguage: (lng: string) => {
|
|
91
|
+
void AsyncStorage.setItem(StorageKey.appLang, lng)
|
|
92
|
+
logger.log('i18n detector cacheUserLanguage', lng)
|
|
93
|
+
|
|
94
|
+
return
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void i18n
|
|
99
|
+
.use(languageDetector)
|
|
100
|
+
.use(initReactI18next)
|
|
101
|
+
.init(i18nOptions)
|
|
102
|
+
.then(() => {
|
|
103
|
+
// init
|
|
104
|
+
})
|
|
105
|
+
.finally(() => {
|
|
106
|
+
// finally
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
export default i18n
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_name": "ProjectName",
|
|
3
|
+
"button": {
|
|
4
|
+
"cancel": "取消",
|
|
5
|
+
"choose": "選擇",
|
|
6
|
+
"confirm": "確認",
|
|
7
|
+
"done": "完成",
|
|
8
|
+
"edit": "修改",
|
|
9
|
+
"learn_more": "查看詳情",
|
|
10
|
+
"ok": "好",
|
|
11
|
+
"redeem": "兌換",
|
|
12
|
+
"reset": "重設",
|
|
13
|
+
"retry": "重試",
|
|
14
|
+
"show_more": "顯示更多",
|
|
15
|
+
"submit": "提交",
|
|
16
|
+
"save": "儲存"
|
|
17
|
+
},
|
|
18
|
+
"date_display": "{{year}}年{{month}}月{{day}}日",
|
|
19
|
+
"loading": "載入中...",
|
|
20
|
+
"placeholder": {
|
|
21
|
+
"search": "搜尋"
|
|
22
|
+
},
|
|
23
|
+
"version": "版本",
|
|
24
|
+
"version_string": "{{version_name}}",
|
|
25
|
+
"version_stringb": "{{version_name}} (Build {{build}})"
|
|
26
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SerializedError } from '@reduxjs/toolkit'
|
|
2
|
+
import { FetchBaseQueryError } from '@reduxjs/toolkit/query'
|
|
3
|
+
|
|
4
|
+
export interface IBaseResponse<T> {
|
|
5
|
+
timestamp: number
|
|
6
|
+
success: boolean
|
|
7
|
+
code: number
|
|
8
|
+
message: string
|
|
9
|
+
result: T
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface IBaseRequestWithSign extends IBaseRequest {
|
|
13
|
+
noncr: number
|
|
14
|
+
timestamp: number
|
|
15
|
+
sign: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface IBaseRequest {
|
|
19
|
+
language?: string
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
21
|
+
_ts?: number // use to refresh cache
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type IRequest<T> = T & IBaseRequest
|
|
25
|
+
|
|
26
|
+
type IPageable = {
|
|
27
|
+
pageIndex?: number
|
|
28
|
+
pageSize?: number
|
|
29
|
+
}
|
|
30
|
+
export type IPageableRequest<T> = IRequest<T> & IPageable
|
|
31
|
+
|
|
32
|
+
export type IResponseError = {
|
|
33
|
+
status: number
|
|
34
|
+
message: string
|
|
35
|
+
data: {
|
|
36
|
+
code: number
|
|
37
|
+
message: string
|
|
38
|
+
success: boolean
|
|
39
|
+
}
|
|
40
|
+
exception?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type IUseFetchData<T> = {
|
|
44
|
+
isFetching: boolean
|
|
45
|
+
isLoading: boolean
|
|
46
|
+
isSuccess: boolean
|
|
47
|
+
refetch: () => any
|
|
48
|
+
data?: T
|
|
49
|
+
error: FetchBaseQueryError | SerializedError | undefined
|
|
50
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DrawerContentComponentProps, DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { useTranslation } from 'react-i18next'
|
|
4
|
+
import { Linking, ScrollView, TouchableOpacity, View } from 'react-native'
|
|
5
|
+
import { Text } from 'react-native-paper'
|
|
6
|
+
import Icon from 'react-native-paper/src/components/Icon'
|
|
7
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
8
|
+
|
|
9
|
+
import { images } from '@/assets'
|
|
10
|
+
import { IconX, PressableOpacity } from '@/components/basic'
|
|
11
|
+
import useTheme from '@/hooks/useTheme'
|
|
12
|
+
import logger from '@/infrastructures/common/logger'
|
|
13
|
+
import { AppRoutes } from '@/navigators/types'
|
|
14
|
+
|
|
15
|
+
import DrawerItem from './DrawerItem'
|
|
16
|
+
|
|
17
|
+
const DrawerContent = (props: DrawerContentComponentProps) => {
|
|
18
|
+
const insets = useSafeAreaInsets()
|
|
19
|
+
const { Colors, Fonts, Gutters, Layout } = useTheme()
|
|
20
|
+
const { t } = useTranslation()
|
|
21
|
+
|
|
22
|
+
const { navigation, state } = props
|
|
23
|
+
const { index, routes } = state
|
|
24
|
+
const currentRouteName = routes[index].name
|
|
25
|
+
|
|
26
|
+
const gotoSettings = () => {
|
|
27
|
+
navigation.navigate(AppRoutes.SettingsScreen)
|
|
28
|
+
navigation.closeDrawer()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const navigateTo = (routeName: string) => {
|
|
32
|
+
navigation.navigate(routeName)
|
|
33
|
+
navigation.closeDrawer()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const closeDrawer = () => {
|
|
37
|
+
navigation.closeDrawer()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<DrawerContentScrollView {...props}>
|
|
42
|
+
{/* <DrawerItemList {...props}/> */}
|
|
43
|
+
<View
|
|
44
|
+
style={[Layout.row, Layout.fill, Layout.justifyContentEnd, Gutters.smallHPadding]}
|
|
45
|
+
>
|
|
46
|
+
{/* <Icon size={40} source={images.menu_settings} /> */}
|
|
47
|
+
<PressableOpacity onPress={closeDrawer}>
|
|
48
|
+
<IconX size={40} color={Colors.text} origin={IconX.ANT_DESIGN} name="close" />
|
|
49
|
+
</PressableOpacity>
|
|
50
|
+
</View>
|
|
51
|
+
<DrawerItem
|
|
52
|
+
label={({ color, focused }) => <Text style={[{ color }]}>{`${t('screens:home')}`}</Text>}
|
|
53
|
+
icon={({ color, focused, size }) => <IconX size={40} color={color} origin={IconX.ANT_DESIGN} name={'home'} />}
|
|
54
|
+
// labelStyle={[Fonts.drawerItem, { color: currentRouteName === AppRoutes.DrawerMain ? Colors.primary : Colors.text }]}
|
|
55
|
+
focused={currentRouteName === `${AppRoutes.MainBottomTabNav}`}
|
|
56
|
+
activeTintColor={Colors.primary}
|
|
57
|
+
inactiveTintColor={Colors.text}
|
|
58
|
+
activeBackgroundColor={Colors.transparent}
|
|
59
|
+
onPress={() => navigateTo(AppRoutes.MainBottomTabNav)}
|
|
60
|
+
/>
|
|
61
|
+
</DrawerContentScrollView>
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default DrawerContent
|