avatar_area.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**
  2. * This file is part of Threema Web.
  3. *
  4. * Threema Web is free software: you can redistribute it and/or modify it
  5. * under the terms of the GNU Affero General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or (at
  7. * your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Affero General Public License
  15. * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. // tslint:disable:max-line-length
  18. import {bufferToUrl} from '../helpers';
  19. import {LogService} from '../services/log';
  20. import {WebClientService} from '../services/webclient';
  21. /**
  22. * Support uploading and resizing avatar
  23. */
  24. export default [
  25. '$rootScope',
  26. '$mdDialog',
  27. 'LogService',
  28. 'WebClientService',
  29. function($rootScope: ng.IRootScopeService,
  30. $mdDialog: ng.material.IDialogService,
  31. logService: LogService,
  32. webClientService: WebClientService) {
  33. const log = logService.getLogger('AvatarArea-C');
  34. return {
  35. restrict: 'EA',
  36. scope: true,
  37. bindToController: {
  38. onChange: '=',
  39. loadAvatar: '=',
  40. enableClear: '=?',
  41. color: '=?',
  42. },
  43. controllerAs: 'ctrl',
  44. controller: [function() {
  45. this.isLoading = false;
  46. this.avatar = null; // String
  47. const avatarFormat = webClientService.appCapabilities.imageFormat.avatar;
  48. this.$onInit = function() {
  49. this.setAvatar = (avatarBytes: ArrayBuffer) => {
  50. this.avatar = (avatarBytes === null)
  51. ? null
  52. : bufferToUrl(avatarBytes, avatarFormat, log);
  53. };
  54. this.imageChanged = (image: ArrayBuffer, notify = true) => {
  55. this.isLoading = true;
  56. if (notify === true && this.onChange !== undefined) {
  57. this.onChange(image);
  58. }
  59. this.setAvatar(image);
  60. this.isLoading = false;
  61. };
  62. if (this.loadAvatar !== undefined) {
  63. this.isLoading = true;
  64. (this.loadAvatar as Promise<ArrayBuffer>)
  65. .then((image: ArrayBuffer) => {
  66. $rootScope.$apply(() => {
  67. this.setAvatar(image);
  68. this.isLoading = false;
  69. });
  70. })
  71. .catch(() => {
  72. $rootScope.$apply(() => {
  73. this.isLoading = false;
  74. });
  75. });
  76. }
  77. this.delete = () => {
  78. this.imageChanged(null, true);
  79. };
  80. // show editor in a dialog
  81. this.modify = (ev) => {
  82. $mdDialog.show({
  83. controllerAs: 'ctrl',
  84. controller: function() {
  85. this.avatar = null;
  86. this.apply = () => $mdDialog.hide(this.avatar);
  87. this.cancel = () => $mdDialog.cancel();
  88. this.changeAvatar = (image: ArrayBuffer) => this.avatar = image;
  89. },
  90. template: `
  91. <md-dialog translate-attr="{'aria-label': 'messenger.UPLOAD_AVATAR'}">
  92. <form ng-cloak>
  93. <md-toolbar>
  94. <div class="md-toolbar-tools">
  95. <h2 translate>messenger.UPLOAD_AVATAR</h2>
  96. </div>
  97. </md-toolbar>
  98. <md-dialog-content>
  99. <div class="md-dialog-content avatar-area editor">
  100. <avatar-editor on-change="ctrl.changeAvatar"></avatar-editor>
  101. </div>
  102. </md-dialog-content>
  103. <md-dialog-actions layout="row" >
  104. <md-button ng-click="ctrl.cancel()">
  105. <span translate>common.CANCEL</span>
  106. </md-button>
  107. <md-button ng-click="ctrl.apply()">
  108. <span translate>common.OK</span>
  109. </md-button>
  110. </md-dialog-actions>
  111. </form>
  112. </md-dialog>
  113. `,
  114. parent: angular.element(document.body),
  115. targetEvent: ev,
  116. clickOutsideToClose: true,
  117. })
  118. .then((newImage: ArrayBuffer) => {
  119. // update image only if a image was set or if enable clear is true
  120. if (this.enableClear === true || newImage !== null) {
  121. this.imageChanged(newImage, true);
  122. }
  123. }, () => null);
  124. };
  125. };
  126. }],
  127. template: `
  128. <div class="avatar-area overview">
  129. <div class="avatar-image" ng-style="{ 'background-color': ctrl.color }">
  130. <div class="loading-element" ng-class="{'active': ctrl.isLoading}">
  131. <md-progress-circular
  132. class="md-primary"
  133. md-diameter="96"></md-progress-circular>
  134. </div>
  135. <img ng-src="{{ ctrl.avatar }}" ng-if="ctrl.avatar !== null">
  136. </div>
  137. <div class="avatar-area-navigation" layout="row" layout-wrap layout-margin layout-align="center">
  138. <md-button type="submit" class="md-raised" ng-click="ctrl.delete()" ng-if="ctrl.enableClear === true">
  139. <span translate>common.DELETE</span>
  140. </md-button>
  141. <md-button type="submit" class="md-raised md-primary" ng-click="ctrl.modify()">
  142. <span translate>messenger.UPLOAD_AVATAR</span>
  143. </md-button>
  144. </div>
  145. </div>
  146. </div>
  147. `,
  148. };
  149. },
  150. ];