feat: scaffold ShieldAI React Native mobile app MVP (FRE-4572)

Build complete Expo/React Native mobile app with:
- Auth flow: email/password login, registration, biometric auth
- Dashboard: exposure summary, spam stats, voice protection status
- DarkWatch: watch list management, exposure feed, alert toggles
- SpamShield: call/text history, whitelist/blacklist management
- VoicePrint: family member enrollment, voice analysis
- Settings: tier management, notification preferences, security
- Push notification integration via FCM/APNs
- Offline-first state management with Zustand + AsyncStorage
- Integration with @shieldai/mobile-api-client for API services
- React Navigation with auth-aware routing (stack + bottom tabs)
- Dark theme with consistent design system (colors, spacing, typography)
- Network status monitoring and offline request queuing

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-05-17 10:12:46 -04:00
parent 7fb8b83810
commit a071aa736e
50 changed files with 3026 additions and 13 deletions

View File

@@ -0,0 +1,40 @@
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
import type { NotificationPreference } from '@/types';
interface SettingsState {
preferences: NotificationPreference;
isBiometricEnabled: boolean;
updatePreferences: (prefs: Partial<NotificationPreference>) => void;
toggleBiometric: (enabled: boolean) => void;
}
const defaultPreferences: NotificationPreference = {
emailNotifications: true,
pushNotifications: true,
darkwatchAlert: true,
spamBlocked: true,
voiceprintAnalysis: true,
};
export const useSettingsStore = create<SettingsState>()(
persist(
(set) => ({
preferences: defaultPreferences,
isBiometricEnabled: false,
updatePreferences: (prefs) => {
set((state) => ({
preferences: { ...state.preferences, ...prefs },
}));
},
toggleBiometric: (enabled) => set({ isBiometricEnabled: enabled }),
}),
{
name: '@shieldai_settings',
storage: createJSONStorage(() => AsyncStorage),
}
)
);