feat: Sprint 5 — PIN lock, biometric auth, sync screen, QR code, merge logic

- lib/pinService.ts: PIN storage/verification via expo-secure-store
- lib/syncService.ts: sync abstraction with full merge logic (mDNS/TCP stubbed)
- app/lock.tsx: full-screen PIN lock with biometric support
- components/ui/PinPad.tsx: reusable 6-digit PIN pad component
- components/sync/QRScanner.tsx: QR code scanner via expo-camera
- app/(tabs)/sync.tsx: Sync tab with QR display, partner input, history
- app/sync-progress.tsx: animated sync progress screen with summary
- app/(tabs)/settings.tsx: full settings with PIN setup, security, data sections
- app/(tabs)/_layout.tsx: added Sync tab (RefreshCw icon)
- app/_layout.tsx: AppState listener locks app after 60s background
- package.json: added expo-secure-store, react-native-qrcode-svg
This commit is contained in:
2026-02-18 19:57:35 +08:00
parent 123b21f4db
commit 6fe6ebef13
12 changed files with 18385 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
// app/(tabs)/_layout.tsx
import { Tabs, router } from 'expo-router';
import { useEffect } from 'react';
import { Home, Users, Map, Settings, MapPin } from 'lucide-react-native';
import { Home, Users, Map, Settings, MapPin, RefreshCw } from 'lucide-react-native';
import { useUserStore } from '@/store/useUserStore';
export default function TabLayout() {
@@ -21,11 +21,48 @@ export default function TabLayout() {
headerShown: false,
}}
>
<Tabs.Screen name="index" options={{ title: 'Home', tabBarIcon: ({ color, size }) => <Home size={size} color={color} /> }} />
<Tabs.Screen name="contacts" options={{ title: 'Contacts', tabBarIcon: ({ color, size }) => <Users size={size} color={color} /> }} />
<Tabs.Screen name="territories" options={{ title: 'Territories', tabBarIcon: ({ color, size }) => <MapPin size={size} color={color} /> }} />
<Tabs.Screen name="map" options={{ title: 'Map', tabBarIcon: ({ color, size }) => <Map size={size} color={color} /> }} />
<Tabs.Screen name="settings" options={{ title: 'Settings', tabBarIcon: ({ color, size }) => <Settings size={size} color={color} /> }} />
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => <Home size={size} color={color} />,
}}
/>
<Tabs.Screen
name="contacts"
options={{
title: 'Contacts',
tabBarIcon: ({ color, size }) => <Users size={size} color={color} />,
}}
/>
<Tabs.Screen
name="territories"
options={{
title: 'Territories',
tabBarIcon: ({ color, size }) => <MapPin size={size} color={color} />,
}}
/>
<Tabs.Screen
name="map"
options={{
title: 'Map',
tabBarIcon: ({ color, size }) => <Map size={size} color={color} />,
}}
/>
<Tabs.Screen
name="sync"
options={{
title: 'Sync',
tabBarIcon: ({ color, size }) => <RefreshCw size={size} color={color} />,
}}
/>
<Tabs.Screen
name="settings"
options={{
title: 'Settings',
tabBarIcon: ({ color, size }) => <Settings size={size} color={color} />,
}}
/>
</Tabs>
);
}