diff --git a/src/styles/components/_buddylist.scss b/src/styles/components/_buddylist.scss
index 4a11f974..1d000e03 100644
--- a/src/styles/components/_buddylist.scss
+++ b/src/styles/components/_buddylist.scss
@@ -126,10 +126,10 @@
}
.buddy {
- &.withSubline .buddy1 {
+ &.withSubline .buddy1, &.contact .buddy1 {
top: 15px;
}
- &.withSubline .buddy2 {
+ &.withSubline .buddy2, &.contact .buddy2 {
display: block;
}
&.hovered .buddyactions {
diff --git a/static/js/controllers/mediastreamcontroller.js b/static/js/controllers/mediastreamcontroller.js
index 17322dcb..d9a936a6 100644
--- a/static/js/controllers/mediastreamcontroller.js
+++ b/static/js/controllers/mediastreamcontroller.js
@@ -624,6 +624,7 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'webrtc.adapter'], function
if (userid) {
console.info("Session is now authenticated:", userid);
}
+ appData.e.triggerHandler("authenticationChanged", [userid]);
});
// Apply all layout stuff as classes to our element.
diff --git a/static/js/services/appdata.js b/static/js/services/appdata.js
index 2344904c..dea2595f 100644
--- a/static/js/services/appdata.js
+++ b/static/js/services/appdata.js
@@ -18,13 +18,17 @@
* along with this program. If not, see .
*
*/
-define([], function() {
+define(["jquery"], function($) {
+
+ // appData.e events
+ // - authenticationChanged(userid)
// appData
return [function() {
var data = {
- data: null
+ data: null,
+ e: $({})
}
var appData = {
get: function() {
@@ -33,7 +37,8 @@ define([], function() {
set: function(d) {
data.data = d;
return d;
- }
+ },
+ e: data.e
}
return appData;
diff --git a/static/js/services/buddylist.js b/static/js/services/buddylist.js
index 833e4562..5920e77d 100644
--- a/static/js/services/buddylist.js
+++ b/static/js/services/buddylist.js
@@ -67,6 +67,12 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
};
+ BuddyTree.prototype.check = function(id) {
+
+ return this.data.hasOwnProperty(id);
+
+ };
+
/**
* Returns undefined when no change required. Position result otherwise.
*/
@@ -535,7 +541,10 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
this.updateDisplay(sessionData.Id, scope, sessionData, "status");
} else if (scope.contact) {
// Use it with userid as id in tree.
- this.tree.add(session.Userid, scope);
+ if (!this.tree.check(session.Userid)) {
+ this.tree.add(session.Userid, scope);
+ buddyCount++;
+ }
}
if (!noApply) {
scope.$apply();
@@ -567,7 +576,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
Buddylist.prototype.onContactAdded = function(contact) {
- console.log("onContactAdded", contact);
+ //console.log("onContactAdded", contact);
var userid = contact.Userid;
var scope = buddyData.get(userid);
@@ -581,17 +590,23 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
console.log("Injected status into contact", contact);
}
this.updateDisplay(sessionData.Id, scope, contact, "status");
+ scope.$apply();
}
} else {
- // TODO(longsleep): Implement rendering of contacts without scope.
- console.log("No scope for contact", userid);
+ // Create new scope for contact.
+ scope = this.onJoined({
+ Id: contact.Userid,
+ Userid: contact.Userid,
+ Status: contact.Status
+ });
+ scope.contact = contact;
}
};
Buddylist.prototype.onContactRemoved = function(contact) {
- console.log("onContactRemoved", contact);
+ //console.log("onContactRemoved", contact);
var userid = contact.Userid;
var scope = buddyData.get(userid);
diff --git a/static/js/services/buddysession.js b/static/js/services/buddysession.js
index cf2a2013..7d153c51 100644
--- a/static/js/services/buddysession.js
+++ b/static/js/services/buddysession.js
@@ -30,7 +30,7 @@ define(["underscore"], function(_) {
this.serial = serials++;
this.sessions = {};
this.count = 0;
- //console.log("creating session", this.serial, this);
+ //console.log("creating session", this.serial, data.Id, data.Userid, this);
var id = data.Id;
if (data.Id) {
var userid = data.Userid || null;
@@ -78,7 +78,7 @@ define(["underscore"], function(_) {
} else {
this.Id = null;
}
- console.log("Use session as default", id, data, this);
+ //console.log("Use session as default", id, data, this);
};
BuddySession.prototype.remove = function(id, onEmptyCallback) {
@@ -96,9 +96,9 @@ define(["underscore"], function(_) {
if (sessionData) {
this.use(sessionData.Id, sessionData);
} else {
- console.log("Last session removed", sessions);
+ //console.log("Last session removed", sessions);
if (this.Userid) {
- console.log("Using userid as session id");
+ //console.log("Using userid as session id");
this.use(this.Userid);
} else {
this.use(null);
@@ -112,22 +112,29 @@ define(["underscore"], function(_) {
BuddySession.prototype.update = function(id, data, onUseridCallback) {
- var sessionData = this.get(id);
- if (!sessionData) {
- sessionData = this.add(id, data);
- }
-
var userid = data.Userid;
+ //console.log("session update", id, userid, this, data);
+
+ var sessionData
+ if (id === userid) {
+ // Fake updates from userid ids.
+ sessionData = data;
+ } else {
+ sessionData = this.get(id);
+ if (!sessionData) {
+ sessionData = this.add(id, data);
+ }
+ }
if (userid) {
this.auth(userid, sessionData, onUseridCallback);
}
-
- if (data.Rev) {
- sessionData.Rev = data.Rev;
- }
-
- if (data.Status) {
- sessionData.Status = data.Status;
+ if (data !== sessionData) {
+ if (data.Rev) {
+ sessionData.Rev = data.Rev;
+ }
+ if (data.Status) {
+ sessionData.Status = data.Status;
+ }
}
if (id === this.Id) {
@@ -142,7 +149,7 @@ define(["underscore"], function(_) {
if (!this.Userid) {
this.Userid = userid;
- console.log("Session now has a user id", this.Id, userid);
+ //console.log("Session now has a user id", this.Id, userid);
}
// Trigger callback if defined and not triggered before.
if (onUseridCallback && !sessionData.auth) {
diff --git a/static/js/services/contactdata.js b/static/js/services/contactdata.js
index 0ab3f0dd..b06d2f0e 100644
--- a/static/js/services/contactdata.js
+++ b/static/js/services/contactdata.js
@@ -29,7 +29,7 @@ define(['underscore', 'jquery'], function(underscore, $) {
var contactData = {
addByRequest: function(request, status) {
- console.log("addByRequest", request, status);
+ //console.log("addByRequest", request, status);
var userid = request.Userid;
var token = request.Token;
var id;
@@ -46,7 +46,19 @@ define(['underscore', 'jquery'], function(underscore, $) {
Token: token,
Status: null
}
- // TODO(longsleep): Trigger this to somewhere.
+ return contact;
+ },
+ addByData: function(data) {
+ //console.log("addByData", data.Userid, data);
+ var userid = data.Userid;
+ if (users.hasOwnProperty(userid)) {
+ id = users[userid]
+ } else {
+ id = String(count++);
+ users[userid] = id;
+ }
+ var contact = contacts[id] = data;
+ contact.Id = id;
return contact;
},
get: function(userid) {
diff --git a/static/js/services/contacts.js b/static/js/services/contacts.js
index cc89d90c..5cd2d2e4 100644
--- a/static/js/services/contacts.js
+++ b/static/js/services/contacts.js
@@ -18,28 +18,142 @@
* along with this program. If not, see .
*
*/
-define(['underscore', 'jquery'], function(underscore, $) {
+define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr) {
+
+ var Database = function(name, version) {
+ this.ready = false;
+ this.db = null;
+ this.name = name;
+ this.e = $({});
+ var request = indexedDB.open("mediastream", version);
+ var that = this;
+ request.onupgradeneeded = function(event) {
+ var db = event.target.result;
+ var transaction = event.target.transaction;
+ transaction.onerror = _.bind(that.onerror, that);
+ if (db.objectStoreNames.contains(name)) {
+ // TODO(longsleep): Database upgrade should keep the data and migrate it.
+ db.deleteObjectStore("contacts")
+ console.warn("Removed contacts database with old format.")
+ }
+ db.createObjectStore(name, {
+ // We use id field as our unique identifier.
+ keyPath: "id"
+ });
+ console.log("Created contacts database.")
+ };
+ request.onsuccess = _.bind(that.onsuccess, that);
+ };
+ Database.prototype.onerror = function(event) {
+ console.log("IndexDB database error", event);
+ };
+ Database.prototype.onsuccess = function(event) {
+ this.db = event.target.result;
+ this.ready = true;
+ console.log("Openend database for contacts", this.db);
+ this.e.triggerHandler("ready");
+ };
+ Database.prototype.put = function(data, successCallback, errorCallback) {
+ var transaction = this.db.transaction(this.name, "readwrite");
+ var store = transaction.objectStore(this.name);
+ var request = store.put(data);
+ if (!errorCallback) {
+ errorCallback = _.bind(this.onerror, this);
+ }
+ transaction.onerror = request.onerror = errorCallback;
+ if (successCallback) {
+ request.onsuccess = successCallback;
+ }
+ return request;
+ };
+ Database.prototype.delete = function(id, successCallback, errorCallback) {
+ var transaction = this.db.transaction(this.name, "readwrite");
+ var store = transaction.objectStore(this.name);
+ var request = store.delete(id);
+ if (!errorCallback) {
+ errorCallback = _.bind(this.onerror, this);
+ }
+ transaction.onerror = request.onerror = errorCallback;
+ if (successCallback) {
+ request.onsuccess = successCallback;
+ }
+ return request;
+ };
+ Database.prototype.all = function(iteratorCallback, errorCallback) {
+ var transaction = this.db.transaction(this.name);
+ var store = transaction.objectStore(this.name);
+ var keyRange = IDBKeyRange.lowerBound(0);
+ var cursorRequest = store.openCursor(keyRange);
+ cursorRequest.onsuccess = function(event) {
+ var result = event.target.result;
+ if (!!result === false) {
+ return;
+ }
+ //console.log("read data idb", result, event);
+ iteratorCallback(result.value);
+ result.continue();
+ };
+ if (!errorCallback) {
+ errorCallback = _.bind(this.onerror, this);
+ }
+ transaction.onerror = cursorRequest.onerror = errorCallback;
+ return cursorRequest;
+ };
+
+ var database;
+ if (Modernizr.indexeddb) {
+ database = new Database("contacts", 1);
+ }
// contacts
- return ["contactData", function(contactData) {
+ return ["appData", "contactData", function(appData, contactData) {
var Contacts = function() {
this.e = $({});
+ this.userid = null;
+ appData.e.on("authenticationChanged", _.bind(function(event, userid) {
+ this.userid = userid;
+ if (database && userid) {
+ // TODO(longsleep): This needs to be delayed util self has ha userid.
+ if (database.ready) {
+ _.defer(_.bind(this.load, this));
+ } else {
+ database.e.one("ready", _.bind(this.load, this));
+ }
+ }
+ }, this));
+ };
+
+ Contacts.prototype.load = function() {
+ console.log("Load contacts from storage", database);
+ database.all(_.bind(function(data) {
+ var contact = contactData.addByData(data.contact);
+ this.e.triggerHandler("contactadded", contact);
+ }, this));
};
Contacts.prototype.add = function(request, status) {
var contact = contactData.addByRequest(request, status);
this.e.triggerHandler("contactadded", contact);
+ if (database) {
+ database.put({
+ id: contact.Userid,
+ contact: contact
+ })
+ }
};
Contacts.prototype.remove = function(userid) {
var contact = contactData.get(userid);
- //console.log("contacts remove", userid, contact);
+ console.log("contacts remove", userid, contact);
if (contact) {
contactData.remove(userid);
+ if (database) {
+ database.delete(userid);
+ }
this.e.triggerHandler("contactremoved", contact);
}
diff --git a/static/partials/buddy.html b/static/partials/buddy.html
index d0075eea..ceae38d2 100644
--- a/static/partials/buddy.html
+++ b/static/partials/buddy.html
@@ -1,5 +1,5 @@
-
{{session.Id|displayName}}
+
{{session.Id|displayName}} {{session.serial}}
({{session.count}}) {{display.subLine}}