Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working image full size modal #2567

Open
webatar-office-b-aliaksei opened this issue Dec 15, 2024 · 5 comments
Open

Not working image full size modal #2567

webatar-office-b-aliaksei opened this issue Dec 15, 2024 · 5 comments

Comments

@webatar-office-b-aliaksei

sup, guys
in short, such a thing happens, messages with pictures work fine, but when you click on the picture, a modal opens without the picture itself (just a black background). Although the chat message is displayed normally

import React, {
useCallback,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
} from "react";
import {
View,
Text,
StyleSheet,
TextInput,
TouchableOpacity,
FlatList,
Image,
I18nManager,
Platform,
Keyboard,
Dimensions,
} from "react-native";
import { useTranslation } from "react-i18next";
import { useAppSelector } from "../../redux/store/hooks";
import CustomBttn from "../../components/CustomButton";
import Plane from "../../assets/pictures/plane.svg";
import {
Bubble,
GiftedChat,
IMessage,
InputToolbar,
MessageImage,
} from "react-native-gifted-chat";
import {
collection,
addDoc,
orderBy,
query,
onSnapshot,
} from "firebase/firestore";
import { db, auth } from "../../../firebase";
import { add, set } from "lodash";
import FastImage from "react-native-fast-image";
import i18n from "../../services/i18n";
import PhotoPicker from "../../components/PhotoPicker";
import * as FileSystem from "expo-file-system";
import * as ImageManipulator from "expo-image-manipulator";
import { getImageType } from "../../utils/getPhotoType";

const ChatScreen = ({ navigation, route }: any) => {
const { chat } = route.params;
const user = useAppSelector((state) => state.user);
const [isPickerVisible, setIsPickerVisible] = useState(false);
const [fileUri, setFileUri] = useState('');
const fileBase64 = useRef('');
const anotherUser = chat.participants.find(
(member: { id: number }) => member.id !== user.id
);
const [messages, setMessages] = useState<IMessage[]>([]);
useLayoutEffect(() => {
const collectionRef = collection(db, "chats", chat.id, "messages");
const q = query(collectionRef, orderBy("createdAt", "desc"));
const unsubscribe = onSnapshot(q, (snapshot) => {
setMessages(
snapshot.docs.map((doc) => ({
_id: doc.id,
createdAt: doc.data().createdAt.toDate(),
image: doc.data().image,
text: doc.data().text,
user: doc.data().user,
}))
);
});

return () => unsubscribe();

}, []);

const onSend = useCallback((messages: IMessage[] = []) => {
setMessages((previousMessages) =>
GiftedChat.append(previousMessages, messages)
);
const { _id, createdAt, text, user } = messages[0];
addDoc(collection(db, "chats", chat.id, "messages"), {
_id,
createdAt,
text,
user,
// video,
image: fileBase64.current ? data:jpg;base64,${fileBase64.current} : '',
});
setFileUri('');
fileBase64.current = '';
Keyboard.dismiss();
}, []);

const selectFile = async (uri: string | null) => {
if (uri) {
try {
const manipulatedImage = await ImageManipulator.manipulateAsync(
uri,
[{ resize: { width: 200 } }],
{ compress: 0.1, format: ImageManipulator.SaveFormat.JPEG }
);
const base64String = await FileSystem.readAsStringAsync(
manipulatedImage.uri,
{
encoding: FileSystem.EncodingType.Base64,
}
);

    setFileUri(manipulatedImage.uri);
    fileBase64.current = base64String;
  } catch (error) {
    console.error("Error processing image:", error);
  }
} else {
}

};
return (

<GiftedChat
messages={messages}
onSend={(messages) => onSend(messages)}
user={{
_id: user.id,
}}
placeholder=""

    renderMessageImage={(props)=>{
      return (
        <MessageImage
          {...props}
          imageStyle={{
            width: 200,
            height: 200,
          }}
        />
      ); 
    }}
    renderInputToolbar={(props) => (
      <InputToolbar
        {...props}
        containerStyle={{
          borderTopWidth: 1,
          borderTopColor: "#ccc",
        }}
      />
    )}
    textInputProps={{
      textAlign: I18nManager.isRTL ? "right" : "left", // Текст справа
      color: "#000", // Цвет текста
      fontSize: 16, // Размер шрифта
    }}
    renderSend={(props) => (
      <TouchableOpacity
        style={styles.sendButton}
        onPress={() => {
          if ((props.text?.trim() && props.onSend)) {
            props.onSend({ text: props.text.trim() }, true);
          }
          if (props.onSend && !props.text && fileUri) {
            
            props.onSend({text: ""}, true);
          }
        }}
      >
        <Plane width={20} height={20} color="#ffffff" />
      </TouchableOpacity>
    )}
    renderBubble={(props) => (
      <Bubble
        {...props}
        wrapperStyle={{
          right: styles.userMessage,
          left: styles.botMessage,
        }}
        textStyle={{
          right: styles.userText,
          left: styles.botText,
        }}
      />
    )}
    renderTime={(props) => (
      <View
        style={{
          backgroundColor:
            props.position === "right" ? "#F8F8F8" : "#E8E8E8", // Цвет фона для времени
          borderRadius: 5,
          paddingHorizontal: 5,
          paddingVertical: 2,
          marginTop: 2,
          alignSelf: props.position === "right" ? "flex-end" : "flex-start",
        }}
      >
        <Text
          style={{
            color: "#000000", // Цвет текста времени
            fontSize: 10,
          }}
        >
          {props.currentMessage.createdAt &&
            new Date(props.currentMessage.createdAt).toLocaleTimeString(
              [],
              {
                hour: "2-digit",
                minute: "2-digit",
              }
            )}
        </Text>
      </View>
    )}
  />
  <View>
    <TouchableOpacity
      onPress={() => setIsPickerVisible(true)}
      style={styles.sendButton}
    >
      <Plane width={20} height={20} color="#ffffff" />
    </TouchableOpacity>
    <FastImage
      source={fileUri ? { uri: fileUri } : {}}
      style={fileUri ? { width: 100, height: 100 } : {}}
    />
    <PhotoPicker
      isVisible={isPickerVisible}
      onClose={() => setIsPickerVisible(false)}
      onPhotoSelected={selectFile}
    />
  </View>
</View>

);
};

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#FBFBFB",
},
sendButton: {
width: 35,
height: 35,
alignItems: "center",
justifyContent: "center",
borderRadius: 17.5,
backgroundColor: "#3498db",
marginRight: 5,
marginVertical: 4,
},
sendIcon: {
width: 20,
height: 20,
},
botMessage: {
backgroundColor: "#E8E8E8",
paddingVertical: 10,
margin: 10,
alignSelf: I18nManager.isRTL ? "flex-end" : "flex-start",
paddingHorizontal: 16,
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
borderBottomLeftRadius: I18nManager.isRTL && Platform.OS === "ios" ? 10 : 0,
borderBottomRightRadius:
I18nManager.isRTL && Platform.OS === "ios" ? 0 : 10,
marginRight: 23,
},
userMessage: {
backgroundColor: "#F8F8F8",
paddingVertical: 10,
margin: 10,
alignSelf: I18nManager.isRTL ? "flex-start" : "flex-end",
paddingHorizontal: 16,
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
borderBottomLeftRadius: I18nManager.isRTL && Platform.OS === "ios" ? 0 : 10,
borderBottomRightRadius:
I18nManager.isRTL && Platform.OS === "ios" ? 10 : 0,
marginLeft: 13,
},
botText: {
fontSize: 16,
fontWeight: "400",
color: "#262930",
fontFamily: "Varela Round",
},
userText: {
fontSize: 16,
fontWeight: "400",
color: "#000000",
fontFamily: "Varela Round",
},
});

export default ChatScreen;

Снимок экрана 2024-12-15 в 17 55 25 Снимок экрана 2024-12-15 в 17 55 46
  • Platform Android
@Ashwani201HTPL
Copy link

Ashwani201HTPL commented Dec 25, 2024

renderBubble={(props) => ( <Bubble onPress={} // here we have onpress and onlongpress {...props} wrapperStyle={{ right: styles.userMessage, left: styles.botMessage, }} textStyle={{ right: styles.userText, left: styles.botText, }} /> )}
bubble have onpress and onLongPress methods, while creating function onPress filter out only messages with image .
<Bubble onLongPress={handleLongPress} onPress={handlePress} // use in this way {...bubbleProps} currentMessage={messageWithoutImage} containerStyle={{ left: { maxWidth: 350 }, right: { maxWidth: 350, width: '100%' }, }}

you can find you  

` const handlePress = () => {
   currentMessage.image // you can find out image in this way in current message

};`

@tvuquoc17a
Copy link

same problem

@AndreevskiAleksandar
Copy link

I had the same problem, and looked into the lightbox implementation and the code of how gifted chat uses it.
After setting these props (note the width prop), the image is shown.

lightboxProps={{
  activeProps: {
    style: {
      flex: 1,
      resizeMode: 'contain',
      width,
    },
  },
}}

The width is the width of the screen from const { width } = useWindowDimensions();
This might not be the ideal solution but works for the most used image aspect ratios. Playing around with the width/height and resizeMode may give better solution.

@tvuquoc17a
Copy link

I had the same problem, and looked into the lightbox implementation and the code of how gifted chat uses it. After setting these props (note the width prop), the image is shown.

lightboxProps={{
  activeProps: {
    style: {
      flex: 1,
      resizeMode: 'contain',
      width,
    },
  },
}}

The width is the width of the screen from const { width } = useWindowDimensions(); This might not be the ideal solution but works for the most used image aspect ratios. Playing around with the width/height and resizeMode may give better solution.

Can u point me where can I find this code ?

@AndreevskiAleksandar
Copy link

I had the same problem, and looked into the lightbox implementation and the code of how gifted chat uses it. After setting these props (note the width prop), the image is shown.

lightboxProps={{
  activeProps: {
    style: {
      flex: 1,
      resizeMode: 'contain',
      width,
    },
  },
}}

The width is the width of the screen from const { width } = useWindowDimensions(); This might not be the ideal solution but works for the most used image aspect ratios. Playing around with the width/height and resizeMode may give better solution.

Can u point me where can I find this code ?

@tvuquoc17a lightboxProps is a prop in the RN Gifted Chat. In the package.json you can see it uses react-native-lightbox-v2 - https://github.com/cbbfcd/react-native-lightbox
There you can find all of the properties the lightbox support and also look into the code of what it uses as basic configuration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants