Firebase presence system that works for multiple devices
Asked Answered
P

0

4

In my chat application based on Firebase, I wanted the ability for a user to know if another user is online on any one of the devices (browser / iOS / Android).

I referred to the sample shown on this page. But using this example, I noticed multiple connection keys getting created, but not getting deleted properly. So I ended up enhancing the example like this:

function _managePresence(uid) {
  // top level presence node
  var ref = coreService.presence.child(uid);
  // stores connections from various browsers or devices
  var myConnectionsRef = ref.child('connections');
  // stores the timestamp of my last disconnect (the last time I was seen online)
  var lastOnlineRef = ref.child('lastOnline');
  // this one is special, it tells locally to the device, if I'm connected or not
  var connectedRef = coreService.connection;

  // add this device to my connections list
  var addConnection = function(myConnectionsRef) {
    // TODO: this value could contain info about the device or a timestamp too
    var con = myConnectionsRef.push(true);

    // save the connection key (con.key) locally also
    console.log("saving connection key", con.key);
    localStorage.setItem('currentConnectionKey', con.key);

    // when I disconnect, remove this connection key (from firebase)
    con.onDisconnect().remove();
  };

  connectedRef.on('value', function(snap) {
    if (snap.val() === true) {
      // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect)

      // retrieve connection key from local storage
      var connectionKey = localStorage.getItem('currentConnectionKey');
      console.log("connection key found", connectionKey);

      if (connectionKey) {
        // connection key already exists locally, lets check firebase
        // NOTE: the use of once here, we don't want on('value')
        // because when the connection is removed, on('value') will get called
        // with snap.val() being null and we dont want to create a new connection key in that case
        // new connection key should only be created when we see a change in connectedRef.on('value')
        myConnectionsRef.child(connectionKey).once('value', function (snap) {
          if (snap.val() === true) {
            // connection key already exists in firebase also, we wont add a new connection key
            console.log("key already exists locally and in firebase", connectionKey);
          } else {
            // this connection key does not exist in firebase, lets create a new connection
            console.log("key not found in firebase, lets add a new one");
            addConnection(myConnectionsRef);
          }
        });
      } else {
        console.log("First time, lets addConnection");
        addConnection(myConnectionsRef);
      }

      // when I disconnect, update the last time I was seen online
      lastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);
    } else {
      console.log("disconnecting...");
    }
  });
}

To know if someone is online or not, I just look at the num of children for /presence/uid/connections

  _isOnline() {
    var ref = coreService.presence.child(this.uid);
    var myConnectionsRef = ref.child('connections');
    var self = this;

    myConnectionsRef.on('value', function (snap) {
      if (snap.hasChildren()) self.isON = true;
      else self.isON = false;
    });
  }

  _lastOnline() {
    var ref = coreService.presence.child(this.uid);
    var lastOnlineRef = ref.child('lastOnline');
    var self = this;

    lastOnlineRef.on( 'value',  function (snap) {
      self.lastOnlineTime = snap.val();
    });
  }

Is this the correct way to go about determining if a user is online? This may be too much of code to read, but I'll appreciate if someone can help me verify it.

Phyletic answered 27/4, 2017 at 7:11 Comment(2)
I have same problem, did this code worked for you? Did you see not deleted connections again?Sophomore
This is great, thanks for posting. There's not a lot of information on this topic out there. I found this post quite helpful too: #16452574Tenno

© 2022 - 2024 — McMap. All rights reserved.