diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/js/client.js | 150 | ||||
-rw-r--r-- | media/js/views/browser.js | 53 | ||||
-rw-r--r-- | media/js/views/client.js | 4 | ||||
-rw-r--r-- | media/js/views/modals.js | 86 | ||||
-rw-r--r-- | media/js/views/room.js | 57 | ||||
-rw-r--r-- | media/js/views/transcript.js | 2 | ||||
-rw-r--r-- | media/js/views/window.js | 5 | ||||
-rw-r--r-- | media/less/style/chat/browser.less | 2 | ||||
-rw-r--r-- | media/less/style/chat/client.less | 23 | ||||
-rw-r--r-- | media/less/style/chat/rooms.less | 4 |
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; } |