--- /dev/null
+/*
+
+Jappix - An open social platform
+These are the notification JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+// Resets the notifications alert if no one remaining
+function closeEmptyNotifications() {
+ if(!$('.one-notification').size())
+ closeBubbles();
+}
+
+// Checks if there are pending notifications
+function checkNotifications() {
+ // Define the selectors
+ var notif = '#top-content .notifications';
+ var nothing = '.notifications-content .nothing';
+ var empty = '.notifications-content .empty';
+
+ // Get the notifications number
+ var number = $('.one-notification').size();
+
+ // Remove the red notify bubble
+ $(notif + ' .notify').remove();
+
+ // Any notification?
+ if(number) {
+ $(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>');
+ $(nothing).hide();
+ $(empty).show();
+ }
+
+ // No notification!
+ else {
+ $(empty).hide();
+ $(nothing).show();
+
+ // Purge the social inbox node
+ purgeNotifications();
+ }
+
+ // Update the page title
+ updateTitle();
+}
+
+// Creates a new notification
+function newNotification(type, from, data, body, id, inverse) {
+ if(!type || !from)
+ return;
+
+ // Generate an ID hash
+ if(!id)
+ var id = hex_md5(type + from);
+
+ // Generate the text to be displayed
+ var text, action, code;
+ var yes_path = 'href="#"';
+
+ // User things
+ from = bareXID(from);
+ var hash = hex_md5(from);
+
+ switch(type) {
+ case 'subscribe':
+ // Get the name to display
+ var display_name = data[1];
+
+ if(!display_name)
+ display_name = data[0];
+
+ text = '<b>' + display_name.htmlEnc() + '</b> ' + _e("would like to add you as a friend.") + ' ' + _e("Do you accept?");
+
+ break;
+
+ case 'invite_room':
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + _e("would like you to join this chatroom:") + ' <em>' + data[0].htmlEnc() + '</em> ' + _e("Do you accept?");
+
+ break;
+
+ case 'request':
+ text = '<b>' + from.htmlEnc() + '</b> ' + _e("would like to get authorization.") + ' ' + _e("Do you accept?");
+
+ break;
+
+ case 'send':
+ yes_path = 'href="' + encodeQuotes(data[1]) + '" target="_blank"';
+
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("would like to send you a file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>') + ' ' + _e("Do you accept?");
+
+ break;
+
+ case 'send_pending':
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has received a file exchange request: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'send_accept':
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has accepted to received your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'send_reject':
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has rejected to receive your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'send_fail':
+ text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("could not receive your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'rosterx':
+ text = printf(_e("Do you want to see the friends %s suggests you?").htmlEnc(), '<b>' + getBuddyName(from).htmlEnc() + '</b>');
+
+ break;
+
+ case 'comment':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("commented an item you follow: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'like':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("liked your post: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'quote':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("quoted you somewhere: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'wall':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("published on your wall: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'photo':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("tagged you in a photo (%s).").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ case 'video':
+ text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("tagged you in a video (%s).").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+
+ break;
+
+ default:
+ break;
+ }
+
+ // No text?
+ if(!text)
+ return;
+
+ // Action links?
+ if((type == 'send_pending') || (type == 'send_accept') || (type == 'send_reject') || (type == 'send_fail') || (type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
+ action = '<a href="#" class="no">' + _e("Hide") + '</a>';
+
+ // Any parent link?
+ if((type == 'comment') && data[2])
+ action = '<a href="#" class="yes">' + _e("Show") + '</a>' + action;
+ }
+
+ else
+ action = '<a ' + yes_path + ' class="yes">' + _e("Yes") + '</a><a href="#" class="no">' + _e("No") + '</a>';
+
+ if(text) {
+ // We display the notification
+ if(!exists('.notifications-content .' + id)) {
+ // We create the html markup depending of the notification type
+ code = '<div class="one-notification ' + id + ' ' + hash + '" title="' + encodeQuotes(body) + '" data-type="' + encodeQuotes(type) + '">' +
+ '<div class="avatar-container">' +
+ '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' +
+ '</div>' +
+
+ '<p class="notification-text">' + text + '</p>' +
+ '<p class="notification-actions">' +
+ '<span class="talk-images" />' +
+ action +
+ '</p>' +
+ '</div>';
+
+ // Add the HTML code
+ if(inverse)
+ $('.notifications-content .nothing').before(code);
+ else
+ $('.notifications-content .empty').after(code);
+
+ // Play a sound to alert the user
+ soundPlay(2);
+
+ // The yes click function
+ $('.' + id + ' a.yes').click(function() {
+ actionNotification(type, data, 'yes', id);
+
+ if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank'))
+ return false;
+ });
+
+ // The no click function
+ $('.' + id + ' a.no').click(function() {
+ return actionNotification(type, data, 'no', id);
+ });
+
+ // Get the user avatar
+ getAvatar(from, 'cache', 'true', 'forget');
+ }
+ }
+
+ // We tell the user he has a new pending notification
+ checkNotifications();
+
+ logThis('New notification: ' + from, 3);
+}
+
+// Performs an action on a given notification
+function actionNotification(type, data, value, id) {
+ // We launch a function depending of the type
+ if((type == 'subscribe') && (value == 'yes'))
+ acceptSubscribe(data[0], data[1]);
+
+ else if((type == 'subscribe') && (value == 'no'))
+ sendSubscribe(data[0], 'unsubscribed');
+
+ else if((type == 'invite_room') && (value == 'yes'))
+ checkChatCreate(data[0], 'groupchat');
+
+ else if(type == 'request')
+ requestReply(value, data[0]);
+
+ if((type == 'send') && (value == 'yes'))
+ replyOOB(data[0], data[3], 'accept', data[2], data[4]);
+
+ else if((type == 'send') && (value == 'no'))
+ replyOOB(data[0], data[3], 'reject', data[2], data[4]);
+
+ else if((type == 'rosterx') && (value == 'yes'))
+ openRosterX(data[0]);
+
+ else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
+ if(value == 'yes') {
+ // Get the microblog item
+ fromInfosMicroblog(data[2]);
+
+ // Append the marker
+ $('#channel .top.individual').append('<input type="hidden" name="comments" value="' + encodeQuotes(data[1]) + '" />');
+ }
+
+ removeNotification(data[3]);
+ }
+
+ // We remove the notification
+ $('.notifications-content .' + id).remove();
+
+ // We check if there's any other pending notification
+ closeEmptyNotifications();
+ checkNotifications();
+
+ return false;
+}
+
+// Clear the social notifications
+function clearNotifications() {
+ // Remove notifications
+ $('.one-notification').remove();
+
+ // Refresh
+ closeEmptyNotifications();
+ checkNotifications();
+
+ return false;
+}
+
+// Gets the pending social notifications
+function getNotifications() {
+ var iq = new JSJaCIQ();
+ iq.setType('get');
+
+ var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+ pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+
+ con.send(iq, handleNotifications);
+
+ logThis('Getting social notifications...');
+}
+
+// Handles the social notifications
+function handleNotifications(iq) {
+ // Any error?
+ if((iq.getType() == 'error') && $(iq.getNode()).find('item-not-found').size()) {
+ // The node may not exist, create it!
+ setupMicroblog('', NS_URN_INBOX, '1', '1000000', 'whitelist', 'open', true);
+
+ logThis('Error while getting social notifications, trying to reconfigure the Pubsub node!', 2);
+ }
+
+ // Selector
+ var items = $(iq.getNode()).find('item');
+
+ // Should we inverse?
+ var inverse = true;
+
+ if(items.size() == 1)
+ inverse = false;
+
+ // Parse notifications
+ items.each(function() {
+ // Parse the current item
+ var current_item = $(this).attr('id');
+ var current_type = $(this).find('link[rel=via]:first').attr('title');
+ var current_href = $(this).find('link[rel=via]:first').attr('href');
+ var current_parent_href = $(this).find('link[rel=related]:first').attr('href');
+ var current_xid = explodeThis(':', $(this).find('source author uri').text(), 1);
+ var current_name = $(this).find('source author name').text();
+ var current_text = $(this).find('content[type=text]:first').text();
+ var current_bname = getBuddyName(current_xid);
+ var current_id = hex_md5(current_type + current_xid + current_href + current_text);
+
+ // Choose the good name!
+ if(!current_name || (current_bname != getXIDNick(current_xid)))
+ current_name = current_bname;
+
+ // Create it!
+ newNotification(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse);
+ });
+
+ logThis(items.size() + ' social notification(s) got!', 3);
+}
+
+// Sends a social notification
+function sendNotification(xid, type, href, text, parent) {
+ // Notification ID
+ var id = hex_md5(xid + text + getTimeStamp());
+
+ // IQ
+ var iq = new JSJaCIQ();
+ iq.setType('set');
+ iq.setTo(xid);
+
+ // ATOM content
+ var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+ var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+ var item = publish.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+ var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
+
+ // Notification author (us)
+ var Source = entry.appendChild(iq.buildNode('source', {'xmlns': NS_ATOM}));
+ var author = Source.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
+ author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, getName()));
+ author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + getXID()));
+
+ // Notification content
+ entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, getXMPPTime('utc')));
+ entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, text));
+ entry.appendChild(iq.buildNode('link', {'rel': 'via', 'title': type, 'href': href, 'xmlns': NS_ATOM}));
+
+ // Any parent item?
+ if(parent && parent[0] && parent[1] && parent[2]) {
+ // Generate the parent XMPP URI
+ var parent_href = 'xmpp:' + parent[0] + '?;node=' + encodeURIComponent(parent[1]) + ';item=' + encodeURIComponent(parent[2]);
+
+ entry.appendChild(iq.buildNode('link', {'rel': 'related', 'href': parent_href, 'xmlns': NS_ATOM}));
+ }
+
+ con.send(iq);
+
+ logThis('Sending a social notification to ' + xid + ' (type: ' + type + ')...');
+}
+
+// Removes a social notification
+function removeNotification(id) {
+ var iq = new JSJaCIQ();
+ iq.setType('set');
+
+ var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+ var retract = pubsub.appendChild(iq.buildNode('retract', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+ retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+
+ con.send(iq);
+}
+
+// Purge the social notifications
+function purgeNotifications() {
+ var iq = new JSJaCIQ();
+ iq.setType('set');
+
+ var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
+ pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB_OWNER}));
+
+ con.send(iq);
+
+ return false;
+}
+
+// Adapt the notifications bubble max-height
+function adaptNotifications() {
+ // Process the new height
+ var max_height = $('#right-content').height() - 22;
+
+ // New height too small
+ if(max_height < 250)
+ max_height = 250;
+
+ // Apply the new height
+ $('.notifications-content .tools-content-subitem').css('max-height', max_height);
+}
+
+// Plugin launcher
+function launchNotifications() {
+ // Adapt the notifications height
+ adaptNotifications();
+}
+
+// Window resize event handler
+$(window).resize(adaptNotifications);