diff --git a/css/style.css b/css/style.css
index 55865ec2e..c6e230450 100644
--- a/css/style.css
+++ b/css/style.css
@@ -20,9 +20,8 @@
}
.oca-spreedme-add-person {
- width: 225px;
- top: 0;
- border-bottom: 1px solid #eee;
+ width: 100%;
+ border: 1px solid #eee;
}
/**
@@ -89,17 +88,6 @@
height: 32px;
}
-#oca-spreedme-add-room button {
- position: absolute;
- background-color: transparent;
- border: none;
- right: 0;
- top: 0;
- padding: 23px;
- margin: 0;
- opacity: .3;
-}
-
.public-room {
display: block !important;
}
@@ -128,7 +116,7 @@
.password-input,
.rename-input {
- margin-top: 0px !important;
+ margin-top: 0 !important;
margin-bottom: 4px !important;
}
@@ -409,7 +397,7 @@ video {
#video-fullscreen {
position: absolute;
- right: 0px;
+ right: 0;
z-index: 90;
}
@@ -754,3 +742,41 @@ video {
background-position: center;
background-image: url('../../../core/img/actions/more.svg?v=1');
}
+
+/**
+ * Sidebar details view
+ */
+
+.detailCallInfoContainer h3 {
+ max-width: calc(100% - 72px);
+ display: inline-block;
+}
+
+.detailCallInfoContainer .rename-button {
+ display: none;
+}
+
+.detailCallInfoContainer .clipboard-button,
+.detailCallInfoContainer:hover .rename-button {
+ display: inline-block;
+}
+
+.detailCallInfoContainer .clipboard-button .icon,
+.detailCallInfoContainer .rename-button .icon {
+ cursor: pointer;
+ width: 16px;
+ height: 16px;
+ margin: -2px 10px;
+}
+
+.detailCallInfoContainer .rename-option,
+.detailCallInfoContainer .password-option {
+ position: relative;
+ max-width: calc(100% - 72px);
+ display: inline-block;
+}
+
+.detailCallInfoContainer .rename-input,
+.detailCallInfoContainer .password-input {
+ width: 100%;
+}
diff --git a/js/app.js b/js/app.js
index c18c4c81c..1801c1e25 100644
--- a/js/app.js
+++ b/js/app.js
@@ -350,10 +350,11 @@
_showParticipantList: function() {
this._participants = new OCA.SpreedMe.Models.ParticipantCollection();
this._participantsView = new OCA.SpreedMe.Views.ParticipantView({
+ room: this.activeRoom,
collection: this._participants
});
- this._participants.listenTo(this._rooms, 'change:active', function(model, active) {
+ this._participantsView.listenTo(this._rooms, 'change:active', function(model, active) {
if (active) {
this.setRoom(model);
}
diff --git a/js/views/callinfoview.js b/js/views/callinfoview.js
index 8da66d4ae..44be53120 100644
--- a/js/views/callinfoview.js
+++ b/js/views/callinfoview.js
@@ -21,7 +21,7 @@
*
*/
-(function(OCA, Marionette, Handlebars) {
+(function(OC, OCA, Marionette, Handlebars, $, _) {
'use strict';
@@ -29,27 +29,266 @@
OCA.SpreedMe.Views = OCA.SpreedMe.Views || {};
var TEMPLATE =
- '{{displayName}}';
+ '
{{displayName}}
' +
+ '{{#if showShareLink}}' +
+ '
' +
+ '{{/if}}' +
+ '{{#if canModerate}}' +
+ ' ' +
+ '
' +
+ '{{/if}}' +
+ '{{#if canModerate}}' +
+ ' ' +
+ '
' +
+ '
' +
+ ' {{#if isPublic}}' +
+ '
' +
+ '
' +
+ ' {{/if}}' +
+ '
' +
+ '{{/if}}';
var CallInfoView = Marionette.View.extend({
- tagName: 'h3',
+ tagName: 'div',
template: Handlebars.compile(TEMPLATE),
+
+ renderTimeout: undefined,
+
templateContext: function() {
- return {
- displayName: this.model.get('displayName')
- };
+ var canModerate = this.model.get('participantType') === 1 || this.model.get('participantType') === 2;
+ return $.extend(this.model.toJSON(), {
+ canModerate: canModerate,
+ isPublic: this.model.get('type') === 3,
+ showShareLink: !canModerate && this.model.get('type') === 3,
+ isNameEditable: canModerate && this.model.get('type') !== 1,
+ isDeletable: canModerate && (Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0)
+ });
+ },
+
+ ui: {
+ 'roomName': 'h3.room-name',
+ 'clipboardButton': '.clipboard-button',
+ 'linkCheckbox': '.link-checkbox',
+
+ 'renameButton': '.rename-button',
+ 'renameOption': '.rename-option',
+ 'renameInput': '.rename-input',
+ 'renameConfirm': '.rename-confirm',
+
+ 'passwordOption': '.password-option',
+ 'passwordInput': '.password-input',
+ 'passwordConfirm': '.password-confirm'
+ },
+
+ events: {
+ 'change @ui.linkCheckbox': 'toggleLinkCheckbox',
+
+ 'click @ui.renameButton': 'showRenameInput',
+ 'keyup @ui.renameInput': 'keyUpRename',
+ 'click @ui.renameConfirm': 'confirmRename',
+
+ 'keyup @ui.passwordInput': 'keyUpPassword',
+ 'click @ui.passwordConfirm': 'confirmPassword'
},
modelEvents: {
'change:displayName': function() {
+ this.renderWhenInactive();
+ },
+ 'change:hasPassword': function() {
+ this.renderWhenInactive();
+ },
+ 'change:participantType': function() {
+ // User permission change, refresh even when typing, because the
+ // action will fail in the future anyway.
this.render();
},
- }
+ 'change:type': function() {
+ this.renderWhenInactive();
+ }
+ },
+ renderWhenInactive: function() {
+ if (!this.ui.renameInput.is(':visible') &&
+ this.ui.passwordInput.val() === '') {
+ this.render();
+ return;
+ }
+
+ this.renderTimeout = setTimeout(_.bind(this.renderWhenInactive, this), 500);
+ },
+
+ onRender: function() {
+ if (!_.isUndefined(this.renderTimeout)) {
+ clearTimeout(this.renderTimeout);
+ this.renderTimeout = undefined;
+ }
+
+ var roomURL = OC.generateUrl('/call/' + this.model.get('token')),
+ completeURL = window.location.protocol + '//' + window.location.host + roomURL;
+
+ this.ui.clipboardButton.attr('value', completeURL);
+ this.ui.clipboardButton.attr('data-clipboard-text', completeURL);
+ this.ui.clipboardButton.tooltip({
+ placement: 'bottom',
+ trigger: 'hover',
+ title: t('spreed', 'Copy')
+ });
+ this.initClipboard();
+ },
+
+ /**
+ * Rename
+ */
+ showRenameInput: function() {
+ this.ui.renameOption.removeClass('hidden-important');
+ this.ui.roomName.addClass('hidden-important');
+ this.ui.renameButton.addClass('hidden-important');
+ },
+
+ hideRenameInput: function() {
+ this.ui.renameOption.addClass('hidden-important');
+ this.ui.roomName.removeClass('hidden-important');
+ this.ui.renameButton.removeClass('hidden-important');
+ },
+
+ confirmRename: function() {
+ var newRoomName = this.ui.renameInput.val().trim();
+
+ if (newRoomName === this.model.get('name')) {
+ this.hideRenameInput();
+ return;
+ }
+
+ console.log('Changing room name from "' + this.model.get('name') + '" to "' + newRoomName + '".');
+
+ $.ajax({
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token'),
+ type: 'PUT',
+ data: {
+ roomName: newRoomName
+ },
+ success: function() {
+ this.ui.roomName.text(newRoomName);
+ this.hideRenameInput();
+ OCA.SpreedMe.app.syncRooms();
+ }.bind(this)
+ });
+
+ console.log('.rename-option');
+ },
+
+ keyUpRename: function(e) {
+ if (e.keyCode === 13) {
+ // Enter
+ this.confirmRename();
+ } else if (e.keyCode === 27) {
+ // ESC
+ this.hideRenameInput();
+ this.ui.renameInput.val(this.model.get('name'));
+ }
+ },
+
+ /**
+ * Share link
+ */
+ toggleLinkCheckbox: function() {
+ var shareLink = this.ui.linkCheckbox.attr('checked') === 'checked';
+
+ $.ajax({
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/public',
+ type: shareLink ? 'POST' : 'DELETE',
+ success: function() {
+ OCA.SpreedMe.app.syncRooms();
+ }
+ });
+ },
+
+ /**
+ * Password
+ */
+ confirmPassword: function() {
+ var newPassword = this.ui.passwordInput.val().trim();
+
+ console.log('Setting room password to "' + newPassword + '".');
+ console.log('Setting room password to "' + this.model.get('hasPassword') + '".');
+
+ $.ajax({
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/password',
+ type: 'PUT',
+ data: {
+ password: newPassword
+ },
+ success: function() {
+ OCA.SpreedMe.app.syncRooms();
+ }.bind(this)
+ });
+
+ console.log('.rename-option');
+ },
+
+ keyUpPassword: function(e) {
+ if (e.keyCode === 13) {
+ // Enter
+ this.confirmPassword();
+ } else if (e.keyCode === 27) {
+ // ESC
+ this.ui.passwordInput.val('');
+ }
+ },
+
+ /**
+ * Clipboard
+ */
+ initClipboard: function() {
+ var clipboard = new Clipboard('.clipboard-button');
+ clipboard.on('success', function(e) {
+ var $input = $(e.trigger);
+ $input.tooltip('hide')
+ .attr('data-original-title', t('core', 'Copied!'))
+ .tooltip('fixTitle')
+ .tooltip({placement: 'bottom', trigger: 'manual'})
+ .tooltip('show');
+ _.delay(function() {
+ $input.tooltip('hide')
+ .attr('data-original-title', t('core', 'Copy'))
+ .tooltip('fixTitle');
+ }, 3000);
+ });
+ clipboard.on('error', function (e) {
+ var $input = $(e.trigger);
+ var actionMsg = '';
+ if (/iPhone|iPad/i.test(navigator.userAgent)) {
+ actionMsg = t('core', 'Not supported!');
+ } else if (/Mac/i.test(navigator.userAgent)) {
+ actionMsg = t('core', 'Press ⌘-C to copy.');
+ } else {
+ actionMsg = t('core', 'Press Ctrl-C to copy.');
+ }
+
+ $input.tooltip('hide')
+ .attr('data-original-title', actionMsg)
+ .tooltip('fixTitle')
+ .tooltip({placement: 'bottom', trigger: 'manual'})
+ .tooltip('show');
+ _.delay(function () {
+ $input.tooltip('hide')
+ .attr('data-original-title', t('spreed', 'Copy'))
+ .tooltip('fixTitle');
+ }, 3000);
+ });
+ }
});
OCA.SpreedMe.Views.CallInfoView = CallInfoView;
-})(OCA, Marionette, Handlebars);
+})(OC, OCA, Marionette, Handlebars, $, _);
diff --git a/js/views/participantlistview.js b/js/views/participantlistview.js
new file mode 100644
index 000000000..22359758e
--- /dev/null
+++ b/js/views/participantlistview.js
@@ -0,0 +1,248 @@
+/* global Marionette, Handlebars */
+
+/**
+ * @author Christoph Wurst
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+
+(function(OC, OCA, Marionette, Handlebars) {
+ 'use strict';
+
+ OCA.SpreedMe = OCA.SpreedMe || {};
+ OCA.SpreedMe.Views = OCA.SpreedMe.Views || {};
+
+ var uiChannel = Backbone.Radio.channel('ui');
+
+ var ITEM_TEMPLATE = '' +
+ '' +
+ '' +
+ ' {{name}}' +
+ '{{#if participantIsOwner}}(' + t('spreed', 'moderator') + '){{/if}}' +
+ '{{#if participantIsModerator}}(' + t('spreed', 'moderator') + '){{/if}}' +
+ ''+
+ '{{#if canModerate}}' +
+ ''+
+ '' +
+ '{{/if}}';
+
+ OCA.SpreedMe.Views.ParticipantListView = Marionette.CollectionView.extend({
+ tagName: 'ul',
+ className: 'participantWithList',
+ collectionEvents: {
+ 'update': function() {
+ this.render();
+ },
+ 'reset': function() {
+ this.render();
+ },
+ 'sort': function() {
+ this.render();
+ },
+ 'sync': function() {
+ this.render();
+ }
+ },
+ childView: Marionette.View.extend({
+ tagName: 'li',
+ modelEvents: {
+ 'change:active': function() {
+ this.render();
+ },
+ 'change:displayName': function() {
+ this.render();
+ },
+ 'change:participants': function() {
+ this.render();
+ },
+ 'change:type': function() {
+ this.render();
+ this.checkSharingStatus();
+ }
+ },
+ initialize: function() {
+ this.listenTo(uiChannel, 'document:click', function(event) {
+ var target = $(event.target);
+ if (!this.$el.is(target.closest('.participant'))) {
+ // Click was not triggered by this element -> close menu
+ this.menuShown = false;
+ this.toggleMenuClass();
+ }
+ });
+ },
+ templateContext: function() {
+ var canModerate = this.model.get('participantType') !== OCA.SpreedMe.app.OWNER && // can not moderate owners
+ this.model.get('userId') !== oc_current_user && // can not moderate yourself
+ (OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.OWNER || // current user must be owner
+ OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.MODERATOR); // or moderator.
+
+ return {
+ canModerate: canModerate,
+ name: this.model.get('userId').length ? this.model.get('displayName') : t('spreed', 'Guest'),
+ participantIsUser: this.model.get('participantType') === OCA.SpreedMe.app.USER,
+ participantIsModerator: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR,
+ participantIsOwner: this.model.get('participantType') === OCA.SpreedMe.app.OWNER
+ };
+ },
+ onRender: function() {
+ this.$el.find('.avatar').each(function() {
+ var element = $(this);
+ if (element.data('displayname').length) {
+ element.avatar(element.data('user-id'), 32, undefined, false, undefined, element.data('displayname'));
+ } else {
+ element.imageplaceholder('?', undefined, 32);
+ element.css('background-color', '#b9b9b9');
+ }
+ });
+
+ this.$el.attr('data-session-id', this.model.get('sessionId'));
+ this.$el.attr('data-participant', this.model.get('userId'));
+ this.$el.addClass('participant');
+
+ if (!this.model.isOnline()) {
+ this.$el.addClass('participant-offline');
+ }
+
+ this.toggleMenuClass();
+ },
+ events: {
+ 'click .participant-entry-utils-menu-button button': 'toggleMenu',
+ 'click .popovermenu .promote-moderator': 'promoteToModerator',
+ 'click .popovermenu .demote-moderator': 'demoteFromModerator',
+ 'click .popovermenu .remove-participant': 'removeParticipant'
+ },
+ ui: {
+ 'participant': 'li.participant',
+ 'menu': '.popovermenu'
+ },
+ template: Handlebars.compile(ITEM_TEMPLATE),
+ menuShown: false,
+ toggleMenu: function(e) {
+ e.preventDefault();
+ this.menuShown = !this.menuShown;
+ this.toggleMenuClass();
+ },
+ toggleMenuClass: function() {
+ this.ui.menu.toggleClass('open', this.menuShown);
+ },
+ promoteToModerator: function() {
+ if (this.model.get('participantType') !== OCA.SpreedMe.app.USER) {
+ return;
+ }
+
+ var participantId = this.model.get('userId'),
+ self = this;
+
+ $.ajax({
+ type: 'POST',
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators',
+ data: {
+ participant: participantId
+ },
+ success: function() {
+ self.render();
+ },
+ error: function() {
+ console.log('Error while promoting user to moderator');
+ }
+ });
+ },
+ demoteFromModerator: function() {
+ if (this.model.get('participantType') !== OCA.SpreedMe.app.MODERATOR) {
+ return;
+ }
+
+ var participantId = this.model.get('userId'),
+ self = this;
+
+ $.ajax({
+ type: 'DELETE',
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators',
+ data: {
+ participant: participantId
+ },
+ success: function() {
+ self.render();
+ },
+ error: function() {
+ console.log('Error while demoting moderator');
+ }
+ });
+ },
+ removeParticipant: function() {
+ if (this.model.get('participantType') === OCA.SpreedMe.app.OWNER) {
+ return;
+ }
+
+ var self = this,
+ participantId = this.model.get('userId'),
+ endpoint = '/participants';
+
+ if (this.model.get('participantType') === OCA.SpreedMe.app.GUEST) {
+ participantId = this.model.get('sessionId');
+ endpoint += '/guests';
+ }
+
+ $.ajax({
+ type: 'DELETE',
+ url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + endpoint,
+ data: {
+ participant: participantId
+ },
+ success: function() {
+ self.render();
+ },
+ error: function() {
+ console.log('Error while removing user from room');
+ }
+ });
+ }
+ })
+ });
+
+})(OC, OCA, Marionette, Handlebars);
diff --git a/js/views/participantview.js b/js/views/participantview.js
index 5bcd5ce9c..6ed838b4b 100644
--- a/js/views/participantview.js
+++ b/js/views/participantview.js
@@ -1,7 +1,8 @@
/* global Marionette, Handlebars */
/**
- * @author Christoph Wurst
+ *
+ * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
*
* @license GNU AGPL version 3 or any later version
*
@@ -20,229 +21,164 @@
*
*/
-
(function(OC, OCA, Marionette, Handlebars) {
'use strict';
OCA.SpreedMe = OCA.SpreedMe || {};
OCA.SpreedMe.Views = OCA.SpreedMe.Views || {};
- var uiChannel = Backbone.Radio.channel('ui');
+ var TEMPLATE = ''+
+ ''+
+ '';
- var ITEM_TEMPLATE = '' +
- '' +
- '' +
- ' {{name}}' +
- '{{#if participantIsOwner}}(' + t('spreed', 'moderator') + '){{/if}}' +
- '{{#if participantIsModerator}}(' + t('spreed', 'moderator') + '){{/if}}' +
- ''+
- '{{#if canModerate}}' +
- ''+
- '' +
- '{{/if}}';
+ OCA.SpreedMe.Views.ParticipantView = Marionette.View.extend({
- OCA.SpreedMe.Views.ParticipantView = Marionette.CollectionView.extend({
- tagName: 'ul',
- className: 'participantWithList',
- collectionEvents: {
- 'update': function() {
- this.render();
- },
- 'reset': function() {
- this.render();
- },
- 'sort': function() {
- this.render();
- },
- 'sync': function() {
- this.render();
- }
+ tagName: 'div',
+
+ ui: {
+ addParticipantInput: '.add-person-input',
+ participantList: '.participantWithList'
},
- childView: Marionette.View.extend({
- tagName: 'li',
- modelEvents: {
- 'change:active': function() {
- this.render();
- },
- 'change:displayName': function() {
- this.render();
- },
- 'change:participants': function() {
- this.render();
- },
- 'change:type': function() {
- this.render();
- this.checkSharingStatus();
- }
- },
- initialize: function() {
- this.listenTo(uiChannel, 'document:click', function(event) {
- var target = $(event.target);
- if (!this.$el.is(target.closest('.participant'))) {
- // Click was not triggered by this element -> close menu
- this.menuShown = false;
- this.toggleMenuClass();
- }
- });
- },
- templateContext: function() {
- var canModerate = this.model.get('participantType') !== OCA.SpreedMe.app.OWNER && // can not moderate owners
- this.model.get('userId') !== oc_current_user && // can not moderate yourself
- (OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.OWNER || // current user must be owner
- OCA.SpreedMe.app.activeRoom.get('participantType') === OCA.SpreedMe.app.MODERATOR); // or moderator.
- return {
- canModerate: canModerate,
- name: this.model.get('userId').length ? this.model.get('displayName') : t('spreed', 'Guest'),
- participantIsUser: this.model.get('participantType') === OCA.SpreedMe.app.USER,
- participantIsModerator: this.model.get('participantType') === OCA.SpreedMe.app.MODERATOR,
- participantIsOwner: this.model.get('participantType') === OCA.SpreedMe.app.OWNER
- };
- },
- onRender: function() {
- this.$el.find('.avatar').each(function() {
+ regions: {
+ participantList: '@ui.participantList'
+ },
+
+ template: Handlebars.compile(TEMPLATE),
+
+ initialize: function(options) {
+ this.room = options.room;
+ this.collection = options.collection;
+ this._participantListView = new OCA.SpreedMe.Views.ParticipantListView({ collection: options.collection });
+
+ // In Marionette 3.0 the view is not rendered automatically if
+ // needed when showing a child view, so it must be rendered
+ // explicitly to ensure that the DOM element in which the child view
+ // will be appended exists.
+ this.render();
+ this.showChildView('participantList', this._participantListView, { replaceElement: true } );
+ },
+
+ /**
+ * @param {OCA.SpreedMe.Models.Room} room
+ * @returns {Array}
+ */
+ setRoom: function(room) {
+ this.room = room;
+ this.collection.setRoom(room);
+ },
+
+ onRender: function() {
+ this.initAddParticipantSelector();
+ },
+
+ initAddParticipantSelector: function() {
+ this.ui.addParticipantInput.select2({
+ ajax: {
+ url: OC.linkToOCS('apps/files_sharing/api/v1') + 'sharees',
+ dataType: 'json',
+ quietMillis: 100,
+ data: function (term) {
+ return {
+ format: 'json',
+ search: term,
+ perPage: 200,
+ itemType: 'call'
+ };
+ },
+ results: function (response) {
+ // TODO improve error case
+ if (_.isUndefined(response.ocs.data)) {
+ return;
+ }
+
+ var results = [],
+ participants = this.room.get('participants');
+
+ $.each(response.ocs.data.exact.users, function(id, user) {
+ var isExactUserInGroup = false;
+
+ $.each(participants, function(participantId) {
+ if (participantId === user.value.shareWith) {
+ isExactUserInGroup = true;
+ }
+ });
+
+ if (!isExactUserInGroup) {
+ results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
+ }
+ });
+
+ $.each(response.ocs.data.users, function(id, user) {
+ var isUserInGroup = false;
+
+ $.each(participants, function(participantId) {
+ if (participantId === user.value.shareWith) {
+ isUserInGroup = true;
+ }
+ });
+
+ if (!isUserInGroup) {
+ results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
+ }
+ });
+
+ return {
+ results: results,
+ more: false
+ };
+ }.bind(this)
+ },
+ initSelection: function (element, callback) {
+ callback({id: element.val()});
+ },
+ formatResult: function (element) {
+ return '' + escapeHTML(element.displayName) + '';
+ },
+ formatSelection: function () {
+ return ''+OC.L10N.translate('spreed', 'Choose person…')+'';
+ }
+ });
+ this.ui.addParticipantInput.on('change', function(e) {
+ var token = this.room.get('token');
+ var participant = e.val;
+ OCA.SpreedMe.app.addParticipantToRoom(token, participant);
+
+ $('.select2-drop').find('.avatar').each(function () {
var element = $(this);
- if (element.data('displayname').length) {
- element.avatar(element.data('user-id'), 32, undefined, false, undefined, element.data('displayname'));
+ if (element.data('user-display-name')) {
+ element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
} else {
- element.imageplaceholder('?', undefined, 32);
- element.css('background-color', '#b9b9b9');
+ element.avatar(element.data('user'), 32);
}
});
-
- this.$el.attr('data-session-id', this.model.get('sessionId'));
- this.$el.attr('data-participant', this.model.get('userId'));
- this.$el.addClass('participant');
-
- if (!this.model.isOnline()) {
- this.$el.addClass('participant-offline');
- }
-
- this.toggleMenuClass();
- },
- events: {
- 'click .participant-entry-utils-menu-button button': 'toggleMenu',
- 'click .popovermenu .promote-moderator': 'promoteToModerator',
- 'click .popovermenu .demote-moderator': 'demoteFromModerator',
- 'click .popovermenu .remove-participant': 'removeParticipant'
- },
- ui: {
- 'participant': 'li.participant',
- 'menu': '.popovermenu'
- },
- template: Handlebars.compile(ITEM_TEMPLATE),
- menuShown: false,
- toggleMenu: function(e) {
- e.preventDefault();
- this.menuShown = !this.menuShown;
- this.toggleMenuClass();
- },
- toggleMenuClass: function() {
- this.ui.menu.toggleClass('open', this.menuShown);
- },
- promoteToModerator: function() {
- if (this.model.get('participantType') !== OCA.SpreedMe.app.USER) {
- return;
- }
-
- var participantId = this.model.get('userId'),
- self = this;
-
- $.ajax({
- type: 'POST',
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators',
- data: {
- participant: participantId
- },
- success: function() {
- self.render();
- },
- error: function() {
- console.log('Error while promoting user to moderator');
+ }.bind(this));
+ this.ui.addParticipantInput.on('click', function() {
+ $('.select2-drop').find('.avatar').each(function () {
+ var element = $(this);
+ if (element.data('user-display-name')) {
+ element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
+ } else {
+ element.avatar(element.data('user'), 32);
}
});
- },
- demoteFromModerator: function() {
- if (this.model.get('participantType') !== OCA.SpreedMe.app.MODERATOR) {
- return;
- }
+ });
- var participantId = this.model.get('userId'),
- self = this;
-
- $.ajax({
- type: 'DELETE',
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + '/moderators',
- data: {
- participant: participantId
- },
- success: function() {
- self.render();
- },
- error: function() {
- console.log('Error while demoting moderator');
+ this.ui.addParticipantInput.on('select2-loaded', function() {
+ $('.select2-drop').find('.avatar').each(function () {
+ var element = $(this);
+ if (element.data('user-display-name')) {
+ element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
+ } else {
+ element.avatar(element.data('user'), 32);
}
});
- },
- removeParticipant: function() {
- if (this.model.get('participantType') === OCA.SpreedMe.app.OWNER) {
- return;
- }
+ });
+ }
- var self = this,
- participantId = this.model.get('userId'),
- endpoint = '/participants';
-
- if (this.model.get('participantType') === OCA.SpreedMe.app.GUEST) {
- participantId = this.model.get('sessionId');
- endpoint += '/guests';
- }
-
- $.ajax({
- type: 'DELETE',
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + OCA.SpreedMe.app.activeRoom.get('token') + endpoint,
- data: {
- participant: participantId
- },
- success: function() {
- self.render();
- },
- error: function() {
- console.log('Error while removing user from room');
- }
- });
- }
- })
});
})(OC, OCA, Marionette, Handlebars);
diff --git a/js/views/roomlistview.js b/js/views/roomlistview.js
index 4e8b05db8..06889cab6 100644
--- a/js/views/roomlistview.js
+++ b/js/views/roomlistview.js
@@ -42,70 +42,24 @@
''+
'';
- var RoomItenView = Marionette.View.extend({
+ var RoomItemView = Marionette.View.extend({
tagName: 'li',
modelEvents: {
'change:active': function() {
@@ -119,7 +73,6 @@
},
'change:type': function() {
this.render();
- this.checkSharingStatus();
}
},
initialize: function() {
@@ -135,32 +88,17 @@
});
},
templateContext: function() {
- var canModerate = this.model.get('participantType') === 1 || this.model.get('participantType') === 2;
return {
- canModerate: canModerate,
- showShareLink: !canModerate && this.model.get('type') === ROOM_TYPE_PUBLIC_CALL,
- isNameEditable: canModerate && this.model.get('type') !== ROOM_TYPE_ONE_TO_ONE,
- isDeletable: canModerate && (Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0)
+ isDeletable: (this.model.get('participantType') === 1 || this.model.get('participantType') === 2) &&
+ (Object.keys(this.model.get('participants')).length > 2 || this.model.get('numGuests') > 0)
};
},
onRender: function() {
- var roomURL, completeURL;
+ var roomURL;
- this.initPersonSelector();
this.checkSharingStatus();
roomURL = OC.generateUrl('/call/' + this.model.get('token'));
- completeURL = window.location.protocol + '//' + window.location.host + roomURL;
-
- this.ui.shareLinkInput.attr('value', completeURL);
- this.$el.find('.clipboardButton').attr('data-clipboard-text', completeURL);
- this.$el.find('.clipboardButton').tooltip({
- placement: 'bottom',
- trigger: 'hover',
- title: t('spreed', 'Copy')
- });
- this.initClipboard();
-
this.$el.find('.app-navigation-entry-link').attr('href', roomURL);
if (this.model.get('active')) {
@@ -179,26 +117,14 @@
},
events: {
'click .app-navigation-entry-utils-menu-button button': 'toggleMenu',
- 'click .app-navigation-entry-menu .add-person-button': 'addPerson',
- 'click .app-navigation-entry-menu .rename-room-button': 'showRenameInput',
- 'click .app-navigation-entry-menu .rename-confirm': 'confirmRoomRename',
- 'keyup .rename-input': 'renameKeyUp',
- 'click .app-navigation-entry-menu .password-room-button': 'showPasswordInput',
- 'click .app-navigation-entry-menu .password-confirm': 'confirmRoomPassword',
- 'keyup .password-input': 'passwordKeyUp',
- 'click .app-navigation-entry-menu .share-link-button': 'shareGroup',
- 'click .app-navigation-entry-menu .leave-room-button': 'leaveRoom',
- 'click .app-navigation-entry-menu .delete-room-button': 'deleteRoom',
- 'click .icon-delete': 'unshareGroup',
- 'click .app-navigation-entry-link': 'joinRoom'
+ 'click @ui.menu .leave-room-button': 'leaveRoom',
+ 'click @ui.menu .delete-room-button': 'deleteRoom',
+ 'click @ui.room': 'joinRoom'
},
ui: {
'room': '.app-navigation-entry-link',
'menu': '.app-navigation-entry-menu',
- 'shareLinkInput': '.share-link-input',
- 'menuList': '.app-navigation-entry-menu-list',
- 'personSelectorForm' : '.oca-spreedme-add-person',
- 'personSelectorInput': '.add-person-input'
+ 'menuList': '.app-navigation-entry-menu-list'
},
template: Handlebars.compile(ITEM_TEMPLATE),
menuShown: false,
@@ -209,14 +135,6 @@
},
toggleMenuClass: function() {
this.ui.menu.toggleClass('open', this.menuShown);
-
- // Hide rename and password input and show button when opening menu
- if (this.menuShown) {
- this.$el.find('.rename-element').addClass('hidden-important');
- this.$el.find('.rename-room-button').removeClass('hidden-important');
- this.$el.find('.password-element').addClass('hidden-important');
- this.$el.find('.password-room-button').removeClass('hidden-important');
- }
},
checkSharingStatus: function() {
if (this.model.get('type') === ROOM_TYPE_ONE_TO_ONE) { // 1on1
@@ -247,126 +165,6 @@
this.addRoomMessage();
}
},
- addPerson: function() {
- this.ui.menuList.attr('style', 'display: none !important');
- this.ui.personSelectorForm.toggleClass('hidden');
- this.ui.personSelectorInput.select2('open');
- },
- showRenameInput: function() {
- var currentRoomName = this.model.get('name');
-
- this.$el.find('.rename-element').removeClass('hidden-important');
- this.$el.find('.rename-room-button').addClass('hidden-important');
-
- if (currentRoomName) {
- this.$el.find('.rename-input').val(currentRoomName);
- }
-
- this.$el.find('.rename-input').focus();
- this.$el.find('.rename-input').select();
- },
- hideRenameInput: function() {
- this.$el.find('.rename-element').addClass('hidden-important');
- this.$el.find('.rename-room-button').removeClass('hidden-important');
- },
- confirmRoomRename: function() {
- var currentRoomName = this.model.get('name');
- var newRoomName = $.trim(this.$el.find('.rename-input').val());
-
- if (currentRoomName !== newRoomName) {
- console.log('Changing room name to: '+newRoomName+' from: '+currentRoomName);
- this.renameRoom(newRoomName);
- }
-
- this.hideRenameInput();
- },
- renameKeyUp: function(e) {
- if (e.keyCode === 13) {
- this.confirmRoomRename();
- } else if (e.keyCode === 27) {
- this.hideRenameInput();
- }
- },
- renameRoom: function(roomName) {
- var app = OCA.SpreedMe.app;
-
- // This should be the only case
- if ((this.model.get('type') !== ROOM_TYPE_ONE_TO_ONE) && (roomName.length <= 200)) {
- $.ajax({
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token'),
- type: 'PUT',
- data: 'roomName='+roomName,
- success: function() {
- app.syncRooms();
- }
- });
- }
- },
- showPasswordInput: function() {
- this.$el.find('.password-element').removeClass('hidden-important');
- this.$el.find('.password-room-button').addClass('hidden-important');
-
- this.$el.find('.password-input').focus();
- this.$el.find('.password-input').select();
- },
- hidePasswordInput: function() {
- this.$el.find('.password-element').addClass('hidden-important');
- this.$el.find('.password-room-button').removeClass('hidden-important');
- },
- confirmRoomPassword: function() {
- var newRoomPassword = $.trim(this.$el.find('.password-input').val());
- this.passwordRoom(newRoomPassword);
- this.hidePasswordInput();
- },
- passwordKeyUp: function(e) {
- if (e.keyCode === 13) {
- this.confirmRoomPassword();
- } else if (e.keyCode === 27) {
- this.hidePasswordInput();
- }
- },
- passwordRoom: function(roomPassword) {
- var app = OCA.SpreedMe.app;
-
- if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
- $.ajax({
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/password',
- type: 'PUT',
- data: 'password='+roomPassword,
- success: function() {
- app.syncRooms();
- }
- });
- }
- },
- shareGroup: function() {
- var app = OCA.SpreedMe.app;
-
- // This should be the only case
- if (this.model.get('type') !== ROOM_TYPE_PUBLIC_CALL) {
- $.ajax({
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/public',
- type: 'POST',
- success: function() {
- app.syncRooms();
- }
- });
- }
- },
- unshareGroup: function() {
- var app = OCA.SpreedMe.app;
-
- // This should be the only case
- if (this.model.get('type') === ROOM_TYPE_PUBLIC_CALL) {
- $.ajax({
- url: OC.linkToOCS('apps/spreed/api/v1/room', 2) + this.model.get('token') + '/public',
- type: 'DELETE',
- success: function() {
- app.syncRooms();
- }
- });
- }
- },
leaveRoom: function() {
// If user is in that room, it should leave the associated call first.
if (this.model.get('active')) {
@@ -507,164 +305,12 @@
html: 'true',
title: htmlstring
});
- },
- initClipboard: function () {
- var clipboard = new Clipboard('.clipboardButton');
- clipboard.on('success', function(e) {
- var $input = $(e.trigger);
- $input.tooltip('hide')
- .attr('data-original-title', t('core', 'Copied!'))
- .tooltip('fixTitle')
- .tooltip({placement: 'bottom', trigger: 'manual'})
- .tooltip('show');
- _.delay(function() {
- $input.tooltip('hide')
- .attr('data-original-title', t('core', 'Copy'))
- .tooltip('fixTitle');
- }, 3000);
- });
- clipboard.on('error', function (e) {
- var $input = $(e.trigger);
- var actionMsg = '';
- if (/iPhone|iPad/i.test(navigator.userAgent)) {
- actionMsg = t('core', 'Not supported!');
- } else if (/Mac/i.test(navigator.userAgent)) {
- actionMsg = t('core', 'Press ⌘-C to copy.');
- } else {
- actionMsg = t('core', 'Press Ctrl-C to copy.');
- }
-
- $input.tooltip('hide')
- .attr('data-original-title', actionMsg)
- .tooltip('fixTitle')
- .tooltip({placement: 'bottom', trigger: 'manual'})
- .tooltip('show');
- _.delay(function () {
- $input.tooltip('hide')
- .attr('data-original-title', t('spreed', 'Copy'))
- .tooltip('fixTitle');
- }, 3000);
- });
- },
- initPersonSelector: function() {
- var _this = this;
-
- this.ui.personSelectorInput.select2({
- ajax: {
- url: OC.linkToOCS('apps/files_sharing/api/v1') + 'sharees',
- dataType: 'json',
- quietMillis: 100,
- data: function (term) {
- return {
- format: 'json',
- search: term,
- perPage: 200,
- itemType: 'call'
- };
- },
- results: function (response) {
- // TODO improve error case
- if (response.ocs.data === undefined) {
- console.error('Failure happened', response);
- return;
- }
-
- var results = [],
- participants = _this.model.get('participants');
-
- $.each(response.ocs.data.exact.users, function(id, user) {
- var isExactUserInGroup = false;
-
- $.each(participants, function(participantId) {
- if (participantId === user.value.shareWith) {
- isExactUserInGroup = true;
- }
- });
-
- if (!isExactUserInGroup) {
- results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
- }
- });
-
- $.each(response.ocs.data.users, function(id, user) {
- var isUserInGroup = false;
-
- $.each(participants, function(participantId) {
- if (participantId === user.value.shareWith) {
- isUserInGroup = true;
- }
- });
-
- if (!isUserInGroup) {
- results.push({ id: user.value.shareWith, displayName: user.label, type: "user"});
- }
- });
-
- return {
- results: results,
- more: false
- };
- }
- },
- initSelection: function (element, callback) {
- console.log(element);
- callback({id: element.val()});
- },
- formatResult: function (element) {
- return '' + escapeHTML(element.displayName) + '';
- },
- formatSelection: function () {
- return ''+OC.L10N.translate('spreed', 'Choose person…')+'';
- }
- });
- this.ui.personSelectorInput.on('change', function(e) {
- var token = _this.model.get('token');
- var participant = e.val;
- OCA.SpreedMe.app.addParticipantToRoom(token, participant);
-
- $('.select2-drop').find('.avatar').each(function () {
- var element = $(this);
- if (element.data('user-display-name')) {
- element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
- } else {
- element.avatar(element.data('user'), 32);
- }
- });
- });
- this.ui.personSelectorInput.on('click', function() {
- $('.select2-drop').find('.avatar').each(function () {
- var element = $(this);
- if (element.data('user-display-name')) {
- element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
- } else {
- element.avatar(element.data('user'), 32);
- }
- });
- });
-
- this.ui.personSelectorInput.on('select2-loaded', function() {
- $('.select2-drop').find('.avatar').each(function () {
- var element = $(this);
- if (element.data('user-display-name')) {
- element.avatar(element.data('user'), 32, undefined, false, undefined, element.data('user-display-name'));
- } else {
- element.avatar(element.data('user'), 32);
- }
- });
- });
-
- this.ui.personSelectorInput.on('select2-close', function () {
- _this.ui.menuList.attr('style', 'display: block !important');
- _this.ui.personSelectorForm.toggleClass('hidden');
- _this.menuShown = false;
- _this.toggleMenuClass();
- });
}
});
var RoomListView = Marionette.CollectionView.extend({
tagName: 'ul',
- childView: RoomItenView
+ childView: RoomItemView
});
OCA.SpreedMe.Views.RoomListView = RoomListView;
diff --git a/templates/index.php b/templates/index.php
index 1b5259b38..2fe1da924 100644
--- a/templates/index.php
+++ b/templates/index.php
@@ -17,6 +17,7 @@ script(
'models/participant',
'models/participantcollection',
'views/callinfoview',
+ 'views/participantlistview',
'views/participantview',
'views/roomlistview',
'views/sidebarview',