1
0
mirror of https://github.com/moparisthebest/kaiwa synced 2024-11-23 01:32:18 -05:00
kaiwa/clientapp/models/contact.js

247 lines
8.1 KiB
JavaScript
Raw Normal View History

2013-08-29 23:38:28 -04:00
/*global XMPP, app, me, client*/
"use strict";
2013-08-29 23:38:28 -04:00
var _ = require('underscore');
2013-08-29 23:38:28 -04:00
var async = require('async');
var uuid = require('node-uuid');
var HumanModel = require('human-model');
2013-08-29 23:38:28 -04:00
var Resources = require('./resources');
var Messages = require('./messages');
var Message = require('./message');
var crypto = XMPP.crypto;
2013-09-05 19:53:23 -04:00
module.exports = HumanModel.define({
2013-08-29 23:38:28 -04:00
initialize: function (attrs) {
if (attrs.jid) {
this.id = attrs.jid;
2013-08-29 23:38:28 -04:00
}
this.setAvatar(attrs.avatarID);
this.resources.bind('add remove reset change', this.onResourceChange, this);
2013-08-29 23:38:28 -04:00
},
type: 'contact',
props: {
id: ['string', true, false],
avatarID: ['string', true, ''],
groups: ['array', true, []],
inRoster: ['bool', true, false],
2013-08-29 23:38:28 -04:00
jid: ['string', true],
name: ['string', true, ''],
owner: ['string', true, ''],
storageId: ['string', true, ''],
subscription: ['string', true, 'none']
2013-08-29 23:38:28 -04:00
},
session: {
activeContact: ['bool', true, false],
avatar: 'string',
chatState: ['string', true, 'gone'],
2013-09-13 16:55:46 -04:00
idleSince: 'string',
lastInteraction: 'date',
lastSentMessage: 'object',
2013-09-13 16:55:46 -04:00
lockedResource: 'string',
offlineStatus: ['string', true, ''],
2013-09-13 16:55:46 -04:00
show: ['string', true, 'offline'],
status: ['string', true, ''],
timezoneOffset: 'number',
topResource: 'string',
unreadCount: ['number', true, 0]
},
2013-08-29 23:38:28 -04:00
derived: {
displayName: {
deps: ['name', 'jid'],
fn: function () {
return this.name || this.jid;
2013-08-29 23:38:28 -04:00
}
},
2013-09-03 18:25:14 -04:00
formattedTZO: {
deps: ['timezoneOffset', 'displayName'],
2013-08-29 23:38:28 -04:00
fn: function () {
2013-09-03 18:25:14 -04:00
if (this.timezoneOffset !== undefined) {
var localTZO = (new Date()).getTimezoneOffset();
2013-09-13 16:55:46 -04:00
var diff = Math.abs(localTZO % (24 * 60) - this.timezoneOffset % (24 * 60)) / 60;
2013-09-03 18:25:14 -04:00
if (diff === 0) {
return this.displayName + ' is in the same timezone as you';
}
2013-09-17 14:16:08 -04:00
var dir = (localTZO > this.timezoneOffset) ? 'ahead of' : 'behind';
2013-09-03 18:25:14 -04:00
return this.displayName + ' is ' + diff + 'hrs ' + dir + ' you';
} else {
return '';
2013-08-29 23:38:28 -04:00
}
}
},
hasUnread: {
deps: ['unreadCount'],
fn: function () {
return this.unreadCount > 0;
}
2013-08-29 23:38:28 -04:00
}
},
collections: {
resources: Resources,
messages: Messages
},
setAvatar: function (id, type) {
var self = this;
if (!id) {
var gID = crypto.createHash('md5').update(this.jid).digest('hex');
self.avatar = 'https://gravatar.com/avatar/' + gID + '?s=30&d=mm';
return;
}
app.storage.avatars.get(id, function (err, avatar) {
if (err) {
if (!type) {
// We can't find the ID, and we don't know the type, so fallback.
var gID = crypto.createHash('md5').update(self.jid).digest('hex');
self.avatar = 'https://gravatar.com/avatar/' + gID + '?s=30&d=mm';
return;
}
app.whenConnected(function () {
client.getAvatar(self.jid, id, function (err, resp) {
if (err) return;
resp = resp.toJSON();
var avatarData = resp.pubsub.retrieve.item.avatarData;
var dataURI = 'data:' + type + ';base64,' + avatarData;
app.storage.avatars.add({id: id, uri: dataURI});
self.set({
avatar: dataURI,
avatarID: id
});
self.save();
});
});
} else {
self.set({
avatar: avatar.uri,
avatarID: avatar.id
});
self.save();
}
});
},
2013-09-13 16:55:46 -04:00
onLockedResourceChange: function () {
var res = this.resources.get(this.lockedResource);
if (res) {
this.status = res.status;
this.show = res.show || 'online';
this.timezoneOffset = res.timezoneOffset;
this.idleSince = res.idleSince;
}
},
onResourceChange: function () {
2013-08-29 23:38:28 -04:00
// Manually propagate change events for properties that
// depend on the resources collection.
this.resources.sort();
var res = this.resources.first();
if (res) {
this.offlineStatus = '';
2013-09-13 16:55:46 -04:00
this.topResource = res.id;
if (!this.lockedResource) {
this.status = res.status;
this.show = res.show || 'online';
this.timezoneOffset = res.timezoneOffset;
this.idleSince = res.idleSince;
}
2013-08-29 23:38:28 -04:00
} else {
this.topResource = undefined;
2013-09-09 19:13:42 -04:00
this.chatState = 'gone';
2013-09-13 16:55:46 -04:00
this.status = this.offlineStatus;
this.show = 'offline';
this.timezoneOffset = undefined;
this.idleSince = undefined;
2013-08-29 23:38:28 -04:00
}
this.lockedResource = undefined;
},
addMessage: function (message, notify) {
message.owner = me.jid.bare;
2013-09-17 14:22:42 -04:00
if (notify && (!this.activeContact || (this.activeContact && !me.hasFocus)) && message.from.bare === this.jid) {
this.unreadCount++;
app.notifier.show({
title: this.displayName,
description: message.body,
icon: this.avatar,
onclick: _.bind(app.navigate, app, '/chat/' + this.jid)
});
}
this.messages.add(message);
message.save();
var newInteraction = new Date(message.created);
if (!this.lastInteraction || this.lastInteraction < newInteraction) {
this.lastInteraction = newInteraction;
}
2013-08-29 23:38:28 -04:00
},
fetchHistory: function () {
var self = this;
app.whenConnected(function () {
var filter = {
count: 20,
before: true,
};
var lastMessage = self.messages.last();
if (lastMessage && lastMessage.archivedId) {
filter.after = lastMessage.archivedId;
}
2013-08-29 23:38:28 -04:00
client.getHistory({
with: self.jid,
start: self.lastInteraction,
rsm: filter
2013-08-29 23:38:28 -04:00
}, function (err, res) {
if (err) return;
var results = res.mamQuery.results || [];
results.reverse();
results.forEach(function (result) {
result = result.toJSON();
var msg = result.mam.forwarded.message;
if (!msg.id) {
msg.id = uuid.v4();
}
2013-08-29 23:38:28 -04:00
if (!msg.delay) {
msg.delay = result.mam.forwarded.delay;
}
if (msg.replace) {
var original = self.messages.get(msg.replace);
// Drop the message if editing a previous, but
// keep it if it didn't actually change an
// existing message.
if (original && original.correct(msg)) return;
2013-08-29 23:38:28 -04:00
}
var message = new Message(msg);
message.archivedId = result.mam.id;
self.addMessage(message, false);
2013-08-29 23:38:28 -04:00
});
});
});
},
save: function () {
if (!this.inRoster) return;
2013-08-29 23:38:28 -04:00
var data = {
2013-09-11 17:58:39 -04:00
storageId: this.storageId,
owner: this.owner,
2013-08-29 23:38:28 -04:00
jid: this.jid,
name: this.name,
groups: this.groups,
subscription: this.subscription,
avatarID: this.avatarID
};
app.storage.roster.add(data);
}
});