Fix Live Activity lock screen rendering and polish multi-account auth.
Flatten widget layouts and use system colors so banner and expanded regions render on vibrant lock screens; migrate auth sessions per account to prevent double sign-in; scope app lock PIN to accounts; default clock description to "Clock In"; add architecture docs and deferred form validation on auth screens. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
# beenvoice Mobile
|
||||
|
||||
Expo companion app for [beenvoice](../beenvoice) — dashboard, time clock, invoices, and account settings.
|
||||
Expo companion for [beenvoice](../beenvoice) — dashboard, time clock, invoices, clients, businesses, and settings. Shares the **same tRPC API** and **better-auth** sessions as the web app.
|
||||
|
||||
**Architecture (dense):** [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Bun](https://bun.sh) 1.3+
|
||||
- beenvoice server running (see `../beenvoice/README.md`)
|
||||
- iOS development build for Live Activities (`expo-widgets`)
|
||||
- beenvoice API running ([setup](../beenvoice/README.md))
|
||||
- Xcode + iOS Simulator (or device) for native dev build
|
||||
- **Not Expo Go** — widgets, SecureStore auth, and biometrics need `expo-dev-client`
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -16,68 +19,103 @@ bun install
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` and set your API URL:
|
||||
`.env`:
|
||||
|
||||
```env
|
||||
# Simulator
|
||||
EXPO_PUBLIC_API_URL=http://localhost:3000
|
||||
|
||||
# Physical iPhone (use your Mac's LAN IP)
|
||||
# Physical iPhone — Mac LAN IP
|
||||
EXPO_PUBLIC_API_URL=http://192.168.1.42:3000
|
||||
```
|
||||
|
||||
The beenvoice server must have the Expo auth plugin enabled (`@better-auth/expo` in `beenvoice/src/lib/auth.ts`).
|
||||
Omit `EXPO_PUBLIC_API_URL` in production builds to default to `https://beenvoice.soconnor.dev`.
|
||||
|
||||
Server must enable `@better-auth/expo` in `beenvoice/src/lib/auth.ts` with `beenvoice://` in `trustedOrigins`.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
# Terminal 1 — API server
|
||||
# Terminal 1 — API
|
||||
cd ../beenvoice && bun run dev
|
||||
|
||||
# Terminal 2 — mobile app (development build)
|
||||
cd beenvoice-app
|
||||
bun run ios
|
||||
# Terminal 2 — mobile (builds native app if needed)
|
||||
cd beenvoice-app && bun run ios
|
||||
```
|
||||
|
||||
This uses port **8082** for Metro so it does not collide with other Expo projects on 8081.
|
||||
Metro uses port **8082** (avoids other Expo projects on 8081).
|
||||
|
||||
If you already built the app and only need Metro:
|
||||
Metro only (app already installed):
|
||||
|
||||
```bash
|
||||
bun run start -- --clear
|
||||
```
|
||||
|
||||
Then open the **beenvoice** app on the simulator (not Expo Go).
|
||||
Open the **beenvoice** dev build on the simulator — not Expo Go.
|
||||
|
||||
Live Activities require a native build (`bun run ios`). They do not work in Expo Go.
|
||||
### After native changes
|
||||
|
||||
After changing `assets/beenvoice.icon`, rebuild iOS:
|
||||
Icon (`assets/beenvoice.icon`), widgets, or new native modules:
|
||||
|
||||
```bash
|
||||
bunx expo prebuild --platform ios --clean
|
||||
bun run ios
|
||||
```
|
||||
|
||||
### Troubleshooting `PlatformConstants` / `[runtime not ready]`
|
||||
|
||||
Usually one of:
|
||||
|
||||
1. **Wrong Metro bundler** — another project's dev server is on the same port. Stop it or use `--port 8082`.
|
||||
2. **Stale native build** — after adding native modules, rebuild:
|
||||
```bash
|
||||
bunx expo prebuild --platform ios --clean
|
||||
bun run ios
|
||||
```
|
||||
3. **Expo Go** — native modules like widgets need the custom dev build from `bun run ios`, not Expo Go.
|
||||
|
||||
## Features
|
||||
|
||||
- **Auth** — sign in, register, forgot password, reset password; multiple saved accounts
|
||||
- **Dashboard** — revenue, pending, overdue, recent invoices
|
||||
- **Timer** — clock in/out with client, invoice, and hourly rate; iOS Live Activity (dev build)
|
||||
- **Invoices** — list, filter by status, tap to update status
|
||||
- **Settings** — profile, accounts, theme (system/light/dark), server URL, sign out
|
||||
| Area | Details |
|
||||
|------|---------|
|
||||
| **Auth** | Sign in, register, forgot/reset password; official or self-hosted server |
|
||||
| **Multi-account** | Bitwarden-style switcher; per-account session in SecureStore |
|
||||
| **Dashboard** | Revenue, pending, overdue, running timer, recent invoices |
|
||||
| **Timer** | Clock in/out, client + invoice + rate; optional description (default "Clock In"); iOS Live Activity |
|
||||
| **Entities** | Clients and businesses — list, create, edit |
|
||||
| **Invoices** | List, filter, create, edit, status updates |
|
||||
| **Settings** | Profile, accounts, theme, per-account app lock (PIN + Face ID), sign out |
|
||||
| **App lock** | Per-account; locks on background return |
|
||||
|
||||
## Auth & accounts (summary)
|
||||
|
||||
- **Guest** auth storage: `beenvoice:guest` until first successful login
|
||||
- **Per account**: `beenvoice:auth:{host::userId}` in SecureStore
|
||||
- After login, `finalizeAuthenticatedAccount()` migrates session keys before activating the account (avoids double login)
|
||||
- **Server picker**: Official (`beenvoice.soconnor.dev`) or custom URL on auth screens
|
||||
|
||||
Full flow: [docs/ARCHITECTURE.md#multi-account-model](./docs/ARCHITECTURE.md#multi-account-model)
|
||||
|
||||
## Deep links
|
||||
|
||||
- `beenvoice://reset-password?token=...` — open reset password screen with token prefilled
|
||||
| Scheme | Screen |
|
||||
|--------|--------|
|
||||
| `beenvoice://reset-password?token=…` | Reset password |
|
||||
| `beenvoice://timer` | Timer tab (from Live Activity) |
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
app/
|
||||
_layout.tsx # Providers, auth guard
|
||||
(auth)/ # sign-in, register, password flows
|
||||
(app)/ # tab shell + nested stacks
|
||||
components/ # UI, forms, chrome, time clock
|
||||
contexts/ # Auth, Accounts, AppLock, Theme
|
||||
lib/ # tRPC, auth storage, config, theming
|
||||
widgets/ # iOS Live Activity (TimeClockActivity)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| `PlatformConstants` / runtime not ready | Stop other Metro on 8081/8082; rebuild with `prebuild --clean` |
|
||||
| Expo Go | Use `bun run ios` dev build |
|
||||
| API errors on device | `EXPO_PUBLIC_API_URL` = Mac LAN IP; server `BETTER_AUTH_URL` must match |
|
||||
| Live Activity empty | Rebuild iOS; widget UI must live inside `"widget"` function |
|
||||
| Login twice | Server + app versions with session migration (`lib/auth-storage.ts`) |
|
||||
|
||||
## Related
|
||||
|
||||
- [beenvoice README](../beenvoice/README.md)
|
||||
- [beenvoice ARCHITECTURE](../beenvoice/docs/ARCHITECTURE.md)
|
||||
- [Workspace root README](../README.md)
|
||||
|
||||
Reference in New Issue
Block a user