mmkv added

This commit is contained in:
Samandar Turgunboyev
2025-12-04 15:39:48 +05:00
parent 684d09e6b5
commit 87bd8cdea6
15 changed files with 1470 additions and 1450 deletions

210
App.tsx
View File

@@ -1,5 +1,4 @@
// App.tsx
import AsyncStorage from '@react-native-async-storage/async-storage';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
@@ -20,6 +19,13 @@ import Toast from 'react-native-toast-message';
import SplashScreen from './src/components/SplashScreen';
// Screens
import {
authEvents,
getLanguage,
getToken,
loadInitialAuthData,
storage,
} from 'helpers/event';
import Login from 'screens/auth/login/ui';
import Confirm from 'screens/auth/login/ui/Confirm';
import Register from 'screens/auth/registeration/ui';
@@ -47,137 +53,80 @@ import PaymentQrCode from 'screens/wallet/successPayment/ui/PaymentQrCode';
import Onboarding from 'screens/welcome/Onboarding';
LogBox.ignoreLogs([
'Non-serializable values were found in the navigation state',
'ViewPropTypes will be removed',
// NOTE: I recommend NOT ignoring "Non-serializable values were found in the navigation state"
// because it hides bugs that can cause crashes. Keep only if you understand the implications.
]);
const Stack = createNativeStackNavigator();
const screenWidth = Dimensions.get('window').width;
const queryClient = new QueryClient();
// const saveNotification = async (remoteMessage: any) => {
// try {
// const stored = await AsyncStorage.getItem('notifications');
// const notifications = stored ? JSON.parse(stored) : [];
// const newNotification = {
// id: Date.now(),
// title:
// remoteMessage.notification?.title ||
// remoteMessage.data?.title ||
// 'Yangi bildirishnoma',
// message:
// remoteMessage.notification?.body ||
// remoteMessage.data?.body ||
// 'Matn yoq',
// sentTime: remoteMessage.sentTime || Date.now(),
// };
// await AsyncStorage.setItem(
// 'notifications',
// JSON.stringify([newNotification, ...notifications]),
// );
// } catch (e) {
// console.error('Notification saqlashda xato:', e);
// }
// };
// async function onDisplayNotification(remoteMessage: any) {
// const channelId = await notifee.createChannel({
// id: 'default',
// name: 'Umumiy bildirishnomalar',
// sound: 'default',
// importance: AndroidImportance.HIGH,
// });
// await notifee.displayNotification({
// title:
// remoteMessage.notification?.title ||
// remoteMessage.data?.title ||
// 'Yangi xabar',
// body:
// remoteMessage.notification?.body ||
// remoteMessage.data?.body ||
// 'Matn yoq',
// android: {
// channelId,
// largeIcon: 'ic_launcher_foreground',
// sound: 'default',
// pressAction: {
// id: 'default',
// },
// },
// });
// }
// async function requestNotificationPermission() {
// if (Platform.OS === 'android' && Platform.Version >= 33) {
// const granted = await PermissionsAndroid.request(
// PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
// );
// console.log('POST_NOTIFICATIONS permission:', granted);
// }
// }
export default function App() {
const [initialRoute, setInitialRoute] = useState<string | null>(null);
const slideAnim = useRef(new Animated.Value(0)).current;
const [isSplashVisible, setIsSplashVisible] = useState(true);
const isMounted = useRef(false);
const currentAnimation = useRef<Animated.CompositeAnimation | null>(null);
// useEffect(() => {
// requestNotificationPermission();
useEffect(() => {
loadInitialAuthData();
}, []);
// const messagingInstance = getMessaging();
useEffect(() => {
const logoutListener = () => {
if (navigationRef.isReady()) {
navigationRef.reset({
index: 0,
routes: [{ name: 'Login' }],
});
}
};
// const unsubscribe = onMessage(messagingInstance, async remoteMessage => {
// console.log('Foreground message:', remoteMessage);
// await saveNotification(remoteMessage);
// await onDisplayNotification(remoteMessage);
// });
authEvents.on('logout', logoutListener);
// const unsubscribeOpened = onNotificationOpenedApp(
// messagingInstance,
// remoteMessage => {
// console.log('Backgrounddan ochildi:', remoteMessage);
// saveNotification(remoteMessage);
// },
// );
return () => {
authEvents.removeListener('logout', logoutListener);
};
}, []);
// (async () => {
// const remoteMessage = await getInitialNotification(messagingInstance);
// if (remoteMessage) {
// console.log('Killeddan ochildi:', remoteMessage);
// saveNotification(remoteMessage);
// }
// })();
// return () => {
// unsubscribe();
// unsubscribeOpened();
// };
// }, []);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
if (currentAnimation.current) {
currentAnimation.current.stop();
}
};
}, []);
useEffect(() => {
const initializeApp = async () => {
try {
const [seen, token, lang] = await Promise.all([
AsyncStorage.getItem('hasSeenOnboarding'),
AsyncStorage.getItem('token'),
const seen = storage.getString('hasSeenOnboarding');
const token = getToken();
const lang = getLanguage();
AsyncStorage.getItem('language'),
]);
if (lang) await i18n.changeLanguage(lang);
if (lang) {
try {
await i18n.changeLanguage(lang);
} catch (e) {
console.warn('i18n.changeLanguage failed:', e);
}
}
const initialRouteName = !seen
? 'Onboarding'
: token
? 'Home'
: 'select-auth';
setInitialRoute(initialRouteName);
if (isMounted.current) {
setInitialRoute(initialRouteName);
}
} catch (error) {
console.error('App initialization error:', error);
setInitialRoute('select-auth');
if (isMounted.current) setInitialRoute('select-auth');
}
};
@@ -186,52 +135,39 @@ export default function App() {
const handleSplashFinish = useMemo(
() => () => {
Animated.timing(slideAnim, {
// create animation and keep ref so we can stop it on unmount
const animation = Animated.timing(slideAnim, {
toValue: -screenWidth,
duration: 600,
useNativeDriver: true,
}).start(() => setIsSplashVisible(false));
});
currentAnimation.current = animation;
animation.start(() => {
// ensure component still mounted before setting state
if (isMounted.current) {
setIsSplashVisible(false);
}
currentAnimation.current = null;
});
},
[slideAnim],
);
const handleOnboardingFinish = useMemo(
() => async (navigation: any) => {
await AsyncStorage.setItem('hasSeenOnboarding', 'true');
try {
storage.set('hasSeenOnboarding', 'true');
} catch (e) {
console.warn('Failed to set hasSeenOnboarding', e);
}
navigation.replace('select-auth');
},
[],
);
// const [firebaseToken, setFirebseToken] = useState<{
// fcmToken: string;
// deviceId: string;
// deviceName: string;
// } | null>();
// const app = getApp();
// const messaging = getMessaging(app);
// const getDeviceData = async () => {
// try {
// const fcmToken = await getToken(messaging);
// return {
// fcmToken,
// deviceId: await DeviceInfo.getUniqueId(),
// deviceName: await DeviceInfo.getDeviceName(),
// };
// } catch (e) {
// console.log('Xato:', e);
// return null;
// }
// };
// console.log(firebaseToken);
// useEffect(() => {
// getDeviceData().then(data => {
// setFirebseToken(data);
// });
// }, []);
if (!initialRoute) return null;
if (initialRoute === null) {
return <View style={{ flex: 1, backgroundColor: '#000' }} />;
}
return (
<QueryClientProvider client={queryClient}>
@@ -245,6 +181,7 @@ export default function App() {
animation: 'none',
gestureEnabled: false,
}}
// initialRouteName set once (we ensure it's available before first render)
initialRouteName={initialRoute}
>
<Stack.Screen name="Onboarding">
@@ -273,9 +210,6 @@ export default function App() {
<Stack.Screen name="PaymentQrCode" component={PaymentQrCode} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
{/* {Platform.OS === 'android' && (
<Stack.Screen name="Notifications" component={Notifications} />
)} */}
<Stack.Screen name="Warehouses" component={Warehouses} />
<Stack.Screen name="Support" component={Support} />
<Stack.Screen name="ListBranches" component={ListBranches} />