Creating a Chat Application using Vue-Native and Firebase
Vue Native is a framework created to bring the best of VueJS to build hybrid mobile apps.
In this tutorial, we are going to build a chat-application using Vue-Native and Firebase as a backend service. This project will include some basic features of a chat application. First of all, users will have to get through the authentication layer of the app to access their account and then they will be able to do real-time chat with their contacts. Before starting the steps to integrate Firebase, lets see some advantages of Vue-Native.
Internally, Vue-Native uses the React Native API which means getting benefits of both Vue and React Native properties under a single hood. Since Vue Native is based on VueJs, it gives developers the freedom to code in a template based syntax, like web, which makes transitioning to mobile based frameworks trouble-free. Firebase, on the other hand, is a powerful backend tool for building great mobile apps with services like crashlytics, authentication, storage etc.
Integrating Firebase with Vue Native is not as tough as it may sound. Following the below steps, you will be able to integrate Firebase with Vue Native in no time. If you are a newbie in Vue-Native, this link will help you with the installation and initial project setup.
Installing Firebase Dependency:
Open your Vue-Native project in the terminal and type the below commands to install firebase package.
npm install react-native-firebase
or
yarn add react-native-firebase
react-native link react-native-firebase
To achieve chat application features, we will be needing:
Firebase will provide us with all the above services.
Project Directory Setup:
Firebase Project Setup:
Firstly, sign up for the Firebase console and create a new project using the ‘+’ button in it. Enter the project's name and click on the 'create project' button. After creating a successful project, open the project's dashboard.
For creating a basic chat-app, we will create two collections in Firebase database. One for the Users information and one for the messages.
Android Setup:
After successful creation of project you will see 'add app +' icon on the project dashboard.
Click on it and add the android app. Post that, a list of steps will appear. Follow all the steps carefully shown in the dashboard to integrate it successfully in Android. Then:
Hire our Development experts.
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules
+implementation "com.google.android.gms:play-services-base:16.1.0"
+implementation "com.google.firebase:firebase-core:16.0.9"
+implementation "com.google.firebase:firebase-auth:17.0.0"
+implementation "com.google.firebase:firebase-firestore:19.0.0"
On the top of this file, add apply plugin:'com.google.gms.google-services'
. Also add multiDexEnabled true
in the defaultConfig
object.
classpath 'com.android.tools.build:gradle:3.4.0'
to classpath 'com.android.tools.build:gradle:3.4.1'.
Hire our Development experts.
dependencies {
- classpath("com.android.tools.build:gradle:3.4.0")
+ classpath("com.android.tools.build:gradle:3.4.1")
+ classpath 'com.google.gms:google-services:4.2.0'
google()
in allprojects/repositories
module in build.gradle file.
Hire our Development experts.
allprojects {
repositories {
mavenLocal()
+ google()
jcenter()
new RNFirebaseAuthPackage()
, new RNFirebaseFirestorePackage()
inside the getPackages()
function.
Hire our Development experts.
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFirebasePackage(),
+ new RNFirebaseAuthPackage(),
+ new RNFirebaseFirestorePackage()
);
}
Hire our Development experts.
import com.facebook.react.ReactApplication;
import io.invertase.firebase.RNFirebasePackage;
+import io.invertase.firebase.auth.RNFirebaseAuthPackage;
+import io.invertase.firebase.firestore.RNFirebaseFirestorePackage;
react-native run-android
in the terminal to check if everything is working correctly.Log in to firebase console and you will see the android app icon with your project's information.
The Android integration journey is now complete. Pretty easy, right? I assure you, the iOS integration is even easier.
iOS Setup:
Open your project in the Firebase console, click on 'add app +' button and select iOS. A new screen will open.
Then:
Hire our Development experts.
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@import Firebase //!! add this line !!
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure]; // !! add this line !!
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"chat_app"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
pod install
.Open project.xcworkspace file of your project and click on play button. Check in the Firebase console for iOS app to see whether integration was successful.Wow!! Integration completed.
Vue Native is now completely integrated with Firebase. Now, we can make a small chat application.
Creating Registration and Sign In functionality:
Let's start by creating the authentication flow for the chat application. We will create a component named Register and Login in Register.vue
and login.vue
file respectively inside the components folder. You can check the basic Vue-Native components to create a basic template.
For using Firebase authentication service, we will be using email/password type authentication.
firebase.auth().createUserWithEmailAndPassword(email, password)
firebase.auth().signInWithEmailAndPassword(email,
password)
Hire our Development experts.
async function register (email, password, name) {
try {
const registered = await firebase.auth().createUserWithEmailAndPassword(email, password)
if (registered) {
await addUser(registered, name)
return registered.user
} else {
return null
}
} catch (e) {
return null
}
}
async function addUser (userObject, name) {
firebase.firestore().collection('users').doc().set({
// user data
}).then(res => console.log(res))
}
Hire our Development experts.
async mounted () {
await firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// go to contacts screen
} else {
// go to sign-in
}
})
},
firebase.auth().signOut()
Creating contacts screen and its functionality:
After the authentication screen, let's start creating the 'contacts' screen functionality. Let's create a file named
Users.vue
for Users component inside the components folder.
Hire our Development experts.
async function getUsers (userId) {
let users = []
firebase.firestore().collection('users').get().then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
if (doc.data().uid != userId) { users.push(doc.data()) }
})
}).then(res => console.log(res)).catch(err => console.log(err))
return users
}
Hire our Development experts.
<template>
<view>
<text class="text-white">Contacts</text>
<flat-list :data = 'users'
:render-item= "(user) => renderUsers(user)"/>
</view>
</template>
Hire our Development experts.
props:{
...other props
userUid:{
Type:String
},
}
getUsers()
function in mounted()
. This function will be called after the component renders for the first time.Hire our Development experts.
mounted: async function () {
this.users = await getUsers(this.userUid)
},
Creating Chat Screen and its functionality:
Now we are only left with chat functionality. For that, we will create the final component in file called Chat.vue
inside components folder.
Hire our Development experts.
import firebase from 'react-native-firebase'
Hire our Development experts.
async function sendMessage (userId, friendId, text) {
try {
await firebase.firestore().collection('messages').doc().set({
message: text,
time: newDate(),
timestamp: Date.now(),
sender: userId,
sentTo: friendId,
})
} catch (e) {
return e.message
}
return {
message: text,
time: newDate(),
timestamp: Date.now(),
sender: userId,
sentTo: friendId,
}
}
For receiving messages, Consider the below function `addListener()
`.
Hire our Development experts.
async function addListener (userId, friendId, messages) {
await firebase.firestore().collection('messages').where('sender', '==',
friendId).where('sentTo', '==', userId).onSnapshot(async function (querySnapshot) {
console.log(querySnapshot._changes)
await querySnapshot._changes.forEach(function (doc) {
if (doc._type == 'added') {
messages.push(doc.doc.data())
messages.sort((message1, message2) => message1.timestamp -
message2.timestamp)
}
})
})
await firebase.firestore().collection('messages').where('sender', '==',
userId).where('sentTo', '==', friendId).onSnapshot(async function (querySnapshot) {
await querySnapshot._changes.forEach(function (doc) {
if (doc._type == 'added') {
messages.push(doc.doc.data())
messages.sort((message1, message2) => message1.timestamp -
message2.timestamp)
}
})
})
return messages
}
Hire our Development experts.
<template>
<view>
<view class="user">
<image :source="require('../assets/user-male.png')" class="profile-pic"/>
<text class="text-bold">
{{ friendName }}
<text>
</view>
<view class="message-view">
<text-input v-model="text" class="message-box" placeholder="Type Message" />
<touchable-opacity :on-press="()=>sendMessage()" :disabled="(text == '')">
<view class="button-view">
<text class="color-white">Send</text>
</view>
</touchable-opacity>
</view>
<scroll-view :content-container-style="{contentContainer: {
flex:1
}}">
<flat-list :data='messages'
:render-item= "(message) => renderMessage(message)"
>
</flat-list>
</scroll-view>
</view>
</template>
Hire our Development experts.
data: function () {
return {
text: '',
messages: [],
friendName: '',
date: '',
}
},
Hire our Development experts.
methods: {
sendMessage: async function () {
var newMessage = await sendMessage(this.userId, this.friendId, this.text)
this.text = ''
},
},
Hire our Development experts.
mounted: async function () {
this.messages = await addListener(this.userId, this.friendId, this.messages)
},
Since we have added the messages
variable to data, it becomes reactive. Now for every change in messages array, there will be change in the UI or the view. At the end, import all components in App.vue to conditionally render according to user existing or not. Also you can simply use vue-native-router for navigation b/w screens.
If you followed the above steps correctly, a simple demo for the chat application using Vue Native & Firebase is ready for you.
Check out the full project on https://github.com/anmoljain10/chat-app-vue-native
It contains all Vue Native components and also the authentication layer for the app. If there are any queries or suggestions that you have, please leave them in the comments section on GitHub and I will respond to as many as I can.
For more information about Vue Native, you can go to this link.
Thank you for reading!