Browse Source

Add returnOld flag to Conversations.updateOrAdd

Also add some deep/shallow copy helpers.
Danilo Bargen 7 years ago
parent
commit
7a5e6c1da6
4 changed files with 35 additions and 9 deletions
  1. 14 0
      src/helpers.ts
  2. 3 3
      src/services/webclient.ts
  3. 1 1
      src/threema.d.ts
  4. 17 5
      src/threema/container.ts

+ 14 - 0
src/helpers.ts

@@ -371,3 +371,17 @@ export function isActionTrigger(ev: KeyboardEvent): boolean {
             return false;
     }
 }
+
+/*
+ * Create a shallow copy of an object.
+ */
+export function copyShallow<T extends object>(obj: T): T {
+    return Object.assign({}, obj);
+}
+
+/**
+ * Create a deep copy of an object by serializing and deserializing it.
+ */
+export function copyDeep<T extends object>(obj: T): T {
+    return JSON.parse(JSON.stringify(obj));
+}

+ 3 - 3
src/services/webclient.ts

@@ -2853,7 +2853,7 @@ export class WebClientService {
                 // To find out, we'll look at the unread count. If it has been
                 // incremented, it must be a new message.
                 if (data.unreadCount > 0) {
-                    const oldConversation = this.conversations.updateOrAdd(data);
+                    const oldConversation = this.conversations.updateOrAdd(data, true);
                     if (oldConversation === null) {
                         this.onNewMessage(data.latestMessage, data, receiver);
                     } else {
@@ -2871,7 +2871,7 @@ export class WebClientService {
                     }
                 } else {
                     // Update the conversation and hide any notifications
-                    this.conversations.updateOrAdd(data);
+                    this.conversations.updateOrAdd(data, false);
                     this.notificationService.hideNotification(data.type + '-' + data.id);
                 }
 
@@ -3832,7 +3832,7 @@ export class WebClientService {
         // If desired, log message type / subtype
         if (this.config.MSG_DEBUGGING) {
             // Deep copy message to prevent issues with JS debugger
-            const deepcopy = JSON.parse(JSON.stringify(message));
+            const deepcopy = copyDeep(message);
             this.$log.debug('[Message] Incoming:', message.type, '/', message.subType, deepcopy);
         }
 

+ 1 - 1
src/threema.d.ts

@@ -787,7 +787,7 @@ declare namespace threema {
             set(data: Conversation[]): void;
             find(pattern: Conversation | Receiver): Conversation | null;
             add(conversation: Conversation): void;
-            updateOrAdd(conversation: Conversation): Conversation | null;
+            updateOrAdd(conversation: Conversation, returnOld?: boolean): Conversation | null;
             remove(conversation: Conversation): void;
             setFilter(filter: (data: Conversation[]) => Conversation[]): void;
             setConverter(converter: (data: Conversation) => Conversation): void;

+ 17 - 5
src/threema/container.ts

@@ -15,6 +15,7 @@
  * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  */
 
+import {copyShallow} from '../helpers';
 import {isFirstUnreadStatusMessage} from '../message_helpers';
 import {ReceiverService} from '../services/receiver';
 
@@ -315,17 +316,28 @@ export class Conversations implements threema.Container.Conversations {
 
     /**
      * Add a conversation at the correct position.
-     * If a conversation already exists, replace it and return the old conversation.
+     * If a conversation already exists, update it and – in case returnOld is set –
+     * return a copy of the old conversation.
      */
-    public updateOrAdd(conversation: threema.ConversationWithPosition): threema.Conversation | null {
-        let replaced = null;
+    public updateOrAdd(
+        conversation: threema.ConversationWithPosition,
+        returnOld: boolean = false,
+    ): threema.Conversation | null {
         for (const i of this.conversations.keys()) {
             if (this.receiverService.compare(this.conversations[i], conversation)) {
-                replaced = this.conversations.splice(i, 1)[0];
+                // Conversation already exists!
+                // If `returnOld` is set, create a copy of the old conversation
+                let previousConversation = null;
+                if (returnOld) {
+                    previousConversation = copyShallow(this.conversations[i]);
+                }
+                // Copy properties from new conversation to old conversation
+                Object.assign(this.conversations[i], conversation);
+                return previousConversation;
             }
         }
         this.add(conversation);
-        return replaced;
+        return null;
     }
 
     /**