forked from friendica/deprecated-addons
Jappixmini added
This commit is contained in:
parent
56eebfb55d
commit
1cc8afc83f
265 changed files with 98516 additions and 0 deletions
1075
jappixmini/jappix/js/presence.js
Normal file
1075
jappixmini/jappix/js/presence.js
Normal file
|
|
@ -0,0 +1,1075 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
These are the presence JS scripts for Jappix
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Vanaryon
|
||||
Last revision: 23/09/11
|
||||
|
||||
*/
|
||||
|
||||
// Sends the user first presence
|
||||
var FIRST_PRESENCE_SENT = false;
|
||||
|
||||
function firstPresence(checksum) {
|
||||
logThis('First presence sent.', 3);
|
||||
|
||||
// Jappix is now ready: change the title
|
||||
pageTitle('talk');
|
||||
|
||||
// Anonymous check
|
||||
var is_anonymous = isAnonymous();
|
||||
|
||||
// Update our marker
|
||||
FIRST_PRESENCE_SENT = true;
|
||||
|
||||
// Try to use the last status message
|
||||
var status = getDB('options', 'presence-status');
|
||||
|
||||
if(!status)
|
||||
status = '';
|
||||
|
||||
// We tell the world that we are online
|
||||
if(!is_anonymous)
|
||||
sendPresence('', '', '', status, checksum);
|
||||
|
||||
// Any status to apply?
|
||||
if(status)
|
||||
$('#presence-status').val(status);
|
||||
|
||||
// Enable the presence picker
|
||||
$('#presence-status').removeAttr('disabled');
|
||||
$('#my-infos .f-presence a.picker').removeClass('disabled');
|
||||
|
||||
// We set the last activity stamp
|
||||
PRESENCE_LAST_ACTIVITY = getTimeStamp();
|
||||
|
||||
// We store our presence
|
||||
setDB('presence-show', 1, 'available');
|
||||
|
||||
// Not anonymous
|
||||
if(!is_anonymous) {
|
||||
// We get the stored bookmarks (because of the photo hash and some other stuffs, we must get it later)
|
||||
getStorage(NS_BOOKMARKS);
|
||||
|
||||
// We open a new chat if a XMPP link was submitted
|
||||
if((parent.location.hash != '#OK') && LINK_VARS['x']) {
|
||||
// A link is submitted in the URL
|
||||
xmppLink(LINK_VARS['x']);
|
||||
|
||||
// Set a OK status
|
||||
parent.location.hash = 'OK';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles incoming presence packets
|
||||
function handlePresence(presence) {
|
||||
// We define everything needed here
|
||||
var from = fullXID(getStanzaFrom(presence));
|
||||
var hash = hex_md5(from);
|
||||
var node = presence.getNode();
|
||||
var xid = bareXID(from);
|
||||
var xidHash = hex_md5(xid);
|
||||
|
||||
// We get the type content
|
||||
var type = presence.getType();
|
||||
if(!type)
|
||||
type = '';
|
||||
|
||||
// We get the priority content
|
||||
var priority = presence.getPriority() + '';
|
||||
if(!priority || (type == 'error'))
|
||||
priority = '0';
|
||||
|
||||
// We get the show content
|
||||
var show = presence.getShow();
|
||||
if(!show || (type == 'error'))
|
||||
show = '';
|
||||
|
||||
// We get the status content
|
||||
var status = presence.getStatus();
|
||||
if(!status || (type == 'error'))
|
||||
status = '';
|
||||
|
||||
// We get the photo content
|
||||
var photo = $(node).find('x[xmlns=' + NS_VCARD_P + ']:first photo');
|
||||
var checksum = photo.text();
|
||||
var hasPhoto = photo.size();
|
||||
|
||||
if(hasPhoto && (type != 'error'))
|
||||
hasPhoto = 'true';
|
||||
else
|
||||
hasPhoto = 'false';
|
||||
|
||||
// We get the CAPS content
|
||||
var caps = $(node).find('c[xmlns=' + NS_CAPS + ']:first').attr('ver');
|
||||
if(!caps || (type == 'error'))
|
||||
caps = '';
|
||||
|
||||
// This presence comes from another resource of my account with a difference avatar checksum
|
||||
if((xid == getXID()) && (hasPhoto == 'true') && (checksum != getDB('checksum', 1)))
|
||||
getAvatar(getXID(), 'force', 'true', 'forget');
|
||||
|
||||
// This presence comes from a groupchat
|
||||
if(isPrivate(xid)) {
|
||||
var x_muc = $(node).find('x[xmlns=' + NS_MUC_USER + ']:first');
|
||||
var item = x_muc.find('item');
|
||||
var affiliation = item.attr('affiliation');
|
||||
var role = item.attr('role');
|
||||
var reason = item.find('reason').text();
|
||||
var iXID = item.attr('jid');
|
||||
var iNick = item.attr('nick');
|
||||
var nick = thisResource(from);
|
||||
var messageTime = getCompleteTime();
|
||||
var notInitial = true;
|
||||
|
||||
// Read the status code
|
||||
var status_code = new Array();
|
||||
|
||||
x_muc.find('status').each(function() {
|
||||
status_code.push(parseInt($(this).attr('code')));
|
||||
});
|
||||
|
||||
// If this is an initial presence (when user join the room)
|
||||
if(exists('#' + xidHash + '[data-initial=true]'))
|
||||
notInitial = false;
|
||||
|
||||
// If one user is quitting
|
||||
if(type && (type == 'unavailable')) {
|
||||
displayMucPresence(from, xidHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, notInitial);
|
||||
|
||||
removeDB('presence', from);
|
||||
}
|
||||
|
||||
// If one user is joining
|
||||
else {
|
||||
// Fixes M-Link first presence bug (missing ID!)
|
||||
if((nick == getMUCNick(xidHash)) && (presence.getID() == null) && !exists('#page-engine #' + xidHash + ' .list .' + hash)) {
|
||||
handleMUC(presence);
|
||||
|
||||
logThis('Passed M-Link MUC first presence handling.', 2);
|
||||
}
|
||||
|
||||
else {
|
||||
displayMucPresence(from, xidHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, notInitial);
|
||||
|
||||
var xml = '<presence from="' + encodeQuotes(from) + '"><priority>' + priority.htmlEnc() + '</priority><show>' + show.htmlEnc() + '</show><type>' + type.htmlEnc() + '</type><status>' + status.htmlEnc() + '</status><avatar>' + hasPhoto.htmlEnc() + '</avatar><checksum>' + checksum.htmlEnc() + '</checksum><caps>' + caps.htmlEnc() + '</caps></presence>';
|
||||
|
||||
setDB('presence', from, xml);
|
||||
}
|
||||
}
|
||||
|
||||
// Manage the presence
|
||||
presenceFunnel(from, hash);
|
||||
}
|
||||
|
||||
// This presence comes from an user or a gateway
|
||||
else {
|
||||
// Subscribed & unsubscribed stanzas
|
||||
if((type == 'subscribed') || (type == 'unsubscribed'))
|
||||
return;
|
||||
|
||||
// Subscribe stanza
|
||||
else if(type == 'subscribe') {
|
||||
// This is a buddy we can safely authorize, because we added him to our roster
|
||||
if(exists('#buddy-list .buddy[data-xid=' + escape(xid) + ']'))
|
||||
acceptSubscribe(xid);
|
||||
|
||||
// We do not know this entity, we'd be better ask the user
|
||||
else {
|
||||
// Get the nickname
|
||||
var nickname = $(node).find('nick[xmlns=' + NS_NICK + ']:first').text();
|
||||
|
||||
// New notification
|
||||
newNotification('subscribe', xid, [xid, nickname], status);
|
||||
}
|
||||
}
|
||||
|
||||
// Unsubscribe stanza
|
||||
else if(type == 'unsubscribe')
|
||||
sendRoster(xid, 'remove');
|
||||
|
||||
// Other stanzas
|
||||
else {
|
||||
// Unavailable/error presence
|
||||
if(type == 'unavailable')
|
||||
removeDB('presence', from);
|
||||
|
||||
// Other presence (available, subscribe...)
|
||||
else {
|
||||
var xml = '<presence from="' + encodeQuotes(from) + '"><priority>' + priority.htmlEnc() + '</priority><show>' + show.htmlEnc() + '</show><type>' + type.htmlEnc() + '</type><status>' + status.htmlEnc() + '</status><avatar>' + hasPhoto.htmlEnc() + '</avatar><checksum>' + checksum.htmlEnc() + '</checksum><caps>' + caps.htmlEnc() + '</caps></presence>';
|
||||
|
||||
setDB('presence', from, xml);
|
||||
}
|
||||
|
||||
// We manage the presence
|
||||
presenceFunnel(xid, xidHash);
|
||||
|
||||
// We display the presence in the current chat
|
||||
if(exists('#' + xidHash)) {
|
||||
var dStatus = filterStatus(xid, status, false);
|
||||
|
||||
if(dStatus)
|
||||
dStatus = ' (' + dStatus + ')';
|
||||
|
||||
// Generate the presence-in-chat code
|
||||
var dName = getBuddyName(from).htmlEnc();
|
||||
var dBody = dName + ' (' + from + ') ' + _e("is now") + ' ' + humanShow(show, type) + dStatus;
|
||||
|
||||
// Check whether it has been previously displayed
|
||||
var can_display = true;
|
||||
|
||||
if($('#' + xidHash + ' .one-line.system-message:last').html() == dBody)
|
||||
can_display = false;
|
||||
|
||||
if(can_display)
|
||||
displayMessage('chat', xid, xidHash, dName, dBody, getCompleteTime(), getTimeStamp(), 'system-message', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For logger
|
||||
if(!show) {
|
||||
if(!type)
|
||||
show = 'available';
|
||||
else
|
||||
show = 'unavailable';
|
||||
}
|
||||
|
||||
logThis('Presence received: ' + show + ', from ' + from);
|
||||
}
|
||||
|
||||
// Displays a MUC presence
|
||||
function displayMucPresence(from, roomHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, initial) {
|
||||
// Generate the values
|
||||
var thisUser = '#page-engine #' + roomHash + ' .list .' + hash;
|
||||
var thisPrivate = $('#' + hash + ' .message-area');
|
||||
var nick_html = nick.htmlEnc();
|
||||
var real_xid = '';
|
||||
var write = nick_html + ' ';
|
||||
var notify = false;
|
||||
|
||||
// Reset data?
|
||||
if(!role)
|
||||
role = 'participant';
|
||||
if(!affiliation)
|
||||
affiliation = 'none';
|
||||
|
||||
// Must update the role?
|
||||
if(exists(thisUser) && (($(thisUser).attr('data-role') != role) || ($(thisUser).attr('data-affiliation') != affiliation)))
|
||||
$(thisUser).remove();
|
||||
|
||||
// Any XID submitted?
|
||||
if(iXID) {
|
||||
real_xid = ' data-realxid="' + iXID + '"';
|
||||
iXID = bareXID(iXID);
|
||||
write += ' (<a onclick="return checkChatCreate(\'' + encodeOnclick(iXID) + '\', \'chat\');" href="xmpp:' + encodeOnclick(iXID) + '">' + iXID + '</a>) ';
|
||||
}
|
||||
|
||||
// User does not exists yet
|
||||
if(!exists(thisUser) && (!type || (type == 'available'))) {
|
||||
var myself = '';
|
||||
|
||||
// Is it me?
|
||||
if(nick == getMUCNick(roomHash)) {
|
||||
// Enable the room
|
||||
$('#' + roomHash + ' .message-area').removeAttr('disabled');
|
||||
|
||||
// Marker
|
||||
myself = ' myself';
|
||||
}
|
||||
|
||||
// Set the user in the MUC list
|
||||
$('#' + roomHash + ' .list .' + role + ' .title').after(
|
||||
'<div class="user ' + hash + myself + '" data-xid="' + encodeQuotes(from) + '" data-nick="' + escape(nick) + '"' + real_xid + ' data-role="' + encodeQuotes(role) + '" data-affiliation="' + encodeQuotes(affiliation) + '">' +
|
||||
'<div class="name talk-images available">' + nick_html + '</div>' +
|
||||
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Click event
|
||||
if(nick != getMUCNick(roomHash))
|
||||
$(thisUser).live('click', function() {
|
||||
checkChatCreate(from, 'private');
|
||||
});
|
||||
|
||||
// We tell the user that someone entered the room
|
||||
if(!initial) {
|
||||
notify = true;
|
||||
write += _e("joined the chat room");
|
||||
|
||||
// Any status?
|
||||
if(status)
|
||||
write += ' (' + filterThisMessage(status, nick_html, true) + ')';
|
||||
else
|
||||
write += ' (' + _e("no status") + ')';
|
||||
}
|
||||
|
||||
// Enable the private chat input
|
||||
thisPrivate.removeAttr('disabled');
|
||||
}
|
||||
|
||||
else if((type == 'unavailable') || (type == 'error')) {
|
||||
// Is it me?
|
||||
if(nick == getMUCNick(roomHash)) {
|
||||
$(thisUser).remove();
|
||||
|
||||
// Disable the groupchat input
|
||||
$('#' + roomHash + ' .message-area').attr('disabled', true);
|
||||
|
||||
// Remove all the groupchat users
|
||||
$('#' + roomHash + ' .list .user').remove();
|
||||
}
|
||||
|
||||
// Someone has been kicked or banned?
|
||||
if(existArrayValue(status_code, 301) || existArrayValue(status_code, 307)) {
|
||||
$(thisUser).remove();
|
||||
notify = true;
|
||||
|
||||
// Kicked?
|
||||
if(existArrayValue(status_code, 307))
|
||||
write += _e("has been kicked");
|
||||
|
||||
// Banned?
|
||||
if(existArrayValue(status_code, 301))
|
||||
write += _e("has been banned");
|
||||
|
||||
// Any reason?
|
||||
if(reason)
|
||||
write += ' (' + filterThisMessage(reason, nick_html, true) + ')';
|
||||
else
|
||||
write += ' (' + _e("no reason") + ')';
|
||||
}
|
||||
|
||||
// Nickname change?
|
||||
else if(existArrayValue(status_code, 303) && iNick) {
|
||||
notify = true;
|
||||
write += printf(_e("changed his/her nickname to %s"), iNick.htmlEnc());
|
||||
|
||||
// New values
|
||||
var new_xid = cutResource(from) + '/' + iNick;
|
||||
var new_hash = hex_md5(new_xid);
|
||||
var new_class = 'user ' + new_hash;
|
||||
|
||||
if($(thisUser).hasClass('myself'))
|
||||
new_class += ' myself';
|
||||
|
||||
// Die the click event
|
||||
$(thisUser).die('click');
|
||||
|
||||
// Change to the new nickname
|
||||
$(thisUser).attr('data-nick', iNick)
|
||||
.attr('data-xid', new_xid)
|
||||
.find('.name').text(iNick);
|
||||
|
||||
// Change the user class
|
||||
$(thisUser).attr('class', new_class);
|
||||
|
||||
// New click event
|
||||
$('#page-engine #' + roomHash + ' .list .' + new_hash).live('click', function() {
|
||||
checkChatCreate(new_xid, 'private');
|
||||
});
|
||||
}
|
||||
|
||||
// We tell the user that someone left the room
|
||||
else if(!initial) {
|
||||
$(thisUser).remove();
|
||||
notify = true;
|
||||
write += _e("left the chat room");
|
||||
|
||||
// Any status?
|
||||
if(status)
|
||||
write += ' (' + filterThisMessage(status, nick_html, true) + ')';
|
||||
else
|
||||
write += ' (' + _e("no status") + ')';
|
||||
}
|
||||
|
||||
// Disable the private chat input
|
||||
thisPrivate.attr('disabled', true);
|
||||
}
|
||||
|
||||
// Must notify something
|
||||
if(notify)
|
||||
displayMessage('groupchat', from, roomHash, nick_html, write, messageTime, getTimeStamp(), 'system-message', false);
|
||||
|
||||
// Set the good status show icon
|
||||
switch(show) {
|
||||
case 'chat':
|
||||
case 'away':
|
||||
case 'xa':
|
||||
case 'dnd':
|
||||
break;
|
||||
|
||||
default:
|
||||
show = 'available';
|
||||
break;
|
||||
}
|
||||
|
||||
$(thisUser + ' .name').attr('class', 'name talk-images ' + show);
|
||||
|
||||
// Set the good status text
|
||||
var uTitle = nick;
|
||||
|
||||
// Any XID to add?
|
||||
if(iXID)
|
||||
uTitle += ' (' + iXID + ')';
|
||||
|
||||
// Any status to add?
|
||||
if(status)
|
||||
uTitle += ' - ' + status;
|
||||
|
||||
$(thisUser).attr('title', uTitle);
|
||||
|
||||
// Show or hide the role category, depending of its content
|
||||
$('#' + roomHash + ' .list .role').each(function() {
|
||||
if($(this).find('.user').size())
|
||||
$(this).show();
|
||||
else
|
||||
$(this).hide();
|
||||
});
|
||||
}
|
||||
|
||||
// Filters a given status
|
||||
function filterStatus(xid, status, cut) {
|
||||
var dStatus = '';
|
||||
|
||||
if(!status)
|
||||
status = '';
|
||||
|
||||
else {
|
||||
if(cut)
|
||||
dStatus = truncate(status, 50);
|
||||
else
|
||||
dStatus = status;
|
||||
|
||||
dStatus = filterThisMessage(dStatus, getBuddyName(xid).htmlEnc(), true);
|
||||
}
|
||||
|
||||
return dStatus;
|
||||
}
|
||||
|
||||
// Displays a user's presence
|
||||
function displayPresence(value, type, show, status, hash, xid, avatar, checksum, caps) {
|
||||
// Display the presence in the roster
|
||||
var path = '#buddy-list .' + hash;
|
||||
var buddy = $('#buddy-list .content .' + hash);
|
||||
var dStatus = filterStatus(xid, status, false);
|
||||
var tStatus = encodeQuotes(status);
|
||||
var biStatus;
|
||||
|
||||
// The buddy presence behind his name
|
||||
$(path + ' .name .buddy-presence').replaceWith('<p class="buddy-presence talk-images ' + type + '">' + value + '</p>');
|
||||
|
||||
// The buddy presence in the buddy infos
|
||||
if(dStatus)
|
||||
biStatus = dStatus;
|
||||
else
|
||||
biStatus = value;
|
||||
|
||||
$(path + ' .bi-status').replaceWith('<p class="bi-status talk-images ' + type + '" title="' + tStatus + '">' + biStatus + '</p>');
|
||||
|
||||
// When the buddy disconnect himself, we hide him
|
||||
if((type == 'unavailable') || (type == 'error')) {
|
||||
// Set a special class to the buddy
|
||||
buddy.addClass('hidden-buddy');
|
||||
|
||||
// No filtering is launched?
|
||||
if(!SEARCH_FILTERED)
|
||||
buddy.hide();
|
||||
|
||||
// All the buddies are shown?
|
||||
if(BLIST_ALL)
|
||||
buddy.show();
|
||||
|
||||
// Chat stuffs
|
||||
if(exists('#' + hash)) {
|
||||
// Remove the chatstate stuffs
|
||||
resetChatState(hash);
|
||||
$('#' + hash + ' .chatstate').remove();
|
||||
$('#' + hash + ' .message-area').removeAttr('data-chatstates');
|
||||
|
||||
// Get the buddy avatar (only if a chat is opened)
|
||||
getAvatar(xid, 'cache', 'true', 'forget');
|
||||
}
|
||||
}
|
||||
|
||||
// If the buddy is online
|
||||
else {
|
||||
// When the buddy is online, we show it
|
||||
buddy.removeClass('hidden-buddy');
|
||||
|
||||
// No filtering is launched?
|
||||
if(!SEARCH_FILTERED)
|
||||
buddy.show();
|
||||
|
||||
// Get the online buddy avatar if not a gateway
|
||||
getAvatar(xid, 'cache', avatar, checksum);
|
||||
}
|
||||
|
||||
// Display the presence in the chat
|
||||
if(exists('#' + hash)) {
|
||||
// We generate a well formed status message
|
||||
if(dStatus) {
|
||||
// No need to write the same status two times
|
||||
if(dStatus == value)
|
||||
dStatus = '';
|
||||
else
|
||||
dStatus = ' (' + dStatus + ')';
|
||||
}
|
||||
|
||||
// We show the presence value
|
||||
$('#' + hash + ' .bc-infos').replaceWith('<p class="bc-infos" title="' + tStatus + '"><span class="' + type + ' show talk-images">' + value + '</span>' + dStatus + '</p>');
|
||||
|
||||
// Process the new status position
|
||||
adaptChatPresence(hash);
|
||||
|
||||
// Get the disco#infos for this user
|
||||
var highest = getHighestResource(xid);
|
||||
|
||||
if(highest)
|
||||
getDiscoInfos(highest, caps);
|
||||
else
|
||||
displayDiscoInfos(xid, '');
|
||||
}
|
||||
|
||||
// Display the presence in the switcher
|
||||
if(exists('#page-switch .' + hash))
|
||||
$('#page-switch .' + hash + ' .icon').removeClass('available unavailable error away busy').addClass(type);
|
||||
|
||||
// Update roster groups
|
||||
if(!SEARCH_FILTERED)
|
||||
updateGroups();
|
||||
else
|
||||
funnelFilterBuddySearch();
|
||||
}
|
||||
|
||||
// Process the chat presence position
|
||||
function adaptChatPresence(hash) {
|
||||
// Get values
|
||||
var pep_numb = $('#' + hash + ' .bc-pep').find('a').size();
|
||||
|
||||
// Process the right position
|
||||
var presence_right = 12;
|
||||
|
||||
if(pep_numb)
|
||||
presence_right = (pep_numb * 20) + 18;
|
||||
|
||||
// Apply the right position
|
||||
$('#' + hash + ' p.bc-infos').css('right', presence_right);
|
||||
}
|
||||
|
||||
// Convert the presence "show" element into a human-readable output
|
||||
function humanShow(show, type) {
|
||||
if(type == 'unavailable')
|
||||
show = _e("Unavailable");
|
||||
|
||||
else if(type == 'error')
|
||||
show = _e("Error");
|
||||
|
||||
else {
|
||||
switch(show) {
|
||||
case 'chat':
|
||||
show = _e("Talkative");
|
||||
break;
|
||||
|
||||
case 'away':
|
||||
show = _e("Away");
|
||||
break;
|
||||
|
||||
case 'xa':
|
||||
show = _e("Not available");
|
||||
break;
|
||||
|
||||
case 'dnd':
|
||||
show = _e("Busy");
|
||||
break;
|
||||
|
||||
default:
|
||||
show = _e("Available");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return show;
|
||||
}
|
||||
|
||||
// Makes the presence data go in the right way
|
||||
function presenceIA(type, show, status, hash, xid, avatar, checksum, caps) {
|
||||
// Is there a status defined?
|
||||
if(!status)
|
||||
status = humanShow(show, type);
|
||||
|
||||
// Then we can handle the events
|
||||
if(type == 'error')
|
||||
displayPresence(_e("Error"), 'error', show, status, hash, xid, avatar, checksum, caps);
|
||||
|
||||
else if(type == 'unavailable')
|
||||
displayPresence(_e("Unavailable"), 'unavailable', show, status, hash, xid, avatar, checksum, caps);
|
||||
|
||||
else {
|
||||
switch(show) {
|
||||
case 'chat':
|
||||
displayPresence(_e("Talkative"), 'available', show, status, hash, xid, avatar, checksum, caps);
|
||||
break;
|
||||
|
||||
case 'away':
|
||||
displayPresence(_e("Away"), 'away', show, status, hash, xid, avatar, checksum, caps);
|
||||
break;
|
||||
|
||||
case 'xa':
|
||||
displayPresence(_e("Not available"), 'busy', show, status, hash, xid, avatar, checksum, caps);
|
||||
break;
|
||||
|
||||
case 'dnd':
|
||||
displayPresence(_e("Busy"), 'busy', show, status, hash, xid, avatar, checksum, caps);
|
||||
break;
|
||||
|
||||
default:
|
||||
displayPresence(_e("Available"), 'available', show, status, hash, xid, avatar, checksum, caps);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the highest resource priority for an user
|
||||
function highestPriority(xid) {
|
||||
var maximum = null;
|
||||
var selector, priority, type, highest;
|
||||
|
||||
// This is a groupchat presence
|
||||
if(xid.indexOf('/') != -1)
|
||||
highest = XMLFromString(getDB('presence', xid));
|
||||
|
||||
// This is a "normal" presence: get the highest priority resource
|
||||
else {
|
||||
for(var i = 0; i < sessionStorage.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = sessionStorage.key(i);
|
||||
|
||||
// If the pointer is on a stored presence
|
||||
if(explodeThis('_', current, 0) == 'presence') {
|
||||
// Get the current XID
|
||||
var now = bareXID(explodeThis('_', current, 1));
|
||||
|
||||
// If the current XID equals the asked XID
|
||||
if(now == xid) {
|
||||
var xml = XMLFromString(sessionStorage.getItem(current));
|
||||
var priority = parseInt($(xml).find('priority').text());
|
||||
|
||||
// Higher priority
|
||||
if((priority >= maximum) || (maximum == null)) {
|
||||
maximum = priority;
|
||||
highest = xml;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The user might be offline if no highest
|
||||
if(!highest)
|
||||
highest = XMLFromString('<presence><type>unavailable</type></presence>');
|
||||
|
||||
return highest;
|
||||
}
|
||||
|
||||
// Gets the resource from a XID which has the highest priority
|
||||
function getHighestResource(xid) {
|
||||
var xml = $(highestPriority(xid));
|
||||
var highest = xml.find('presence').attr('from');
|
||||
var type = xml.find('type').text();
|
||||
|
||||
// If the use is online, we can return its highest resource
|
||||
if(!type || (type == 'available') || (type == 'null'))
|
||||
return highest;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Makes something easy to process for the presence IA
|
||||
function presenceFunnel(xid, hash) {
|
||||
// Get the highest priority presence value
|
||||
var xml = $(highestPriority(xid));
|
||||
var type = xml.find('type').text();
|
||||
var show = xml.find('show').text();
|
||||
var status = xml.find('status').text();
|
||||
var avatar = xml.find('avatar').text();
|
||||
var checksum = xml.find('checksum').text();
|
||||
var caps = xml.find('caps').text();
|
||||
|
||||
// Display the presence with that stored value
|
||||
if(!type && !show)
|
||||
presenceIA('', 'available', status, hash, xid, avatar, checksum, caps);
|
||||
else
|
||||
presenceIA(type, show, status, hash, xid, avatar, checksum, caps);
|
||||
}
|
||||
|
||||
// Sends a defined presence packet
|
||||
function sendPresence(to, type, show, status, checksum, limit_history, password, handle) {
|
||||
// Get some stuffs
|
||||
var priority = getDB('priority', 1);
|
||||
|
||||
if(!priority)
|
||||
priority = '1';
|
||||
if(!checksum)
|
||||
checksum = getDB('checksum', 1);
|
||||
if(show == 'available')
|
||||
show = '';
|
||||
if(type == 'available')
|
||||
type = '';
|
||||
|
||||
// New presence
|
||||
var presence = new JSJaCPresence();
|
||||
|
||||
// Avoid "null" or "none" if nothing stored
|
||||
if(!checksum || (checksum == 'none'))
|
||||
checksum = '';
|
||||
|
||||
// Presence headers
|
||||
if(to)
|
||||
presence.setTo(to);
|
||||
if(type)
|
||||
presence.setType(type);
|
||||
if(show)
|
||||
presence.setShow(show);
|
||||
if(status)
|
||||
presence.setStatus(status);
|
||||
|
||||
presence.setPriority(priority);
|
||||
|
||||
// CAPS (entity capabilities)
|
||||
presence.appendNode('c', {'xmlns': NS_CAPS, 'hash': 'sha-1', 'node': 'https://www.jappix.com/', 'ver': myCaps()});
|
||||
|
||||
// Nickname
|
||||
var nickname = getName();
|
||||
|
||||
if(nickname)
|
||||
presence.appendNode('nick', {'xmlns': NS_NICK}, nickname);
|
||||
|
||||
// vcard-temp:x:update node
|
||||
var x = presence.appendNode('x', {'xmlns': NS_VCARD_P});
|
||||
x.appendChild(presence.buildNode('photo', {'xmlns': NS_VCARD_P}, checksum));
|
||||
|
||||
// MUC X data
|
||||
if(limit_history || password) {
|
||||
var xMUC = presence.appendNode('x', {'xmlns': NS_MUC});
|
||||
|
||||
// Max messages age (for MUC)
|
||||
if(limit_history)
|
||||
xMUC.appendChild(presence.buildNode('history', {'maxstanzas': 20, 'seconds': 86400, 'xmlns': NS_MUC}));
|
||||
|
||||
// Room password
|
||||
if(password)
|
||||
xMUC.appendChild(presence.buildNode('password', {'xmlns': NS_MUC}, password));
|
||||
}
|
||||
|
||||
// If away, send a last activity time
|
||||
if((show == 'away') || (show == 'xa')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0256.html */
|
||||
|
||||
presence.appendNode(presence.buildNode('query', {
|
||||
'xmlns': NS_LAST,
|
||||
'seconds': getPresenceLast()
|
||||
}));
|
||||
}
|
||||
|
||||
// Else, set a new last activity stamp
|
||||
else
|
||||
PRESENCE_LAST_ACTIVITY = getTimeStamp();
|
||||
|
||||
// Send the presence packet
|
||||
if(handle)
|
||||
con.send(presence, handle);
|
||||
else
|
||||
con.send(presence);
|
||||
|
||||
if(!type)
|
||||
type = 'available';
|
||||
|
||||
logThis('Presence sent: ' + type, 3);
|
||||
}
|
||||
|
||||
// Performs all the actions to get the presence data
|
||||
function presenceSend(checksum, autoidle) {
|
||||
// We get the values of the inputs
|
||||
var show = getUserShow();
|
||||
var status = getUserStatus();
|
||||
|
||||
// Send the presence
|
||||
if(!isAnonymous())
|
||||
sendPresence('', '', show, status, checksum);
|
||||
|
||||
// We set the good icon
|
||||
presenceIcon(show);
|
||||
|
||||
// We store our presence
|
||||
if(!autoidle)
|
||||
setDB('presence-show', 1, show);
|
||||
|
||||
// We send the presence to our active MUC
|
||||
$('.page-engine-chan[data-type=groupchat]').each(function() {
|
||||
var tmp_nick = $(this).attr('data-nick');
|
||||
|
||||
if(!tmp_nick)
|
||||
return;
|
||||
|
||||
var room = unescape($(this).attr('data-xid'));
|
||||
var nick = unescape(tmp_nick);
|
||||
|
||||
// Must re-initialize?
|
||||
if(RESUME)
|
||||
getMUC(room, nick);
|
||||
|
||||
// Not disabled?
|
||||
else if(!$(this).find('.message-area').attr('disabled'))
|
||||
sendPresence(room + '/' + nick, '', show, status, '', true);
|
||||
});
|
||||
}
|
||||
|
||||
// Changes the presence icon
|
||||
function presenceIcon(value) {
|
||||
$('#my-infos .f-presence a.picker').attr('data-value', value);
|
||||
}
|
||||
|
||||
// Sends a subscribe stanza
|
||||
function sendSubscribe(to, type) {
|
||||
var status = '';
|
||||
|
||||
// Subscribe request?
|
||||
if(type == 'subscribe')
|
||||
status = printf(_e("Hi, I am %s, I would like to add you as my friend."), getName());
|
||||
|
||||
sendPresence(to, type, '', status);
|
||||
}
|
||||
|
||||
// Accepts the subscription from another entity
|
||||
function acceptSubscribe(xid, name) {
|
||||
// We update our chat
|
||||
$('#' + hex_md5(xid) + ' .tools-add').hide();
|
||||
|
||||
// We send a subsribed presence (to confirm)
|
||||
sendSubscribe(xid, 'subscribed');
|
||||
|
||||
// We send a subscription request (subscribe both sides)
|
||||
sendSubscribe(xid, 'subscribe');
|
||||
|
||||
// Specify the buddy name (if any)
|
||||
if(name)
|
||||
sendRoster(xid, '', name)
|
||||
}
|
||||
|
||||
// Sends automatic away presence
|
||||
var AUTO_IDLE = false;
|
||||
|
||||
function autoIdle() {
|
||||
// Not connected?
|
||||
if(!isConnected())
|
||||
return;
|
||||
|
||||
// Stop if an xa presence was set manually
|
||||
var last_presence = getUserShow();
|
||||
|
||||
if(!AUTO_IDLE && ((last_presence == 'away') || (last_presence == 'xa')))
|
||||
return;
|
||||
|
||||
var idle_presence;
|
||||
var activity_limit;
|
||||
|
||||
// Can we extend to auto extended away mode (20 minutes)?
|
||||
if(AUTO_IDLE && (last_presence == 'away')) {
|
||||
idle_presence = 'xa';
|
||||
activity_limit = 1200;
|
||||
}
|
||||
|
||||
// We must set the user to auto-away (10 minutes)
|
||||
else {
|
||||
idle_presence = 'away';
|
||||
activity_limit = 600;
|
||||
}
|
||||
|
||||
// The user is really inactive and has set another presence than extended away
|
||||
if(((!AUTO_IDLE && (last_presence != 'away')) || (AUTO_IDLE && (last_presence == 'away'))) && (getLastActivity() >= activity_limit)) {
|
||||
// Then tell we use an auto presence
|
||||
AUTO_IDLE = true;
|
||||
|
||||
// Get the old status message
|
||||
var status = getDB('options', 'presence-status');
|
||||
|
||||
if(!status)
|
||||
status = '';
|
||||
|
||||
// Change the presence input
|
||||
$('#my-infos .f-presence a.picker').attr('data-value', idle_presence);
|
||||
$('#presence-status').val(status);
|
||||
|
||||
// Then send the xa presence
|
||||
presenceSend('', true);
|
||||
|
||||
logThis('Auto-idle presence sent: ' + idle_presence, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Restores the old presence on a document bind
|
||||
function eventIdle() {
|
||||
// If we were idle, restore our old presence
|
||||
if(AUTO_IDLE) {
|
||||
// Get the values
|
||||
var show = getDB('presence-show', 1);
|
||||
var status = getDB('options', 'presence-status');
|
||||
|
||||
// Change the presence input
|
||||
$('#my-infos .f-presence a.picker').attr('data-value', show);
|
||||
$('#presence-status').val(status);
|
||||
$('#presence-status').placeholder();
|
||||
|
||||
// Then restore the old presence
|
||||
presenceSend('', true);
|
||||
|
||||
if(!show)
|
||||
show = 'available';
|
||||
|
||||
logThis('Presence restored: ' + show, 3);
|
||||
}
|
||||
|
||||
// Apply some values
|
||||
AUTO_IDLE = false;
|
||||
LAST_ACTIVITY = getTimeStamp();
|
||||
}
|
||||
|
||||
// Lives the auto idle functions
|
||||
function liveIdle() {
|
||||
// Apply the autoIdle function every minute
|
||||
AUTO_IDLE = false;
|
||||
$('#my-infos .f-presence').everyTime('30s', autoIdle);
|
||||
|
||||
// On body bind (click & key event)
|
||||
$('body').live('mousedown', eventIdle)
|
||||
.live('mousemove', eventIdle)
|
||||
.live('keydown', eventIdle);
|
||||
}
|
||||
|
||||
// Kills the auto idle functions
|
||||
function dieIdle() {
|
||||
// Remove the event detector
|
||||
$('body').die('mousedown', eventIdle)
|
||||
.die('mousemove', eventIdle)
|
||||
.die('keydown', eventIdle);
|
||||
}
|
||||
|
||||
// Gets the user presence show
|
||||
function getUserShow() {
|
||||
return $('#my-infos .f-presence a.picker').attr('data-value');
|
||||
}
|
||||
|
||||
// Gets the user presence status
|
||||
function getUserStatus() {
|
||||
return $('#presence-status').val();
|
||||
}
|
||||
|
||||
// Addon launcher
|
||||
function launchPresence() {
|
||||
// Click event for user presence show
|
||||
$('#my-infos .f-presence a.picker').click(function() {
|
||||
// Disabled?
|
||||
if($(this).hasClass('disabled'))
|
||||
return false;
|
||||
|
||||
// Initialize some vars
|
||||
var path = '#my-infos .f-presence div.bubble';
|
||||
var show_id = ['xa', 'away', 'available'];
|
||||
var show_lang = [_e("Not available"), _e("Away"), _e("Available")];
|
||||
var show_val = getUserShow();
|
||||
|
||||
// Yet displayed?
|
||||
var can_append = true;
|
||||
|
||||
if(exists(path))
|
||||
can_append = false;
|
||||
|
||||
// Add this bubble!
|
||||
showBubble(path);
|
||||
|
||||
if(!can_append)
|
||||
return false;
|
||||
|
||||
// Generate the HTML code
|
||||
var html = '<div class="bubble removable">';
|
||||
|
||||
for(i in show_id) {
|
||||
// Yet in use: no need to display it!
|
||||
if(show_id[i] == show_val)
|
||||
continue;
|
||||
|
||||
html += '<a href="#" class="talk-images" data-value="' + show_id[i] + '" title="' + show_lang[i] + '"></a>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
// Append the HTML code
|
||||
$('#my-infos .f-presence').append(html);
|
||||
|
||||
// Click event
|
||||
$(path + ' a').click(function() {
|
||||
// Update the presence show marker
|
||||
$('#my-infos .f-presence a.picker').attr('data-value', $(this).attr('data-value'));
|
||||
|
||||
// Close the bubble
|
||||
closeBubbles();
|
||||
|
||||
// Focus on the status input
|
||||
$(document).oneTime(10, function() {
|
||||
$('#presence-status').focus();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Submit events for user presence status
|
||||
$('#presence-status').placeholder()
|
||||
|
||||
.keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
$(this).blur();
|
||||
|
||||
return false;
|
||||
}
|
||||
})
|
||||
|
||||
.blur(function() {
|
||||
// Read the parameters
|
||||
var show = getUserShow();
|
||||
var status = getUserStatus();
|
||||
|
||||
// Read the old parameters
|
||||
var old_show = getDB('presence-show', 1);
|
||||
var old_status = getDB('options', 'presence-status');
|
||||
|
||||
// Must send the presence?
|
||||
if((show != old_show) || (status != old_status)) {
|
||||
// Update the local stored status
|
||||
setDB('options', 'presence-status', status);
|
||||
|
||||
// Update the server stored status
|
||||
if(status != old_status)
|
||||
storeOptions();
|
||||
|
||||
// Send the presence
|
||||
presenceSend();
|
||||
}
|
||||
})
|
||||
|
||||
// Input focus handler
|
||||
.focus(function() {
|
||||
closeBubbles();
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue