Commit 0c356099 authored by avinash wijenayake's avatar avinash wijenayake

inital commit

parents
Pipeline #4195 failed with stages
{
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
node_modules/
.expo/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
{
}
\ No newline at end of file
import 'react-native-gesture-handler';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import LoginScreen from './screen/LoginScreen';
import RegisterScreen from './screen/RegisterScreen';
import HomeScreen from './screen/HomeScreen';
import AddChatScreen from './screen/AddChatScreen';
import ChatScreen from './screen/ChatScreen';
import Camera from'./components/video';
import { ToastProvider } from 'react-toast-notifications'
const Stack = createStackNavigator();
const globalScreenOptions = {
headerStyle: {backgroundColor: "#FF6464"},
headerTitleStyle: {color: "white" ,fontWeight: 'bold'},
headerTintColor: "white",
headerTitleAlign: "center",
};
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Camera"
screenOptions={globalScreenOptions}
>
<Stack.Screen name='Login' component={LoginScreen}/>
<Stack.Screen name='Register' component={RegisterScreen}/>
<Stack.Screen name='Home' component={HomeScreen}/>
<Stack.Screen name='AddChat' component={AddChatScreen}/>
<Stack.Screen name='Chat' component={ChatScreen}/>
<Stack.Screen name='Camera' component={Camera}/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
{
"expo": {
"name": "EasyChat",
"slug": "EasyChat",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
}
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
import React from "react";
import { useEffect } from "react";
import { useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import { ListItem, Avatar } from "react-native-elements";
import { db } from "../firebase";
const CustomListItem = ({ id, chatName, enterChat }) => {
const [chatMessages, setChatMessages] = useState([]);
useEffect(() => {
const unsubscribe = db
.collection('chats')
.doc(id)
.collection('messages')
.orderBy('timestamp', 'desc')
.onSnapshot((snapshot) =>
setChatMessages(snapshot.docs.map((doc) => doc.data()))
);
return unsubscribe;
});
return (
<ListItem
key={id}
onPress={() => enterChat(id, chatName)}
key={id}
bottomDivider
>
<Avatar
rounded
source={{
uri:
chatMessages?.[0]?.photoURL ||
"https://www.pinclipart.com/picdir/big/78-780477_about-us-avatar-icon-red-png-clipart.png",
}}
/>
<ListItem.Content>
<ListItem.Title styles={{ fontWeight: "800" }}>
{chatName}
</ListItem.Title>
<ListItem.Subtitle numberOfLines={1} ellipsizeMode="tail">
{chatMessages?.[0]?.displayName} : {chatMessages?.[0]?.message}
</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
);
};
export default CustomListItem;
const styles = StyleSheet.create({});
import React, { useState, useRef, useEffect } from "react";
import {
StyleSheet,
Dimensions,
View,
Text,
TouchableOpacity,
SafeAreaView,
Image
} from "react-native";
import axios from 'axios';
import { Camera } from "expo-camera";
import { Video } from "expo-av";
import { clockRunning } from "react-native-reanimated";
const WINDOW_HEIGHT = Dimensions.get("window").height;
const closeButtonSize = Math.floor(WINDOW_HEIGHT * 0.032);
const captureSize = Math.floor(WINDOW_HEIGHT * 0.09);
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [cameraType, setCameraType] = useState(Camera.Constants.Type.back);
const [isPreview, setIsPreview] = useState(false);
const [isCameraReady, setIsCameraReady] = useState(false);
const [isVideoRecording, setIsVideoRecording] = useState(false);
const [videoSource, setVideoSource] = useState(null);
const cameraRef = useRef();
const baseUrl = 'https://easychat160.herokuapp.com/';
const onCameraReady = () => {
setIsCameraReady(true);
};
useEffect(() => {
(async () => {
const { status } = await Camera.requestMicrophonePermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
useEffect(() => {
(async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
const takePicture = async () => {
if (cameraRef.current) {
const options = { quality: 0.5, base64: true, skipProcessing: true };
const data = await cameraRef.current.takePictureAsync(options);
const source = data.uri;
if (source) {
await cameraRef.current.pausePreview();
setIsPreview(true);
console.log("picture source", source);
}
}
};
const fetchVideo = async (video) => {
console.log(`video`, video)
const configurationObject = {
method: 'post',
url: `${baseUrl}/video2text`,
body:video
};
const response = await axios(configurationObject).then(function(response){
console.log(response.data.prediction);
}).catch((error)=> console.log(error))
console.log(response);
};
const uploadVideo = async (Videouri,Videotype) =>{
const video = new FormData();
video.append("video", {
name: "mobile-video-upload",
type:'video/quicktime',
uri:Videouri
});
fetchVideo(video)
// try {
// const data = fetch('http://127.0.0.1:5000/video2text', {
// method: "post",
// body: video
// });
// } catch (e) {
// console.error(e);
// }
}
const recordVideo = async () => {
if (cameraRef.current) {
try {
const videoRecordPromise = cameraRef.current.recordAsync();
if (videoRecordPromise) {
setIsVideoRecording(true);
const data = await videoRecordPromise;
const source = data.uri;
if (source) {
setIsPreview(true);
console.log("video source", source);
setVideoSource(source);
// uploadVideo(source,data.type);
let formData = new FormData();
formData.append('video', {
uri:source,
name: "mobild.mov",
type:'video/quicktime',
});
console.log(`formData`, formData)
fetch('http://192.168.1.5:5000', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData,
})
.then(response => response.json())
.then(response => {
console.log(`sss`,); console.log('response 🔥', response);
navigation.navigate('Result', {resData});
})
.catch(err => console.error('error',err));
}
}
} catch (error) {
console.warn(error);
}
}
};
const stopVideoRecording = () => {
if (cameraRef.current) {
setIsPreview(false);
setIsVideoRecording(false);
cameraRef.current.stopRecording();
}
};
const switchCamera = () => {
if (isPreview) {
return;
}
setCameraType((prevCameraType) =>
prevCameraType === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
};
const cancelPreview = async () => {
await cameraRef.current.resumePreview();
setIsPreview(false);
setVideoSource(null);
};
const renderCancelPreviewButton = () => (
<TouchableOpacity onPress={cancelPreview} style={styles.closeButton}>
<View style={[styles.closeCross, { transform: [{ rotate: "45deg" }] }]} />
<View
style={[styles.closeCross, { transform: [{ rotate: "-45deg" }] }]}
/>
</TouchableOpacity>
);
const renderVideoPlayer = () => (
<Video
source={{ uri: videoSource }}
shouldPlay={true}
style={styles.media}
/>
);
const renderVideoRecordIndicator = () => (
<View style={styles.recordIndicatorContainer}>
<View style={styles.recordDot} />
<Text style={styles.recordTitle}>{"Recording..."}</Text>
</View>
);
const renderCaptureControl = () => (
<View style={styles.control}>
<TouchableOpacity disabled={!isCameraReady} onPress={switchCamera}>
<Text style={styles.text}>{"Flip"}</Text>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.7}
disabled={!isCameraReady}
onLongPress={recordVideo}
onPressOut={stopVideoRecording}
// onPress={takePicture}
style={styles.capture}
/>
</View>
);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text style={styles.text}>No access to camera</Text>;
}
return (
<SafeAreaView style={styles.container}>
<Camera
ref={cameraRef}
style={styles.container}
type={cameraType}
flashMode={Camera.Constants.FlashMode.on}
onCameraReady={onCameraReady}
onMountError={(error) => {
console.log("cammera error", error);
}}
/>
<View style={styles.container}>
{isVideoRecording && renderVideoRecordIndicator()}
{videoSource && renderVideoPlayer()}
{isPreview && renderCancelPreviewButton()}
{!videoSource && !isPreview && renderCaptureControl()}
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
},
closeButton: {
position: "absolute",
top: 35,
left: 15,
height: closeButtonSize,
width: closeButtonSize,
borderRadius: Math.floor(closeButtonSize / 2),
justifyContent: "center",
alignItems: "center",
backgroundColor: "#c4c5c4",
opacity: 0.7,
zIndex: 2,
},
media: {
...StyleSheet.absoluteFillObject,
},
closeCross: {
width: "68%",
height: 1,
backgroundColor: "black",
},
control: {
position: "absolute",
flexDirection: "row",
bottom: 38,
width: "100%",
alignItems: "center",
justifyContent: "center",
},
capture: {
backgroundColor: "#f5f6f5",
borderRadius: 5,
height: captureSize,
width: captureSize,
borderRadius: Math.floor(captureSize / 2),
marginHorizontal: 31,
},
recordIndicatorContainer: {
flexDirection: "row",
position: "absolute",
top: 25,
alignSelf: "center",
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent",
opacity: 0.7,
},
recordTitle: {
fontSize: 14,
color: "#ffffff",
textAlign: "center",
},
recordDot: {
borderRadius: 3,
height: 6,
width: 6,
backgroundColor: "#ff0000",
marginHorizontal: 5,
},
text: {
color: "#fff",
},
});
\ No newline at end of file
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
const firebaseConfig = {
apiKey: "AIzaSyAtVxQ5DE4lVl38dPhc-FkKpVgWTGoyorc",
authDomain: "easy-chat-8f2c0.firebaseapp.com",
databaseURL: "https://easy-chat-8f2c0-default-rtdb.firebaseio.com",
projectId: "easy-chat-8f2c0",
storageBucket: "easy-chat-8f2c0.appspot.com",
messagingSenderId: "356652137595",
appId: "1:356652137595:web:d7529b3b9da7dc332476de",
measurementId: "G-MXRLF0PFCL"
};
let app;
if (firebase.apps.length === 0) {
app = firebase.initializeApp(firebaseConfig);
} else {
app = firebase.app();
}
const db = app.firestore();
const auth = firebase.auth();
export { db, auth }
\ No newline at end of file
This diff is collapsed.
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@firebase/auth": "^0.19.3",
"@firebase/database": "^0.12.4",
"@react-native-community/masked-view": "0.1.10",
"@react-navigation/native": "^5.9.4",
"@react-navigation/stack": "^5.14.5",
"axios": "^0.24.0",
"expo": "~42.0.1",
"expo-av": "^10.1.3",
"expo-camera": "^12.0.3",
"expo-status-bar": "~1.0.4",
"firebase": "8.2.3",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
"react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~1.10.2",
"react-native-reanimated": "~2.2.0",
"react-native-safe-area-context": "3.2.0",
"react-native-screens": "~3.4.0",
"react-native-web": "~0.13.12",
"react-toast-notifications": "^2.5.1"
},
"devDependencies": {
"@babel/core": "^7.9.0"
},
"private": true
}
import { HeaderTitle } from '@react-navigation/stack'
import React from 'react'
import { useState } from 'react'
import { useLayoutEffect } from 'react'
import { StyleSheet, Text, View,ScrollView } from 'react-native'
import { Button, Input ,Avatar} from 'react-native-elements'
// import Icon from 'react-native-vector-icons/FontAwesome'
import IonIcon from 'react-native-vector-icons/Ionicons';
import { db } from '../firebase'
import Firebase from 'firebase';
import CustomListItem from '../components/CustomListItem'
const AddChatScreen = ({ navigation }) => {
const [input, setInput] = useState("");
const [chat, setChat] = useState([]);
const [chatUsers, setChatUsers] = useState([]);
/**
* if user name existing in database get data from the user
* @param {*}
*/
const onchange= (text) => {
setInput(text)
console.log(chat)
if(input != ""){
showChat();
for(var i = 0 ;i <chat.length ; i++){
if(input == chat[i].data.name){
setChatUsers(
chat.map((doc) => ({
'id': doc.id,
'data': doc.data,
}))
)
}
}
}else{
setChatUsers([])
}
console.log(chatUsers)
}
/**
* Navigation
*/
useLayoutEffect(() => {
navigation.setOptions({
title: "Add a new Chat",
headerBackTitle: "Chats",
});
}, [navigation])
/**
* create a new chat and save in the firestore
*/
const createChat = async () => {
await db.collection('chats').add({
chatName: input,
userId: Firebase.auth().currentUser.uid,
}).then(() => {
navigation.goBack();
})
.catch((error) => alert(error));
}
/**
* get all firebase user detail list
*/
const showChat =() => {
var curUser = Firebase.auth().currentUser;
var userRef = Firebase.database().ref('user/');
userRef.on('value', (snapshot) => {
var chatArr=[];
const data = snapshot.val();
for(var i in data){
chatArr.push([i, data [i]]);}
setChat(
chatArr.map((doc) => ({
'id': doc[0],
'data': doc[1],
}))
)
});
};
return (
<View style={styles.container}>
<Input
placeholder="Enter a chat name"
value={input}
onChangeText={(text) => onchange(text)}
onSubmitEditing={showChat}
leftIcon={
<IonIcon name="md-chatbubbles-outline" size={24} color="black" />
}
/>
<ScrollView contentContainerStyle={{ paddingTop: 15 ,marginTop:10}}>
{chatUsers.map((data ) => {
console.log(data.data.name);
<View >{data.data.name}</View>
})}
</ScrollView>
<Button
containerStyle={styles.button}
disabled={!input}
onPress={createChat}
title='Create new Chat'
type="clear"
titleStyle={{ color: "#fff" }} />
</View>
)
}
export default AddChatScreen
const styles = StyleSheet.create({
container: {
backgroundColor: "white",
padding: 30,
height: "100%",
},
button: {
backgroundColor: "#43E68D",
borderRadius: 5,
},
})
import React, { useLayoutEffect } from "react";
import {
KeyboardAvoidingView,
TouchableOpacity,
Keyboard,
ScrollView,
Platform,
StatusBar,
SafeAreaView,
TouchableWithoutFeedback,
StyleSheet,
Text,
TextInput,
View,
} from "react-native";
import { Avatar } from "react-native-elements/dist/avatar/Avatar";
import { AntDesign, FontAwesome, Ionicons } from "@expo/vector-icons";
import { useState ,useEffect} from "react";
import * as firebase from "firebase";
import { db, auth } from "../firebase";
import Firebase from 'firebase';
const ChatScreen = ({ navigation, route }) => {
const [input, setInput] = useState("");
const [messages, setMessages] = useState([]);
useLayoutEffect(() => {
navigation.setOptions({
title: "Chat",
headerBackTitleVisible: false,
headerTitleAlign: "left",
headerTitle: () => (
<View
style={{
flexDirection: "row",
alignItems: "center",
}}
>
<Avatar
rounded
// source={{
// uri: messages[0]?.data.photoURL,
// }}
/>
<Text
style={{
fontSize: 20,
color: "white",
marginLeft: 10,
fontWeight: "700",
}}
>
{route.params.chatName}
</Text>
</View>
),
headerLeft: () => (
<TouchableOpacity
style={{ marginLeft: 10 }}
onPress={navigation.goBack}
>
<AntDesign name="arrowleft" size={24} color="white" />
</TouchableOpacity>
),
headerRight: () => (
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
width: 80,
marginRight: 20,
}}
>
<TouchableOpacity>
<FontAwesome name="video-camera" size={23} color="white" />
</TouchableOpacity>
<TouchableOpacity>
<Ionicons name="call" size={23} color="white" />
</TouchableOpacity>
</View>
),
});
}, [navigation, messages]);
/**
* save the send messages in the database
*/
const sendMessage = () => {
Keyboard.dismiss();
var curUser = Firebase.auth().currentUser;
const chat = {
'message': input,
'displayName': curUser.displayName,
'email': curUser.email,
'photoURL': curUser.photoURL,
'uid':curUser.uid,
};
let path = 'user/' + curUser.uid +'/chat';
Firebase.database().ref('/').child(path).push().set(chat);
console.log('DATA SAVED' + curUser.uid);
setInput("");
}
/**
* get messages from the database
*/
useLayoutEffect(() => {
var curUser = Firebase.auth().currentUser;
var starCountRef = Firebase.database().ref('user/' + curUser.uid +'/chat');
starCountRef.on('value', (snapshot) => {
var chatArr=[];
const data = snapshot.val();
for(var i in data){
chatArr.push([i, data [i]]);}
setMessages(
chatArr.map((doc) => ({
'id': doc[0],
'data': doc[1],
}))
)
console.log(data);
console.log(chatArr);
});
}, [route]);
return (
<SafeAreaView style={{ flex: 1, backgroundColor: "white" }}>
<StatusBar style="light" />
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.container}
keyboardVerticalOffset={90}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<>
<ScrollView contentContainerStyle={{ paddingTop: 15 }}>
{messages.map(({ id, data }) =>
data.email === auth.currentUser.email ? (
<View key={id} style={styles.reciever}>
<Avatar
position="absolute"
rounded
//Web
containerStyle={{
position: "absolute",
bottom: -15,
right: -5,
}}
bottom={-15}
right={-5}
size={30}
source={{
uri: data.photoURL,
}}
/>
<Text style={styles.recieverText}>{data.message}</Text>
</View>
) : (
<View key={id} style={styles.sender}>
<Avatar
position="absolute"
rounded
//Web
containerStyle={{
position: "absolute",
bottom: -15,
left: -5,
}}
bottom={-15}
left={-5}
size={30}
source={{
uri: data.photoURL,
}}
/>
<Text style={styles.senderText}>{data.message}</Text>
<Text style={styles.senderName}>{data.displayName}</Text>
</View>
)
)}
</ScrollView>
<View style={styles.footer}>
<View style={styles.buttonrow}>
<TouchableOpacity style={styles.icon} activeOpacity={0.5} onPress={() => navigation.navigate("Camera")}>
<Ionicons name="recording" size={23} color="#be0c57" />
</TouchableOpacity>
<TouchableOpacity style={styles.icon} activeOpacity={0.5}>
<Ionicons name="hand-right" size={23} color="#be0c57" />
</TouchableOpacity>
<TouchableOpacity style={styles.icon} activeOpacity={0.5}>
<Ionicons name="mic" size={23} color="#be0c57" />
</TouchableOpacity>
<TouchableOpacity style={styles.icon} activeOpacity={0.5}>
<Ionicons name="thumbs-up" size={23} color="#be0c57" />
</TouchableOpacity>
</View>
<View style={styles.chatRow}>
<TextInput
style={styles.textInput}
value={input}
onChangeText={(text) => setInput(text)}
onSubmitEditing={sendMessage}
placeholder="EasyChat Message"
/>
<TouchableOpacity onPress={sendMessage} activeOpacity={0.5}>
<Ionicons name="send" size={23} color="#43E68D" />
</TouchableOpacity>
</View>
</View>
</>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
);
};
export default ChatScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
},
chatRow:{
display:'flex',
flexDirection:'row',
width:'100%',
alignItems:'center'
},
icon:{
margin:3,
marginLeft:20,
padding:1,
},
buttonrow:{
display:'flex',
flexDirection:'row',
width:'100%',
marginBottom:5,
},
reciever: {
padding: 15,
backgroundColor: "#ECECEC",
alignSelf: "flex-end",
borderRadius: 20,
marginRight: 15,
marginBottom: 20,
maxWidth: "80%",
position: "relative",
},
recieverText: {
color: "black",
fontWeight: "500",
marginLeft: 10,
},
sender: {
padding: 15,
backgroundColor: "#2B68E6",
alignSelf: "flex-start",
borderRadius: 20,
margin: 15,
maxWidth: "80%",
position: "relative",
},
senderText: {
color: "white",
fontWeight: "500",
marginLeft: 10,
marginBottom: 15,
},
senderName: {
left: 10,
paddingRight: 10,
fontSize: 10,
color: "white",
},
footer: {
flexDirection: "column",
alignItems: "center",
width: "100%",
padding: 15,
},
textInput: {
bottom: 0,
height: 40,
flex: 1,
marginRight: 15,
borderColor: "transparent",
backgroundColor: "#ECECEC",
padding: 10,
color: "gray",
borderRadius: 30,
},
});
import React from 'react'
import { TouchableOpacity, SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native'
import { useEffect, useState, useLayoutEffect } from 'react'
import CustomListItem from '../components/CustomListItem'
import { Avatar } from 'react-native-elements/dist/avatar/Avatar'
import { AntDesign, SimpleLineIcons } from '@expo/vector-icons'
import { auth, db } from '../firebase'
const HomeScreen = ({ navigation }) => {
const [chats, setChats] = useState([]);
const signOutUser = () => {
auth.signOut().then(() => {
navigation.replace("Login");
})
}
/**
* user name list
*/
useEffect(() => {
const unsubscribe = db.collection('chats').onSnapshot(snapshot => (
setChats(snapshot.docs.map(doc => ({
id: doc.id,
data: doc.data(),
})))
))
return unsubscribe;
},[])
useLayoutEffect(() => {
navigation.setOptions({
title: "EasyChat",
headerStyle: { backgroundColor: "#fff" },
headerTitleStyle: { color: "black" },
headerTintColor: "black",
// headerTitleAlign: "left",
headerLeft: () => (
<View style={{ marginLeft: 20 }}>
<TouchableOpacity onPress={signOutUser} activeOpacity={0.5}>
<Avatar rounded source={{ uri: auth?.currentUser?.photoURL }} />
</TouchableOpacity>
</View>
),
headerRight: () => (
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
width: 80,
marginRight: 20,
}}>
<TouchableOpacity activeOpacity={0.5}>
<AntDesign name="camerao" size={24} color="black" />
</TouchableOpacity>
<TouchableOpacity
onPress={() => navigation.navigate("AddChat")}
activeOpacity={0.5}>
<SimpleLineIcons name="pencil" size={24} color="black" />
</TouchableOpacity>
</View>
)
})
}, [navigation])
const enterChat = (id, chatName) => {
navigation.navigate("Chat",{
id,
chatName,
})
}
return (
<SafeAreaView>
<ScrollView style={styles.container}>
{chats.map(({ id, data: { chatName } }) => (
<CustomListItem
key={ id }
id={ id }
chatName={ chatName }
enterChat={enterChat}
/>
))}
</ScrollView>
</SafeAreaView>
)
}
export default HomeScreen
const styles = StyleSheet.create({
container: {
height: "100%",
// backgroundColor: "white"
}
})
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { useEffect, useState } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, View,TextInput ,TouchableOpacity, SafeAreaView, ScrollView,} from 'react-native'
import { Button, Input, Image } from 'react-native-elements'
import { auth } from '../firebase'
import loginImage from'./images/login-image.png'
const LoginScreen = ({ navigation }) => {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((authUser) => {
console.log(authUser);
if (authUser) {
navigation.replace('Home');
}
})
return unsubscribe;
}, [])
const signIn = () => {
auth.signInWithEmailAndPassword(email, password)
.catch((error) => console.log(error.message));
};
return (
<KeyboardAvoidingView behavior="padding" style={styles.container}>
<StatusBar style='light' />
<SafeAreaView>
<ScrollView >
<Text style={styles.LoginTitle}>Easy Chat</Text>
<Image source={ loginImage}
style={{ width: 200, height: 200 }} />
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
placeholder='Email'
autoFocus
type='email'
value={email}
onChangeText={(text) => setEmail(text)} />
<TextInput
style={styles.input}
placeholder='Password'
type='password'
value={password}
onChangeText={(text) => setPassword(text)}
onSubmitEditing={signIn}
returnKeyType='go'
secureTextEntry
autoCorrect={false}/>
</View>
<Button
containerStyle={styles.button}
type="clear"
onPress={signIn}
title="Login"
titleStyle={{ color: "#fff" }}
/>
<TouchableOpacity style={styles.marginTop} onPress={() => navigation.navigate("Register")}>
<Text style={styles.signUpLink}>Need a Account ? Sign Up</Text>
</TouchableOpacity>
<View style={{ height: 50 }} />
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>)
}
export default LoginScreen
const styles = StyleSheet.create({
input:{
padding:10,
height: 40,
margin: 12,
borderBottomColor: '#000000',
borderBottomWidth: 1,
padding: 10,
},
container: {
flex: 1,
alignItems: "center",
padding: 10,
backgroundColor: "white",
},
inputContainer: {
width: 300,
},
button: {
marginTop:15,
width: 300,
marginTop: 10,
backgroundColor: "#E76565",
borderRadius: 5,
},
LoginTitle:{
height: 66,
alignItems: "center",
fontSize:46,
fontWeight:'400',
left:55,
color: '#227721',
bottom:10,
},
signUpLink:{
marginTop:15,
fontSize:18,
lineHeight:22,
width:250,
color:'#333FA7',
left:20,
top:30
},
marginTop:{
marginTop:15,
}
})
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { useLayoutEffect, useState } from 'react'
import { KeyboardAvoidingView, StyleSheet, View ,TouchableOpacity, SafeAreaView, ScrollView,} from 'react-native'
import { Button, Input, Text,Image } from 'react-native-elements'
import { auth,app } from '../firebase'
import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";
import Firebase from 'firebase';
import { ToastProvider, useToasts } from 'react-toast-notifications';
import loginImage from'./images/login-image.png'
const RegisterScreen = ({ navigation }) => {
const [error,setError] =useState("")
const [errorType,setErrorType] =useState("")
const [showError,setShowError] =useState(false)
const [name, setName] = useState("")
const [email, setEmail] = useState("")
const [number, setNumber] = useState("")
const [password, setPassword] = useState("")
const [imageUrl, setImageUrl] = useState("")
const [userName,seUserName] = useState("");
useLayoutEffect(() => {
navigation.setOptions({
headerBackTitle: "Login",
})
}, [navigation])
const register = () => {
if( email =="" && password =="" && name =="" ) {
addToast("fill the information",{ appearance: "info",autoDismiss: true,placement :"top-right"})
}else{
auth
.createUserWithEmailAndPassword(email, password)
.then(authUser => {
authUser.user.updateProfile({
displayName: name,
photoURL: imageUrl ||
"https://www.pinclipart.com/picdir/big/78-780477_about-us-avatar-icon-red-png-clipart.png",
})
writeUserData();
})
.catch(error => {
console.log(error.message)
})
}
}
/**
* send user regiter data to the firebase database
*/
const writeUserData = () => {
var curUser = Firebase.auth().currentUser;
const newUser = {
"userName":userName,
"profilePic":imageUrl,
"name":name,
"phoneNumber":number,
"email": email,
"password" :password,
"uid":curUser.uid,
};
let path = 'user/' + curUser.uid;
Firebase.database().ref('/').child(path).set(newUser);
console.log('DATA SAVED' + curUser.uid);
console.log("newUser : " + newUser);
}
return (
<KeyboardAvoidingView behavior='padding' style={styles.container}>
<StatusBar style="light" />
<SafeAreaView>
<ScrollView >
<Text style={styles.LoginTitle}>Easy Chat</Text>
<Text h4 style={{ marginBottom: 50 }}>
Create a EasyChat account
</Text>
<Image source={ loginImage
}
style={{ width: 200, height: 200 }} />
<View style={styles.inputContainer}>
<Input
placeholder="Full Name"
autoFocus
type='text'
value={name}
onChangeText={(text) => setName(text)}
/>
<Input
placeholder="Email"
type='text'
value={email}
onChangeText={(text) => setEmail(text)}
/>
<Input
placeholder="Password"
type='password'
secureTextEntry
value={password}
onChangeText={(text) => setPassword(text)}
/>
<Input
placeholder="Profile Picture URL (Optional)"
type='text'
value={imageUrl}
onChangeText={(text) => setImageUrl(text)}
onSubmitEditing={register}
/>
</View>
<Button
containerStyle={styles.button}
raised
onPress={register}
title='Register'
type="clear"
titleStyle={{ color: "#fff" }}
/>
<TouchableOpacity style={styles.marginTop} onPress={() => navigation.navigate("Login")}>
<Text style={styles.LoginLink}>Already have an account ? Sign In</Text>
</TouchableOpacity>
<View style={{ height: 100 }} />
</ScrollView>
</SafeAreaView>
</KeyboardAvoidingView>
)
}
export default RegisterScreen
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
padding: 10,
backgroundColor: "white",
},
inputContainer: {
width: 300,
},
button: {
width: 300,
marginTop: 10,
backgroundColor: "#E76565",
borderRadius: 5,
},
LoginTitle:{
height: 66,
fontSize:46,
fontWeight:'400',
color: '#227721',
bottom:10,
},
LoginLink:{
fontSize:18,
lineHeight:22,
width:280,
color:'#333FA7',
left:10,
top:20,
marginTop:15,
},
marginTop:{
marginTop:15,
}
})
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment