From a275703ba6e34c05155b667b6b8983e0c98c3332 Mon Sep 17 00:00:00 2001 From: byGalax Date: Wed, 13 May 2026 23:54:10 +0200 Subject: [PATCH] feat(mobile): add AsyncStorage dep + env reader + theme constants --- apps/mobile/.env.example | 7 +++++++ apps/mobile/lib/env.ts | 19 +++++++++++++++++++ apps/mobile/package.json | 1 + apps/mobile/theme/colors.ts | 25 +++++++++++++++++++++++++ pnpm-lock.yaml | 20 ++++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 apps/mobile/.env.example create mode 100644 apps/mobile/lib/env.ts create mode 100644 apps/mobile/theme/colors.ts diff --git a/apps/mobile/.env.example b/apps/mobile/.env.example new file mode 100644 index 0000000..0c8005d --- /dev/null +++ b/apps/mobile/.env.example @@ -0,0 +1,7 @@ +# Copy to `.env.local` and fill in. Expo bundles only EXPO_PUBLIC_* vars +# into the JS, which is what we want for these — they are public Supabase +# project keys (anon key + URL) protected by RLS on the server. + +EXPO_PUBLIC_SUPABASE_URL=https://your-supabase-host.example +EXPO_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_... +EXPO_PUBLIC_AUTH_REDIRECT_URL=netralax://auth/callback diff --git a/apps/mobile/lib/env.ts b/apps/mobile/lib/env.ts new file mode 100644 index 0000000..181d913 --- /dev/null +++ b/apps/mobile/lib/env.ts @@ -0,0 +1,19 @@ +// EXPO_PUBLIC_* vars are inlined at bundle time by Expo's Babel plugin. +// We pull them through a single typed module so a missing var is a loud +// startup error rather than a confusing Supabase 401 later. + +function required(name: string): string { + const v = process.env[name]; + if (!v || v.length === 0) { + throw new Error( + 'Missing required env var ' + name + '. Set it in apps/mobile/.env.local — see .env.example.', + ); + } + return v; +} + +export const env = { + supabaseUrl: required('EXPO_PUBLIC_SUPABASE_URL'), + supabaseAnonKey: required('EXPO_PUBLIC_SUPABASE_ANON_KEY'), + authRedirectUrl: process.env.EXPO_PUBLIC_AUTH_REDIRECT_URL ?? 'netralax://auth/callback', +} as const; diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 0c47de5..6283f5d 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -20,6 +20,7 @@ "dependencies": { "@chat-app/db-types": "workspace:*", "@chat-app/shared": "workspace:*", + "@react-native-async-storage/async-storage": "^3.0.2", "@supabase/supabase-js": "^2.46.0", "expo": "^52.0.0", "expo-application": "^55.0.15", diff --git a/apps/mobile/theme/colors.ts b/apps/mobile/theme/colors.ts new file mode 100644 index 0000000..ff00a9d --- /dev/null +++ b/apps/mobile/theme/colors.ts @@ -0,0 +1,25 @@ +// Centralised hex constants. Anything new screen / component should +// import from here instead of inlining a literal so we have a single +// place to swap brand tones later. The Phase-0 review flagged five +// hex codes duplicated across components — this is the fix. +export const colors = { + // Surfaces / chrome + bg: '#0b0b0f', + surface: '#16161c', + border: '#27272e', + + // Text + text: '#ffffff', + textMuted: '#9ca3af', + textDim: '#6b7280', + + // Accents + accent: '#5865f2', + accentMuted: 'rgba(88,101,242,0.15)', + + // Status + danger: '#ef4444', + success: '#10b981', +} as const; + +export type ColorKey = keyof typeof colors; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 80d2694..fa19724 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -156,6 +156,9 @@ importers: '@chat-app/shared': specifier: workspace:* version: link:../../packages/shared + '@react-native-async-storage/async-storage': + specifier: ^3.0.2 + version: 3.0.2(react-native@0.76.0(@babel/core@7.29.0)(@babel/preset-env@7.29.2(@babel/core@7.29.0))(@types/react@18.3.28)(encoding@0.1.13)(react@18.3.1))(react@18.3.1) '@supabase/supabase-js': specifier: ^2.46.0 version: 2.103.3 @@ -1475,6 +1478,12 @@ packages: peerDependencies: react: ^16.8 || ^17.0 || ^18.0 + '@react-native-async-storage/async-storage@3.0.2': + resolution: {integrity: sha512-XP0zDIl+1XoeuQ7f878qXKdl77zLwzLALPpxvNRc7ZtDh9ew36WSvOdQOhFkexMySapFAWxEbZxS8K8J2DU4eg==} + peerDependencies: + react: '*' + react-native: '*' + '@react-native/assets-registry@0.76.0': resolution: {integrity: sha512-U8KLV+PC/cRIiDpb1VbeGuEfKq2riZZtNVLp1UOyKWfPbWWu8j6Fr95w7j+nglp41z70iBeF2OmCiVnRvtNklA==} engines: {node: '>=18'} @@ -3700,6 +3709,9 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + idb@8.0.3: + resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -7858,6 +7870,12 @@ snapshots: '@radix-ui/react-compose-refs': 1.0.0(react@18.3.1) react: 18.3.1 + '@react-native-async-storage/async-storage@3.0.2(react-native@0.76.0(@babel/core@7.29.0)(@babel/preset-env@7.29.2(@babel/core@7.29.0))(@types/react@18.3.28)(encoding@0.1.13)(react@18.3.1))(react@18.3.1)': + dependencies: + idb: 8.0.3 + react: 18.3.1 + react-native: 0.76.0(@babel/core@7.29.0)(@babel/preset-env@7.29.2(@babel/core@7.29.0))(@types/react@18.3.28)(encoding@0.1.13)(react@18.3.1) + '@react-native/assets-registry@0.76.0': {} '@react-native/babel-plugin-codegen@0.76.0(@babel/preset-env@7.29.2(@babel/core@7.29.0))': @@ -10699,6 +10717,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + idb@8.0.3: {} + ieee754@1.2.1: {} ignore@5.3.2: {}