Browse Source

Store contacts in per user database.

pull/48/head
Simon Eisenmann 11 years ago
parent
commit
2da69c4087
  1. 7
      static/js/directives/contactrequest.js
  2. 15
      static/js/services/contactdata.js
  3. 126
      static/js/services/contacts.js

7
static/js/directives/contactrequest.js

@ -50,7 +50,12 @@ define(['jquery', 'underscore'], function($, _) {
// Add support for contacts on controller creation. // Add support for contacts on controller creation.
var request = $scope.request; var request = $scope.request;
if (request.Success && request.Userid && request.Token) { if (request.Success && request.Userid && request.Token) {
$scope.addContact(request, buddyData.lookup($scope.id).status || null); var buddy = buddyData.lookup($scope.id);
var status = {};
if (buddy) {
$.extend(status, buddy.status);
}
$scope.addContact(request, status);
} }
}]; }];

15
static/js/services/contactdata.js

@ -28,6 +28,16 @@ define(['underscore', 'jquery'], function(underscore, $) {
var count = 0; var count = 0;
var contactData = { var contactData = {
clear: function(cb) {
_.each(users, _.bind(function(idx, userid) {
var contact = contacts[idx];
if (cb && contact) {
cb(contact);
}
this.remove(userid);
}, this));
count = 0;
},
addByRequest: function(request, status) { addByRequest: function(request, status) {
//console.log("addByRequest", request, status); //console.log("addByRequest", request, status);
var userid = request.Userid; var userid = request.Userid;
@ -69,6 +79,10 @@ define(['underscore', 'jquery'], function(underscore, $) {
return null; return null;
}, },
remove: function(userid) { remove: function(userid) {
if (users.hasOwnProperty(userid)) {
var id = users[userid];
delete contacts[id];
}
delete users[userid]; delete users[userid];
}, },
getById: function(id) { getById: function(id) {
@ -81,6 +95,7 @@ define(['underscore', 'jquery'], function(underscore, $) {
return null return null
} }
}; };
return contactData; return contactData;
}]; }];

126
static/js/services/contacts.js

@ -18,31 +18,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr) { define(['underscore', 'jquery', 'modernizr', 'sjcl'], function(underscore, $, Modernizr, sjcl) {
var Database = function(name, version) { var Database = function(name) {
this.version = 3;
this.ready = false; this.ready = false;
this.db = null; this.db = null;
this.name = name; this.name = name;
this.e = $({}); this.e = $({});
var request = indexedDB.open("mediastream", version); var request = indexedDB.open(this.name, this.version);
var that = this; var that = this;
request.onupgradeneeded = function(event) { request.onupgradeneeded = function(event) {
var db = event.target.result; var db = event.target.result;
var transaction = event.target.transaction; var transaction = event.target.transaction;
transaction.onerror = _.bind(that.onerror, that); transaction.onerror = _.bind(that.onerror, that);
that.init(db);
console.log("Created contacts database.")
};
request.onsuccess = _.bind(that.onsuccess, that);
};
Database.prototype.init = function(db) {
var createOrUpdateStore = function(name, obj) {
if (db.objectStoreNames.contains(name)) { if (db.objectStoreNames.contains(name)) {
// TODO(longsleep): Database upgrade should keep the data and migrate it. // TODO(longsleep): Migrate data.
db.deleteObjectStore("contacts") db.deleteObjectStore(name);
console.warn("Removed contacts database with old format.") }
db.createObjectStore(name, obj);
} }
db.createObjectStore(name, { // Create our object stores.
createOrUpdateStore("contacts", {
// We use id field as our unique identifier. // We use id field as our unique identifier.
keyPath: "id" keyPath: "id"
}); });
console.log("Created contacts database.")
};
request.onsuccess = _.bind(that.onsuccess, that);
}; };
Database.prototype.onerror = function(event) { Database.prototype.onerror = function(event) {
console.log("IndexDB database error", event); console.log("IndexDB database error", event);
@ -50,12 +57,12 @@ define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr)
Database.prototype.onsuccess = function(event) { Database.prototype.onsuccess = function(event) {
this.db = event.target.result; this.db = event.target.result;
this.ready = true; this.ready = true;
console.log("Openend database for contacts", this.db); console.log("Openend database", this.db);
this.e.triggerHandler("ready"); this.e.triggerHandler("ready");
}; };
Database.prototype.put = function(data, successCallback, errorCallback) { Database.prototype.put = function(store, data, successCallback, errorCallback) {
var transaction = this.db.transaction(this.name, "readwrite"); var transaction = this.db.transaction(store, "readwrite");
var store = transaction.objectStore(this.name); var store = transaction.objectStore(store);
var request = store.put(data); var request = store.put(data);
if (!errorCallback) { if (!errorCallback) {
errorCallback = _.bind(this.onerror, this); errorCallback = _.bind(this.onerror, this);
@ -66,9 +73,9 @@ define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr)
} }
return request; return request;
}; };
Database.prototype.delete = function(id, successCallback, errorCallback) { Database.prototype.delete = function(store, id, successCallback, errorCallback) {
var transaction = this.db.transaction(this.name, "readwrite"); var transaction = this.db.transaction(store, "readwrite");
var store = transaction.objectStore(this.name); var store = transaction.objectStore(store);
var request = store.delete(id); var request = store.delete(id);
if (!errorCallback) { if (!errorCallback) {
errorCallback = _.bind(this.onerror, this); errorCallback = _.bind(this.onerror, this);
@ -79,9 +86,9 @@ define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr)
} }
return request; return request;
}; };
Database.prototype.all = function(iteratorCallback, errorCallback) { Database.prototype.all = function(store, iteratorCallback, errorCallback) {
var transaction = this.db.transaction(this.name); var transaction = this.db.transaction(store);
var store = transaction.objectStore(this.name); var store = transaction.objectStore(store);
var keyRange = IDBKeyRange.lowerBound(0); var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange); var cursorRequest = store.openCursor(keyRange);
cursorRequest.onsuccess = function(event) { cursorRequest.onsuccess = function(event) {
@ -99,45 +106,98 @@ define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr)
transaction.onerror = cursorRequest.onerror = errorCallback; transaction.onerror = cursorRequest.onerror = errorCallback;
return cursorRequest; return cursorRequest;
}; };
Database.prototype.close = function() {
var database; // TODO(longsleep): Database close.
if (Modernizr.indexeddb) { this.e.off();
database = new Database("contacts", 1); if (this.db) {
this.db.close();
this.db = null;
this.ready = false;
} }
_.defer(_.bind(function() {
this.e.triggerHandler("closed");
}, this));
};
// contacts // contacts
return ["appData", "contactData", function(appData, contactData) { return ["appData", "contactData", function(appData, contactData) {
var Contacts = function() { var Contacts = function() {
this.e = $({}); this.e = $({});
this.userid = null; this.userid = null;
this.database = null;
appData.e.on("authenticationChanged", _.bind(function(event, userid) { appData.e.on("authenticationChanged", _.bind(function(event, userid) {
this.userid = userid; var database = this.open(userid);
if (database && userid) { if (database && userid) {
// TODO(longsleep): This needs to be delayed util self has ha userid. // TODO(longsleep): This needs to be delayed util self has ha userid.
if (database.ready) { if (database.ready) {
_.defer(_.bind(this.load, this)); _.defer(_.bind(function() {
if (this.database === database) {
this.load();
}
}, this));
} else { } else {
database.e.one("ready", _.bind(this.load, this)); database.e.one("ready", _.bind(function() {
if (this.database === database) {
this.load();
}
}, this));
} }
} }
}, this)); }, this));
};
Contacts.prototype.open = function(userid) {
if (this.database && (!userid || this.userid !== userid)) {
// Unload existing contacts.
this.unload();
// Close existing database.
this.database.close();
this.database = null;
}
if (userid) {
if (!Modernizr.indexeddb) {
return;
}
// Create HMAC database name for user.
var hmac = new sjcl.misc.hmac('mediastream');
var id = "mediastream-"+sjcl.codec.base64.fromBits(hmac.encrypt(userid));
console.log("Open of database:", id);
var database = this.database = new Database(id);
return database;
} else {
this.database = null;
return null;
}
}; };
Contacts.prototype.load = function() { Contacts.prototype.load = function() {
console.log("Load contacts from storage", database); if (this.database) {
database.all(_.bind(function(data) { console.log("Load contacts from storage", this);
this.database.all("contacts", _.bind(function(data) {
var contact = contactData.addByData(data.contact); var contact = contactData.addByData(data.contact);
// TODO(longsleep): Convert buddyImage string to Blob. // TODO(longsleep): Convert buddyImage string to Blob.
this.e.triggerHandler("contactadded", contact); this.e.triggerHandler("contactadded", contact);
}, this)); }, this));
}
};
Contacts.prototype.unload = function() {
contactData.clear(_.bind(function(contact) {
this.e.triggerHandler("contactremoved", contact);
}, this));
}; };
Contacts.prototype.add = function(request, status) { Contacts.prototype.add = function(request, status) {
var contact = contactData.addByRequest(request, status); var contact = contactData.addByRequest(request, status);
this.e.triggerHandler("contactadded", contact); this.e.triggerHandler("contactadded", contact);
if (database) { if (this.database) {
database.put({ this.database.put("contacts", {
id: contact.Userid, id: contact.Userid,
contact: contact contact: contact
}) })
@ -149,8 +209,8 @@ define(['underscore', 'jquery', 'modernizr'], function(underscore, $, Modernizr)
console.log("contacts remove", userid, contact); console.log("contacts remove", userid, contact);
if (contact) { if (contact) {
contactData.remove(userid); contactData.remove(userid);
if (database) { if (this.database) {
database.delete(userid); this.database.delete("contacts", userid);
} }
this.e.triggerHandler("contactremoved", contact); this.e.triggerHandler("contactremoved", contact);
} }

Loading…
Cancel
Save