1
0
mirror of https://github.com/moparisthebest/kaiwa synced 2024-12-24 08:28:56 -05:00

Add centralized app state tracking; use it for idle updates

This commit is contained in:
Lance Stout 2013-09-26 20:19:46 -07:00
parent 15f61d8bb4
commit 37e4fa3502
8 changed files with 85 additions and 28 deletions

View File

@ -4,6 +4,7 @@
var _ = require('underscore');
var async = require('async');
var Backbone = require('backbone');
var AppState = require('./models/state');
var MeModel = require('./models/me');
var MainView = require('./views/main');
var Router = require('./router');
@ -42,37 +43,30 @@ module.exports = {
});
},
function (cb) {
window.me = new MeModel();
app.state = new AppState();
app.me = window.me = new MeModel();
me.hasFocus = false;
$(window).blur(function () {
me.hasFocus = false;
});
$(window).focus(function () {
me.hasFocus = true;
});
window.onbeforeunload = function () {
if (client.sessionStarted) {
client.disconnect();
if (app.api.sessionStarted) {
app.api.disconnect();
}
};
self.api = window.client = XMPP.createClient(config);
xmppEventHandlers(self.api, self);
self.api.connect();
self.api.once('session:started', function () {
app.hasConnected = true;
app.state.hasConnected = true;
cb();
});
self.api.connect();
},
function (cb) {
new Router();
app.history = Backbone.history;
self.view = new MainView({
model: me,
model: app.state,
el: document.body
});
self.view.render();
@ -92,6 +86,7 @@ module.exports = {
},
navigate: function (page) {
var url = (page.charAt(0) === '/') ? page.slice(1) : page;
app.state.markActive();
app.history.navigate(url, true);
},
renderPage: function (view, animation) {

View File

@ -1,5 +1,5 @@
/*global app, client*/
/*global app*/
"use strict";
var crypto = require('crypto');
@ -26,7 +26,7 @@ module.exports = function (jid, id, type, cb) {
}
app.whenConnected(function () {
client.getAvatar(jid, id, function (err, resp) {
app.api.getAvatar(jid, id, function (err, resp) {
if (err) {
return cb(fallback(jid));
}

View File

@ -58,6 +58,9 @@ module.exports = function (client, app) {
client.on('*', function (name, data) {
log.debug(name, data);
if (name === 'raw:outgoing') {
log.debug(data.toString());
}
});
client.on('credentials:update', function (creds) {
@ -79,11 +82,11 @@ module.exports = function (client, app) {
});
client.on('disconnected', function (err) {
me.connected = false;
app.state.connected = false;
if (err) {
console.error(err);
}
if (!app.hasConnected) {
if (!app.state.hasConnected) {
window.location = '/login';
}
});
@ -94,13 +97,13 @@ module.exports = function (client, app) {
});
client.on('stream:management:resumed', function () {
me.connected = true;
app.state.connected = true;
});
client.on('session:started', function (jid) {
me.jid = jid;
me.connected = true;
app.state.connected = true;
client.getRoster(function (err, resp) {
resp = resp.toJSON();

View File

@ -1,4 +1,4 @@
/*global XMPP, app, me, client*/
/*global app, me, client*/
"use strict";
var _ = require('underscore');

View File

@ -1,4 +1,4 @@
/*global app, client, XMPP*/
/*global app, client*/
"use strict";
var HumanModel = require('human-model');
@ -16,6 +16,8 @@ module.exports = HumanModel.define({
this.bind('change:hasFocus', function () {
this.setActiveContact(this._activeContact);
}, this);
app.state.bind('change:active', this.updateIdlePresence, this);
},
session: {
jid: ['object', true],
@ -98,5 +100,18 @@ module.exports = HumanModel.define({
},
isMe: function (jid) {
return jid.bare === this.jid.bare;
},
updateIdlePresence: function () {
var update = {
status: this.status,
show: this.show,
caps: app.api.disco.caps
};
if (!app.state.active) {
update.idle = {since: app.state.idleSince};
}
app.api.sendPresence(update);
}
});

43
clientapp/models/state.js Normal file
View File

@ -0,0 +1,43 @@
/*global app, $*/
"use strict";
var HumanModel = require('human-model');
module.exports = HumanModel.define({
initialize: function () {
var self = this;
$(window).blur(function () {
self.focused = false;
});
$(window).focus(function () {
self.focused = true;
self.markActive();
});
this.markActive();
},
session: {
focused: ['bool', true, true],
active: ['bool', true, false],
connected: ['bool', true, false],
hasConnected: ['bool', true, false],
idleTimeout: ['number', true, 600000],
idleSince: 'date'
},
markActive: function () {
clearTimeout(this.idleTimer);
var wasInactive = !this.active;
this.active = true;
this.idleSince = new Date(Date.now());
this.idleTimer = setTimeout(this.markInactive.bind(this), this.idleTimeout);
},
markInactive: function () {
if (this.focused) {
return this.markActive();
}
this.active = false;
this.idleSince = new Date(Date.now());
}
});

View File

@ -93,6 +93,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
handleKeyDown: function (e) {
clearTimeout(this.typingTimer);
if (e.which === 13 && !e.shiftKey) {
this.sendChat();
e.preventDefault();
@ -120,6 +121,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
handleKeyUp: function (e) {
this.resizeInput();
clearTimeout(this.typingTimer);
this.typingTimer = setTimeout(this.pausedTyping.bind(this), 5000);
if (this.typing && this.$chatInput.val().length === 0) {
this.typing = false;

View File

@ -1,6 +1,7 @@
/*global app, me, XMPP, client, Resample*/
"use strict";
var crypto = require('crypto');
var BasePage = require('./base');
var templates = require('../templates');
@ -56,13 +57,11 @@ module.exports = BasePage.extend({
}
if (file.type.match('image.*')) {
console.log('Got an image file!', file.type);
var fileTracker = new FileReader();
fileTracker.onload = function () {
var resampler = new Resample(this.result, 80, 80, function (data) {
var b64Data = data.split(',')[1];
var id = XMPP.crypto.createHash('sha1').update(atob(b64Data)).digest('hex');
console.log(id);
var id = crypto.createHash('sha1').update(atob(b64Data)).digest('hex');
app.storage.avatars.add({id: id, uri: data});
client.publishAvatar(id, b64Data, function (err, res) {
if (err) return;