You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
User Presence System in Realtime - Online, Offline, Away
Episode 41 written by Jeff DelaneyUpdate! Watch the latest video and get the most up-to-date code from Angular Firebase Realtime Presence on Fireship.io
The Firebase blog provides a good overview for building a presence system in Firebase, but it doesn’t exactly fit with AngularFire2. In this lesson, I will show you how to create a full-fledged user presence system with Angular4 and Firebase. This is a must-have feature if you’re building a chat app or anything that has realtime user interaction.
Our users will have three possible status.
- Online - Connected to database
- Offline - Disconnected from database
- Away - Connected to database, but no recent activity
Prerequisites
I am assuming that you already have user authentication in place with AngularFire2. The topic of Firebase user auth is covered extensively, so I will only be brushing over it. This user presence system will work with any Firebase auth paradigm, i.e. OAuth, Anonymous, Email/Password, Phone, etc.
See if User is Connected to the Firebase Database
Firebase has a secret database location .info/connected
that will tell you if a connection is currently active to the realtime database. This will be the variable that determines our online/offline statuses. It is not tied to a specific user, but rather the instance of an app that is consuming it.
Set Online Status
Below we have created an AuthService. When the user successfully authenticates, we will subscribe to the connection info and update their status accordingly. We are giving users in the database a status
property that we can query from anywhere in the app.
import { Injectable } from '@angular/core'; |
Set Offline Status
Currently, when a users closers their browser tab or app their status will remain online. So how do we update the status to offline after the app is closed?. Thankfully, the core Firebase SDK has an onDisconect()
function that will be fired when the connection is closed. In this case, we can just make a reference to the user’s status, then update the value to offline.
constructor(private afAuth: AngularFireAuth, |
Set Away Status Status
First, import a few RxJS pieces.
import { Observable } from 'rxjs/Observable' |
We can determine if a user has gone idle by listening for mousemove
events. Here’s how the process works:
- Convert mouse events to an Observable
- Reset an Observable timer when a new mouse event fires
- If timer runs out, set user status to away
Mouse events fire way more often than we need, but we can throttle then with RxJS throttleTime. In this example, we throttle every 2 seconds, so this will emit only the first event within a 2 second time period.
This code creates an Observable timer that will emit a value after 5000ms (5 seconds). In the real world, you would want to set it much longer than that - maybe 5 minutes or so.
Keep in mind, we are are creating two new subscriptions here. Because this could result in memory leaks, you want to unsubscribe when you no longer need them. In this case, we call unsubscribe when the user signs out.
mouseEvents: Subscription |
Displaying the User Status with NgSwitch
This is a perfect opportunity to use the NgSwitch directive in Angular. It works just like a switch statement in JavaScript or any other programming language for that matter.
user-list.html
First, you’re probably going to be looping over a list of users in a parent component. You should have something that looks like this.
<div *ngFor="let user of users | async"> |
user-status.component.html
With NgSwitch
we show a different message, CSS style, and icon based on the status. If none of the statuses match the switch cases, then it will just show the default unknown template at the bottom.
<span [ngSwitch]="status"> |
user-status.component.html
In the TypeScript, we can use the @Input
decorator to pass the status variable from the parent to the child. Learn more about sharing data between Angular components.
import { Component, Input } from '@angular/core'; |
The End
That’s it for realtime user presence with Firebase and Angular - pretty easy! Let me know what you think in the comments are via Slack.