Преглед на файлове

link to "blog-auth" + only 1 error modal

Viktoriia преди 3 месеца
родител
ревизия
a2fe57f8c8
променени са 4 файла, в които са добавени 77 реда и са изтрити 18 реда
  1. 11 4
      src/components/ErrorModal/index.tsx
  2. 25 6
      src/contexts/ErrorContext.tsx
  3. 11 0
      src/stores/errorStore.ts
  4. 30 8
      src/utils/request.ts

+ 11 - 4
src/components/ErrorModal/index.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { View, Text, TouchableOpacity } from 'react-native';
+import { View, Text, TouchableOpacity, Linking } from 'react-native';
 import Modal from 'react-native-modal';
 import { useError } from 'src/contexts/ErrorContext';
 
@@ -16,7 +16,7 @@ import { useMessagesStore } from 'src/stores/unreadMessagesStore';
 import { useFriendsNotificationsStore } from 'src/stores/friendsNotificationsStore';
 
 export const ErrorModal = () => {
-  const { error, hideError, navigateToLogin } = useError();
+  const { error, hideError, navigateToLogin, navigateToAuth, resetErrorState } = useError();
   const navigation = useNavigation();
   const updateNotificationStatus = useFriendsNotificationsStore(
     (state) => state.updateNotificationStatus
@@ -43,8 +43,15 @@ export const ErrorModal = () => {
     hideError();
   };
 
+  const handleGoToWeb = () => {
+    Linking.openURL('https://nomadmania.com/blog-authentication/').catch((err) =>
+      console.error('Failed to open auth URL:', err)
+    );
+    hideError();
+  };
+
   return (
-    <Modal isVisible={!!error}>
+    <Modal isVisible={!!error} onModalHide={resetErrorState}>
       <View style={styles.centeredView}>
         <View style={styles.modalView}>
           <View style={{ alignSelf: 'flex-end' }}>
@@ -66,7 +73,7 @@ export const ErrorModal = () => {
                 textStyles={{
                   color: Colors.WHITE
                 }}
-                onPress={handleClose}
+                onPress={navigateToAuth ? handleGoToWeb : handleClose}
                 children="OK"
               />
             </View>

+ 25 - 6
src/contexts/ErrorContext.tsx

@@ -1,32 +1,51 @@
-import React, { createContext, useState, useContext } from 'react';
+import React, { createContext, useState, useContext, useRef } from 'react';
+import { useErrorStore } from 'src/stores/errorStore';
 
 const ErrorContext = createContext<{
   error: string | null;
   showError: (message: string, loginNeeded: boolean) => void;
   hideError: () => void;
+  resetErrorState: () => void;
   navigateToLogin: boolean;
+  navigateToAuth: boolean;
 }>({
   error: null,
   showError: (message: string, loginNeeded: boolean) => {},
   hideError: () => {},
-  navigateToLogin: false
+  resetErrorState: () => {},
+  navigateToLogin: false,
+  navigateToAuth: false
 });
 
 export const ErrorProvider = ({ children }: { children: React.ReactNode }) => {
+  const { isErrorShown, setErrorShown } = useErrorStore.getState();
   const [error, setError] = useState<string | null>(null);
   const [navigateToLogin, setNavigateToLogin] = useState<boolean>(false);
+  const [navigateToAuth, setNavigateToAuth] = useState<boolean>(false);
 
-  const showError = (message: string, loginNeeded: boolean) => {
-    setError(message);
-    setNavigateToLogin(loginNeeded);
+  const showError = (message: string, loginNeeded: boolean, authNeeded: boolean = false) => {
+    if (!isErrorShown) {
+      setErrorShown(true);
+      setError(message);
+      setNavigateToLogin(loginNeeded);
+      setNavigateToAuth(authNeeded);
+    }
   };
 
   const hideError = () => {
     setError(null);
   };
 
+  const resetErrorState = () => {
+    setTimeout(() => {
+      setErrorShown(false);
+    }, 10000);
+  };
+
   return (
-    <ErrorContext.Provider value={{ error, showError, hideError, navigateToLogin }}>
+    <ErrorContext.Provider
+      value={{ error, showError, hideError, resetErrorState, navigateToLogin, navigateToAuth }}
+    >
       {children}
     </ErrorContext.Provider>
   );

+ 11 - 0
src/stores/errorStore.ts

@@ -0,0 +1,11 @@
+import { create } from 'zustand';
+
+interface ErrorState {
+  isErrorShown: boolean;
+  setErrorShown: (shown: boolean) => void;
+}
+
+export const useErrorStore = create<ErrorState>((set) => ({
+  isErrorShown: false,
+  setErrorShown: (shown) => set({ isErrorShown: shown })
+}));

+ 30 - 8
src/utils/request.ts

@@ -2,6 +2,7 @@ import axios from 'axios';
 import { API_URL, APP_VERSION } from '../constants';
 import { Platform } from 'react-native';
 import { showBanner } from './bannerUtils';
+import { useErrorStore } from 'src/stores/errorStore';
 
 export const request = axios.create({
   baseURL: API_URL,
@@ -11,7 +12,7 @@ export const request = axios.create({
 export const setupInterceptors = ({
   showError
 }: {
-  showError: (message: string, loginNeeded: boolean) => void;
+  showError: (message: string, loginNeeded: boolean, authNeeded: boolean) => void;
 }) => {
   request.interceptors.request.use(
     (config) => {
@@ -31,22 +32,40 @@ export const setupInterceptors = ({
 
   request.interceptors.response.use(
     (response) => {
+      const { isErrorShown, setErrorShown } = useErrorStore.getState();
+
       if (response.data.result === 'ERROR' && response.data.result_description) {
-        const showErrorWithDelay = (message: string, requiresLogin: boolean) => {
-          setTimeout(() => {
-            showError(message, requiresLogin);
-          }, 1000);
+        const showErrorWithDelay = (
+          message: string,
+          requiresLogin: boolean,
+          requiresAuth: boolean
+        ) => {
+          if (!isErrorShown) {
+            setErrorShown(true);
+            setTimeout(() => {
+              showError(message, requiresLogin, requiresAuth);
+            }, 1000);
+          }
         };
 
         if (response.data?.login_needed && response.data.login_needed === 1) {
-          showErrorWithDelay(response.data.result_description, true);
+          showErrorWithDelay(response.data.result_description, true, false);
+          return response;
+        } else if (
+          // todo: response.data.auth_needed === 1
+          response.data.result_description ===
+          'Only authenticated users are allowed to send messages.'
+        ) {
+          showErrorWithDelay(response.data.result_description, false, true);
           return response;
         }
-        showErrorWithDelay(response.data.result_description, false);
+        showErrorWithDelay(response.data.result_description, false, false);
       }
       return response;
     },
     (error) => {
+      const { isErrorShown, setErrorShown } = useErrorStore.getState();
+
       if (error.code === 'ECONNABORTED') {
         error.isTimeout = true;
         showBanner('Slow internet connection!');
@@ -60,7 +79,10 @@ export const setupInterceptors = ({
         ? error.config.url?.split('/')?.filter(Boolean)?.pop()
         : 'Unknown URL';
 
-      showError(`${error.message} (${shortUrl})`, false);
+      if (!isErrorShown) {
+        setErrorShown(true);
+        showError(`${error.message} (${shortUrl})`, false, false);
+      }
 
       return Promise.reject(error);
     }