Procházet zdrojové kódy

universal search modal fix

Viktoriia před 5 měsíci
rodič
revize
002c409002

+ 2 - 1
src/components/MessagesDot/index.tsx

@@ -1,5 +1,6 @@
 import React from 'react';
 import { DimensionValue, Text, View } from 'react-native';
+import formatNumber from 'src/screens/InAppScreens/TravelsScreen/utils/formatNumber';
 import { Colors } from 'src/theme';
 
 const MessagesDot = ({
@@ -38,7 +39,7 @@ const MessagesDot = ({
       >
         {messagesCount > 0 && (
           <Text style={{ fontFamily: 'montserrat-700', fontSize: 10, color: Colors.WHITE }}>
-            {messagesCount > 99 && !fullNumber ? '99+' : messagesCount}
+            {messagesCount > 99 && !fullNumber ? '99+' : formatNumber(messagesCount)}
           </Text>
         )}
       </View>

+ 2 - 1
src/screens/InAppScreens/MapScreen/FilterModal/index.tsx

@@ -33,6 +33,7 @@ import * as Location from 'expo-location';
 import SharingIcon from 'assets/icons/location-sharing.svg';
 import UsersIcon from 'assets/icons/bottom-navigation/travellers.svg';
 import LocationIcon from 'assets/icons/location.svg';
+import formatNumber from '../../TravelsScreen/utils/formatNumber';
 
 const FilterModal = ({
   isFilterVisible,
@@ -489,7 +490,7 @@ const FilterModal = ({
               height={20}
             />
             <Text style={[styles.buttonLabel, !isSharing ? { color: Colors.LIGHT_GRAY } : {}]}>
-              Show Nomads - {usersOnMapCount} online
+              Show Nomads - {usersOnMapCount ? formatNumber(usersOnMapCount) : null} online
             </Text>
           </View>
           <View>

+ 153 - 115
src/screens/InAppScreens/MapScreen/UniversalSearch/index.tsx

@@ -1,7 +1,6 @@
-import React, { useEffect, useState } from 'react';
-import { View, Text, TouchableOpacity, Image } from 'react-native';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import { View, Text, TouchableOpacity, Image, Dimensions } from 'react-native';
 import { TabView, TabBar } from 'react-native-tab-view';
-import ReactModal from 'react-native-modal';
 import { FlashList } from '@shopify/flash-list';
 import { useNavigation } from '@react-navigation/native';
 
@@ -10,8 +9,27 @@ import { styles } from './styles';
 import { NAVIGATION_PAGES } from 'src/types';
 import { API_HOST } from 'src/constants';
 import { Loading, WarningModal } from 'src/components';
-import { StoreType, storage } from 'src/storage';
 import MessagesDot from 'src/components/MessagesDot';
+import ActionSheet, { ActionSheetRef } from 'react-native-actions-sheet';
+
+export function TabViewDelayed({
+  children,
+  waitBeforeShow = 0
+}: {
+  children: React.ReactNode;
+  waitBeforeShow?: number;
+}) {
+  const [isShown, setIsShown] = useState(false);
+
+  useEffect(() => {
+    const timer = setTimeout(() => {
+      setIsShown(true);
+    }, waitBeforeShow);
+    return () => clearTimeout(timer);
+  }, [waitBeforeShow]);
+
+  return isShown ? children : null;
+}
 
 const SearchModal = ({
   searchVisible,
@@ -31,6 +49,9 @@ const SearchModal = ({
   token: string | undefined;
 }) => {
   const navigation = useNavigation();
+  const actionSheetRef = useRef<ActionSheetRef>(null);
+  const modalHeight = Dimensions.get('window').height * 0.75;
+
   const [routes] = useState([
     { key: 'users', title: 'Nomads' },
     { key: 'regions', title: 'NM regions' },
@@ -42,6 +63,16 @@ const SearchModal = ({
   } | null>(null);
   const [warningVisible, setWarningVisible] = useState(false);
 
+  useEffect(() => {
+    if (searchVisible) {
+      actionSheetRef.current?.show();
+    } else {
+      if (actionSheetRef.current?.isOpen()) {
+        actionSheetRef.current?.hide();
+      }
+    }
+  }, [searchVisible]);
+
   useEffect(() => {
     if (!searchData) return;
 
@@ -56,85 +87,88 @@ const SearchModal = ({
     }
   }, [searchData]);
 
-  const renderItem = ({ item }: { item: any }) => {
-    const [name, ...rest] = item.name?.split(/ – | - /);
-    const subname = rest?.join(' - ');
+  const renderItem = useCallback(
+    ({ item }: { item: any }) => {
+      const [name, ...rest] = item.name?.split(/ – | - /);
+      const subname = rest?.join(' - ');
 
-    return index === 0 ? (
-      <TouchableOpacity
-        style={{ paddingVertical: 12 }}
-        onPress={() => {
-          if (!token) {
-            setWarningVisible(true);
-          } else {
-            handleCloseModal();
-            navigation.navigate(
-              ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
-            );
-          }
-        }}
-      >
-        <View style={styles.container}>
-          <Image
-            source={
-              item.avatar
-                ? { uri: API_HOST + item.avatar }
-                : require('../../../../../assets/logo-ua.png')
+      return index === 0 ? (
+        <TouchableOpacity
+          style={{ paddingVertical: 12 }}
+          onPress={() => {
+            if (!token) {
+              setWarningVisible(true);
+            } else {
+              handleCloseModal();
+              navigation.navigate(
+                ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.id }] as never)
+              );
             }
-            style={styles.img}
-          />
-          <View style={styles.textContainer}>
-            <Text style={styles.title}>{item.name}</Text>
-            <View style={{ flexDirection: 'row', alignItems: 'center' }}>
-              <Image source={{ uri: API_HOST + item.flag1 }} style={styles.flagSmall} />
-              {item.flag2 && item.flag2 !== item.flag1 && (
-                <Image
-                  source={{ uri: API_HOST + item.flag2 }}
-                  style={[
-                    styles.flagSmall,
-                    {
-                      marginLeft: -6
-                    }
-                  ]}
-                />
-              )}
-            </View>
-          </View>
-        </View>
-      </TouchableOpacity>
-    ) : (
-      <TouchableOpacity
-        style={{ paddingVertical: 12 }}
-        onPress={() => {
-          handleCloseModal();
-          if (index === 1) {
-            setShouldOpenModal({ id: item.id, type: 'regions' });
-          } else {
-            setShouldOpenModal({ id: item.id, type: 'places' });
-          }
-        }}
-      >
-        <View style={styles.container}>
-          {item.flag1 && <Image source={{ uri: API_HOST + item.flag1 }} style={styles.img} />}
-          {item.flag2 && (
+          }}
+        >
+          <View style={styles.container}>
             <Image
-              source={{ uri: API_HOST + item.flag2 }}
-              style={[
-                styles.img,
-                {
-                  marginLeft: -20
-                }
-              ]}
+              source={
+                item.avatar
+                  ? { uri: API_HOST + item.avatar }
+                  : require('../../../../../assets/logo-ua.png')
+              }
+              style={styles.img}
             />
-          )}
-          <View style={styles.textContainer}>
-            <Text style={styles.title}>{name}</Text>
-            <Text style={styles.subTitle}>{subname}</Text>
+            <View style={styles.textContainer}>
+              <Text style={styles.title}>{item.name}</Text>
+              <View style={{ flexDirection: 'row', alignItems: 'center' }}>
+                <Image source={{ uri: API_HOST + item.flag1 }} style={styles.flagSmall} />
+                {item.flag2 && item.flag2 !== item.flag1 && (
+                  <Image
+                    source={{ uri: API_HOST + item.flag2 }}
+                    style={[
+                      styles.flagSmall,
+                      {
+                        marginLeft: -6
+                      }
+                    ]}
+                  />
+                )}
+              </View>
+            </View>
           </View>
-        </View>
-      </TouchableOpacity>
-    );
-  };
+        </TouchableOpacity>
+      ) : (
+        <TouchableOpacity
+          style={{ paddingVertical: 12 }}
+          onPress={() => {
+            handleCloseModal();
+            if (index === 1) {
+              setShouldOpenModal({ id: item.id, type: 'regions' });
+            } else {
+              setShouldOpenModal({ id: item.id, type: 'places' });
+            }
+          }}
+        >
+          <View style={styles.container}>
+            {item.flag1 && <Image source={{ uri: API_HOST + item.flag1 }} style={styles.img} />}
+            {item.flag2 && (
+              <Image
+                source={{ uri: API_HOST + item.flag2 }}
+                style={[
+                  styles.img,
+                  {
+                    marginLeft: -20
+                  }
+                ]}
+              />
+            )}
+            <View style={styles.textContainer}>
+              <Text style={styles.title}>{name}</Text>
+              <Text style={styles.subTitle}>{subname}</Text>
+            </View>
+          </View>
+        </TouchableOpacity>
+      );
+    },
+    [index]
+  );
 
   const renderScene = ({ route }: { route: any }) => {
     return (
@@ -167,50 +201,54 @@ const SearchModal = ({
   };
 
   return (
-    <ReactModal
-      isVisible={searchVisible}
-      onBackdropPress={handleCloseModal}
-      onBackButtonPress={handleCloseModal}
-      style={styles.modal}
-      statusBarTranslucent={true}
-      presentationStyle="overFullScreen"
-      onModalHide={() => {
+    <ActionSheet
+      ref={actionSheetRef}
+      onClose={() => {
+        handleCloseModal();
         if (shouldOpenModal) {
           handleFindRegion(shouldOpenModal.id, shouldOpenModal.type);
           setShouldOpenModal(null);
         }
       }}
+      containerStyle={styles.modal}
+      gestureEnabled={false}
+      defaultOverlayOpacity={0.5}
     >
-      <View style={styles.modalContainer}>
-        <TabView
-          navigationState={{ index, routes }}
-          renderScene={renderScene}
-          onIndexChange={setIndex}
-          lazy={true}
-          renderTabBar={(props) => (
-            <TabBar
-              {...props}
-              indicatorStyle={{ backgroundColor: Colors.DARK_BLUE }}
-              style={styles.tabBar}
-              tabStyle={styles.tabStyle}
-              pressColor={'transparent'}
-              renderLabel={({ route, focused }) => (
-                <Text
-                  style={[styles.tabLabel, { color: Colors.DARK_BLUE, opacity: focused ? 1 : 0.4 }]}
-                >
-                  {route.title}
-                </Text>
-              )}
-              renderBadge={({ route }) =>
-                searchData?.[route.key] && searchData?.[route.key].length > 0 ? (
-                  <MessagesDot messagesCount={searchData?.[route.key].length} top={4} />
-                ) : null
-              }
-            />
-          )}
-        />
+      <View style={[styles.modalContainer, { height: modalHeight }]}>
+        <TabViewDelayed>
+          <TabView
+            navigationState={{ index, routes }}
+            renderScene={renderScene}
+            onIndexChange={setIndex}
+            lazy={true}
+            renderTabBar={(props) => (
+              <TabBar
+                {...props}
+                indicatorStyle={{ backgroundColor: Colors.DARK_BLUE }}
+                style={styles.tabBar}
+                tabStyle={styles.tabStyle}
+                pressColor={'transparent'}
+                renderLabel={({ route, focused }) => (
+                  <Text
+                    style={[
+                      styles.tabLabel,
+                      { color: Colors.DARK_BLUE, opacity: focused ? 1 : 0.4 }
+                    ]}
+                  >
+                    {route.title}
+                  </Text>
+                )}
+                renderBadge={({ route }) =>
+                  searchData?.[route.key] && searchData?.[route.key].length > 0 ? (
+                    <MessagesDot messagesCount={searchData?.[route.key].length} top={4} />
+                  ) : null
+                }
+              />
+            )}
+          />
+        </TabViewDelayed>
       </View>
-    </ReactModal>
+    </ActionSheet>
   );
 };
 

+ 4 - 3
src/screens/InAppScreens/MapScreen/UniversalSearch/styles.tsx

@@ -49,11 +49,12 @@ export const styles = StyleSheet.create({
   textContainer: { gap: 2, justifyContent: 'center', flex: 1 },
   container: { flexDirection: 'row', gap: 8, alignItems: 'center' },
   modal: {
-    justifyContent: 'flex-end',
-    margin: 0
+    borderTopLeftRadius: 15,
+    borderTopRightRadius: 15,
+    backgroundColor: Colors.WHITE
   },
   modalContainer: {
-    backgroundColor: 'white',
+    backgroundColor: Colors.WHITE,
     borderRadius: 15,
     paddingHorizontal: '4%',
     gap: 12,

+ 0 - 1
src/screens/InAppScreens/MapScreen/index.tsx

@@ -683,7 +683,6 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
 
   const handlePress = () => {
     if (isExpanded) {
-      setIndex(0);
       setSearchInput('');
     }
     setIsExpanded((prev) => !prev);

+ 5 - 5
src/screens/InAppScreens/MessagesScreen/Components/AttachmentsModal.tsx

@@ -175,6 +175,11 @@ const AttachmentsModal = () => {
             <Text style={styles.optionLabel}>Camera</Text>
           </TouchableOpacity>
 
+          <TouchableOpacity style={styles.optionItem} onPress={handleSendFile}>
+            <MaterialCommunityIcons name="file" size={36} color={Colors.ORANGE} />
+            <Text style={styles.optionLabel}>File</Text>
+          </TouchableOpacity>
+
           <TouchableOpacity
             style={styles.optionItem}
             onPress={() => {
@@ -190,11 +195,6 @@ const AttachmentsModal = () => {
             <Text style={styles.optionLabel}>Live</Text>
           </TouchableOpacity> */}
 
-          <TouchableOpacity style={styles.optionItem} onPress={handleSendFile}>
-            <MaterialCommunityIcons name="file" size={36} color={Colors.ORANGE} />
-            <Text style={styles.optionLabel}>File</Text>
-          </TouchableOpacity>
-
           <TouchableOpacity style={styles.optionItem} onPress={handleReport}>
             <MegaphoneIcon fill={Colors.RED} width={36} height={36} />
             <Text style={styles.optionLabel}>Report</Text>