|
109 | 109 | '</div>' + |
110 | 110 | '</span>' + |
111 | 111 | '</li>' + |
| 112 | + '{{#if isTalkEnabled}}' + |
| 113 | + '<li>' + |
| 114 | + '<span class="shareOption menuitem">' + |
| 115 | + '<input id="passwordByTalk-{{cid}}-{{shareId}}" type="checkbox" name="passwordByTalk" class="passwordByTalk checkbox" {{#if isPasswordByTalkSet}}checked="checked"{{/if}} />' + |
| 116 | + '<label for="passwordByTalk-{{cid}}-{{shareId}}">{{passwordByTalkLabel}}</label>' + |
| 117 | + '<div class="passwordByTalkContainer-{{cid}}-{{shareId}} {{#unless isPasswordByTalkSet}}hidden{{/unless}}">' + |
| 118 | + ' <label for="passwordByTalkField-{{cid}}-{{shareId}}" class="hidden-visually" value="{{password}}">{{passwordByTalkLabel}}</label>' + |
| 119 | + ' <input id="passwordByTalkField-{{cid}}-{{shareId}}" class="passwordField" type="password" placeholder="{{passwordByTalkPlaceholder}}" value="{{passwordValue}}" autocomplete="new-password" />' + |
| 120 | + ' <span class="icon-loading-small hidden"></span>' + |
| 121 | + '</div>' + |
| 122 | + '</span>' + |
| 123 | + '</li>' + |
| 124 | + '{{/if}}' + |
112 | 125 | '{{/if}}' + |
113 | 126 | '<li>' + |
114 | 127 | '<span class="shareOption menuitem">' + |
|
160 | 173 | 'click .permissions': 'onPermissionChange', |
161 | 174 | 'click .expireDate' : 'onExpireDateChange', |
162 | 175 | 'click .password' : 'onMailSharePasswordProtectChange', |
| 176 | + 'click .passwordByTalk' : 'onMailSharePasswordProtectByTalkChange', |
163 | 177 | 'click .secureDrop' : 'onSecureDropChange', |
164 | 178 | 'keyup input.passwordField': 'onMailSharePasswordKeyUp', |
165 | 179 | 'focusout input.passwordField': 'onMailSharePasswordEntered', |
|
174 | 188 | throw 'missing OC.Share.ShareConfigModel'; |
175 | 189 | } |
176 | 190 |
|
| 191 | + this.isTalkEnabled = false; |
| 192 | + |
| 193 | + OCP.AppConfig.getValue('spreed', 'enabled', false, { |
| 194 | + success: _.bind(function(ocsResponse) { |
| 195 | + if (ocsResponse.evaluate('/ocs/data/data', ocsResponse, null, XPathResult.STRING_TYPE, null).stringValue === 'yes') { |
| 196 | + this.isTalkEnabled = true; |
| 197 | + // Render again just in case it was rendered before |
| 198 | + // receiving the response. |
| 199 | + this.render(); |
| 200 | + } |
| 201 | + }, this) |
| 202 | + }); |
| 203 | + |
177 | 204 | var view = this; |
178 | 205 | this.model.on('change:shares', function() { |
179 | 206 | view.render(); |
|
237 | 264 | var share = this.model.get('shares')[shareIndex]; |
238 | 265 | var password = share.password; |
239 | 266 | var hasPassword = password !== null && password !== ''; |
240 | | - |
| 267 | + var sendPasswordByTalk = share.send_password_by_talk; |
241 | 268 |
|
242 | 269 | return _.extend(hasPermissionOverride, { |
243 | 270 | cid: this.cid, |
|
258 | 285 | isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL, |
259 | 286 | isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE, |
260 | 287 | isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(), |
261 | | - isPasswordSet: hasPassword, |
| 288 | + isPasswordSet: hasPassword && !sendPasswordByTalk, |
| 289 | + isPasswordByTalkSet: hasPassword && sendPasswordByTalk, |
| 290 | + isTalkEnabled: this.isTalkEnabled, |
262 | 291 | secureDropMode: !this.model.hasReadPermission(shareIndex), |
263 | 292 | hasExpireDate: this.model.getExpireDate(shareIndex) !== null, |
264 | 293 | expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), |
| 294 | + // The password placeholder does not take into account if |
| 295 | + // sending the password by Talk is enabled or not; when |
| 296 | + // switching from sending the password by Talk to sending the |
| 297 | + // password by email the password is reused and the share |
| 298 | + // updated, so the placeholder already shows the password in the |
| 299 | + // brief time between disabling sending the password by email |
| 300 | + // and receiving the updated share. |
265 | 301 | passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, |
| 302 | + passwordByTalkPlaceholder: (hasPassword && sendPasswordByTalk)? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, |
266 | 303 | }); |
267 | 304 | }, |
268 | 305 |
|
|
277 | 314 | secureDropLabel: t('core', 'File drop (upload only)'), |
278 | 315 | expireDateLabel: t('core', 'Set expiration date'), |
279 | 316 | passwordLabel: t('core', 'Password protect'), |
| 317 | + passwordByTalkLabel: t('core', 'Password protect by Talk'), |
280 | 318 | crudsLabel: t('core', 'Access control'), |
281 | 319 | expirationDatePlaceholder: t('core', 'Expiration date'), |
282 | 320 | defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today |
|
558 | 596 | var inputClass = '#passwordField-' + this.cid + '-' + shareId; |
559 | 597 | var passwordField = $(inputClass); |
560 | 598 | var state = element.prop('checked'); |
561 | | - if (!state) { |
562 | | - this.model.updateShare(shareId, {password: ''}); |
| 599 | + var passwordByTalkElement = $('#passwordByTalk-' + this.cid + '-' + shareId); |
| 600 | + var passwordByTalkState = passwordByTalkElement.prop('checked'); |
| 601 | + if (!state && !passwordByTalkState) { |
| 602 | + this.model.updateShare(shareId, {password: '', sendPasswordByTalk: false}); |
563 | 603 | passwordField.attr('value', ''); |
564 | 604 | passwordField.removeClass('error'); |
565 | 605 | passwordField.tooltip('hide'); |
566 | 606 | loading.addClass('hidden'); |
567 | 607 | passwordField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE); |
568 | 608 | // We first need to reset the password field before we hide it |
569 | 609 | passwordContainer.toggleClass('hidden', !state); |
570 | | - } else { |
| 610 | + } else if (state) { |
| 611 | + if (passwordByTalkState) { |
| 612 | + // Switching from sending the password by Talk to sending |
| 613 | + // the password by mail can be done keeping the previous |
| 614 | + // password sent by Talk. |
| 615 | + this.model.updateShare(shareId, {sendPasswordByTalk: false}); |
| 616 | + |
| 617 | + var passwordByTalkContainerClass = '.passwordByTalkContainer-' + this.cid + '-' + shareId; |
| 618 | + var passwordByTalkContainer = $(passwordByTalkContainerClass); |
| 619 | + passwordByTalkContainer.addClass('hidden'); |
| 620 | + passwordByTalkElement.prop('checked', false); |
| 621 | + } |
| 622 | + |
571 | 623 | passwordContainer.toggleClass('hidden', !state); |
572 | 624 | passwordField = '#passwordField-' + this.cid + '-' + shareId; |
573 | 625 | this.$(passwordField).focus(); |
574 | 626 | } |
575 | 627 | }, |
576 | 628 |
|
| 629 | + onMailSharePasswordProtectByTalkChange: function(event) { |
| 630 | + var element = $(event.target); |
| 631 | + var li = element.closest('li[data-share-id]'); |
| 632 | + var shareId = li.data('share-id'); |
| 633 | + var passwordByTalkContainerClass = '.passwordByTalkContainer-' + this.cid + '-' + shareId; |
| 634 | + var passwordByTalkContainer = $(passwordByTalkContainerClass); |
| 635 | + var loading = this.$el.find(passwordByTalkContainerClass + ' .icon-loading-small'); |
| 636 | + var inputClass = '#passwordByTalkField-' + this.cid + '-' + shareId; |
| 637 | + var passwordByTalkField = $(inputClass); |
| 638 | + var state = element.prop('checked'); |
| 639 | + var passwordElement = $('#password-' + this.cid + '-' + shareId); |
| 640 | + var passwordState = passwordElement.prop('checked'); |
| 641 | + if (!state) { |
| 642 | + this.model.updateShare(shareId, {password: '', sendPasswordByTalk: false}); |
| 643 | + passwordByTalkField.attr('value', ''); |
| 644 | + passwordByTalkField.removeClass('error'); |
| 645 | + passwordByTalkField.tooltip('hide'); |
| 646 | + loading.addClass('hidden'); |
| 647 | + passwordByTalkField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE); |
| 648 | + // We first need to reset the password field before we hide it |
| 649 | + passwordByTalkContainer.toggleClass('hidden', !state); |
| 650 | + } else if (state) { |
| 651 | + if (passwordState) { |
| 652 | + // Enabling sending the password by Talk requires a new |
| 653 | + // password to be given (the one sent by mail is not reused, |
| 654 | + // as it would defeat the purpose of checking the identity |
| 655 | + // of the sharee by Talk if it was already sent by mail), so |
| 656 | + // the share is not updated until the user explicitly gives |
| 657 | + // the new password. |
| 658 | + |
| 659 | + var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; |
| 660 | + var passwordContainer = $(passwordContainerClass); |
| 661 | + passwordContainer.addClass('hidden'); |
| 662 | + passwordElement.prop('checked', false); |
| 663 | + } |
| 664 | + |
| 665 | + passwordByTalkContainer.toggleClass('hidden', !state); |
| 666 | + passwordByTalkField = '#passwordByTalkField-' + this.cid + '-' + shareId; |
| 667 | + this.$(passwordByTalkField).focus(); |
| 668 | + } |
| 669 | + }, |
| 670 | + |
577 | 671 | onMailSharePasswordKeyUp: function(event) { |
578 | 672 | if(event.keyCode === 13) { |
579 | 673 | this.onMailSharePasswordEntered(event); |
|
585 | 679 | var li = passwordField.closest('li[data-share-id]'); |
586 | 680 | var shareId = li.data('share-id'); |
587 | 681 | var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId; |
588 | | - var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); |
| 682 | + var passwordByTalkContainerClass = '.passwordByTalkContainer-' + this.cid + '-' + shareId; |
| 683 | + var sendPasswordByTalk = passwordField.attr('id').startsWith('passwordByTalk'); |
| 684 | + var loading; |
| 685 | + if (sendPasswordByTalk) { |
| 686 | + loading = this.$el.find(passwordByTalkContainerClass + ' .icon-loading-small'); |
| 687 | + } else { |
| 688 | + loading = this.$el.find(passwordContainerClass + ' .icon-loading-small'); |
| 689 | + } |
589 | 690 | if (!loading.hasClass('hidden')) { |
590 | 691 | // still in process |
591 | 692 | return; |
|
604 | 705 |
|
605 | 706 |
|
606 | 707 | this.model.updateShare(shareId, { |
607 | | - password: password |
| 708 | + password: password, |
| 709 | + sendPasswordByTalk: sendPasswordByTalk |
608 | 710 | }, { |
609 | 711 | error: function(model, msg) { |
610 | 712 | // destroy old tooltips |
|
0 commit comments