I'm trying to display all users connected or "away" of my app.
90% of the time it works fine but sometimes they are users that leaves and they are still marked as online, I can't find why. As far as I know desktop app works better than mobile (but it can be wrong on desktop)
Here is the code of the service:
export class PresenceService {
constructor(private afAuth: AngularFireAuth, private db: AngularFireDatabase) {
this.updateOnUser().subscribe();
this.updateOnDisconnect().subscribe();
this.updateOnAway();
}
getPresence(uid: string) {
return this.db.object(`status/${uid}`).valueChanges() as Observable<any>;
}
getUser() {
return this.afAuth.authState.pipe(first()).toPromise();
}
async setPresence(status: string) {
const user = await this.getUser();
if (user) {
return this.db.object(`status/${user.uid}`).update({ status, timestamp: this.timestamp, uid: user.uid });
}
}
get timestamp() {
return firebase.database.ServerValue.TIMESTAMP;
}
// Updates status when logged-in connection to Firebase starts
updateOnUser() {
const connection = this.db.object('.info/connected').valueChanges().pipe(
map(connected => connected ? 'online' : 'offline')
);
return this.afAuth.authState.pipe(
switchMap(user => user ? connection : of('offline')),
tap(status => this.setPresence(status))
);
}
updateOnDisconnect() {
return this.afAuth.authState.pipe(
tap(user => {
if (user) {
this.db.object(`status/${user.uid}`).query.ref.onDisconnect()
.update({
status: 'offline',
timestamp: this.timestamp,
uid: user.uid
});
}
})
);
}
async signOut() {
await this.setPresence('offline');
}
// User navigates to a new tab
updateOnAway() {
document.onvisibilitychange = (e) => {
if (document.visibilityState === 'hidden') {
this.setPresence('away');
} else {
this.setPresence('online');
}
};
}
}