Forráskód Böngészése

Receiver editing: Only send avatar if changed (#244)

* TSLint: Allow leading underscores in variable names

* Add avatarChanged getter to AvatarControllerModel

* Contact editing: Only send avatar if changed

* Contact editing: Rename "highResolution" field to "avatar"

* Group editing: Only send avatar if changed

* Group editing: Rename "highResolution" field to "avatar"
Danilo Bargen 8 éve
szülő
commit
27a4024e93

+ 17 - 1
src/controller_model/avatar.ts

@@ -21,7 +21,8 @@ export class AvatarControllerModel {
     private $log: ng.ILogService;
     private avatar: ArrayBuffer = null;
     private loadAvatar: Promise<string>;
-    public onChangeAvatar: (image: ArrayBuffer) => void;
+    private onChangeAvatar: (image: ArrayBuffer) => void;
+    private _avatarChanged: boolean = false;
 
     constructor($log: ng.ILogService,
                 webClientService: WebClientService,
@@ -44,10 +45,25 @@ export class AvatarControllerModel {
         // bind to the editor
         this.onChangeAvatar = (image: ArrayBuffer) => {
             this.avatar = image;
+            this._avatarChanged = true;
         };
     }
 
+    /**
+     * Return the avatar bytes (or null if no avatar is defined).
+     */
     public getAvatar(): ArrayBuffer | null {
         return this.avatar;
     }
+
+    /**
+     * Return whether this avatar was changed.
+     *
+     * This will return true if an avatar was added or removed. It does not
+     * actually look at the content to determine whether the bytes of the
+     * avatar really changed.
+     */
+    public get avatarChanged(): boolean {
+        return this._avatarChanged;
+    }
 }

+ 1 - 1
src/controller_model/contact.ts

@@ -118,7 +118,7 @@ export class ContactControllerModel implements threema.ControllerModel {
                     this.contact.id,
                     this.firstName,
                     this.lastName,
-                    this.avatarController.getAvatar(),
+                    this.avatarController.avatarChanged ? this.avatarController.getAvatar() : undefined,
                 );
             case ControllerModelMode.NEW:
                 return this.webClientService.addContact(this.identity);

+ 1 - 2
src/controller_model/group.ts

@@ -199,10 +199,9 @@ export class GroupControllerModel implements threema.ControllerModel {
                     this.group.id,
                     this.members,
                     this.name,
-                    this.avatarController.getAvatar(),
+                    this.avatarController.avatarChanged ? this.avatarController.getAvatar() : undefined,
                 );
             case ControllerModelMode.NEW:
-
                 return this.webClientService.createGroup(
                     this.members,
                     this.name,

+ 6 - 6
src/partials/welcome.ts

@@ -57,7 +57,7 @@ class WelcomeController {
 
     // Custom services
     private webClientService: WebClientService;
-    private TrustedKeyStore: TrustedKeyStoreService;
+    private trustedKeyStore: TrustedKeyStoreService;
     private pushService: PushService;
     private stateService: StateService;
 
@@ -76,7 +76,7 @@ class WelcomeController {
                 $timeout: ng.ITimeoutService, $interval: ng.IIntervalService,
                 $log: ng.ILogService, $window: ng.IWindowService, $mdDialog: ng.material.IDialogService,
                 $translate: ng.translate.ITranslateService,
-                webClientService: WebClientService, TrustedKeyStore: TrustedKeyStoreService,
+                webClientService: WebClientService, trustedKeyStore: TrustedKeyStoreService,
                 stateService: StateService, pushService: PushService,
                 browserService: BrowserService,
                 versionService: VersionService,
@@ -95,7 +95,7 @@ class WelcomeController {
 
         // Own services
         this.webClientService = webClientService;
-        this.TrustedKeyStore = TrustedKeyStore;
+        this.trustedKeyStore = trustedKeyStore;
         this.stateService = stateService;
         this.pushService = pushService;
 
@@ -127,7 +127,7 @@ class WelcomeController {
         }
 
         // Determine whether local storage is available
-        if (this.TrustedKeyStore.blocked === true) {
+        if (this.trustedKeyStore.blocked === true) {
             $log.error('Cannot access local storage. Is it being blocked by a browser add-on?');
             this.showLocalStorageWarning();
         }
@@ -144,7 +144,7 @@ class WelcomeController {
             const keyStore = $stateParams.initParams.keyStore;
             const peerTrustedKey = $stateParams.initParams.peerTrustedKey;
             this.reconnect(keyStore, peerTrustedKey);
-        } else if (TrustedKeyStore.hasTrustedKey()) {
+        } else if (trustedKeyStore.hasTrustedKey()) {
             this.mode = 'unlock';
             this.unlock();
         } else {
@@ -225,7 +225,7 @@ class WelcomeController {
      * Decrypt the keys and initiate the session.
      */
     private unlockConfirm(): void {
-        const decrypted: threema.TrustedKeyStoreData = this.TrustedKeyStore.retrieveTrustedKey(this.password);
+        const decrypted: threema.TrustedKeyStoreData = this.trustedKeyStore.retrieveTrustedKey(this.password);
         if (decrypted === null) {
             return this.showDecryptionFailed();
         }

+ 51 - 35
src/services/webclient.ts

@@ -103,6 +103,7 @@ export class WebClientService {
     private static ARGUMENT_RECEIVER_ID = 'id';
     private static ARGUMENT_TEMPORARY_ID = 'temporaryId';
     private static ARGUMENT_REFERENCE_MSG_ID = 'refMsgId';
+    private static ARGUMENT_AVATAR = 'avatar';
     private static ARGUMENT_AVATAR_HIGH_RESOLUTION = 'highResolution';
     private static ARGUMENT_CONTACT_IS_TYPING = 'isTyping';
     private static ARGUMENT_MESSAGE_ID = 'messageId';
@@ -220,7 +221,7 @@ export class WebClientService {
                 qrCodeService: QrCodeService,
                 mimeService: MimeService,
                 receiverService: ReceiverService,
-                VersionService: VersionService,
+                versionService: VersionService,
                 CONFIG: threema.Config) {
 
         // Angular services
@@ -243,7 +244,7 @@ export class WebClientService {
         this.qrCodeService = qrCodeService;
         this.mimeService = mimeService;
         this.receiverService = receiverService;
-        this.versionService = VersionService;
+        this.versionService = versionService;
 
         // Configuration object
         this.config = CONFIG;
@@ -1050,7 +1051,7 @@ export class WebClientService {
     /**
      * Send a add Contact request
      */
-    public addContact(threemaId: String): Promise<threema.ContactReceiver> {
+    public addContact(threemaId: string): Promise<threema.ContactReceiver> {
         return this._sendCreatePromise(WebClientService.SUB_TYPE_CONTACT, {
             [WebClientService.ARGUMENT_IDENTITY]: threemaId,
         });
@@ -1059,38 +1060,52 @@ export class WebClientService {
     /**
      * Modify a contact name or a avatar
      */
-    public modifyContact(threemaId: String,
-                         firstName: String,
-                         lastName: String,
+    public modifyContact(threemaId: string,
+                         firstName?: string,
+                         lastName?: string,
                          avatar?: ArrayBuffer): Promise<threema.ContactReceiver> {
-        let promise = this._sendUpdatePromise(WebClientService.SUB_TYPE_CONTACT, {
+        // Prepare payload data
+        const data = {};
+        if (firstName !== undefined) {
+            data[WebClientService.ARGUMENT_FIRST_NAME] = firstName;
+        }
+        if (lastName !== undefined) {
+            data[WebClientService.ARGUMENT_LAST_NAME] = lastName;
+        }
+        if (avatar !== undefined) {
+            data[WebClientService.ARGUMENT_AVATAR] = avatar;
+        }
+
+        // If no changes happened, resolve the promise immediately.
+        if (Object.keys(data).length === 0) {
+            this.$log.warn(this.logTag, 'Trying to modify contact without any changes');
+            return Promise.resolve(this.contacts.get(threemaId));
+        }
+
+        // Send update
+        const args = {
             [WebClientService.ARGUMENT_IDENTITY]: threemaId,
-        }, {
-            [WebClientService.ARGUMENT_FIRST_NAME]: firstName,
-            [WebClientService.ARGUMENT_LAST_NAME]: lastName,
-            [WebClientService.ARGUMENT_AVATAR_HIGH_RESOLUTION]: avatar,
-        });
+        };
+        const promise = this._sendUpdatePromise(WebClientService.SUB_TYPE_CONTACT, args, data);
 
+        // If necessary, reset avatar to force a avatar reload
         if (avatar !== undefined) {
-            // reset avatar to force a avatar reload
-            this.receivers.getData({
-                type: 'contact',
-                id: threemaId,
-            } as threema.Receiver).avatar = {};
+            this.contacts.get(threemaId).avatar = {};
         }
+
         return promise;
     }
 
     /**
      * Create a group receiver
      */
-    public createGroup(members: String[],
-                       name: String = null,
+    public createGroup(members: string[],
+                       name: string = null,
                        avatar?: ArrayBuffer): Promise<threema.GroupReceiver> {
-        let data = {
+        const data = {
             [WebClientService.ARGUMENT_MEMBERS]: members,
             [WebClientService.ARGUMENT_NAME]: name,
-        } as any;
+        } as Object;
 
         if (avatar !== undefined) {
             data[WebClientService.ARGUMENT_AVATAR_HIGH_RESOLUTION] = avatar;
@@ -1101,26 +1116,27 @@ export class WebClientService {
 
     public modifyGroup(id: string,
                        members: String[],
-                       name: String = null,
+                       name?: String,
                        avatar?: ArrayBuffer): Promise<threema.GroupReceiver> {
-        let data = {
-            [WebClientService.ARGUMENT_MEMBERS]: members,
-            [WebClientService.ARGUMENT_NAME]: name,
-        } as any;
-
+        // Prepare payload data
+        const data = {};
+        data[WebClientService.ARGUMENT_MEMBERS] = members;
+        if (name !== undefined) {
+            data[WebClientService.ARGUMENT_NAME] = name;
+        }
         if (avatar !== undefined) {
-            data[WebClientService.ARGUMENT_AVATAR_HIGH_RESOLUTION] = avatar;
+            data[WebClientService.ARGUMENT_AVATAR] = avatar;
         }
-        let promise = this._sendUpdatePromise(WebClientService.SUB_TYPE_GROUP, {
+
+        // Send update
+        const args = {
             [WebClientService.ARGUMENT_RECEIVER_ID]: id,
-        }, data);
+        };
+        let promise = this._sendUpdatePromise(WebClientService.SUB_TYPE_GROUP, args, data);
 
+        // If necessary, reset avatar to force a avatar reload
         if (avatar !== undefined) {
-            // reset avatar to force a avatar reload
-            this.receivers.getData({
-                type: 'group',
-                id: id,
-            } as threema.GroupReceiver).avatar = {};
+            this.groups.get(id).avatar = {};
         }
         return promise;
     }

+ 2 - 1
tslint.json

@@ -11,6 +11,7 @@
         "only-arrow-functions": false,
         "quotemark": [true, "single", "avoid-escape"],
         "indent": [true, "spaces"],
-        "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type", "check-typecast", "check-preblock"]
+        "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type", "check-typecast", "check-preblock"],
+        "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"]
     }
 }