@varunindiit/create-rn-starter 1.0.1
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/LICENSE +21 -0
- package/README.md +93 -0
- package/bin/index.js +270 -0
- package/lib/prompt.js +63 -0
- package/lib/rename.js +239 -0
- package/lib/scaffold.js +110 -0
- package/lib/utils.js +122 -0
- package/package.json +38 -0
- package/template/.eslintrc.js +4 -0
- package/template/.prettierrc.js +5 -0
- package/template/.watchmanconfig +1 -0
- package/template/App.tsx +100 -0
- package/template/Gemfile +17 -0
- package/template/README.md +97 -0
- package/template/__tests__/App.test.tsx +13 -0
- package/template/_gitignore +75 -0
- package/template/android/app/build.gradle +119 -0
- package/template/android/app/debug.keystore +0 -0
- package/template/android/app/proguard-rules.pro +10 -0
- package/template/android/app/src/main/AndroidManifest.xml +45 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Black.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-BlackItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Bold.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-BoldItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-ExtraBold.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-ExtraBoldItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-ExtraLight.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-ExtraLightItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Italic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Light.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-LightItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Medium.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-MediumItalic.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-Regular.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-SemiBold.ttf +0 -0
- package/template/android/app/src/main/assets/fonts/MonaSans-SemiBoldItalic.ttf +0 -0
- package/template/android/app/src/main/java/com/awesomeproject/MainActivity.kt +22 -0
- package/template/android/app/src/main/java/com/awesomeproject/MainApplication.kt +27 -0
- package/template/android/app/src/main/res/drawable/launch_screen.png +0 -0
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/template/android/app/src/main/res/layout/launch_screen.xml +12 -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/colors.xml +3 -0
- package/template/android/app/src/main/res/values/strings.xml +3 -0
- package/template/android/app/src/main/res/values/styles.xml +11 -0
- package/template/android/build.gradle +21 -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 +44 -0
- package/template/android/gradlew +248 -0
- package/template/android/gradlew.bat +98 -0
- package/template/android/link-assets-manifest.json +69 -0
- package/template/android/settings.gradle +6 -0
- package/template/app.json +4 -0
- package/template/babel.config.js +4 -0
- package/template/declarations.d.ts +6 -0
- package/template/env.example +20 -0
- package/template/index.js +10 -0
- package/template/ios/.xcode.env +11 -0
- package/template/ios/.xcode.env.local +1 -0
- package/template/ios/AwesomeProject/AppDelegate.swift +60 -0
- package/template/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/template/ios/AwesomeProject/Images.xcassets/Contents.json +6 -0
- package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Contents.json +23 -0
- package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@1x.png +0 -0
- package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@2x.png +0 -0
- package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@3x.png +0 -0
- package/template/ios/AwesomeProject/Info.plist +89 -0
- package/template/ios/AwesomeProject/LaunchScreen.storyboard +40 -0
- package/template/ios/AwesomeProject/PrivacyInfo.xcprivacy +38 -0
- package/template/ios/AwesomeProject.xcodeproj/project.pbxproj +576 -0
- package/template/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme +88 -0
- package/template/ios/AwesomeProject.xcworkspace/contents.xcworkspacedata +10 -0
- package/template/ios/Podfile +68 -0
- package/template/ios/link-assets-manifest.json +69 -0
- package/template/jest.config.js +3 -0
- package/template/metro.config.js +24 -0
- package/template/package.json +68 -0
- package/template/react-native.config.js +7 -0
- package/template/src/assets/fonts/MonaSans-Black.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-BlackItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-Bold.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-BoldItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-ExtraBold.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-ExtraBoldItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-ExtraLight.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-ExtraLightItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-Italic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-Light.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-LightItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-Medium.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-MediumItalic.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-Regular.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-SemiBold.ttf +0 -0
- package/template/src/assets/fonts/MonaSans-SemiBoldItalic.ttf +0 -0
- package/template/src/assets/image/BackGroundAuth.png +0 -0
- package/template/src/assets/image/BackgroundVerification.png +0 -0
- package/template/src/assets/image/logo.png +0 -0
- package/template/src/assets/svg/add-circle.svg +5 -0
- package/template/src/assets/svg/airConditioning.svg +12 -0
- package/template/src/assets/svg/apple.svg +3 -0
- package/template/src/assets/svg/arrowDown.svg +3 -0
- package/template/src/assets/svg/back.svg +10 -0
- package/template/src/assets/svg/bag.svg +11 -0
- package/template/src/assets/svg/calender.svg +5 -0
- package/template/src/assets/svg/car.svg +10 -0
- package/template/src/assets/svg/carConfirm.svg +60 -0
- package/template/src/assets/svg/chatActive.svg +3 -0
- package/template/src/assets/svg/chatUnActive.svg +3 -0
- package/template/src/assets/svg/document-text.svg +6 -0
- package/template/src/assets/svg/gender.svg +11 -0
- package/template/src/assets/svg/google.svg +6 -0
- package/template/src/assets/svg/headphone.svg +3 -0
- package/template/src/assets/svg/homeActive.svg +3 -0
- package/template/src/assets/svg/homeUnActive.svg +3 -0
- package/template/src/assets/svg/logo.svg +18 -0
- package/template/src/assets/svg/logout.svg +5 -0
- package/template/src/assets/svg/maxBack.svg +4 -0
- package/template/src/assets/svg/message-text.svg +7 -0
- package/template/src/assets/svg/music.svg +5 -0
- package/template/src/assets/svg/noSmoking.svg +10 -0
- package/template/src/assets/svg/notification.svg +5 -0
- package/template/src/assets/svg/passenger.svg +4 -0
- package/template/src/assets/svg/phone.svg +3 -0
- package/template/src/assets/svg/rightArrow.svg +3 -0
- package/template/src/assets/svg/security-user.svg +5 -0
- package/template/src/assets/svg/star.svg +3 -0
- package/template/src/assets/svg/tick-circle.svg +4 -0
- package/template/src/assets/svg/trafficLight.svg +41 -0
- package/template/src/assets/svg/tripActive.svg +10 -0
- package/template/src/assets/svg/tripUnActive.svg +10 -0
- package/template/src/assets/svg/usbChargers.svg +3 -0
- package/template/src/assets/svg/user.svg +4 -0
- package/template/src/assets/svg/userActive.svg +3 -0
- package/template/src/assets/svg/userPlaceholder.svg +3 -0
- package/template/src/assets/svg/userUnActive.svg +3 -0
- package/template/src/components/AuthLayout/AuthLayout.tsx +170 -0
- package/template/src/components/AuthLayout/index.ts +1 -0
- package/template/src/components/BottomSheet/BottomSheet.tsx +73 -0
- package/template/src/components/BottomSheet/BottomSheetAlert.tsx +100 -0
- package/template/src/components/BottomSheet/CenterAlert.tsx +153 -0
- package/template/src/components/BottomSheet/index.ts +2 -0
- package/template/src/components/BottomTabBar/index.tsx +145 -0
- package/template/src/components/Button/RNButton.tsx +152 -0
- package/template/src/components/Button/index.ts +2 -0
- package/template/src/components/Common/Avatar.tsx +80 -0
- package/template/src/components/Common/Card.tsx +49 -0
- package/template/src/components/Common/CardBrandLogo.tsx +66 -0
- package/template/src/components/Common/Checkbox.tsx +65 -0
- package/template/src/components/Common/Chip.tsx +79 -0
- package/template/src/components/Common/CommonStyles.tsx +594 -0
- package/template/src/components/Common/Divider.tsx +33 -0
- package/template/src/components/Common/DriverTripCard.tsx +308 -0
- package/template/src/components/Common/Dropdown.tsx +161 -0
- package/template/src/components/Common/EmptyState.tsx +52 -0
- package/template/src/components/Common/FAB.tsx +68 -0
- package/template/src/components/Common/HeaderLocation.tsx +108 -0
- package/template/src/components/Common/Loader.tsx +23 -0
- package/template/src/components/Common/RatingStars.tsx +103 -0
- package/template/src/components/Common/RouteDots.tsx +98 -0
- package/template/src/components/Common/SegmentedControl.tsx +126 -0
- package/template/src/components/Common/SosButton.tsx +80 -0
- package/template/src/components/Common/SosSheet.tsx +344 -0
- package/template/src/components/Common/StarRating.tsx +58 -0
- package/template/src/components/Common/StatusBadge.tsx +56 -0
- package/template/src/components/Common/Toggle.tsx +66 -0
- package/template/src/components/Common/TripCard.tsx +247 -0
- package/template/src/components/Common/UploadBox.tsx +106 -0
- package/template/src/components/Container/MainContainer.tsx +76 -0
- package/template/src/components/Container/index.ts +1 -0
- package/template/src/components/Header/index.tsx +143 -0
- package/template/src/components/Icon/SvgIcons.tsx +1991 -0
- package/template/src/components/ImagePickerSheet/ImagePickerSheet.tsx +233 -0
- package/template/src/components/ImagePickerSheet/index.ts +2 -0
- package/template/src/components/Input/CountryDropdown.tsx +71 -0
- package/template/src/components/Input/OtpInput.tsx +117 -0
- package/template/src/components/Input/RNInput.tsx +138 -0
- package/template/src/components/Input/index.ts +4 -0
- package/template/src/components/Picker/DatePickerSheet.tsx +393 -0
- package/template/src/components/Picker/PassengerPickerSheet.tsx +237 -0
- package/template/src/components/Text/RNText.tsx +62 -0
- package/template/src/components/Text/index.ts +1 -0
- package/template/src/components/index.ts +44 -0
- package/template/src/hooks/useCurrentLocation.ts +72 -0
- package/template/src/localization/i18n.ts +29 -0
- package/template/src/localization/i18next.d.ts +11 -0
- package/template/src/localization/index.ts +4 -0
- package/template/src/localization/languageStorage.ts +27 -0
- package/template/src/localization/languages.ts +62 -0
- package/template/src/localization/resources/en.ts +703 -0
- package/template/src/localization/resources/fr.ts +703 -0
- package/template/src/localization/useLanguage.ts +42 -0
- package/template/src/navigation/AuthNavigation.tsx +23 -0
- package/template/src/navigation/BottomTabs.tsx +24 -0
- package/template/src/navigation/RootNavigation.tsx +27 -0
- package/template/src/navigation/RouteKey.ts +22 -0
- package/template/src/navigation/StackNavigation.tsx +52 -0
- package/template/src/navigation/paramLists.ts +25 -0
- package/template/src/redux/slice/app.ts +66 -0
- package/template/src/redux/slice/auth.ts +40 -0
- package/template/src/redux/slice/userProfile.ts +124 -0
- package/template/src/redux/store.ts +17 -0
- package/template/src/screen/auth/Login.tsx +69 -0
- package/template/src/screen/onboarding/LanguageSelection.tsx +231 -0
- package/template/src/screen/root/home/index.tsx +36 -0
- package/template/src/screen/root/profile/index.tsx +69 -0
- package/template/src/screen/shared/Chat.tsx +308 -0
- package/template/src/screen/shared/EditProfile.tsx +407 -0
- package/template/src/screen/shared/HelpSupport.tsx +678 -0
- package/template/src/screen/shared/LocationSearch.tsx +362 -0
- package/template/src/screen/shared/Messages.tsx +115 -0
- package/template/src/screen/shared/Notifications.tsx +86 -0
- package/template/src/screen/shared/PrivacyPolicy.tsx +297 -0
- package/template/src/screen/shared/Profile.tsx +118 -0
- package/template/src/screen/shared/Ratings.tsx +170 -0
- package/template/src/screen/shared/TermsConditions.tsx +315 -0
- package/template/src/screen/shared/profile/DriverProfile.tsx +262 -0
- package/template/src/screen/shared/profile/PassengerProfile.tsx +123 -0
- package/template/src/screen/shared/profile/ProfileParts.tsx +219 -0
- package/template/src/services/Config.ts +37 -0
- package/template/src/services/api.ts +37 -0
- package/template/src/services/index.ts +4 -0
- package/template/src/services/places.ts +320 -0
- package/template/src/services/storage.ts +33 -0
- package/template/src/theme/fonts.ts +30 -0
- package/template/src/theme/index.ts +3 -0
- package/template/src/theme/spacing.ts +66 -0
- package/template/src/theme/theme.ts +58 -0
- package/template/src/types/env.d.ts +8 -0
- package/template/src/types/index.ts +3 -0
- package/template/src/utils/card.ts +101 -0
- package/template/src/utils/constants.ts +39 -0
- package/template/src/utils/functions.ts +24 -0
- package/template/tsconfig.json +8 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export { default as RNText } from "./Text/RNText";
|
|
2
|
+
export { default as RNButton } from "./Button/RNButton";
|
|
3
|
+
export { default as RNInput } from "./Input/RNInput";
|
|
4
|
+
export { default as OtpInput } from "./Input/OtpInput";
|
|
5
|
+
export { default as CountryDropdown } from "./Input/CountryDropdown";
|
|
6
|
+
export type { CountryItem } from "./Input/CountryDropdown";
|
|
7
|
+
export { default as Header } from "./Header";
|
|
8
|
+
export { default as AuthLayout } from "./AuthLayout/AuthLayout";
|
|
9
|
+
export { default as MainContainer } from "./Container/MainContainer";
|
|
10
|
+
export { default as BottomSheet } from "./BottomSheet/BottomSheet";
|
|
11
|
+
export { default as BottomSheetAlert } from "./BottomSheet/BottomSheetAlert";
|
|
12
|
+
export { default as CenterAlert } from "./BottomSheet/CenterAlert";
|
|
13
|
+
export { default as ImagePickerSheet } from "./ImagePickerSheet/ImagePickerSheet";
|
|
14
|
+
export { default as DatePickerSheet } from "./Picker/DatePickerSheet";
|
|
15
|
+
export { default as PassengerPickerSheet } from "./Picker/PassengerPickerSheet";
|
|
16
|
+
export { default as Card } from "./Common/Card";
|
|
17
|
+
export { default as CardBrandLogo } from "./Common/CardBrandLogo";
|
|
18
|
+
export { default as SosButton } from "./Common/SosButton";
|
|
19
|
+
export { default as SosSheet } from "./Common/SosSheet";
|
|
20
|
+
export type {
|
|
21
|
+
EmergencyService,
|
|
22
|
+
TrustedContact,
|
|
23
|
+
} from "./Common/SosSheet";
|
|
24
|
+
export { default as Avatar } from "./Common/Avatar";
|
|
25
|
+
export { default as StarRating } from "./Common/StarRating";
|
|
26
|
+
export { default as RatingStars } from "./Common/RatingStars";
|
|
27
|
+
export { default as Toggle } from "./Common/Toggle";
|
|
28
|
+
export { default as Checkbox } from "./Common/Checkbox";
|
|
29
|
+
export { default as SegmentedControl } from "./Common/SegmentedControl";
|
|
30
|
+
export type { SegmentedTab } from "./Common/SegmentedControl";
|
|
31
|
+
export { default as EmptyState } from "./Common/EmptyState";
|
|
32
|
+
export { default as Loader } from "./Common/Loader";
|
|
33
|
+
export { default as Chip } from "./Common/Chip";
|
|
34
|
+
export { default as Divider } from "./Common/Divider";
|
|
35
|
+
export { default as RouteDots } from "./Common/RouteDots";
|
|
36
|
+
export { default as StatusBadge } from "./Common/StatusBadge";
|
|
37
|
+
export { default as FAB } from "./Common/FAB";
|
|
38
|
+
export { default as Dropdown } from "./Common/Dropdown";
|
|
39
|
+
export type { DropdownOption } from "./Common/Dropdown";
|
|
40
|
+
export { default as UploadBox } from "./Common/UploadBox";
|
|
41
|
+
export { default as TripCard } from "./Common/TripCard";
|
|
42
|
+
export { default as DriverTripCard } from "./Common/DriverTripCard";
|
|
43
|
+
export { default as HeaderLocation } from "./Common/HeaderLocation";
|
|
44
|
+
export * from "./Icon/SvgIcons";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useCallback, useEffect } from "react";
|
|
2
|
+
import GetLocation, { isLocationError } from "react-native-get-location";
|
|
3
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
4
|
+
import { RootState } from "../redux/store";
|
|
5
|
+
import {
|
|
6
|
+
locationDenied,
|
|
7
|
+
locationError,
|
|
8
|
+
locationLoading,
|
|
9
|
+
locationResolved,
|
|
10
|
+
} from "../redux/slice/location";
|
|
11
|
+
import { reverseGeocode } from "../services/places";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reusable device-location hook.
|
|
15
|
+
*
|
|
16
|
+
* Requests location permission (the OS prompt is triggered by GetLocation on
|
|
17
|
+
* both platforms), fetches the current coordinates, reverse-geocodes them into
|
|
18
|
+
* a readable city label and stores everything in the global `location` slice so
|
|
19
|
+
* any screen (Passenger or Driver home) can render it.
|
|
20
|
+
*
|
|
21
|
+
* The fetch runs automatically once per app session (when the slice is still
|
|
22
|
+
* `idle`); call `refetch()` to retry after a denial or error.
|
|
23
|
+
*/
|
|
24
|
+
export const useCurrentLocation = (auto = true) => {
|
|
25
|
+
const dispatch = useDispatch();
|
|
26
|
+
const location = useSelector((s: RootState) => s.location);
|
|
27
|
+
|
|
28
|
+
const fetchLocation = useCallback(async () => {
|
|
29
|
+
dispatch(locationLoading());
|
|
30
|
+
try {
|
|
31
|
+
const position = await GetLocation.getCurrentPosition({
|
|
32
|
+
enableHighAccuracy: false,
|
|
33
|
+
timeout: 15000,
|
|
34
|
+
});
|
|
35
|
+
const result = await reverseGeocode(
|
|
36
|
+
position.latitude,
|
|
37
|
+
position.longitude,
|
|
38
|
+
);
|
|
39
|
+
dispatch(
|
|
40
|
+
locationResolved({
|
|
41
|
+
label: result.shortLabel,
|
|
42
|
+
address: result.address,
|
|
43
|
+
latitude: result.latitude,
|
|
44
|
+
longitude: result.longitude,
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
if (isLocationError(err) && err.code === "UNAUTHORIZED") {
|
|
49
|
+
dispatch(locationDenied());
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const message = isLocationError(err)
|
|
53
|
+
? err.code === "UNAVAILABLE"
|
|
54
|
+
? "Location services are off"
|
|
55
|
+
: "Couldn't get your location"
|
|
56
|
+
: "Couldn't get your location";
|
|
57
|
+
dispatch(locationError(message));
|
|
58
|
+
}
|
|
59
|
+
}, [dispatch]);
|
|
60
|
+
|
|
61
|
+
// Fire once per session while the slice is still idle.
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (auto && location.status === "idle") {
|
|
64
|
+
fetchLocation();
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
return { ...location, refetch: fetchLocation };
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default useCurrentLocation;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import i18n from "i18next";
|
|
2
|
+
import { initReactI18next } from "react-i18next";
|
|
3
|
+
import en from "./resources/en";
|
|
4
|
+
import fr from "./resources/fr";
|
|
5
|
+
import { DEFAULT_LANGUAGE } from "./languages";
|
|
6
|
+
import { getStoredLanguage } from "./languageStorage";
|
|
7
|
+
|
|
8
|
+
export const resources = {
|
|
9
|
+
en: { translation: en },
|
|
10
|
+
fr: { translation: fr },
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
if (!i18n.isInitialized) {
|
|
14
|
+
i18n.use(initReactI18next).init({
|
|
15
|
+
resources,
|
|
16
|
+
lng: getStoredLanguage(),
|
|
17
|
+
fallbackLng: DEFAULT_LANGUAGE,
|
|
18
|
+
defaultNS: "translation",
|
|
19
|
+
interpolation: {
|
|
20
|
+
escapeValue: false,
|
|
21
|
+
},
|
|
22
|
+
returnNull: false,
|
|
23
|
+
react: {
|
|
24
|
+
useSuspense: false,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default i18n;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { storage } from "../services/storage";
|
|
2
|
+
import { LANGUAGE_KEY, LANGUAGE_SELECTED_KEY } from "../utils/constants";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_LANGUAGE,
|
|
5
|
+
LanguageCode,
|
|
6
|
+
getDeviceLanguage,
|
|
7
|
+
isSupportedLanguage,
|
|
8
|
+
} from "./languages";
|
|
9
|
+
|
|
10
|
+
/** Persisted language, or the best device-locale guess on first launch. */
|
|
11
|
+
export const getStoredLanguage = (): LanguageCode => {
|
|
12
|
+
const saved = storage.getString(LANGUAGE_KEY);
|
|
13
|
+
if (isSupportedLanguage(saved)) return saved;
|
|
14
|
+
return getDeviceLanguage() ?? DEFAULT_LANGUAGE;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const setStoredLanguage = (code: LanguageCode) => {
|
|
18
|
+
storage.set(LANGUAGE_KEY, code);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Whether the user has explicitly completed the language step. */
|
|
22
|
+
export const hasSelectedLanguage = (): boolean =>
|
|
23
|
+
storage.getBoolean(LANGUAGE_SELECTED_KEY) ?? false;
|
|
24
|
+
|
|
25
|
+
export const markLanguageSelected = () => {
|
|
26
|
+
storage.set(LANGUAGE_SELECTED_KEY, true);
|
|
27
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { NativeModules, Platform } from "react-native";
|
|
2
|
+
|
|
3
|
+
/** Supported app languages. Add a new entry + resource file to scale. */
|
|
4
|
+
export type LanguageCode = "en" | "fr";
|
|
5
|
+
|
|
6
|
+
export interface LanguageOption {
|
|
7
|
+
code: LanguageCode;
|
|
8
|
+
/** Name shown in the user's own language */
|
|
9
|
+
nativeLabel: string;
|
|
10
|
+
/** English name of the language */
|
|
11
|
+
englishLabel: string;
|
|
12
|
+
/** Short subtitle on the selector card */
|
|
13
|
+
region: string;
|
|
14
|
+
flag: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const LANGUAGES: LanguageOption[] = [
|
|
18
|
+
{
|
|
19
|
+
code: "en",
|
|
20
|
+
nativeLabel: "English",
|
|
21
|
+
englishLabel: "English",
|
|
22
|
+
region: "English",
|
|
23
|
+
flag: "🇬🇧",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
code: "fr",
|
|
27
|
+
nativeLabel: "Français",
|
|
28
|
+
englishLabel: "French",
|
|
29
|
+
region: "Français",
|
|
30
|
+
flag: "🇫🇷",
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const DEFAULT_LANGUAGE: LanguageCode = "en";
|
|
35
|
+
|
|
36
|
+
export const SUPPORTED_CODES: LanguageCode[] = LANGUAGES.map((l) => l.code);
|
|
37
|
+
|
|
38
|
+
export const isSupportedLanguage = (code?: string | null): code is LanguageCode =>
|
|
39
|
+
!!code && SUPPORTED_CODES.includes(code as LanguageCode);
|
|
40
|
+
|
|
41
|
+
export const getLanguageOption = (code: LanguageCode): LanguageOption =>
|
|
42
|
+
LANGUAGES.find((l) => l.code === code) ?? LANGUAGES[0];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Best-effort device locale detection (no extra native deps). Used only to
|
|
46
|
+
* pre-highlight a choice on the first-launch selector — the user always decides.
|
|
47
|
+
*/
|
|
48
|
+
export const getDeviceLanguage = (): LanguageCode => {
|
|
49
|
+
let locale = "en";
|
|
50
|
+
try {
|
|
51
|
+
if (Platform.OS === "ios") {
|
|
52
|
+
const settings = NativeModules.SettingsManager?.settings;
|
|
53
|
+
locale =
|
|
54
|
+
settings?.AppleLocale || settings?.AppleLanguages?.[0] || "en";
|
|
55
|
+
} else {
|
|
56
|
+
locale = NativeModules.I18nManager?.localeIdentifier || "en";
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
locale = "en";
|
|
60
|
+
}
|
|
61
|
+
return String(locale).toLowerCase().startsWith("fr") ? "fr" : "en";
|
|
62
|
+
};
|