From 5c3c00243cf267e8461a255bd5f0892f950cd737 Mon Sep 17 00:00:00 2001
From: Ryan ZHAO <ryanzhaors@qq.com>
Date: Fri, 21 Feb 2020 15:11:07 +1100
Subject: [PATCH] send sync messages with 2 contacts and 1 group each time

---
 Signal/Signal-Info.plist                      |  2 +-
 ...nversationConfigurationSyncOperation.swift |  2 +-
 .../View Controllers/DeviceLinkingModal.swift |  2 +-
 .../DebugUI/DebugUISyncMessages.m             | 15 +--------
 SignalMessaging/contacts/OWSSyncManager.m     | 24 ++++++++++++--
 .../DeviceSyncing/OWSSyncGroupsMessage.h      |  6 +++-
 .../DeviceSyncing/OWSSyncGroupsMessage.m      | 33 +++++++++----------
 7 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/Signal/Signal-Info.plist b/Signal/Signal-Info.plist
index 342d37adb..9d7c02e10 100644
--- a/Signal/Signal-Info.plist
+++ b/Signal/Signal-Info.plist
@@ -7,7 +7,7 @@
 		<key>CarthageVersion</key>
 		<string>0.34.0</string>
 		<key>OSXVersion</key>
-		<string>10.15.3</string>
+		<string>10.15.2</string>
 		<key>WebRTCCommit</key>
 		<string>1445d719bf05280270e9f77576f80f973fd847f8 M73</string>
 	</dict>
diff --git a/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift b/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift
index 783c8af68..0a47382b7 100644
--- a/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift
+++ b/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift
@@ -64,7 +64,7 @@ class ConversationConfigurationSyncOperation: OWSOperation {
         // The current implementation works, but seems wasteful.
         // Does desktop handle single group sync correctly?
         // What does Android do?
-        let syncMessage: OWSSyncGroupsMessage = OWSSyncGroupsMessage()
+        let syncMessage: OWSSyncGroupsMessage = OWSSyncGroupsMessage(groupThread: groupThread)
 
         var dataSource: DataSource?
         self.dbConnection.read { transaction in
diff --git a/Signal/src/Loki/View Controllers/DeviceLinkingModal.swift b/Signal/src/Loki/View Controllers/DeviceLinkingModal.swift
index ba52bcf11..b2a304ea3 100644
--- a/Signal/src/Loki/View Controllers/DeviceLinkingModal.swift	
+++ b/Signal/src/Loki/View Controllers/DeviceLinkingModal.swift	
@@ -166,7 +166,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
         ThreadUtil.enqueue(linkingAuthorizationMessage)
         SSKEnvironment.shared.messageSender.send(linkingAuthorizationMessage, success: {
             let _ = SSKEnvironment.shared.syncManager.syncAllContacts()
-            _ = SSKEnvironment.shared.syncManager.syncAllGroups()
+//            _ = SSKEnvironment.shared.syncManager.syncAllGroups()
         }) { _ in
             print("[Loki] Failed to send device link authorization message.")
         }
diff --git a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m
index cc493cd89..124f14c86 100644
--- a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m
+++ b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m
@@ -108,20 +108,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (void)sendGroupSyncMessage
 {
-    OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
-    __block DataSource *dataSource;
-    [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
-        dataSource = [DataSourceValue
-            dataSourceWithSyncMessageData:[syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction]];
-    }];
-
-    [self.messageSenderJobQueue addMediaMessage:syncGroupsMessage
-                                     dataSource:dataSource
-                                    contentType:OWSMimeTypeApplicationOctetStream
-                                 sourceFilename:nil
-                                        caption:nil
-                                 albumMessageId:nil
-                          isTemporaryAttachment:YES];
+    [[self.syncManager syncAllGroups] retainUntilComplete];
 }
 
 + (void)sendBlockListSyncMessage
diff --git a/SignalMessaging/contacts/OWSSyncManager.m b/SignalMessaging/contacts/OWSSyncManager.m
index ba406ca04..4c4df6d87 100644
--- a/SignalMessaging/contacts/OWSSyncManager.m
+++ b/SignalMessaging/contacts/OWSSyncManager.m
@@ -23,6 +23,7 @@
 #import <SignalServiceKit/TSAccountManager.h>
 #import <SignalServiceKit/YapDatabaseConnection+OWS.h>
 #import <SignalServiceKit/TSContactThread.h>
+#import <SignalServiceKit/TSGroupThread.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -281,13 +282,21 @@ NSString *const kSyncManagerLastContactSyncKey = @"kTSStorageManagerOWSSyncManag
 - (AnyPromise *)syncAllContacts
 {
     NSMutableArray<SignalAccount *> *friends = @[].mutableCopy;
+    NSMutableArray<AnyPromise *> *promises = @[].mutableCopy;
     [TSContactThread enumerateCollectionObjectsUsingBlock:^(TSContactThread *thread, BOOL *stop) {
         NSString *hexEncodedPublicKey = thread.contactIdentifier;
         if (hexEncodedPublicKey != nil && thread.isContactFriend && thread.shouldThreadBeVisible && !thread.isForceHidden) {
             [friends addObject:[[SignalAccount alloc] initWithRecipientId:hexEncodedPublicKey]];
         }
+        if (friends.count >= 2) {
+            [promises addObject:[self syncContactsForSignalAccounts:friends]];
+            [friends removeAllObjects];
+        }
     }];
-    return [self syncContactsForSignalAccounts:friends];
+    if (friends.count > 0) {
+        [promises addObject:[self syncContactsForSignalAccounts:friends]];
+    }
+    return PMKJoin(promises);
 }
 
 - (AnyPromise *)syncContactsForSignalAccounts:(NSArray<SignalAccount *> *)signalAccounts
@@ -310,7 +319,18 @@ NSString *const kSyncManagerLastContactSyncKey = @"kTSStorageManagerOWSSyncManag
 
 - (AnyPromise *)syncAllGroups
 {
-    OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
+    NSMutableArray<AnyPromise *> *promises = @[].mutableCopy;
+    [TSGroupThread enumerateCollectionObjectsUsingBlock:^(TSGroupThread *thread, BOOL *stop) {
+        if (thread.groupModel && thread.shouldThreadBeVisible && !thread.isForceHidden) {
+            [promises addObject:[self syncGroupForThread:thread]];
+        }
+    }];
+    return PMKJoin(promises);
+}
+
+- (AnyPromise *)syncGroupForThread:(TSGroupThread *)thread
+{
+    OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] initWithGroupThread:thread];
     AnyPromise *promise = [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
         [self.messageSender sendMessage:syncGroupsMessage
             success:^{
diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h
index 7f5ba902f..6f7ccc188 100644
--- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h
+++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h
@@ -7,10 +7,14 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @class YapDatabaseReadTransaction;
+@class TSGroupThread;
 
 @interface OWSSyncGroupsMessage : OWSOutgoingSyncMessage
 
-- (instancetype)init NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithGroupThread:(TSGroupThread *)thread NS_DESIGNATED_INITIALIZER;
+
 - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
 
 - (nullable NSData *)buildPlainTextAttachmentDataWithTransaction:(YapDatabaseReadTransaction *)transaction;
diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m
index 5bce40231..9ee62dd34 100644
--- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m
+++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m
@@ -15,11 +15,24 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@interface OWSSyncGroupsMessage ()
+
+@property (nonatomic, readonly) TSGroupThread *groupThread;
+
+@end
+
 @implementation OWSSyncGroupsMessage
 
-- (instancetype)init
+- (instancetype)initWithGroupThread:(TSGroupThread *)thread
 {
-    return [super init];
+    self = [super init];
+    if (!self) {
+        return self;
+    }
+    
+    _groupThread = thread;
+    
+    return self;
 }
 
 - (nullable instancetype)initWithCoder:(NSCoder *)coder
@@ -75,21 +88,7 @@ NS_ASSUME_NONNULL_BEGIN
     NSOutputStream *dataOutputStream = [NSOutputStream outputStreamToMemory];
     [dataOutputStream open];
     OWSGroupsOutputStream *groupsOutputStream = [[OWSGroupsOutputStream alloc] initWithOutputStream:dataOutputStream];
-
-    [TSGroupThread
-        enumerateCollectionObjectsWithTransaction:transaction
-                                       usingBlock:^(id obj, BOOL *stop) {
-                                           if (![obj isKindOfClass:[TSGroupThread class]] || ((TSGroupThread *)obj).groupModel.groupType != closedGroup) {
-                                               if (![obj isKindOfClass:[TSContactThread class]]) {
-                                                   OWSLogWarn(
-                                                       @"Ignoring non group thread in thread collection: %@", obj);
-                                               }
-                                               return;
-                                           }
-                                           TSGroupThread *groupThread = (TSGroupThread *)obj;
-                                           [groupsOutputStream writeGroup:groupThread transaction:transaction];
-                                       }];
-
+    [groupsOutputStream writeGroup:self.groupThread transaction:transaction];
     [dataOutputStream close];
 
     if (groupsOutputStream.hasError) {