355b14faef
Enable App Store builds without EAS, iOS 18 App Intents plugins, and signing fixes for distribution export. Add mobile invoice PDF preview, compact line items, and more reliable shortcut deep-link handling. Co-authored-by: Cursor <cursoragent@cursor.com>
144 lines
4.8 KiB
Markdown
144 lines
4.8 KiB
Markdown
# beenvoice Mobile
|
|
|
|
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 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
|
|
|
|
```bash
|
|
cd beenvoice-app
|
|
bun install
|
|
cp .env.example .env
|
|
```
|
|
|
|
`.env`:
|
|
|
|
```env
|
|
# Simulator
|
|
EXPO_PUBLIC_API_URL=http://localhost:3000
|
|
|
|
# Physical iPhone — Mac LAN IP
|
|
EXPO_PUBLIC_API_URL=http://192.168.1.42:3000
|
|
```
|
|
|
|
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
|
|
cd ../beenvoice && bun run dev
|
|
|
|
# Terminal 2 — mobile (builds native app if needed)
|
|
cd beenvoice-app && bun run ios
|
|
```
|
|
|
|
Metro uses port **8082** (avoids other Expo projects on 8081).
|
|
|
|
Metro only (app already installed):
|
|
|
|
```bash
|
|
bun run start -- --clear
|
|
```
|
|
|
|
Open the **beenvoice** dev build on the simulator — not Expo Go.
|
|
|
|
### After native changes
|
|
|
|
Icon (`assets/beenvoice.icon`), widgets, or new native modules:
|
|
|
|
```bash
|
|
bunx expo prebuild --platform ios --clean
|
|
bun run ios
|
|
```
|
|
|
|
## Features
|
|
|
|
| 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 & Shortcuts
|
|
|
|
| URL | Action |
|
|
|-----|--------|
|
|
| `beenvoice://reset-password?token=…` | Reset password |
|
|
| `beenvoice://timer` | Open time clock |
|
|
| `beenvoice://shortcuts/clock-in` | Clock in (last client) |
|
|
| `beenvoice://shortcuts/clock-in?title=…` | Clock in with title |
|
|
| `beenvoice://shortcuts/clock-out` | Clock out running timer |
|
|
|
|
**iOS Shortcuts / Siri** (requires native rebuild: `bunx expo prebuild --platform ios && bun run ios`):
|
|
|
|
- **Clock In** — starts the timer with your last client
|
|
- **Clock Out** — stops the running timer
|
|
- **Open Time Clock** — opens the timer tab
|
|
|
|
1. Install a fresh build on a physical iPhone (iOS 16+).
|
|
2. Open the app once while signed in (registers shortcuts with the system).
|
|
3. Shortcuts app → search **beenvoice** → add actions, or say “Hey Siri, clock in with beenvoice”.
|
|
4. Pick a client once on the Timer tab before the first clock-in shortcut.
|
|
|
|
**Test deep links:**
|
|
|
|
```bash
|
|
xcrun simctl openurl booted "beenvoice://shortcuts/clock-in"
|
|
xcrun simctl openurl booted "beenvoice://shortcuts/clock-out"
|
|
xcrun simctl openurl booted "beenvoice://timer"
|
|
```
|
|
|
|
## 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)
|