Files
Kordant/packages/mobile/src/store/spamShieldStore.ts
Michael Freno 90a223bc79 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>
2026-05-17 10:51:14 -04:00

64 lines
1.7 KiB
TypeScript

import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
import type { SpamRecord } from '@/types';
/**
* TODO: Wire store operations to @shieldai/mobile-api-client for production.
* Current implementation is local-only (AsyncStorage) for offline-first MVP.
*/
type PhoneList = { number: string; label: string }[];
interface SpamShieldState {
callHistory: SpamRecord[];
textHistory: SpamRecord[];
whitelist: PhoneList;
blacklist: PhoneList;
isLoading: false;
addToWhitelist: (number: string, label: string) => void;
addToBlacklist: (number: string, label: string) => void;
removeFromWhitelist: (number: string) => void;
removeFromBlacklist: (number: string) => void;
}
export const useSpamShieldStore = create<SpamShieldState>()(
persist(
(set) => ({
callHistory: [],
textHistory: [],
whitelist: [],
blacklist: [],
isLoading: false,
addToWhitelist: (number, label) => {
set((state) => ({
whitelist: [...state.whitelist, { number, label }],
}));
},
addToBlacklist: (number, label) => {
set((state) => ({
blacklist: [...state.blacklist, { number, label }],
}));
},
removeFromWhitelist: (number) => {
set((state) => ({
whitelist: state.whitelist.filter((item) => item.number !== number),
}));
},
removeFromBlacklist: (number) => {
set((state) => ({
blacklist: state.blacklist.filter((item) => item.number !== number),
}));
},
}),
{
name: '@shieldai_spamshield',
storage: createJSONStorage(() => AsyncStorage),
}
)
);