From b1cdc4d184b1d1ed43faff841bd8dabd63d84f8b Mon Sep 17 00:00:00 2001 From: byGalax Date: Thu, 14 May 2026 00:08:22 +0200 Subject: [PATCH] chore(mobile): phase 1 quality-review fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three small follow-ups from the post-Phase-1 quality review: * authContext.tsx — drop the dead `userId` extraction + the `void userId` suppressor that masked an unused-locals warning. The session is already implicitly threaded through the supabase client, so no consumer of ensureDevice needed the value. * authContext.tsx — switch the device-name string concat to a template literal for consistency with the rest of the codebase. * ErrorBoundary.tsx — replace the four inline hex literals with their `theme/colors.ts` constants. The boundary was authored in Phase 0 before the theme module existed; this brings it in line with every Phase 1 screen. * apps/mobile/README.md — drop the stale Phase-0 paragraph about the `lib/sharedSmoke.ts` canary (deleted in Phase 1) and add a short pointer to the env-var setup. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/mobile/README.md | 27 +++++++++++++++--------- apps/mobile/components/ErrorBoundary.tsx | 12 ++++++----- apps/mobile/lib/authContext.tsx | 6 ++---- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/apps/mobile/README.md b/apps/mobile/README.md index be28000..8202016 100644 --- a/apps/mobile/README.md +++ b/apps/mobile/README.md @@ -55,16 +55,23 @@ pnpm mobile:typecheck # tsc --noEmit ## Architecture notes - Expo Router (file-based) — screens live under `app/`. -- `expo-secure-store` — Keychain / Keystore-backed secret store (used by - the mobile `SecretStore` adapter in Phase 1). -- `expo-sqlite` — local encrypted history (Phase 1). -- `react-native-libsodium` — crypto primitives (Phase 1's - `CryptoBackend` adapter wraps this). -- `@chat-app/shared` — business logic shared with the desktop, including - the `CryptoBackend` and `SecretStore` interfaces the mobile adapters - plug into. -- `lib/sharedSmoke.ts` exists only to prove Metro can resolve the - workspace package; it's deleted in Phase 1. +- `expo-secure-store` — Keychain / Keystore-backed secret store, wrapped + by `lib/secretStore.ts` to implement `@chat-app/shared`'s `SecretStore`. +- `@react-native-async-storage/async-storage` — Supabase session-token + storage, surfaced via `lib/sessionStorage.ts`. +- `expo-sqlite` — local encrypted history (slated for a later phase). +- `react-native-libsodium` — crypto primitives, wrapped by + `lib/cryptoBackend.ts` to implement `@chat-app/shared`'s `CryptoBackend`. + Registered once at boot in `app/_layout.tsx`. +- `@chat-app/shared` — business logic shared with the desktop; the mobile + adapters plug into its `CryptoBackend` + `SecretStore` interfaces, and + every chat / auth call goes through the namespace exports. + +## Env vars + +Copy `.env.example` to `.env.local` and fill in the same Supabase host + +anon key the desktop uses. Expo bundles only `EXPO_PUBLIC_*`-prefixed +vars into the JS, which is what the three required values use. ## Roadmap diff --git a/apps/mobile/components/ErrorBoundary.tsx b/apps/mobile/components/ErrorBoundary.tsx index fd0452b..2324f53 100644 --- a/apps/mobile/components/ErrorBoundary.tsx +++ b/apps/mobile/components/ErrorBoundary.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { Pressable, StyleSheet, Text, View } from 'react-native'; +import { colors } from '../theme/colors'; + // Catch render errors anywhere below this boundary and show a readable // fallback. Without it, a thrown error during render produces a white // screen on TestFlight / production builds with no way for the user to @@ -53,16 +55,16 @@ const styles = StyleSheet.create({ flex: 1, alignItems: 'center', justifyContent: 'center', - backgroundColor: '#0b0b0f', + backgroundColor: colors.bg, padding: 24, }, - title: { color: '#fff', fontSize: 22, fontWeight: '600', marginBottom: 8 }, - message: { color: '#9ca3af', textAlign: 'center', marginBottom: 24 }, + title: { color: colors.text, fontSize: 22, fontWeight: '600', marginBottom: 8 }, + message: { color: colors.textMuted, textAlign: 'center', marginBottom: 24 }, button: { - backgroundColor: '#5865f2', + backgroundColor: colors.accent, paddingHorizontal: 20, paddingVertical: 12, borderRadius: 10, }, - buttonText: { color: '#fff', fontWeight: '600' }, + buttonText: { color: colors.text, fontWeight: '600' }, }); diff --git a/apps/mobile/lib/authContext.tsx b/apps/mobile/lib/authContext.tsx index 243d19e..fc618ff 100644 --- a/apps/mobile/lib/authContext.tsx +++ b/apps/mobile/lib/authContext.tsx @@ -37,8 +37,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { // Resolve or create the device record for this install given an active // session. Stores the private key in expo-secure-store on first run. - const ensureDevice = useCallback(async (currentSession: Session): Promise => { - const userId = currentSession.user.id; + const ensureDevice = useCallback(async (_currentSession: Session): Promise => { const savedDeviceId = await secretStore.getSecret(KEY_DEVICE_ID); const savedPrivKey = await secretStore.getSecret(KEY_DEVICE_PRIVKEY); @@ -59,7 +58,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const kp = backend.generateKeyPair(); const platform = Platform.OS === 'ios' ? 'ios' : Platform.OS === 'android' ? 'android' : 'linux'; const record = await auth.registerDevice(supabase, { - name: 'Netralax Mobile (' + Platform.OS + ')', + name: `Netralax Mobile (${Platform.OS})`, platform, publicKey: kp.publicKey, }); @@ -67,7 +66,6 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await secretStore.setSecret(KEY_DEVICE_PRIVKEY, kp.privateKey); setDevice(record); setOwnPrivateKey(kp.privateKey); - void userId; }, []); useEffect(() => {