diff --git a/clientapp/app.js b/clientapp/app.js index e7396a1..a8f2673 100644 --- a/clientapp/app.js +++ b/clientapp/app.js @@ -32,6 +32,7 @@ module.exports = { _.extend(this, Backbone.Events); + var profile = {}; async.series([ function (cb) { app.notifications = new Notify(); @@ -40,16 +41,17 @@ module.exports = { app.storage.open(cb); }, function (cb) { - app.storage.rosterver.get(config.jid, function (err, ver) { - if (ver) { - config.rosterVer = ver; + app.storage.profiles.get(config.jid, function (err, res) { + if (res) { + profile = res; + config.rosterVer = res.rosterVer; } cb(); }); }, function (cb) { app.state = new AppState(); - app.me = window.me = new MeModel(); + app.me = window.me = new MeModel(profile); window.onbeforeunload = function () { if (app.api.sessionStarted) { diff --git a/clientapp/helpers/xmppEventHandlers.js b/clientapp/helpers/xmppEventHandlers.js index 7b9d77e..4c0c13e 100644 --- a/clientapp/helpers/xmppEventHandlers.js +++ b/clientapp/helpers/xmppEventHandlers.js @@ -107,7 +107,7 @@ module.exports = function (client, app) { client.getRoster(function (err, resp) { resp = resp.toJSON(); - app.storage.rosterver.set(me.jid.bare, resp.roster.ver); + me.rosterVer = resp.roster.ver; _.each(resp.roster.items, function (item) { me.setContact(item, true); @@ -116,6 +116,7 @@ module.exports = function (client, app) { var caps = client.updateCaps(); app.storage.disco.add(caps.ver, caps.discoInfo, function () { client.sendPresence({ + status: me.status, caps: client.disco.caps }); client.enableCarbons(); @@ -129,7 +130,7 @@ module.exports = function (client, app) { iq = iq.toJSON(); var items = iq.roster.items; - app.storage.rosterver.set(me.jid.bare, iq.roster.ver); + me.rosterVer = iq.roster.ver; _.each(items, function (item) { var contact = me.getContact(item.jid); diff --git a/clientapp/models/me.js b/clientapp/models/me.js index 633804f..70e18b9 100644 --- a/clientapp/models/me.js +++ b/clientapp/models/me.js @@ -11,20 +11,30 @@ var fetchAvatar = require('../helpers/fetchAvatar'); module.exports = HumanModel.define({ - initialize: function () { - this.bind('change:jid', this.loadContacts, this); + initialize: function (opts) { + if (opts.avatarID) { + this.setAvatar(opts.avatarID); + } + + this.bind('change:jid', this.load, this); this.bind('change:hasFocus', function () { this.setActiveContact(this._activeContact); }, this); + this.bind('change:avatarID', this.save, this); + this.bind('change:status', this.save, this); + this.bind('change:rosterVer', this.save, this); this.contacts.bind('change:unreadCount', this.updateUnreadCount, this); app.state.bind('change:active', this.updateIdlePresence, this); }, - session: { + props: { jid: ['object', true], status: ['string', true, ''], - avatar: ['string', true, ''], avatarID: ['string', true, ''], + rosterVer: ['string', true, ''] + }, + session: { + avatar: ['string', true, ''], connected: ['bool', true, false], shouldAskForAlertsPermission: ['bool', true, false], hasFocus: ['bool', true, false], @@ -83,22 +93,30 @@ module.exports = HumanModel.define({ this.contacts.remove(jid.bare); app.storage.roster.remove(jid.bare); }, - loadContacts: function () { + load: function () { if (!this.jid.bare) return; var self = this; - app.storage.roster.getAll(this.jid.bare, function (err, contacts) { - if (err) return; - contacts.forEach(function (contact) { - contact = new Contact(contact); - contact.owner = self.jid.bare; - contact.inRoster = true; - contact.save(); - self.contacts.add(contact); + app.storage.profiles.get(this.jid.bare, function (err, profile) { + if (!err) { + self.status = profile.status; + self.avatarID = profile.avatarID; + } + self.save(); + app.storage.roster.getAll(self.jid.bare, function (err, contacts) { + if (err) return; + + contacts.forEach(function (contact) { + contact = new Contact(contact); + contact.owner = self.jid.bare; + contact.inRoster = true; + contact.save(); + self.contacts.add(contact); + }); + + self.contacts.trigger('loaded'); }); - - self.contacts.trigger('loaded'); }); }, isMe: function (jid) { @@ -124,5 +142,14 @@ module.exports = HumanModel.define({ count = ''; } app.state.badge = '' + count; + }, + save: function () { + var data = { + jid: this.jid.bare, + avatarID: this.avatarID, + status: this.status, + rosterVer: this.rosterVer + }; + app.storage.profiles.set(data); } }); diff --git a/clientapp/storage/index.js b/clientapp/storage/index.js index de83d3d..2a7383c 100644 --- a/clientapp/storage/index.js +++ b/clientapp/storage/index.js @@ -5,7 +5,7 @@ var AvatarStorage = require('./avatars'); var RosterStorage = require('./roster'); var DiscoStorage = require('./disco'); var ArchiveStorage = require('./archive'); -var RosterVerStorage = require('./rosterver'); +var ProfileStorage = require('./profile'); function Storage() { @@ -16,13 +16,13 @@ function Storage() { this.roster = new RosterStorage(this); this.disco = new DiscoStorage(this); this.archive = new ArchiveStorage(this); - this.rosterver = new RosterVerStorage(this); + this.profiles = new ProfileStorage(this); } Storage.prototype = { constructor: { value: Storage }, - version: 2, + version: 3, open: function (cb) { cb = cb || function () {}; @@ -38,7 +38,7 @@ Storage.prototype = { self.roster.setup(db); self.disco.setup(db); self.archive.setup(db); - self.rosterver.setup(db); + self.profiles.setup(db); }; request.onerror = cb; } diff --git a/clientapp/storage/profile.js b/clientapp/storage/profile.js new file mode 100644 index 0000000..d66c3ff --- /dev/null +++ b/clientapp/storage/profile.js @@ -0,0 +1,66 @@ +/*global, IDBKeyRange*/ +"use strict"; + +// SCHEMA +// jid: string +// name: string +// avatarID: string +// status: string +// rosterVer: string + + +function ProfileStorage(storage) { + this.storage = storage; +} + +ProfileStorage.prototype = { + constructor: { + value: ProfileStorage + }, + setup: function (db) { + if (db.objectStoreNames.contains('profiles')) { + db.deleteObjectStore('profiles'); + } + var store = db.createObjectStore('profiles', { + keyPath: 'jid' + }); + }, + transaction: function (mode) { + var trans = this.storage.db.transaction('profiles', mode); + return trans.objectStore('profiles'); + }, + set: function (profile, cb) { + cb = cb || function () {}; + var request = this.transaction('readwrite').put(profile); + request.onsuccess = function () { + cb(false, profile); + }; + request.onerror = cb; + }, + get: function (id, cb) { + cb = cb || function () {}; + if (!id) { + return cb('not-found'); + } + var request = this.transaction('readonly').get(id); + request.onsuccess = function (e) { + var res = request.result; + if (res === undefined) { + return cb('not-found'); + } + cb(false, request.result); + }; + request.onerror = cb; + }, + remove: function (id, cb) { + cb = cb || function () {}; + var request = this.transaction('readwrite')['delete'](id); + request.onsuccess = function (e) { + cb(false, request.result); + }; + request.onerror = cb; + } +}; + + +module.exports = ProfileStorage;