0

For some reason, only on android, the keyboard compatible view with stream chat doesn't calculate the proper height correctly until I start to type. I have tried many different configurations and can't figure out why it is only on android and why it readjusts as soon as I start to type.

Here is the code for the chat.

import "react-native-gesture-handler";
import {
  StyleSheet,
  Text,
  View,
  Pressable,
  KeyboardAvoidingView,
  Platform,
  Dimensions,
  StatusBar,
  Keyboard,
} from "react-native";
import { useHeaderHeight } from "@react-navigation/elements";

import React, { useState, useContext, useEffect } from "react";
import Header from "../components/Header";
import { StreamChat } from "stream-chat";
import {
  SafeAreaView,
  useSafeAreaInsets,
  SafeAreaProvider,
} from "react-native-safe-area-context";
import { GestureHandlerRootView } from "react-native-gesture-handler";

import { ChatContext } from "../../contexts/ChatContext";
import {
  Channel,
  Chat,
  MessageInput,
  MessageList,
  OverlayProvider,
  ChannelList,
  Thread,
} from "stream-chat-expo";
import { Ionicons } from "@expo/vector-icons";
import { getAuth } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { db } from "../../firebase";
import { UserContext } from "../../contexts/UserContext";
import ChatProfileView from "../components/ChatProfileView";

const client = StreamChat.getInstance(api-key);
const auth = getAuth();

const ChatScreen = () => {
  const { channel, setChannel } = useContext(UserContext);
  const [chatContactVisible, setChatContactVisible] = useState(false);
  const [chatContactToView, setChatContactToView] = useState({});
  const [thread, setThread] = useState(null);
  const [userName, setUserName] = useState(null);
  const [chatName, setChatName] = useState(null);
  const [chatId, setChatId] = useState(null);
  const [keyboardHeight, setKeyboardHeight] = useState(0);
  const { bottom } = useSafeAreaInsets();

  const headerHeight = useHeaderHeight();

  useEffect(() => {
    if (!client.user) {
      getStreamUserToken().then((userToken) => {
        client.connectUser(
          {
            id: auth.currentUser.uid,
          },
          userToken.data
        );
        console.log("loggeduserin- login");
      });
    }
  }, []);

  const clearChannel = () => {
    setChannel();
    setChatName();
    setChatContactToView();
  };
  const clearThread = () => {
    setThread(null);
  };

  useEffect(() => {
    console.log(channel);
  }, [channel, setChannel]);

  const theme = {
    messageList: {
      container: {
        backgroundColor: "white",
      },
    },
    channelPreview: {
      container: { backgroundColor: "white" },
    },
  };

  useEffect(() => {
    async function getUserNames() {
      const userRef = doc(db, "users", auth.currentUser.uid);
      const docSnap = await getDoc(userRef);
      if (docSnap.exists()) {
        const info = docSnap.data();
        setUserName(info.firstName);
      }
    }
    getUserNames();
  }, []);

  const getUserData = async () => {
    const userRef = doc(db, "users", chatId);
    const docSnap = await getDoc(userRef);
    if (docSnap.exists()) {
      const info = docSnap.data();
      setChatContactToView(info);
      console.log(info);
    }
  };

  useEffect(() => {
    if (channel) {
      if (userName === channel.data.memberOne) {
        setChatName(channel.data.memberTwo);
        setChatId(channel.data.memberTwoId);
        console.log("---------- id set");
        console.log(channel.data.memberTwoId);
      } else {
        setChatName(channel.data.memberOne);
        setChatId(channel.data.memberOneId);
        console.log("---------- id set now");
        console.log(channel.data.memberTwoId);
      }
    }
  }, [channel, setChannel]);

  const CustomPreviewTitle = ({ channel }) => {
    if (userName === channel.data.memberOne) {
      return <Text>{channel.data.memberTwo}</Text>;
    } else {
      return <Text>{channel.data.memberOne}</Text>;
    }
  };

  const openChatContact = () => {
    getUserData()
      .then(setChatContactVisible(true), console.log("opened"))
      .catch((err) => {
        alert("User no longer exists :(");
      });
  };

  const filters = { members: { $in: [auth.currentUser.uid] } };

  return (
    <ChatContext.Provider
      value={{
        chatContactVisible,
        setChatContactVisible,
        chatContactToView,
        setChatContactToView,
      }}
    >
      <GestureHandlerRootView style={styles.container}>
        <SafeAreaView style={{ flex: 1 }}>
          <Chat client={client} style={theme}>
            <Header screenName="Chat" />

            {channel ? (
              <Channel
                channel={channel}
                thread={thread}
                threadList={!!thread}
                keyboardBehavior={"padding"}
                keyboardVerticalOffset={0}
              >
                <View
                  style={{
                    justifyContent: "space-between",
                    flexDirection: "row",
                    alignItems: "center",
                    height: 40,
                  }}
                >
                  <View
                    style={{
                      marginLeft: 10,
                      flexDirection: "row",
                      justifyContent: "center",
                      alignItems: "center",
                    }}
                  >
                    <Pressable onPress={clearChannel}>
                      <Ionicons
                        name="arrow-back-sharp"
                        size={30}
                        color="black"
                      />
                    </Pressable>
                    <Pressable onPress={openChatContact}>
                      <Text
                        style={{
                          color: "black",

                          fontSize: 20,
                          marginLeft: 10,
                        }}
                      >
                        {chatName}
                      </Text>
                    </Pressable>
                  </View>

                  {thread ? (
                    <Pressable
                      style={{
                        marginRight: 15,
                      }}
                      onPress={clearThread}
                    >
                      <Text style={{ color: "#3b55d9" }}>Close thread</Text>
                    </Pressable>
                  ) : (
                    <></>
                  )}
                </View>
                {thread ? (
                  <Thread />
                ) : (
                  <>
                    <MessageList onThreadSelect={setThread} />
                    <MessageInput />
                  </>
                )}
              </Channel>
            ) : (
              <View style={styles.scroll}>
                <ChannelList
                  onSelect={setChannel}
                  filters={filters}
                  PreviewTitle={CustomPreviewTitle}
                  style={theme}
                />
              </View>
            )}
          </Chat>
          {chatContactVisible ? <ChatProfileView /> : <></>}
        </SafeAreaView>
      </GestureHandlerRootView>
    </ChatContext.Provider>
  );
};

export default ChatScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,

    flexDirection: "column",
    backgroundColor: "white",
  },
  scroll: {
    flex: 9,
  },
});
`

Here is the code for the header component.

`import { StyleSheet, Text, View, Pressable } from "react-native";
import React, { useState, useEffect, useContext } from "react";
import { auth } from "../../firebase";
import { useNavigation } from "@react-navigation/core";
import { Ionicons } from "@expo/vector-icons";
import { StreamChat } from "stream-chat";
import { UserContext } from "../../contexts/UserContext";

import { getDocs, query, where, collection } from "firebase/firestore";
import { getAuth } from "firebase/auth";
import { db } from "../../firebase";

import { LikesContext } from "../../contexts/LikesContext";
import ProfileView from "./Likes";

const client = StreamChat.getInstance(api-key);

const Header = (props) => {
  const [likesVisible, setLikesVisible] = useState(false);
  const { tempLikesArray, setTempLikesArray } = useContext(UserContext);

  const navigation = useNavigation();
  const handleSignOut = () => {
    auth
      .signOut()
      .then(async () => {
        navigation.replace("Login");
        await client.disconnectUser();
        console.log("User disconnected");
      })
      .catch((error) => alert(error.mesage));
  };

  const openLikes = () => {
    setLikesVisible(true);
  };

  return (
    <LikesContext.Provider
      value={{
        likesVisible,
        setLikesVisible,
      }}
    >
      <View style={styles.header}>
        <Text style={styles.logoText}>{props.screenName}</Text>
        <View style={{ flexDirection: "row" }}>
          <Pressable
            style={{ justifyContent: "center", marginRight: 15 }}
            onPress={openLikes}
          >
            <View
              style={[
                tempLikesArray.length > 0
                  ? styles.likeBubbleVisible
                  : styles.likeBubbleInvisible,
              ]}
            ></View>
            <Ionicons name="ios-person-add-outline" size={24} color="black" />
          </Pressable>
          <Pressable
            style={{ justifyContent: "center", marginRight: 15 }}
            onPress={handleSignOut}
          >
            <Ionicons name="ios-log-out-outline" size={24} color="black" />
          </Pressable>
        </View>
        {likesVisible ? <ProfileView /> : <></>}
      </View>
    </LikesContext.Provider>
  );
};

export default Header;

const styles = StyleSheet.create({
  header: {
    flex: 1,
    flexDirection: "row",
    flexWrap: "wrap",
    backgroundColor: "white",
    width: "100%",

    justifyContent: "space-between",
    marginTop: 10,
  },
  logoText: {
    alignSelf: "center",
    fontSize: 30,
    color: "#3b55d9",
    marginLeft: 20,
    fontFamily: "Inter_900Black",
  },
  logoutButton: {
    alignSelf: "center",
  },
  image: {
    width: 20,
    height: 20,
    alignSelf: "center",
    marginRight: 20,
  },
  likeBubbleVisible: {
    width: 5,
    height: 5,
    borderRadius: 10,
    backgroundColor: "blue",
    position: "absolute",
    display: "flex",
    top: 2,
    left: 0,
  },
  likeBubbleInvisible: {
    width: 5,
    height: 5,
    backgroundColor: "blue",
    position: "absolute",
    display: "none",
    top: 2,
    left: 0,
  },
});
`

0 Answers0