@fadyshawky/react-native-magic 2.2.1 → 2.3.0
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 +90 -56
- package/index.js +4 -0
- package/package.json +8 -2
- package/scripts/askPackageName.js +10 -5
- package/template/.env.development +8 -6
- package/template/.env.example +15 -5
- package/template/.env.production +8 -6
- package/template/.env.staging +8 -6
- package/template/.eslintrc.js +14 -0
- package/template/.husky/pre-commit +1 -0
- package/template/App.tsx +47 -16
- package/template/__tests__/App.test.tsx +28 -10
- package/template/babel.config.js +20 -1
- package/template/docs/ARCHITECTURE.md +40 -10
- package/template/docs/BEST_PRACTICES.md +10 -1
- package/template/docs/CUSTOMIZATION.md +118 -5
- package/template/docs/design-system.html +1164 -0
- package/template/docs/wireframes.html +411 -0
- package/template/index.js +10 -0
- package/template/jest.config.js +16 -1
- package/template/jest.setup.js +61 -0
- package/template/package-lock.json +12178 -8293
- package/template/package.json +53 -20
- package/template/react-native.config.js +3 -0
- package/template/resources/fonts/.gitkeep +0 -0
- package/template/scripts/ci-sync-env.cjs +71 -0
- package/template/src/assets/brand/logo-mark.svg +8 -0
- package/template/src/assets/brand/logo-mono.svg +9 -0
- package/template/src/assets/brand/logo-primary.svg +15 -0
- package/template/src/assets/brand/wordmark-dark.svg +18 -0
- package/template/src/common/components/AppBottomSheet.tsx +87 -0
- package/template/src/common/components/AppSwitch.tsx +75 -0
- package/template/src/common/components/AppTextInput.tsx +161 -0
- package/template/src/common/components/Avatar.tsx +75 -0
- package/template/src/common/components/Badge.tsx +66 -0
- package/template/src/common/components/CardScroller.tsx +58 -0
- package/template/src/common/components/Cards.tsx +13 -7
- package/template/src/common/components/Carousel.tsx +196 -0
- package/template/src/common/components/Checkbox.tsx +85 -0
- package/template/src/common/components/Chip.tsx +55 -0
- package/template/src/common/components/Dropdown.tsx +202 -0
- package/template/src/common/components/ErrorBoundary.tsx +82 -0
- package/template/src/common/components/FlatListWrapper.tsx +4 -5
- package/template/src/common/components/ListItem.tsx +90 -0
- package/template/src/common/components/LoadingComponent.tsx +8 -2
- package/template/src/common/components/Logo.tsx +77 -0
- package/template/src/common/components/ModalDialog.tsx +141 -0
- package/template/src/common/components/NetworkBanner.tsx +47 -0
- package/template/src/common/components/OTPInput.tsx +0 -1
- package/template/src/common/components/PrimaryButton.tsx +0 -14
- package/template/src/common/components/PrimaryTextInput.tsx +66 -130
- package/template/src/common/components/RadioGroup.tsx +95 -0
- package/template/src/common/components/SafeText.tsx +4 -3
- package/template/src/common/components/SearchBar.tsx +7 -5
- package/template/src/common/components/SegmentedControl.tsx +77 -0
- package/template/src/common/components/Skeleton.tsx +47 -0
- package/template/src/common/components/TryAgain.tsx +4 -2
- package/template/src/common/helpers/arrayHelpers.ts +2 -2
- package/template/src/common/helpers/defaultKeyIdExtractor.ts +1 -1
- package/template/src/common/helpers/regexHelpers.ts +1 -2
- package/template/src/common/helpers/stringsHelpers.ts +0 -1
- package/template/src/common/hooks/useBackHandler.ts +5 -2
- package/template/src/common/hooks/useEventRegister.ts +1 -1
- package/template/src/common/hooks/useFlatListActions.ts +1 -1
- package/template/src/common/hooks/useWhyDidYouUpdate.ts +1 -1
- package/template/src/common/localization/LocalizationProvider.tsx +1 -1
- package/template/src/common/localization/RTLInitializer.tsx +1 -1
- package/template/src/common/localization/dateFormatter.ts +0 -1
- package/template/src/common/localization/intlFormatter.ts +0 -1
- package/template/src/common/localization/localization.ts +2 -2
- package/template/src/common/localization/translations/homeLocalization.ts +14 -0
- package/template/src/common/localization/translations/loginLocalization.ts +8 -0
- package/template/src/common/localization/translations/mainNavigationLocalization.ts +2 -0
- package/template/src/common/localization/translations/profileLocalization.ts +16 -0
- package/template/src/common/utils/index.tsx +0 -6
- package/template/src/common/validations/commonValidations.ts +2 -2
- package/template/src/core/api/errorHandler.ts +1 -1
- package/template/src/core/api/responseHandlers.ts +1 -3
- package/template/src/core/api/serverHeaders.ts +61 -12
- package/template/src/core/notifications/notificationAuth.ts +6 -0
- package/template/src/core/notifications/notificationService.ts +125 -0
- package/template/src/core/notifications/routeFromNotificationData.ts +32 -0
- package/template/src/core/store/categories/categoriesActions.ts +25 -0
- package/template/src/core/store/categories/categoriesSlice.ts +51 -0
- package/template/src/core/store/categories/categoriesState.ts +19 -0
- package/template/src/core/store/rootReducer.ts +2 -0
- package/template/src/core/store/store.tsx +6 -1
- package/template/src/core/store/user/userActions.ts +75 -14
- package/template/src/core/store/user/userSlice.ts +49 -26
- package/template/src/core/store/user/userState.ts +6 -4
- package/template/src/core/theme/ThemeProvider.tsx +5 -3
- package/template/src/core/theme/brand.ts +50 -0
- package/template/src/core/theme/colors.ts +113 -99
- package/template/src/core/theme/commonConsts.ts +2 -2
- package/template/src/core/theme/commonStyles.ts +1 -1
- package/template/src/core/theme/themes.ts +2 -0
- package/template/src/core/theme/types.ts +4 -2
- package/template/src/core/utils/stringUtils.ts +1 -1
- package/template/src/design-system/index.ts +2 -0
- package/template/src/design-system/tokens/brand.ts +6 -0
- package/template/src/design-system/tokens/index.ts +3 -0
- package/template/src/design-system/tokens/palette.ts +4 -0
- package/template/src/design-system/tokens/typography-spacing.ts +2 -0
- package/template/src/navigation/AuthStack.tsx +1 -4
- package/template/src/navigation/HeaderComponents.tsx +6 -3
- package/template/src/navigation/MainStack.tsx +18 -6
- package/template/src/navigation/RootNavigation.tsx +4 -7
- package/template/src/navigation/TabBar.tsx +7 -6
- package/template/src/navigation/types.ts +10 -31
- package/template/src/screens/Login/Login.tsx +47 -47
- package/template/src/screens/OTP/OTPScreen.tsx +6 -9
- package/template/src/screens/components/ComponentsScreen.tsx +301 -0
- package/template/src/screens/home/HomeScreen.tsx +143 -1
- package/template/src/screens/home/hooks/useHomeData.ts +19 -5
- package/template/src/screens/index.tsx +1 -0
- package/template/src/screens/profile/Profile.tsx +139 -2
- package/template/src/screens/splash/Splash.tsx +44 -11
- package/template/src/sheetManager/sheets.tsx +1 -1
- package/template/tsconfig.json +14 -2
- package/template/types/globals.d.ts +43 -0
- package/template/types/index.ts +2 -6
- package/template/types/modules.d.ts +9 -0
- package/template/types/react-native-config.d.ts +0 -2
- package/.vscode/settings.json +0 -8
- package/CHANGELOG.md +0 -119
- package/CODE_OF_CONDUCT.md +0 -83
- package/CONTRIBUTING.md +0 -60
- package/local.properties +0 -1
- package/template/src/common/components/ImageCropPickerButton.tsx +0 -107
- package/template/src/common/components/PhotoTakingButton.tsx +0 -94
- package/template/src/common/helpers/imageHelpers.ts +0 -5
- package/template/src/common/helpers/inAppReviewHelper.ts +0 -30
- package/template/src/common/helpers/orientationHelpers.ts +0 -25
- package/template/src/common/helpers/shareHelpers.ts +0 -47
- package/template/src/common/utils/FeesCaalculation.tsx +0 -37
- package/template/src/common/utils/printData.tsx +0 -161
- package/template/src/common/validations/examples/TextInputWithValidation.tsx +0 -229
|
@@ -2,26 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
This app uses a layered structure: **UI** (screens, components) → **navigation** → **core** (store, api, theme, config) and **common** (components, localization, helpers).
|
|
5
|
+
This app uses a layered structure: **UI** (screens, components) → **navigation** → **core** (store, api, theme, config, notifications) and **common** (components, localization, helpers). A **design-system** layer re-exports the theme tokens, the brand tokens (gradients/glow), and the theme provider as a single barrel.
|
|
6
|
+
|
|
7
|
+
> Imports in `src/` are **relative**. Path aliases (`@core/*`, `@common/*`, `@design-system`, …) are configured in `babel.config.js`, `tsconfig.json`, and `jest.config.js` and are available if you prefer them, but the shipped code reaches into `core/theme/*` directly rather than going through the barrel.
|
|
6
8
|
|
|
7
9
|
## Folder map
|
|
8
10
|
|
|
9
11
|
| Folder | Purpose |
|
|
10
12
|
|--------|--------|
|
|
11
|
-
| `src/common/` | Shared UI components, localization (i18n), helpers, validations, hooks, urls, utils |
|
|
12
|
-
| `src/core/` |
|
|
13
|
-
| `src/
|
|
14
|
-
| `src/
|
|
13
|
+
| `src/common/` | Shared UI components (incl. `ErrorBoundary`, `NetworkBanner`, `SnackbarProvider`), localization (i18n), helpers, validations, hooks, urls, utils |
|
|
14
|
+
| `src/core/api/` | Single axios instance + interceptors (auth, refresh-token dedup, locale, 401/402 handling) |
|
|
15
|
+
| `src/core/store/` | Redux Toolkit slices (`app`, `user`, `categories`) + persist (AsyncStorage, selective whitelist transforms) |
|
|
16
|
+
| `src/core/theme/` | `colors.ts`, `fonts.ts`, `commonSizes.ts`, `brand.ts` (gradients/glow), `ThemeProvider.tsx`. Light/dark/system theming |
|
|
17
|
+
| `src/core/config/` | Env-driven config (`API_BASE_URL`, `ENV`, feature toggles) |
|
|
18
|
+
| `src/core/notifications/` | FCM listeners (`notificationService.ts`), tap-routing (`routeFromNotificationData.ts`), auth check |
|
|
19
|
+
| `src/design-system/` | Theme + brand token re-exports + theme provider re-export (barrel; `@design-system` alias available but unused) |
|
|
20
|
+
| `src/navigation/` | Navigator setup, auth stack, main stack, root navigation ref, header components |
|
|
21
|
+
| `src/screens/` | Feature screens (Splash, Login, OTP, Home, Profile); each may have local `components/` and `hooks/` |
|
|
22
|
+
| `src/assets/brand/` | Brand logo SVGs (`logo-primary`, `logo-mono`, `logo-mark`, `wordmark-dark`) |
|
|
15
23
|
| `src/sheetManager/` | Action sheet registration |
|
|
16
24
|
|
|
17
25
|
## Data flow
|
|
18
26
|
|
|
19
|
-
- **Auth**: Token is stored in Redux (`user.accessToken`). Navigation shows Auth stack when there is no token, Main stack when there is.
|
|
20
|
-
- **API**: Single axios instance in `src/core/api/serverHeaders.ts`. Base URL comes from `src/core/config` (and `.env`). Request interceptor adds `Authorization: Bearer` and `locale
|
|
21
|
-
- **Redux**: Slices live under `src/core/store/<domain>/` (
|
|
27
|
+
- **Auth**: Token is stored in Redux (`user.accessToken`). Navigation shows Auth stack when there is no token, Main stack when there is. `user.refreshToken` is persisted; the axios response interceptor dedups concurrent 401s via a single in-flight `refreshPromise`, then retries the original request. On refresh failure, `setLogout()` is dispatched.
|
|
28
|
+
- **API**: Single axios instance in `src/core/api/serverHeaders.ts`. Base URL comes from `src/core/config` (and `.env`). Request interceptor adds `Authorization: Bearer` and `locale`. Response interceptor handles 401 (refresh) and 402 (logout).
|
|
29
|
+
- **Redux**: Slices live under `src/core/store/<domain>/` (`app`, `user`, `categories`). Each follows the house pattern — a `newState` reducer helper, a `LoadState` enum for request status, and `createAsyncThunk` thunks that call the API helpers. `categories` is a worked example: its thunk GETs `/categories`, the slice tracks `LoadState`, and the Home screen's `useHomeData` hook renders the result through `FlatListWrapper` (a full data → thunk → slice → list demo). Persist whitelist (`store.tsx`) controls what survives a kill — `user`: `accessToken`, `refreshToken`, `fcmToken`, `user`; `app`: `language`, `isRTL`. The `app` slice defaults `language` to English (`Languages.en`); Arabic / RTL stay wired and switchable at runtime.
|
|
30
|
+
- **Notifications**: `index.js` registers the FCM background handler before app boot — it queues any incoming `data` payload into `pendingBackgroundNotificationData`. `App.tsx` mounts `startPushNotificationListeners()` which wires foreground/background/cold-start/token-refresh listeners, plus an `AppState` + store subscriber that flushes the pending route when the user is logged in and the navigator is ready.
|
|
31
|
+
- **Theming**: The "Indigo → Cyan" tokens live in `src/core/theme/colors.ts`; gradient and glow tokens (`BrandGradients`, `Glow`) live in `src/core/theme/brand.ts` and pair with `react-native-linear-gradient`. `ThemeProvider` exposes `useTheme()` and **follows the system color scheme by default** (`App.tsx` renders `<ThemeProvider>` with no forced theme). Light and dark are both supported; the Profile screen offers a manual toggle. The brand `Logo` (`src/common/components/Logo.tsx`) renders the "FS" monogram from `react-native-svg` in four variants (`gradient` / `mono` / `light` / `mark`).
|
|
32
|
+
|
|
33
|
+
## Provider order in `App.tsx`
|
|
34
|
+
|
|
35
|
+
Outer → inner:
|
|
36
|
+
|
|
37
|
+
1. `ErrorBoundary` (catches render errors with a retry fallback)
|
|
38
|
+
2. `Provider` (Redux store)
|
|
39
|
+
3. `PersistGate` (redux-persist)
|
|
40
|
+
4. `GestureHandlerRootView`
|
|
41
|
+
5. `SnackbarProvider`
|
|
42
|
+
6. `ThemeProvider`
|
|
43
|
+
7. `RTLInitializer` (must wrap `LocalizationProvider`)
|
|
44
|
+
8. `LocalizationProvider`
|
|
45
|
+
9. `SafeAreaProvider`
|
|
46
|
+
10. `SheetProvider` (react-native-actions-sheet)
|
|
47
|
+
11. `BottomSheetModalProvider` (@gorhom/bottom-sheet)
|
|
48
|
+
12. `AppNavigator`
|
|
49
|
+
13. `NetworkBanner` (sibling of navigator, fixed position)
|
|
50
|
+
|
|
51
|
+
Order is load-bearing: persist must be ready before redux-aware components mount; gesture-handler must wrap everything that uses gestures; RTL must initialize before localized text renders.
|
|
22
52
|
|
|
23
53
|
## SOLID mapping
|
|
24
54
|
|
|
25
55
|
- **SRP**: One domain per store folder; one primary concern per component file; theme split into colors, fonts, sizes, consts, styles.
|
|
26
|
-
- **OCP**: Extend by adding screens, slices, or routes without changing existing stack logic; extend theme by editing theme files.
|
|
27
|
-
- **DIP**: Core (API, store) does not depend on UI; screens depend on core via hooks/selectors; config abstracts environment.
|
|
56
|
+
- **OCP**: Extend by adding screens, slices, or routes without changing existing stack logic; extend theme by editing theme files; extend notifications by editing `routeFromNotificationData.ts` only.
|
|
57
|
+
- **DIP**: Core (API, store, notifications) does not depend on UI; screens depend on core via hooks/selectors; config abstracts environment.
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
- Use **TypeScript** strictly; avoid `any` where possible.
|
|
6
6
|
- Use typed Redux: `useAppSelector`, `useAppDispatch`, and `createAppAsyncThunk` with `RootState` / `AppDispatch`.
|
|
7
|
+
- Follow the house slice pattern: a `newState` reducer helper, a `LoadState` enum for request status, and `createAsyncThunk` thunks that call the API helpers. The `categories` slice (`src/core/store/categories/`) is the reference.
|
|
8
|
+
- Use relative imports to match the existing code. Path aliases are configured but not used by the shipped `src/`.
|
|
7
9
|
- Run `npm run lint` and fix issues.
|
|
8
10
|
|
|
9
11
|
## Structure
|
|
@@ -21,6 +23,13 @@
|
|
|
21
23
|
|
|
22
24
|
- Avoid creating new objects/functions in render when they are passed as props to children.
|
|
23
25
|
- Use stable keys for list items.
|
|
26
|
+
- For heavy lists, use `src/common/components/FlatListWrapper.tsx` (FlashList-backed) and set `estimatedItemSize`; don't reintroduce a raw `FlatList`.
|
|
27
|
+
|
|
28
|
+
## Theming
|
|
29
|
+
|
|
30
|
+
- Change brand colors, fonts, and sizes only in `src/core/theme/` — keep the token keys stable so the rest of the app keeps working.
|
|
31
|
+
- Reuse the gradient and glow tokens from `src/core/theme/brand.ts` (`BrandGradients`, `Glow`) for the futuristic surfaces rather than hardcoding shadows or gradient stops.
|
|
32
|
+
- The app follows the system color scheme by default; verify new screens in both light and dark.
|
|
24
33
|
|
|
25
34
|
## Security
|
|
26
35
|
|
|
@@ -29,5 +38,5 @@
|
|
|
29
38
|
|
|
30
39
|
## LTS / upgrades
|
|
31
40
|
|
|
32
|
-
- The template targets **Node >= 20** and
|
|
41
|
+
- The template targets **Node >= 20** and **React Native 0.85.x** (React 19.2.x).
|
|
33
42
|
- To upgrade React Native, use [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/): select your current version and the target version, then apply the suggested changes to `package.json`, `android/`, `ios/`, and config files.
|
|
@@ -17,17 +17,40 @@ If you omit `--package-name`, the template will **prompt you** after init to ent
|
|
|
17
17
|
|
|
18
18
|
1. Copy `.env.example` to `.env`.
|
|
19
19
|
2. Set `API_BASE_URL` (and any other keys) for your backend.
|
|
20
|
-
3. The app reads these via `react-native-config`; `src/core/config/index.ts` re-exports them for type-safe use.
|
|
20
|
+
3. The app reads these via `react-native-config`; `src/core/config/index.ts` re-exports them for type-safe use as `API_BASE_URL` and `ENV` (the environment name; falls back to a legacy `ENVIRONMENT` var). Route all env access through this module.
|
|
21
21
|
|
|
22
22
|
Optional: use multiple env files (e.g. `.env.development`, `.env.staging`, `.env.production`) and build variants so each build uses the right URL.
|
|
23
23
|
|
|
24
|
-
## Theme
|
|
24
|
+
## Theme & branding
|
|
25
25
|
|
|
26
|
-
Edit these files for your brand (no need to touch components):
|
|
26
|
+
The template ships a futuristic **"Indigo → Cyan"** system (primary indigo `#5B6CFF`, accent cyan `#22E0D6`, deep ink `#0B1020`). Edit these files for your brand — token *keys* are stable across the app, so changing the hex values rebrands everything (no need to touch components):
|
|
27
27
|
|
|
28
28
|
- **Colors**: `src/core/theme/colors.ts`
|
|
29
29
|
- **Fonts**: `src/core/theme/fonts.ts`
|
|
30
30
|
- **Sizes / spacing**: `src/core/theme/commonSizes.ts`
|
|
31
|
+
- **Gradients & glow**: `src/core/theme/brand.ts` — `BrandColors`, `BrandGradients` (e.g. `BrandGradients.primary = ['#5B6CFF', '#22E0D6']`), `GradientDirection`, and `Glow` (ready-to-spread `ViewStyle` shadows). Gradient surfaces use `react-native-linear-gradient`.
|
|
32
|
+
|
|
33
|
+
These tokens are also re-exported from the `src/design-system` barrel.
|
|
34
|
+
|
|
35
|
+
### Light / dark / system theming
|
|
36
|
+
|
|
37
|
+
`ThemeProvider` (`src/core/theme/ThemeProvider.tsx`) exposes `useTheme()` and **follows the OS color scheme by default** — `App.tsx` renders `<ThemeProvider>` with no forced theme. Both light and dark are supported, and the Profile screen includes a manual toggle. To force one theme, pass it to `<ThemeProvider>` in `App.tsx`.
|
|
38
|
+
|
|
39
|
+
### Logo
|
|
40
|
+
|
|
41
|
+
The brand mark is a forward-leaning **"FS" monogram**:
|
|
42
|
+
|
|
43
|
+
- React component: `src/common/components/Logo.tsx` — `<Logo size={96} variant="gradient" />`, built on `react-native-svg`. Variants: `gradient` (default), `mono`, `light`, `mark`. It is wired into Splash, Login, Home, and Profile.
|
|
44
|
+
- Raw SVGs: `src/assets/brand/` (`logo-primary.svg`, `logo-mono.svg`, `logo-mark.svg`, `wordmark-dark.svg`).
|
|
45
|
+
|
|
46
|
+
To use your own mark, replace the paths in `Logo.tsx` (and the SVGs) — the rest of the app references the component, not the assets directly.
|
|
47
|
+
|
|
48
|
+
### Visual references
|
|
49
|
+
|
|
50
|
+
Two static reference pages ship with the template:
|
|
51
|
+
|
|
52
|
+
- **[`docs/design-system.html`](./design-system.html)** — color ramps, gradients, glow, and logo variants.
|
|
53
|
+
- **[`docs/wireframes.html`](./wireframes.html)** — the screen flow.
|
|
31
54
|
|
|
32
55
|
## Adding a new language
|
|
33
56
|
|
|
@@ -38,9 +61,11 @@ Edit these files for your brand (no need to touch components):
|
|
|
38
61
|
|
|
39
62
|
## Adding a screen
|
|
40
63
|
|
|
64
|
+
The template ships real, branded screens: **Splash** (the Auth stack entry, which hands off to Login), **Login** (logo + phone/password), **OTP** (verifies via a `verifyOTP` thunk), **Home** (greeting + gradient hero card + a categories list), and **Profile** (user card + language toggle + theme toggle + logout). Use any of them as a starting point.
|
|
65
|
+
|
|
41
66
|
1. Create a folder under `src/screens/<Feature>/` with `Feature.tsx` and optional `components/` and `hooks/`.
|
|
42
|
-
2. Register the screen in the right stack in `src/navigation/` (
|
|
43
|
-
3. Add the route and component to the stack
|
|
67
|
+
2. Register the screen in the right stack in `src/navigation/` (the Auth stack or the Main stack).
|
|
68
|
+
3. Add the route to `RootStackParamList` in `src/navigation/types.ts` (currently `Splash`, `Login`, `OTP`, `Main`, `Account`) and add the component to the stack's screen list.
|
|
44
69
|
|
|
45
70
|
## Adding a Redux slice
|
|
46
71
|
|
|
@@ -48,6 +73,94 @@ Edit these files for your brand (no need to touch components):
|
|
|
48
73
|
2. Add the slice to `src/core/store/rootReducer.ts`.
|
|
49
74
|
3. If the slice should persist, add a `createWhitelistFilter('<domain>', ['field1', 'field2'])` entry in `src/core/store/store.tsx` persist config.
|
|
50
75
|
|
|
76
|
+
The `categories` slice (`src/core/store/categories/`) is a complete, copyable example of the house pattern: a `newState` reducer helper, a `LoadState` enum for request status, and a `createAsyncThunk` that calls the `get()` API helper. The Home screen's `useHomeData` hook dispatches it and renders the result through `FlatListWrapper`.
|
|
77
|
+
|
|
51
78
|
## Feature flags / app config
|
|
52
79
|
|
|
53
80
|
Toggle features or app-level constants in `src/core/config/index.ts` or via env vars read there (e.g. `enableRTL`).
|
|
81
|
+
|
|
82
|
+
## Firebase / push notifications (FCM)
|
|
83
|
+
|
|
84
|
+
The template ships with `@react-native-firebase/{app,messaging,analytics}` wired into `src/core/notifications/`. Listeners are started from `App.tsx` and the background handler is registered in `index.js`. To make this work on a real device you need to add your Firebase project credentials.
|
|
85
|
+
|
|
86
|
+
### iOS
|
|
87
|
+
|
|
88
|
+
1. In the [Firebase console](https://console.firebase.google.com), add an iOS app using your `BUNDLE_ID`.
|
|
89
|
+
2. Download `GoogleService-Info.plist` and drag it into `ios/<YourApp>/` in Xcode (Copy items if needed, target = your app).
|
|
90
|
+
3. In `ios/Podfile`, ensure modular headers are enabled near the top:
|
|
91
|
+
```ruby
|
|
92
|
+
use_modular_headers!
|
|
93
|
+
```
|
|
94
|
+
4. In `ios/<YourApp>/AppDelegate.swift`, configure Firebase at startup:
|
|
95
|
+
```swift
|
|
96
|
+
import FirebaseCore
|
|
97
|
+
// …
|
|
98
|
+
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
|
99
|
+
FirebaseApp.configure()
|
|
100
|
+
// …
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
5. Enable **Push Notifications** + **Background Modes → Remote notifications** in the target's Signing & Capabilities.
|
|
104
|
+
6. Upload your APNs auth key in Firebase project settings → Cloud Messaging.
|
|
105
|
+
7. Run `cd ios && pod install`.
|
|
106
|
+
|
|
107
|
+
### Android
|
|
108
|
+
|
|
109
|
+
1. In the Firebase console, add an Android app using your `ANDROID_APP_ID`.
|
|
110
|
+
2. Download `google-services.json` and drop it into `android/app/`.
|
|
111
|
+
3. In `android/build.gradle`, add the Google services classpath:
|
|
112
|
+
```gradle
|
|
113
|
+
buildscript {
|
|
114
|
+
dependencies {
|
|
115
|
+
classpath("com.google.gms:google-services:4.4.2")
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
4. In `android/app/build.gradle`, apply the plugin at the very bottom:
|
|
120
|
+
```gradle
|
|
121
|
+
apply plugin: "com.google.gms.google-services"
|
|
122
|
+
```
|
|
123
|
+
5. Rebuild: `cd android && ./gradlew clean`.
|
|
124
|
+
|
|
125
|
+
### Routing taps
|
|
126
|
+
|
|
127
|
+
Notification taps route via `src/core/notifications/routeFromNotificationData.ts`. Send `data.screen` (and optionally `data.params` as a JSON string) in the FCM payload — the router calls `navigate(screen, params)`. Extend that file with `data.type`/`data.target` switches for richer flows.
|
|
128
|
+
|
|
129
|
+
## React Native 0.85.x
|
|
130
|
+
|
|
131
|
+
The template is on RN 0.85.2. If you upgrade your generated app to a newer RN later, use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) — select your current RN version on the left and the target on the right, then apply the suggested diffs to `package.json`, `ios/`, `android/`, and config files.
|
|
132
|
+
|
|
133
|
+
`react-native-reanimated` 4.x requires `react-native-worklets` and the `react-native-worklets/plugin` babel plugin (already in `babel.config.js`). Do not also add `react-native-reanimated/plugin` — only one of the two.
|
|
134
|
+
|
|
135
|
+
## Path aliases
|
|
136
|
+
|
|
137
|
+
The template wires these aliases through `babel.config.js`, `tsconfig.json`, and `jest.config.js`. **They are configured but not used by the shipped code** — `src/` imports relatively. They are here if you prefer aliases; opt in per file.
|
|
138
|
+
|
|
139
|
+
| Alias | Path |
|
|
140
|
+
|-------|------|
|
|
141
|
+
| `@core/*` | `src/core/*` |
|
|
142
|
+
| `@common/*` | `src/common/*` |
|
|
143
|
+
| `@navigation/*` | `src/navigation/*` |
|
|
144
|
+
| `@screens/*` | `src/screens/*` |
|
|
145
|
+
| `@sheetManager/*` | `src/sheetManager/*` |
|
|
146
|
+
| `@design-system` | `src/design-system` |
|
|
147
|
+
| `@types/*` | `src/types/*` |
|
|
148
|
+
| `@utils/*` | `src/utils/*` |
|
|
149
|
+
|
|
150
|
+
Add new aliases in all three files together — Babel rewrites imports at build time, TS resolves them for the editor, Jest resolves them for tests.
|
|
151
|
+
|
|
152
|
+
## CI / version bumping
|
|
153
|
+
|
|
154
|
+
`scripts/ci-sync-env.cjs` writes/updates `KEY=value` pairs in an env file. Use it in CI to inject Play Store / App Store auto-incremented build numbers:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
node scripts/ci-sync-env.cjs .env.production \
|
|
158
|
+
ANDROID_VERSION_CODE=42 \
|
|
159
|
+
IOS_BUILD_NUMBER=42
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Then run your release build — Gradle and the iOS scheme pick up the values via `react-native-config`.
|
|
163
|
+
|
|
164
|
+
## Git hooks
|
|
165
|
+
|
|
166
|
+
`husky` v9 + `lint-staged` are wired. Hooks live in `.husky/`. The pre-commit hook runs `lint-staged`, which applies `eslint --fix` and `prettier --write` to staged files only. To skip once (rare): `git commit --no-verify`.
|