Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
Updates from private repo
Browse files Browse the repository at this point in the history
  • Loading branch information
that-jill committed Dec 4, 2016
1 parent 9759527 commit 744f57e
Showing 1 changed file with 301 additions and 71 deletions.
372 changes: 301 additions & 71 deletions bookmark/bookmark.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,323 @@
/** File: bookmark.js
* Candy Plugin - Bookmark rooms
* Candy Plugin - Bookmark Rooms
* Author: Rafael Macedo <[email protected]>
* Author: Ben Langfeld <[email protected]>
*/

/* global Candy, jQuery, Strophe, $iq */

var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.Bookmark = (function(self, Candy, $) {
self.init = function(){
$(Candy).on('candy:view.connection.status-5', function(){
self._createBookmarksNode();
return true;
});

self.Bookmark = (function() {
function Bookmark(type, args) {
this.type = type;
this.jid = args.jid;
this.name = args.name || args.jid.split(/@/)[0];
this.id = args.room_id || args.user_id;
this.term = args.term;
this.to = args.to;
this.opened = false;
this.is_private = args.is_private;
this.pending_removal = false;
}

Bookmark.prototype.join = function(foreground) {
if (!this.opened) {
if (this.type.match(/users/)) {
Candy.View.Pane.PrivateRoom.open(this.jid, this.name, foreground, true);
} else if (this.type.match(/rooms/)) {
var data = { roomJid: this.jid, name: this.name, is_private: this.is_private, room_id: this.id };
CandyShop.JoinOnResponse.joinRoom(data, false, foreground);
} else {
Candy.Core.warn('Error: unknown bookmark type: ', this.type);
}
this.opened = true;
}
};

Bookmark.prototype.leave = function() {
if (this.type.match(/users/)) {
Candy.View.Pane.Room.close(this.jid);
} else if (this.type.match(/rooms/)) {
Candy.Core.Action.Jabber.Room.Leave(this.jid);
}
};

Bookmark.prototype.toArgs = function() {
var args = {};

if (this.id) {
if (this.type.match(/users/)) {
args.user_id = this.id;
} else if (this.type.match(/rooms/)) {
args.room_id = this.id;
}
} else {
if (this.type.match(/users/)) {
args.user_jid = this.jid;
} else if (this.type.match(/rooms/)) {
args.room_jid = this.jid;
}
}

return args;
};

return Bookmark;
})();

self.BookmarkCollection = (function() {
function BookmarkCollection() {
this.collection = [];
this.version = undefined;
}

BookmarkCollection.prototype.add = function(bookmark, newlyAdded) {
if (this.collection.filter(function(item) { return item.jid === bookmark; }).length === 0) {
if (newlyAdded) {
this.collection.unshift(bookmark);
if (Candy.Core.getConnection().connected === true) {
bookmark.join();
}
} else {
this.collection.push(bookmark);
}
}
return this.collection;
};

BookmarkCollection.prototype.joinAll = function() {
this.collection.forEach(function (bookmark, position, collection) {
var foreground = false;
if (CandyShop.RoomAnchors.roomAnchorJid()) {
// This bookmark matches the room in the URL
if (CandyShop.RoomAnchors.roomAnchorJid() === bookmark.jid) {
foreground = true;
}
} else if (position === 0) {
foreground = true;
}
bookmark.join(foreground);
});
}

BookmarkCollection.prototype.jids = function() {
return this.collection.map(function(bookmark) {
return bookmark.jid;
});
};

BookmarkCollection.prototype.pendingRemoval = function() {
return this.collection.filter(function(item) { return item.pending_removal; });
};

BookmarkCollection.prototype.valid = function() {
return this.collection.filter(function(item) { return !item.pending_removal; });
};

BookmarkCollection.prototype.tryRemoveByJid = function(jid) {
this.collection.forEach(function (item) {
if (item.jid === jid) {
item.pending_removal = true;
}
});
};

BookmarkCollection.prototype.removeByJid = function(jid) {
this.collection = this.collection.filter(function(bookmark) {
return bookmark.jid !== jid;
});
};

BookmarkCollection.prototype.reset = function(data) {
for (var key in data) {
data[key].forEach($.proxy(function(obj) {
self.bookmarks.add(new self.Bookmark(key, obj));
}), this);
}
};

BookmarkCollection.prototype.sync = function(data) {
for (var key in data) {
data[key].forEach($.proxy(function(obj) {
if ($.inArray(obj.jid, self.bookmarks.jids()) === -1) {
self.bookmarks.add(new self.Bookmark(key, obj));
}
}), this);
}

var jids = [];
jids = jids.concat(data.connect_bookmarked_users.map(function(i) { return i.jid; }));
jids = jids.concat(data.connect_bookmarked_rooms.map(function(i) { return i.jid; }));

this.valid().forEach($.proxy(function(item) {
if ($.inArray(item.jid, jids) === -1) {
this.removeByJid(item.jid);
item.leave();
}
}), this);
};

BookmarkCollection.prototype.setVersion = function(version) {
this.version = version;
};

BookmarkCollection.prototype.toArgs = function() {
var args = {};
var valid = this.valid();

args.version = this.version;

args.connect_bookmarked_users =
valid.filter(function(bookmark) {
return bookmark.type === 'connect_bookmarked_users';
}).map(function(bookmark) { return bookmark.toArgs(); });

args.connect_bookmarked_rooms =
valid.filter(function(bookmark) {
return bookmark.type === 'connect_bookmarked_rooms';
}).map(function(bookmark) { return bookmark.toArgs(); });

return args;
};

BookmarkCollection.prototype.type = function(type) {
return this.collection.filter(function(bookmark) {
return bookmark.type === 'connect_bookmarked_' + type;
});
};

return BookmarkCollection;
})();

self.requestHandler = undefined;

self.init = function() {
self.bookmarks = new self.BookmarkCollection();
self._addEventListeners();
};
/** File: bookmark.js
* Candy Plugin - Bookmark rooms
* Author: Ben Langfeld <[email protected]>
*/

var CandyShop = (function(self) { return self; }(CandyShop || {}));
self._addEventListeners = function() {
$(Candy)
.on('candy:core.presence.error', self._removeBookmarkPresenceError)
.on('candy:view.room.after-close', self._removeBookmark)
.on('candy:view.room.after-add', self._onRoomOpen)
.on('candy:view.connection.status-' + Strophe.Status.CONNECTED, self.joinAll)
.on('candy:view.connection.status-' + Strophe.Status.ATTACHED, self.joinAll);
};

CandyShop.Bookmark = (function(self, Candy, $) {
/** Object: about
*
* Contains:
* (String) name - Candy Plugin - Bookmark rooms
* (Float) version - Candy Plugin - Bookmark rooms
*/
self.about = {
name: 'Candy Plugin - Bookmark rooms',
version: '0.1'
self.joinAll = function () {
self.bookmarks.joinAll();
};

self.init = function(){
Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub');
$(Candy).on('candy:view.connection.status-5', self._createBookmarksNode);
$(Candy).on('candy:view.connection.status-8', self._createBookmarksNode);
self.fetchBookmarks = function(data) {
self.bookmarks.setVersion(data.version);
delete data.version;
self.bookmarks.reset(data);
};

/** Function: add
* Adds a bookmark for the provided MUC room
*
* Parameters:
* (String) roomJid - The JID of the room to bookmark
*/
self.add = function(roomJid) {
Candy.Core.getConnection().sendIQ($iq({
type: 'set'
})
.c('pubsub', {xmlns: Strophe.NS.PUBSUB})
.c('publish', {node: Strophe.NS.BOOKMARKS})
.c('item', {id: roomJid})
.c('storage', {xmlns: Strophe.NS.BOOKMARKS})
.c('conference', {autojoin: 'true', jid: roomJid})
);
self._onRoomOpen = function(e, args) {
if (self.bookmarks) {
if ($.inArray(args.roomJid, self.bookmarks.jids()) === -1) {
var bookmark;
var type;

if (args.type === 'chat') {
type = 'connect_bookmarked_users';
} else if (args.type === 'groupchat') {
type = 'connect_bookmarked_rooms';
}

if (type) {
bookmark = new self.Bookmark(type, { jid: args.roomJid });
self.bookmarks.add(bookmark, true);
self._updateBookmarks();
}
}

// Re-sort the order of Rooms, and One-on-One chats to match
// the order of the bookmarks
var chatTabs = $('#chat-tabs');
var roomsHead = $('#rooms-head').detach();
var rooms = chatTabs.find('.roomtype-groupchat').detach();
var peopleHead = $('#people-head').detach();
var people = chatTabs.find('.roomtype-chat').detach();

// TODO: DRY
chatTabs.append(roomsHead);
self.bookmarks.type('rooms').map(function(bookmark) {
chatTabs.append(rooms.filter(function(i, room) {
return $(room).attr('data-roomjid') === bookmark.jid;
}));
});

chatTabs.append(peopleHead);
self.bookmarks.type('users').map(function(bookmark) {
chatTabs.append(people.filter(function(i, user) {
return $(user).attr('data-roomjid') === bookmark.jid;
}));
});
}
};

/** Function: remove
* Removes a bookmark for the provided MUC room
*
* Parameters:
* (String) roomJid - The JID of the room to remove from bookmarks
*/
self.remove = function(roomJid) {
Candy.Core.getConnection().sendIQ($iq({
type: 'set'
})
.c('pubsub', {xmlns: Strophe.NS.PUBSUB})
.c('retract', {node: Strophe.NS.BOOKMARKS})
.c('item', {id: roomJid})
);
self._removeBookmarkPresenceError = function(e, args) {
if ($(args).attr('error') && Strophe.getBareJidFromJid($(args).attr('from')) !== Strophe.getBareJidFromJid(Candy.Core.getUser().getJid())) {
self._removeBookmark(e, args);
}
};

self._createBookmarksNode = function() {
// We do this instead of using publish-options because this is not mandatory to implement according to XEP-0060
Candy.Core.getConnection().sendIQ($iq({type: 'set'})
.c('pubsub', {xmlns: Strophe.NS.PUBSUB})
.c('create', {node: 'storage:bookmarks'}).up()
.c('configure')
.c('x', {xmlns: 'jabber:x:data', type: 'submit'})
.c('field', {'var': 'FORM_TYPE', type: 'hidden'})
.c('value').t('http://jabber.org/protocol/pubsub#node_config').up().up()
.c('field', {'var': 'pubsub#persist_items'}).c('value').t('1').up().up()
.c('field', {'var': 'pubsub#access_model'}).c('value').t('whitelist')
);

return true;
self._removeBookmark = function(e, args) {
if (args.roomJid) {
self.bookmarks.tryRemoveByJid(args.roomJid);
window.clearTimeout(self.requestHandler);
self.requestHandler = window.setTimeout(self._updateBookmarks, 300);
}
};

self._updateBookmarks = function() {
$.ajax({
type: 'PUT',
url: '/api/v1/connect/bookmarks',
contentType: 'application/json',
data: JSON.stringify(self.bookmarks.toArgs()),
statusCode: {
409: function() {
CandyShop.ConnectStateData.fetch().done(function(data) {
self.bookmarks.setVersion(data.bookmarks.version);
delete data.bookmarks.version;
self.bookmarks.sync(data.bookmarks);
self._updateBookmarks();
});
}
}
}).done(function(data) {
self.bookmarks.setVersion(data.version);
delete data.version;
self.bookmarks.sync(data);

self.bookmarks.pendingRemoval().forEach(function (bookmark) {
if (self._serverHasBookmark(bookmark.jid, data)) {
// The server still has this bookmark. We need to sync again
self._removeBookmark(undefined, { roomJid: bookmark.jid });
} else {
// This bookmark was removed from the server. Remove it from our local collection
self.bookmarks.removeByJid(bookmark.jid);
}
});
});
};

self._serverHasBookmark = function (jid, data) {
var has = false;
for (var key in data) {
data[key].forEach(function (bookmark) {
if (bookmark.jid == jid) {
has = true;
}
})
}
return has;
}

return self;
}(CandyShop.Bookmark || {}, Candy, jQuery));

0 comments on commit 744f57e

Please sign in to comment.