Skip to content

feat: SplitPro React Native app - #39

Merged
KMKoushik merged 12 commits into
mainfrom
feat/mobile-app
Nov 4, 2026
Merged

KMKoushik merged 12 commits into
mainfrom
feat/mobile-app

Conversation

@KMKoushik

@KMKoushik KMKoushik commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

The SplitPro React Native app in mobile/. Draft: stacked on the backend PR, which has to be deployed before the app can sign in to splitpro.app.

What's in it

  • Expo SDK 58, React Native 0.88, Expo Router; its own pnpm package, kept out of the web build.
  • Same features as the web: balances, friends, groups (create, members, default split, repeating expenses, invite/join links), add and edit expense (every split type, currencies, categories, repeat, receipts), expense detail, settle up (friend and group), activity, account.
  • Native UI: system tab bar and headers, large titles, SF Symbols / Material icons, system font and colors, light and dark, native menus, pickers, sheets, swipe actions and long-press previews.
  • Delete account from the Account tab, confirmed with an emailed code (and a Sign in with Apple prompt for Apple-linked accounts, to revoke the token).
  • Sign-in with email code, Google and Apple; push notifications that open the right screen.
  • Talks to the existing tRPC API with the server's AppRouter types and reuses the web's split logic, so changes to either show up as type errors.
  • EAS project @koushikdotdev/splitpro, eas.json with simulator, preview and production profiles.

Checks

In mobile/: typecheck, lint, Prettier and 57 tests pass; Android bundle builds. QA'd on an iPhone 17 Pro simulator (iOS 27) in light and dark against a local server.

Not done yet

  • Real-device checks: push, Apple/Google sign-in, camera and receipt upload.
  • Android on-screen QA.
  • Universal links / App Links (.well-known files on splitpro.app).

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 157 files, which is 57 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c90c1978-a07f-4888-8a9e-032fc0cf5bf1
Commits

Reviewing files that changed from the base of the PR and between 38d0db4 and 6900b3e.

Files ignored due to path filters: 3
  • mobile/assets/icon.png is excluded by !**/*.png
  • mobile/assets/splash-icon.png is excluded by !**/*.png
  • mobile/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing: 157
  • mobile/.claude/settings.json
  • mobile/.gitignore
  • mobile/.npmrc
  • mobile/.prettierignore
  • mobile/.prettierrc.json
  • mobile/AGENTS.md
  • mobile/README.md
  • mobile/app.config.ts
  • mobile/eas.json
  • mobile/eslint.config.js
  • mobile/metro.config.js
  • mobile/package.json
  • mobile/src/app/(app)/(tabs)/(account)/_layout.tsx
  • mobile/src/app/(app)/(tabs)/(account)/account.tsx
  • mobile/src/app/(app)/(tabs)/(activity)/_layout.tsx
  • mobile/src/app/(app)/(tabs)/(activity)/activity.tsx
  • mobile/src/app/(app)/(tabs)/(balances)/_layout.tsx
  • mobile/src/app/(app)/(tabs)/(balances)/balances.tsx
  • mobile/src/app/(app)/(tabs)/(groups)/_layout.tsx
  • mobile/src/app/(app)/(tabs)/(groups)/groups.tsx
  • mobile/src/app/(app)/(tabs)/_layout.tsx
  • mobile/src/app/(app)/_layout.tsx
  • mobile/src/app/(app)/add.tsx
  • mobile/src/app/(app)/balances/[friendId].tsx
  • mobile/src/app/(app)/delete-account.tsx
  • mobile/src/app/(app)/edit-profile.tsx
  • mobile/src/app/(app)/expenses/[expenseId].tsx
  • mobile/src/app/(app)/feedback.tsx
  • mobile/src/app/(app)/groups/[groupId].tsx
  • mobile/src/app/(app)/groups/[groupId]/add-members.tsx
  • mobile/src/app/(app)/groups/[groupId]/default-split.tsx
  • mobile/src/app/(app)/groups/[groupId]/info.tsx
  • mobile/src/app/(app)/groups/new.tsx
  • mobile/src/app/(app)/join-group.tsx
  • mobile/src/app/(app)/new.tsx
  • mobile/src/app/(app)/settle-up.tsx
  • mobile/src/app/(auth)/_layout.tsx
  • mobile/src/app/(auth)/oauth-callback.tsx
  • mobile/src/app/(auth)/sign-in.tsx
  • mobile/src/app/(auth)/verify.tsx
  • mobile/src/app/_layout.tsx
  • mobile/src/app/index.tsx
  • mobile/src/components/account/NotificationsSection.tsx
  • mobile/src/components/account/XLogo.tsx
  • mobile/src/components/account/downloadData.ts
  • mobile/src/components/activity/ActivityItem.tsx
  • mobile/src/components/add-expense/AddExpenseForm.tsx
  • mobile/src/components/add-expense/AmountField.tsx
  • mobile/src/components/add-expense/DetailRows.tsx
  • mobile/src/components/add-expense/ParticipantsInput.tsx
  • mobile/src/components/add-expense/ReceiptRow.tsx
  • mobile/src/components/add-expense/SelectUserOrGroup.tsx
  • mobile/src/components/add-expense/SplitEditorSheet.tsx
  • mobile/src/components/add-expense/addExpense.test.ts
  • mobile/src/components/add-expense/amountInput.ts
  • mobile/src/components/add-expense/calendar.ts
  • mobile/src/components/add-expense/categories.ts
  • mobile/src/components/add-expense/formChanges.ts
  • mobile/src/components/add-expense/offerPush.ts
  • mobile/src/components/add-expense/splitStatus.ts
  • mobile/src/components/add-expense/timeZone.ts
  • mobile/src/components/add-expense/useInviteFriend.ts
  • mobile/src/components/add-expense/useSaveExpense.ts
  • mobile/src/components/expense-detail/ExpenseDetails.tsx
  • mobile/src/components/expense-detail/ReceiptImage.tsx
  • mobile/src/components/expense-detail/RecurringRule.tsx
  • mobile/src/components/expense-detail/expenseDetail.test.ts
  • mobile/src/components/expense-detail/expenseDetail.ts
  • mobile/src/components/expense/AddExpenseAction.tsx
  • mobile/src/components/expense/ExpenseListDate.tsx
  • mobile/src/components/expense/ExpenseListItem.tsx
  • mobile/src/components/expense/categoryIcons.tsx
  • mobile/src/components/expense/index.ts
  • mobile/src/components/expense/useCurrentUser.ts
  • mobile/src/components/friend/BalanceTotals.tsx
  • mobile/src/components/friend/FriendBalanceRow.tsx
  • mobile/src/components/friend/FriendSummary.tsx
  • mobile/src/components/friend/exportCsv.ts
  • mobile/src/components/group/DefaultSplitSummary.tsx
  • mobile/src/components/group/GroupBalanceRow.tsx
  • mobile/src/components/group/GroupRecurringRules.tsx
  • mobile/src/components/group/GroupStatsSheet.tsx
  • mobile/src/components/group/GroupSummary.tsx
  • mobile/src/components/group/NoMembers.tsx
  • mobile/src/components/group/invite.ts
  • mobile/src/components/group/useGroupDetails.ts
  • mobile/src/components/group/useGroupExit.ts
  • mobile/src/components/settle/FriendSettleUp.tsx
  • mobile/src/components/settle/GroupSettleUp.tsx
  • mobile/src/components/settle/PaymentDate.tsx
  • mobile/src/components/settle/SettleUpPayment.tsx
  • mobile/src/components/settle/index.ts
  • mobile/src/components/settle/shared.tsx
  • mobile/src/components/ui/Avatar.tsx
  • mobile/src/components/ui/Button.tsx
  • mobile/src/components/ui/Card.tsx
  • mobile/src/components/ui/CodeInput.tsx
  • mobile/src/components/ui/CurrencySheet.tsx
  • mobile/src/components/ui/EmptyState.tsx
  • mobile/src/components/ui/Fab.tsx
  • mobile/src/components/ui/HeaderActions.tsx
  • mobile/src/components/ui/Icon.tsx
  • mobile/src/components/ui/Input.tsx
  • mobile/src/components/ui/InsetStickyHeader.tsx
  • mobile/src/components/ui/ListRow.tsx
  • mobile/src/components/ui/ModalHeader.tsx
  • mobile/src/components/ui/Money.tsx
  • mobile/src/components/ui/PopUpButton.tsx
  • mobile/src/components/ui/QuickActions.tsx
  • mobile/src/components/ui/Screen.tsx
  • mobile/src/components/ui/SearchField.tsx
  • mobile/src/components/ui/Section.tsx
  • mobile/src/components/ui/SettingsIcon.tsx
  • mobile/src/components/ui/Sheet.tsx
  • mobile/src/components/ui/SheetHeader.tsx
  • mobile/src/components/ui/Skeleton.tsx
  • mobile/src/components/ui/Spinner.tsx
  • mobile/src/components/ui/SwipeActions.tsx
  • mobile/src/components/ui/Text.tsx
  • mobile/src/components/ui/Toast.tsx
  • mobile/src/components/ui/index.ts
  • mobile/src/components/ui/tabIcon.android.tsx
  • mobile/src/components/ui/tabIcon.tsx
  • mobile/src/i18n/i18next.d.ts
  • mobile/src/i18n/index.ts
  • mobile/src/i18n/locales/en.json
  • mobile/src/lib/api.ts
  • mobile/src/lib/appConfig.ts
  • mobile/src/lib/authApi.ts
  • mobile/src/lib/config.ts
  • mobile/src/lib/countdown.ts
  • mobile/src/lib/dates.ts
  • mobile/src/lib/dialogs.ts
  • mobile/src/lib/haptics.ts
  • mobile/src/lib/money.ts
  • mobile/src/lib/navigation.ts
  • mobile/src/lib/pendingLink.test.ts
  • mobile/src/lib/pendingLink.ts
  • mobile/src/lib/pkce.test.mjs
  • mobile/src/lib/pkce.ts
  • mobile/src/lib/push.ts
  • mobile/src/lib/socialAuth.ts
  • mobile/src/lib/storage.ts
  • mobile/src/lib/storage.web.ts
  • mobile/src/providers/ApiProvider.tsx
  • mobile/src/providers/usePendingLink.ts
  • mobile/src/providers/usePushNotifications.ts
  • mobile/src/shims/prisma-client.ts
  • mobile/src/store/addExpenseStore.ts
  • mobile/src/store/authStore.ts
  • mobile/src/store/recentCurrencies.ts
  • mobile/src/theme/navigation.ts
  • mobile/src/theme/palette.test.ts
  • mobile/src/theme/palette.ts
  • mobile/src/theme/tokens.ts
  • mobile/src/types/expo.d.ts
  • mobile/tsconfig.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@KMKoushik
KMKoushik force-pushed the feat/mobile-app branch 3 times, most recently from 9d1f1d4 to 760f13f Compare October 21, 2026 09:55
@KMKoushik
KMKoushik force-pushed the feat/mobile-app branch 2 times, most recently from edf80f3 to f2bedf3 Compare October 31, 2026 04:11
Expo SDK 58 app in mobile/ for splitpro.app with native iOS/Android UI:
balances, friends, groups, add/edit expense with every split type, expense
detail, settle up, activity, account, Google/Apple/email sign-in and push.
Uses the server's AppRouter types and the web's shared split logic.
@KMKoushik
KMKoushik changed the base branch from feat/mobile-backend to main October 31, 2026 04:22
Android resolves the semantic colors once at launch, but the status bar, native
views and useColorScheme followed a later dark-mode switch, leaving white status
bar icons on a light screen. Pin the app to the launch scheme until the next launch.
Android's form sheet is a bare bottom sheet without the native header, so settle
up had no Close or Save there. Present it like the other flows on Android and keep
the form sheet on iOS. The back button now goes to a modal's previous step
(ModalHeader onBack: settle up's amount step, delete account's code step) instead
of closing the whole modal.
Edit profile, feedback and delete account were modals inside the Account tab's
stack. On Android a modal only covers its own stack, so the navigation bar stayed
visible and tappable under them. Declare them in the signed-in stack like the other
flows; their URLs don't change.
The search bar's own back handling doesn't run inside the native tabs, so back
switched to the Balances tab with the search still open, and onCancelButtonPress is
iOS only, so closing the search never reset the filter. Close it on back while the
screen is focused, and reset on onClose.
The Material navigation bar showed a label only under the selected tab. Material 3
labels every destination, as the iOS tab bar does.
…roid

The Android tab bar mixed two palettes: the selected icon and label were the
brand cyan while Material filled the indicator with the wallpaper's secondary
container (a lavender/blue), and pressing a tab drew an opaque `primary` pill
over the icon. Selected tabs also kept the outlined icon, because `md` only
draws outlined Material Symbols.

- indicator: the brand's secondary container (tonal palette of the cyan seed)
- ripple: a 10% tint state layer, the Material pressed opacity. react-native-
  screens re-applies the appearance on every tab change, which rebuilds the
  ripple mid-press; a faint state layer keeps that cut invisible
- selected icons: the filled Material Symbols style, like `.fill` on iOS,
  through `tabIcon` (Android only; iOS props are unchanged)
Guard verify with a ref instead of state (auto-submit and a tap could both
run), always reset in finally, and time out auth requests after 20s so a
stalled request can't leave the sign-in screens spinning.
@KMKoushik
KMKoushik marked this pull request as ready for review November 4, 2026 20:42
@KMKoushik
KMKoushik merged commit f88133a into main Nov 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant