fix: address code review findings for mobile app (FRE-4572)
P0 fixes: - Replace crypto.randomUUID() with uuid v4 (not available in RN) - Replace Platform.Version with expo-device osVersion - Fix auth navigation types, remove unused App route P1 fixes: - Push notification handler respects user preferences (useRef pattern) - Fix stale closure: use zustand subscribe + useRef for live preferences - Add retry logging for device registration failures - Replace emoji tab icons with @expo/vector-icons Ionicons - Document API integration TODOs in all local-only stores P2 fixes: - Add __DEV__ global declaration (global.d.ts) - Fix package.json main field to expo/AppEntry.js - Add retry logging for push device registration - Add z-index/elevation to LoadingOverlay - Add visual indicator to EmptyState icon P3 fixes: - Type navigation with NavigationProp<RootStackParamList> - Move getSeverityColor to theme.ts (single source of truth) - Add useMemo for SpamShield filter computations - Verified usesNonExemptEncryption: false is correct for expo-secure-store Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -1,19 +1,30 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useEffect, useCallback, useRef } from 'react';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import { Platform } from 'react-native';
|
||||
import * as Device from 'expo-device';
|
||||
import { deviceService, notificationService } from '@shieldai/mobile-api-client';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowAlert: true,
|
||||
shouldPlaySound: true,
|
||||
shouldSetBadge: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export function usePushNotifications() {
|
||||
const { preferences } = useSettingsStore();
|
||||
const preferencesRef = useRef(useSettingsStore.getState().preferences);
|
||||
|
||||
useEffect(() => {
|
||||
const subscription = useSettingsStore.subscribe((state) => {
|
||||
preferencesRef.current = state.preferences;
|
||||
});
|
||||
return subscription;
|
||||
}, []);
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => {
|
||||
const prefs = preferencesRef.current;
|
||||
return {
|
||||
shouldShowAlert: prefs.pushNotifications,
|
||||
shouldPlaySound: prefs.pushNotifications,
|
||||
shouldSetBadge: false,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const registerForPushNotifications = useCallback(async () => {
|
||||
try {
|
||||
@@ -33,13 +44,17 @@ export function usePushNotifications() {
|
||||
projectId: 'shieldai-project-id',
|
||||
})).data;
|
||||
|
||||
await deviceService.registerDevice({
|
||||
platform: Platform.OS === 'ios' ? 'ios' : 'android',
|
||||
pushToken: token,
|
||||
modelName: Platform.OS === 'ios' ? 'iPhone' : 'Android',
|
||||
osVersion: Platform.Version.toString(),
|
||||
appVersion: '1.0.0',
|
||||
});
|
||||
try {
|
||||
await deviceService.registerDevice({
|
||||
platform: Platform.OS === 'ios' ? 'ios' : 'android',
|
||||
pushToken: token,
|
||||
modelName: Platform.OS === 'ios' ? 'iPhone' : 'Android',
|
||||
osVersion: Device.osVersion || '0',
|
||||
appVersion: '1.0.0',
|
||||
});
|
||||
} catch (deviceError) {
|
||||
console.warn('Device registration failed (will retry on next launch):', deviceError);
|
||||
}
|
||||
|
||||
return token;
|
||||
} catch (error) {
|
||||
@@ -51,7 +66,7 @@ export function usePushNotifications() {
|
||||
useEffect(() => {
|
||||
const subscription = Notifications.addNotificationReceivedListener((notification) => {
|
||||
const type = notification.request.content.data?.type;
|
||||
const prefs = useSettingsStore.getState().preferences;
|
||||
const prefs = preferencesRef.current;
|
||||
|
||||
if (type === 'darkwatch_alert' && !prefs.darkwatchAlert) return;
|
||||
if (type === 'spam_blocked' && !prefs.spamBlocked) return;
|
||||
|
||||
Reference in New Issue
Block a user