sfm-uikit-react-native
Version:
It is a react native component for SmartFloMeet users.
254 lines (241 loc) • 8.9 kB
JavaScript
import React, { PureComponent,createRef } from "react";
import { View,
Text,
FlatList,
TextInput,
TouchableOpacity,
Dimensions,
Keyboard,
KeyboardAvoidingView,
Platform,
TouchableWithoutFeedback,
Image} from "react-native";
import { format } from 'date-fns';
import { LinkPreview } from '@flyerhq/react-native-link-preview'
import { styles } from "../style/EnxChatScreenStyle";
import { EnxSetting } from "..";
class EnxChatScreen extends PureComponent {
constructor(props) {
super(props);
this.state={
selfClientId: this.props.selfClientId,//this.props.selfClientId,
participantClientId:this.props.participantClientId,
chatType:this.props.chatType,
newMessage: '',
keyboardOffset: 0,
screenWidth: Dimensions.get('window').width, // Current screen width
screenHeight: Dimensions.get('window').height,
shouldScrollToBottom: true, // Flag to indicate if we should scroll
}
this.flatListRef = createRef();
//this.isKeyboardVisible = false; // Track if the keyboard is visible
}
componentDidMount() {
// Add keyboard listeners to adjust the view when the keyboard is opened or closed
this.keyboardDidShowListener = Keyboard.addListener("keyboardDidShow", this._keyboardDidShow);
this.keyboardDidHideListener = Keyboard.addListener("keyboardDidHide", this._keyboardDidHide);
// Listen to orientation changes
this.dimensionsListener = Dimensions.addEventListener("change", this.handleOrientationChange);
//Add listener for notification
EnxSetting.addEventListener('ChatPageBack', this.handleBackEvent);
}
componentWillUnmount() {
// Remove listeners when the component is unmounted
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
this.dimensionsListener.remove();
EnxSetting.removeEventListener('ChatPageBack', this.handleBackEvent);
}
//Handle notification lisner from EnxSetting class
handleBackEvent = (data) => {
this.props.onBack();
};
// Handle orientation change
handleOrientationChange = ({ window: { width, height } }) => {
this.setState({
screenWidth: width,
screenHeight: height,
});
};
// Scroll to the bottom of the list when the keyboard is opened
_keyboardDidShow = (event) => {
const keyboardHeight = event.endCoordinates.height;
this.setState({ keyboardOffset: keyboardHeight }, () => {
// Only scroll if shouldScrollToBottom is true
if (this.state.shouldScrollToBottom) {
this.scrollToBottom();
}
});
};
// Reset the offset when the keyboard is closed
// _keyboardDidHide = () => {
// this.setState({ keyboardOffset: 0 }, () => {
// this.isKeyboardVisible = false; // Reset keyboard visible flag
// });
// };
_keyboardDidHide = () => {
this.setState({ keyboardOffset: 0 });
};
// Scroll the FlatList to the most recent message (bottom)
scrollToBottom = () => {
if (this.flatListRef.current) {
this.flatListRef.current.scrollToEnd({ animated: true });
}
};
shareFile = () => {
var option = {
type: this.state.chatType,
clientId: this.state.participantClientId,
}
this.props.shareFile(option)
}
//Send message
sendMessage = () => {
if(this.state.newMessage != "") {
var option = {
msg:this.state.newMessage,
type:this.state.chatType,
clientId: this.state.participantClientId,
}
this.props.sendMessageInGroup(option)
this.setState({
newMessage:''
},()=>{
this.scrollToBottom(); // Scroll to bottom if keyboard is visible
})
}
}
onScrollBeginDrag = () => {
// User has started scrolling manually, so disable auto-scroll
console.log('keybard getting drag');
this.setState({ shouldScrollToBottom: false });
};
onScrollEndDrag = () => {
console.log('keybard drag end');
// User has finished scrolling
this.setState({ shouldScrollToBottom: true });
};
render() {
const { screenWidth, screenHeight, newMessage, keyboardOffset } = this.state;
return (
<KeyboardAvoidingView
style={[styles.container, { width: screenWidth, height: screenHeight }]}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={[styles.container, { width: screenWidth }]}>
<View style={{ flex: 1 }}>
{this.props.data.length > 0 ? ( <FlatList
ref={this.flatListRef}
data={this.props.data}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
onTouchStart={this.onScrollBeginDrag}
onTouchEnd={this.onScrollEndDrag}
contentContainerStyle={{ paddingBottom: this.state.keyboardOffset }}
showsVerticalScrollIndicator={false}
/>) : (
<View style={styles.placeholder}>
<Text>No messages available.</Text>
</View>
)}
</View>
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
placeholder="Type your message..."
value={newMessage}
onChangeText={(text) => this.setState({ newMessage: text })}
onFocus={this.scrollToBottom} // Optional: Scroll when input is focused
/>
<TouchableOpacity
style={{padding:5}}
onPress={this.shareFile}>
<Image source={require("../image_asset/file_chooser.png")} style={{width: 27,height: 27,alignSelf: 'center'}} />
</TouchableOpacity>
<TouchableOpacity style={styles.sendButton} onPress={this.sendMessage}>
<Image source={require("../image_asset/send.png")} style={styles.itemImage} />
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
renderItem = ({ item,index }) => {
console.log("Item43",item);
// Function to render text with link preview
const renderTextWithLinkPreview = (text) => {
const urlRegex = /(https?:\/\/[^\s]+)/g;
const parts = text.split(urlRegex);
return parts.map((part, i) => {
if (part.match(urlRegex)) {
return (
<LinkPreview
key={i}
text={part}
renderText={(previewText) => <Text style={styles.linkText} key={i}>{previewText}</Text>}
containerStyle={styles.linkPreviewContainer}
textContainerStyle={styles.linkPreviewTextContainer}
/>
);
}
return <Text style={styles.normalText} key={i}>{part}</Text>;
});
};
const isSender = item.isReceived;
const firstLetter = item.sender.charAt(0).toUpperCase();
return (
<View
style={[
styles.messageContainer,
isSender ? styles.senderContainer : styles.receiverContainer,
]}
>
{/* First Row: First letter, Name, Date */}
<View
style={[
styles.firstRow,
isSender ? styles.senderFirstRow : styles.receiverFirstRow,
]}
>
<View
style={[
styles.firstLetterContainer,
isSender ? styles.senderFirstLetter : styles.receiverFirstLetter,
]}
>
<Text style={styles.firstLetterText}>{firstLetter}</Text>
</View>
{isSender ? <View style={styles.nameDateContainer}>
<Text style={styles.dateText}>{format(new Date(item.timestamp), 'hh:mm:ss a')}</Text>
<Text style={styles.nameText}>{item.senderName}</Text>
</View> :
<View style={styles.nameDateContainer}>
<Text style={styles.nameText}>{item.senderName}</Text>
<Text style={styles.dateText}>{format(new Date(item.timestamp), 'hh:mm:ss a')}</Text>
</View> }
</View>
{/* Second Row: Message */}
<View style={[styles.secondRow, isSender ? styles.senderSecondRow : null]}>
<View
style={[
styles.messageBubble,
isSender ? styles.senderBubble : styles.receiverBubble,
]}
>
<Text style={styles.messageText}>{renderTextWithLinkPreview(item.message)}</Text>
{item.jsondata!=null && item.jsondata!=''?
<TouchableOpacity onPress={() => { this.props.downloadFile(index)}}
>
<Text style={{color: 'blue'}}>[Download]</Text>
</TouchableOpacity>
:null
}
</View>
</View>
</View>
);
};
}
export default EnxChatScreen;