39:28ad6d3e2618
Anton Shestakov <av6@dwimlabs.net>, Wed, 23 Mar 2016 16:55:52 +0800
index: maintain only one contact with type 'self' This isn't done in an event handler of contacts collection because doing it in 'add' handler would trigger 'sort' event after the model has been added, but before its 'add' event has propagated, and that's dumb.

next change 41:260f3df482df
previous change 37:16b1f46f4cbf

js/index.js

Permissions: -rw-r--r--

Other formats: Feeds:
// Generated by CoffeeScript 1.10.0
(function() {
var $form, getContact, getContactProfile, getText, getVersion, onConnected, onGetVersion, onPresence, onProfileUpdate;
Strophe.addNamespace('VCARD_UPDATE', 'vcard-temp:x:update');
if (window.contacts == null) {
window.contacts = new Tram.Contacts();
}
if (window.contactsApp == null) {
window.contactsApp = new Tram.ContactsApp({
el: $('[data-app="contacts"]'),
collection: contacts
});
}
if (window.messages == null) {
window.messages = new Tram.Messages();
}
if (window.logApp == null) {
window.logApp = new Tram.LogApp({
el: $('[data-app="log"]'),
collection: messages
});
}
onConnected = function() {
X.conn.addHandler(onPresence, null, 'presence');
X.conn.addHandler(onProfileUpdate, Strophe.NS.VCARD_UPDATE, 'presence');
X.conn.addHandler(onGetVersion, Strophe.NS.VERSION, 'iq', 'get');
X.conn.send($pres().c('priority').t('1').up().c('status').t('Online').tree());
return getVersion();
};
getText = function(el) {
var i, len, node, ref, str;
if (!el) {
return null;
}
str = '';
if (el.childNodes.length === 0 && el.nodeType === Strophe.ElementType.TEXT) {
str += el.nodeValue;
}
ref = el.childNodes;
for (i = 0, len = ref.length; i < len; i++) {
node = ref[i];
if (node.nodeType === Strophe.ElementType.TEXT) {
str += node.nodeValue;
}
}
return str;
};
getVersion = function() {
var failcb, iq, okcb;
iq = $iq({
type: 'get',
id: X.conn.getUniqueId('version'),
to: Tram.config.domain
}).c('query', {
xmlns: Strophe.NS.VERSION
});
okcb = function(stanza) {
var delay, name, os, stamp, version;
name = getText(stanza.getElementsByTagName('name')[0]);
version = getText(stanza.getElementsByTagName('version')[0]);
os = getText(stanza.getElementsByTagName('os')[0]);
delay = stanza.getElementsByTagName('delay')[0];
stamp = delay ? new Date(delay.getAttribute('stamp')) : new Date();
return messages.add({
id: stanza.getAttribute('id'),
type: stanza.getAttribute('type'),
from: stanza.getAttribute('from'),
stamp: stamp,
cls: 'info',
name: name,
version: version,
os: os,
text: "connected to " + name + " " + version + " on " + os
});
};
failcb = function(stanza) {
return console.error("couldn't get version", stanza != null ? stanza.innerHTML : void 0);
};
return X.conn.sendIQ(iq.tree(), okcb, failcb, 5000);
};
onGetVersion = function(stanza) {
var from, id, iq;
id = stanza.getAttribute('id');
from = stanza.getAttribute('from');
iq = $iq({
to: from,
type: 'result',
id: id
}).c('query', {
xmlns: Strophe.NS.VERSION
}).c('name').t(Tram.info.client).up().c('version').t(Tram.info.version);
X.conn.send(iq.tree());
return true;
};
getContact = function(from) {
var contact, self;
contact = contacts.get(from);
if (contact != null) {
return contact;
}
self = from === X.conn.jid;
if (self) {
contacts.each(function(model) {
return model.set('type', 'contact');
});
}
contact = contacts.add({
jid: from,
bjid: Strophe.getBareJidFromJid(from),
type: self ? 'self' : 'contact'
});
getContactProfile(contact);
return contact;
};
getContactProfile = function(contact) {
var bjid, failcb, okcb;
okcb = function(stanza) {
var data, mime, vcard;
vcard = stanza.getElementsByTagName('vCard')[0];
if (!vcard) {
console.warn("no vcard in response", stanza);
return;
}
contact.set({
nickname: getText(vcard.querySelector('NICKNAME')),
fullname: getText(vcard.querySelector('FN')),
firstname: getText(vcard.querySelector('N > GIVEN')),
lastname: getText(vcard.querySelector('N > FAMILY'))
});
mime = getText(vcard.querySelector('PHOTO > TYPE'));
data = getText(vcard.querySelector('PHOTO > BINVAL'));
if (mime && data) {
return contact.set('avatar', {
mime: mime,
data: data
});
} else {
return contact.unset('avatar');
}
};
failcb = function(stanza) {
return console.warn("couldn't get vcard", stanza);
};
bjid = contact.get('bjid');
if (bjid === Strophe.getBareJidFromJid(X.conn.jid)) {
bjid = null;
}
return X.conn.vcard.get(okcb, bjid, failcb);
};
onPresence = function(stanza) {
var contact, delay, from, priority, ref, s, show, stamp, type;
from = stanza.getAttribute('from');
type = (ref = stanza.getAttribute('type')) != null ? ref : 'online';
if (type === 'subscribe') {
console.warn('not handling <presence type="subscribe">', stanza);
return true;
}
if (type === 'subscribed') {
console.warn('not handling <presence type="subscribed">', stanza);
return true;
}
if (type === 'error') {
console.error('got <presence type="error">', stanza);
return true;
}
delay = stanza.getElementsByTagName('delay')[0];
stamp = delay ? new Date(delay.getAttribute('stamp')) : new Date();
priority = stanza.getElementsByTagName('priority')[0];
priority = priority ? getText(priority) : '0';
show = stanza.getElementsByTagName('show')[0];
show = show ? getText(show) : void 0;
s = stanza.getElementsByTagName('status')[0];
s = s ? getText(s) : void 0;
contact = getContact(from);
contact.set({
presence: type,
show: show,
status: s
});
messages.add({
id: stanza.getAttribute('id'),
type: 'presence',
cls: 'presence',
from: from,
stamp: stamp,
contact: contact,
show: show,
priority: priority,
text: 'is now ' + (show != null ? show : type)
});
return true;
};
onProfileUpdate = function(stanza) {
var contact, from;
from = stanza.getAttribute('from');
contact = getContact(from);
getContactProfile(contact);
return true;
};
window.X = new Tram.XMPPInterface();
X.on('connecting', function() {
return $('[data-msg^="a/"]').addClass('uk-hidden');
});
X.on('authfail', function() {
return $('[data-msg="a/fail"]').removeClass('uk-hidden');
});
X.on('disconnected', function() {
$('[data-step="login"]').removeClass('uk-hidden');
return $('[data-step="main"]').addClass('uk-hidden');
});
X.on('connected attached', function() {
$('[data-step="login"]').addClass('uk-hidden');
$('[data-step="main"]').removeClass('uk-hidden');
return onConnected();
});
$('button[data-disconnect]').on('click', function() {
return X.disconnect('Logged out');
});
$(window).on('beforeunload unload', function() {
return X.disconnect('Window closed');
});
$form = $('[data-form="connect"]');
$form.find('input').on('keydown', function(e) {
var $next, index;
if ((!this.required || this.value !== '') && e.keyCode === 13) {
e.preventDefault();
index = $form.find('input').index(this);
$next = $form.find('input').eq(index + 1);
if ($next.length !== 0) {
return $next.focus();
} else {
return $form.find('button').trigger('click');
}
}
});
$form.find('button').on('click', function(e) {
var ok;
e.preventDefault();
ok = true;
Tram.validation.unsetError($('#username, #password'));
ok &= Tram.validation.validateRequired($('#username'), true);
ok &= Tram.validation.validateRequired($('#password'));
if (ok) {
return X.connect($('#username').val().trim(), $('#password').val());
}
});
window.setInterval(function() {
return $('time[datetime]').each(function() {
var $this;
$this = $(this);
return $this.text(moment($this.attr('datetime')).fromNow());
});
}, 15 * 1000);
}).call(this);
//# sourceMappingURL=index.js.map