summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/js/client.js150
-rw-r--r--media/js/views/browser.js53
-rw-r--r--media/js/views/client.js4
-rw-r--r--media/js/views/modals.js86
-rw-r--r--media/js/views/room.js57
-rw-r--r--media/js/views/transcript.js2
-rw-r--r--media/js/views/window.js5
-rw-r--r--media/less/style/chat/browser.less2
-rw-r--r--media/less/style/chat/client.less23
-rw-r--r--media/less/style/chat/rooms.less4
10 files changed, 326 insertions, 60 deletions
diff --git a/media/js/client.js b/media/js/client.js
index c638d03..12386c4 100644
--- a/media/js/client.js
+++ b/media/js/client.js
@@ -3,6 +3,29 @@
//
(function(window, $, _) {
+
+ var RoomStore = {
+ add: function(id) {
+ var rooms = store.get('openrooms') || [];
+ if (!_.contains(rooms, id)) {
+ rooms.push(id);
+ store.set('openrooms', rooms);
+ }
+ },
+ remove: function(id) {
+ var rooms = store.get('openrooms') || [];
+ if (_.contains(rooms, id)) {
+ store.set('openrooms', _.without(rooms, id));
+ }
+ },
+ get: function() {
+ var rooms = store.get('openrooms') || [];
+ rooms = _.uniq(rooms);
+ store.set('openrooms', rooms);
+ return rooms;
+ }
+ };
+
//
// Base
//
@@ -39,7 +62,8 @@
var room = {
name: data.name,
slug: data.slug,
- description: data.description
+ description: data.description,
+ password: data.password
};
var callback = data.callback;
this.socket.emit('rooms:create', room, function(room) {
@@ -88,8 +112,10 @@
replace: true
});
return;
+ } else if(room) {
+ this.joinRoom(room, true);
} else {
- this.joinRoom(id, true);
+ this.joinRoom({id: id}, true);
}
};
Client.prototype.updateRoom = function(room) {
@@ -123,38 +149,81 @@
this.leaveRoom(room.id);
this.rooms.remove(room.id);
};
- Client.prototype.rejoinRoom = function(id) {
- this.joinRoom(id, undefined, true);
+ Client.prototype.rejoinRoom = function(room) {
+ this.joinRoom(room, undefined, true);
};
- Client.prototype.joinRoom = function(id, switchRoom, rejoin) {
- var that = this;
+ Client.prototype.lockJoin = function(id) {
+ if (_.contains(this.joining, id)) {
+ return false;
+ }
- // We need an id and unlocked joining
- if (!id || _.contains(this.joining, id)) {
- // Nothing to do
+ this.joining = this.joining || [];
+ this.joining.push(id);
+ return true;
+ };
+ Client.prototype.unlockJoin = function(id) {
+ var that = this;
+ _.defer(function() {
+ that.joining = _.without(that.joining, id);
+ });
+ };
+ Client.prototype.joinRoom = function(room, switchRoom, rejoin) {
+ if (!room || !room.id) {
return;
}
+ var that = this;
+ var id = room.id;
+ var password = room.password;
+
if (!rejoin) {
// Must not have already joined
- var room = that.rooms.get(id);
- if (room && room.get('joined')) {
+ var room1 = that.rooms.get(id);
+ if (room1 && room1.get('joined')) {
return;
}
}
- //
- // Setup joining lock
- //
- this.joining = this.joining || [];
- this.joining.push(id);
- this.socket.emit('rooms:join', id, function(resRoom) {
+ if (!this.lockJoin(id)) {
+ return;
+ }
+
+ var passwordCB = function(password) {
+ room.password = password;
+ that.joinRoom(room, switchRoom, rejoin);
+ };
+
+ this.socket.emit('rooms:join', {roomId: id, password: password}, function(resRoom) {
// Room was likely archived if this returns
if (!resRoom) {
return;
}
+
+ if (resRoom && resRoom.errors &&
+ resRoom.errors === 'password required') {
+
+ that.passwordModal.show({
+ callback: passwordCB
+ });
+
+ that.unlockJoin(id);
+ return;
+ }
+
+ if (resRoom && resRoom.errors) {
+ that.unlockJoin(id);
+ return;
+ }
+
var room = that.addRoom(resRoom);
room.set('joined', true);
+
+ if (room.get('hasPassword')) {
+ that.getRoomUsers(room.id, _.bind(function(users) {
+ this.setUsers(room.id, users);
+ }, that));
+ }
+
// Get room history
that.getMessages({
room: room.id,
@@ -167,6 +236,7 @@
that.addMessages(messages, !rejoin && !room.lastMessage.get('id'));
!rejoin && room.lastMessage.set(messages[messages.length - 1]);
});
+
if (that.options.filesEnabled) {
that.getFiles({
room: room.id,
@@ -183,21 +253,9 @@
//
// Add room id to localstorage so we can reopen it on refresh
//
- var openRooms = store.get('openrooms');
- if (openRooms instanceof Array) {
- // Check for duplicates
- if (!_.contains(openRooms, id)) {
- openRooms.push(id);
- }
- store.set('openrooms', openRooms);
- } else {
- store.set('openrooms', [id]);
- }
-
- // Remove joining lock
- _.defer(function() {
- that.joining = _.without(that.joining, id);
- });
+ RoomStore.add(id);
+
+ that.unlockJoin(id);
});
};
Client.prototype.leaveRoom = function(id) {
@@ -205,6 +263,9 @@
if (room) {
room.set('joined', false);
room.lastMessage.clear();
+ if (room.get('hasPassword')) {
+ room.users.set([]);
+ }
}
this.socket.emit('rooms:leave', id);
if (id === this.rooms.current.get('id')) {
@@ -212,7 +273,7 @@
this.switchRoom(room && room.get('joined') ? room.id : '');
}
// Remove room id from localstorage
- store.set('openrooms', _.without(store.get('openrooms'), id));
+ RoomStore.remove(id);
};
Client.prototype.getRoomUsers = function(id, callback) {
this.socket.emit('rooms:users', {
@@ -399,19 +460,16 @@
return room.id;
});
- var openRooms = store.get('openrooms');
- if (openRooms instanceof Array) {
- // Flush the stored array
- store.set('openrooms', []);
-
- openRooms = _.uniq(openRooms);
- // Let's open some rooms!
+ var openRooms = RoomStore.get();
+ // Let's open some rooms!
+ _.defer(function() {
+ //slow down because router can start a join with no password
_.each(openRooms, function(id) {
- if (roomIds.indexOf(id) !== -1) {
- that.joinRoom(id);
+ if (_.contains(roomIds, id)) {
+ that.joinRoom({ id: id });
}
});
- }
+ }.bind(this));
}
//
@@ -430,7 +488,7 @@
});
this.socket.on('reconnect', function() {
_.each(that.rooms.where({ joined: true }), function(room) {
- that.rejoinRoom(room.id);
+ that.rejoinRoom(room);
});
});
this.socket.on('messages:new', function(message) {
@@ -470,6 +528,7 @@
this.events.on('rooms:switch', this.switchRoom, this);
this.events.on('rooms:archive', this.archiveRoom, this);
this.events.on('profile:update', this.updateProfile, this);
+ this.events.on('rooms:join', this.joinRoom, this);
};
//
// Start
@@ -482,6 +541,9 @@
this.view = new window.LCB.ClientView({
client: this
});
+ this.passwordModal = new window.LCB.RoomPasswordModalView({
+ el: $('#lcb-password')
+ });
return this;
};
//
diff --git a/media/js/views/browser.js b/media/js/views/browser.js
index 858f059..6235a59 100644
--- a/media/js/views/browser.js
+++ b/media/js/views/browser.js
@@ -44,11 +44,16 @@
$input = $target.is(':checkbox') && $target || $target.siblings('[type="checkbox"]'),
id = $input.data('id'),
room = this.rooms.get(id);
+
if (!room) {
return;
}
- (!$input.is(':checked') && this.client.joinRoom(room.id)) ||
- (this.rooms.get(room.id).get('joined') && this.client.leaveRoom(room.id));
+
+ if (room.get('joined')) {
+ this.client.leaveRoom(room.id);
+ } else {
+ this.client.joinRoom(room);
+ }
},
add: function(room) {
var room = room.toJSON ? room.toJSON() : room,
@@ -100,28 +105,60 @@
});
},
create: function(e) {
+ var that = this;
e.preventDefault();
- var $modal = this.$('#lcb-add-room'),
- $form = this.$(e.target),
+ var $form = this.$(e.target),
+ $modal = this.$('#lcb-add-room'),
+ $name = this.$('.lcb-room-name'),
+ $slug = this.$('.lcb-room-slug'),
+ $description = this.$('.lcb-room-description'),
+ $password = this.$('.lcb-room-password'),
+ $confirmPassword = this.$('.lcb-room-confirm-password'),
data = {
- name: this.$('.lcb-room-name').val().trim(),
- slug: this.$('.lcb-room-slug').val().trim(),
- description: this.$('.lcb-room-description').val(),
+ name: $name.val().trim(),
+ slug: $slug.val().trim(),
+ description: $description.val(),
+ password: $password.val(),
callback: function success() {
$modal.modal('hide');
$form.trigger('reset');
}
};
+
+ $name.parent().removeClass('has-error');
+ $slug.parent().removeClass('has-error');
+ $confirmPassword.parent().removeClass('has-error');
+
// we require name is non-empty
if (!data.name) {
$name.parent().addClass('has-error');
return;
}
+
// we require slug is non-empty
if (!data.slug) {
$slug.parent().addClass('has-error');
return;
}
+
+ // remind the user, that users may share the password with others
+ if (data.password) {
+ if (data.password !== $confirmPassword.val()) {
+ $confirmPassword.parent().addClass('has-error');
+ return;
+ }
+
+ swal({
+ title: 'Password-protected room',
+ text: 'You\'re creating a room with a shared password.\n' +
+ 'Anyone who obtains the password may enter the room.',
+ showCancelButton: true
+ }, function(){
+ that.client.events.trigger('rooms:create', data);
+ });
+ return;
+ }
+
this.client.events.trigger('rooms:create', data);
},
addUser: function(user, room) {
@@ -135,4 +172,4 @@
});
-}(window, $, _); \ No newline at end of file
+}(window, $, _);
diff --git a/media/js/views/client.js b/media/js/views/client.js
index 6231f08..b14b305 100644
--- a/media/js/views/client.js
+++ b/media/js/views/client.js
@@ -61,6 +61,7 @@
rooms: this.client.rooms
});
}
+
//
// Modals
//
@@ -78,6 +79,9 @@
this.notificationsModal = new window.LCB.NotificationsModalView({
el: this.$el.find('#lcb-notifications')
});
+ this.giphyModal = new window.LCB.GiphyModalView({
+ el: this.$el.find('#lcb-giphy')
+ });
//
// Misc
//
diff --git a/media/js/views/modals.js b/media/js/views/modals.js
index e1d2fa7..a6d1c41 100644
--- a/media/js/views/modals.js
+++ b/media/js/views/modals.js
@@ -86,6 +86,29 @@
}
});
+ window.LCB.RoomPasswordModalView = Backbone.View.extend({
+ events: {
+ 'click .btn-primary': 'enterRoom'
+ },
+ initialize: function(options) {
+ this.render();
+ this.$password = this.$('input.lcb-room-password-required');
+ },
+ render: function() {
+ // this.$el.on('shown.bs.modal hidden.bs.modal',
+ // _.bind(this.refresh, this));
+ },
+ show: function(options) {
+ this.callback = options.callback;
+ this.$password.val('');
+ this.$el.modal('show');
+ },
+ enterRoom: function() {
+ this.$el.modal('hide');
+ this.callback(this.$password.val());
+ }
+ });
+
window.LCB.AuthTokensModalView = Backbone.View.extend({
events: {
'click .generate-token': 'generateToken',
@@ -176,4 +199,67 @@
}
});
+ window.LCB.GiphyModalView = Backbone.View.extend({
+ events: {
+ 'keypress .search-giphy': 'stopReturn',
+ 'keyup .search-giphy': 'loadGifs'
+ },
+ initialize: function(options) {
+ this.render();
+ },
+ render: function() {
+ this.$el.on('shown.bs.modal hidden.bs.modal',
+ _.bind(this.refresh, this));
+ },
+ refresh: function() {
+ this.$el.find('.giphy-results ul').empty();
+ this.$('.search-giphy').val('').focus();
+ },
+ stopReturn: function(e) {
+ if(e.keyCode === 13) {
+ return false;
+ }
+ },
+ loadGifs: _.throttle(function() {
+ console.log(1)
+ var that = this;
+ var search = this.$el.find('.search-giphy').val();
+
+ $.get('https://api.giphy.com/v1/gifs/search?limit=24&rating=pg-13&api_key=dc6zaTOxFJmzC&q=' + search)
+ .done(function(result) {
+ var images = result.data.filter(function(entry) {
+ return entry.images.fixed_width.url;
+ }).map(function(entry) {
+ return entry.images.fixed_width.url;
+ });
+
+ that.appendGifs(images);
+ });
+ }, 400, {leading: false}),
+ appendGifs: function(images) {
+ var eles = images.map(function(url) {
+ var that = this;
+ var $img = $('<img src="' + url +
+ '" alt="gif" data-dismiss="modal"/></li>');
+
+ $img.click(function() {
+ var src = $(this).attr('src');
+ $('.lcb-entry-input:visible').val(src);
+ $('.lcb-entry-button:visible').click();
+ that.$el.modal('hide');
+ });
+
+ return $("<li>").append($img);
+ }, this);
+
+ var $div = this.$el.find('.giphy-results ul');
+
+ $div.empty();
+
+ eles.forEach(function($ele) {
+ $div.append($ele);
+ });
+ }
+ });
+
}(window, $, _);
diff --git a/media/js/views/room.js b/media/js/views/room.js
index 48071e9..736f81b 100644
--- a/media/js/views/room.js
+++ b/media/js/views/room.js
@@ -25,6 +25,13 @@
},
initialize: function(options) {
this.client = options.client;
+
+ var iAmOwner = this.model.get('owner') === this.client.user.id;
+ var iCanEdit = iAmOwner || !this.model.get('hasPassword');
+
+ this.model.set('iAmOwner', iAmOwner);
+ this.model.set('iCanEdit', iCanEdit);
+
this.template = options.template;
this.messageTemplate =
Handlebars.compile($('#template-message').html());
@@ -76,11 +83,17 @@
}
},
getAtwhoUserFilter: function(collection) {
+ var currentUser = this.client.user;
+
return function filter(query, data, searchKey) {
var q = query.toLowerCase();
var results = collection.filter(function(user) {
var attr = user.attributes;
+ if (user.id === currentUser.id) {
+ return false;
+ }
+
if (!attr.safeName) {
attr.safeName = attr.displayName.replace(/\W/g, '');
}
@@ -213,7 +226,19 @@
if (e) {
e.preventDefault();
}
- this.$('.lcb-room-edit').modal();
+
+ var $modal = this.$('.lcb-room-edit'),
+ $name = $modal.find('input[name="name"]'),
+ $description = $modal.find('textarea[name="description"]'),
+ $password = $modal.find('input[name="password"]'),
+ $confirmPassword = $modal.find('input[name="confirmPassword"]');
+
+ $name.val(this.model.get('name'));
+ $description.val(this.model.get('description'));
+ $password.val('');
+ $confirmPassword.val('');
+
+ $modal.modal();
},
hideEditRoom: function(e) {
if (e) {
@@ -225,14 +250,34 @@
if (e) {
e.preventDefault();
}
- var name = this.$('.edit-room input[name="name"]').val();
- var description = this.$('.edit-room textarea[name="description"]').val();
+
+ var $modal = this.$('.lcb-room-edit'),
+ $name = $modal.find('input[name="name"]'),
+ $description = $modal.find('textarea[name="description"]'),
+ $password = $modal.find('input[name="password"]'),
+ $confirmPassword = $modal.find('input[name="confirmPassword"]');
+
+ $name.parent().removeClass('has-error');
+ $confirmPassword.parent().removeClass('has-error');
+
+ if (!$name.val()) {
+ $name.parent().addClass('has-error');
+ return;
+ }
+
+ if ($password.val() && $password.val() !== $confirmPassword.val()) {
+ $confirmPassword.parent().addClass('has-error');
+ return;
+ }
+
this.client.events.trigger('rooms:update', {
id: this.model.id,
- name: name,
- description: description
+ name: $name.val(),
+ description: $description.val(),
+ password: $password.val()
});
- this.$('.lcb-room-edit').modal('hide');
+
+ $modal.modal('hide');
},
archiveRoom: function(e) {
var that = this;
diff --git a/media/js/views/transcript.js b/media/js/views/transcript.js
index 0cab630..195343f 100644
--- a/media/js/views/transcript.js
+++ b/media/js/views/transcript.js
@@ -72,7 +72,7 @@
search: _.throttle(function() {
this.query = this.$query.val()
this.loadTranscript();
- }, 400),
+ }, 400, {leading: false}),
loadTranscript: function() {
var that = this;
this.clearMessages();
diff --git a/media/js/views/window.js b/media/js/views/window.js
index bf79ca2..e6f3c97 100644
--- a/media/js/views/window.js
+++ b/media/js/views/window.js
@@ -110,6 +110,7 @@
keys: {
'up+shift+alt down+shift+alt': 'nextRoom',
's+shift+alt': 'toggleRoomSidebar',
+ 'g+shift+alt': 'openGiphyModal',
'space+shift+alt': 'recallRoom'
},
initialize: function(options) {
@@ -132,6 +133,10 @@
e.preventDefault();
var view = this.client.view.panes.views[this.rooms.current.get('id')];
view && view.toggleSidebar && view.toggleSidebar();
+ },
+ openGiphyModal: function(e) {
+ e.preventDefault();
+ $('.lcb-giphy').modal('show');
}
});
diff --git a/media/less/style/chat/browser.less b/media/less/style/chat/browser.less
index 2c53f18..79ff3e2 100644
--- a/media/less/style/chat/browser.less
+++ b/media/less/style/chat/browser.less
@@ -85,7 +85,7 @@
font-size: 20px;
}
-.lcb-rooms-list-item-slug {
+.lcb-rooms-list-item-slug, .lcb-rooms-list-item-password {
font-size: 16px;
font-weight: 300;
color: #aaa;
diff --git a/media/less/style/chat/client.less b/media/less/style/chat/client.less
index 9022653..e7ec6fe 100644
--- a/media/less/style/chat/client.less
+++ b/media/less/style/chat/client.less
@@ -193,3 +193,26 @@
.lcb-avatar {
border-radius: 100%;
}
+
+.lcb-giphy .giphy-results {
+ max-height: 350px;
+ overflow: auto;
+
+ ul {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ text-align: center;
+
+ li {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+ margin:5px;
+
+ img {
+ cursor: pointer;
+ }
+ }
+ }
+}
diff --git a/media/less/style/chat/rooms.less b/media/less/style/chat/rooms.less
index 41438de..e6e5997 100644
--- a/media/less/style/chat/rooms.less
+++ b/media/less/style/chat/rooms.less
@@ -77,6 +77,10 @@
box-shadow: none;
}
}
+ .password {
+ font-size: 14px;
+ cursor: default;
+ }
.btn:hover {
color: #666;
}