mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			178 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			178 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Objective-C
		
	
//
 | 
						|
//  Copyright (c) 2017 Open Whisper Systems. All rights reserved.
 | 
						|
//
 | 
						|
 | 
						|
#import "OWSContactsSyncing.h"
 | 
						|
#import "Environment.h"
 | 
						|
#import "OWSContactsManager.h"
 | 
						|
#import "OWSProfileManager.h"
 | 
						|
#import <SignalServiceKit/DataSource.h>
 | 
						|
#import <SignalServiceKit/MIMETypeUtil.h>
 | 
						|
#import <SignalServiceKit/OWSMessageSender.h>
 | 
						|
#import <SignalServiceKit/OWSSyncContactsMessage.h>
 | 
						|
#import <SignalServiceKit/TSAccountManager.h>
 | 
						|
#import <SignalServiceKit/TSStorageManager.h>
 | 
						|
#import <SignalServiceKit/YapDatabaseConnection+OWS.h>
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_BEGIN
 | 
						|
 | 
						|
NSString *const kTSStorageManagerOWSContactsSyncingCollection = @"kTSStorageManagerOWSContactsSyncingCollection";
 | 
						|
NSString *const kTSStorageManagerOWSContactsSyncingLastMessageKey
 | 
						|
    = @"kTSStorageManagerOWSContactsSyncingLastMessageKey";
 | 
						|
 | 
						|
@interface OWSContactsSyncing ()
 | 
						|
 | 
						|
@property (nonatomic, readonly) dispatch_queue_t serialQueue;
 | 
						|
 | 
						|
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
 | 
						|
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
 | 
						|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
 | 
						|
@property (nonatomic, readonly) OWSProfileManager *profileManager;
 | 
						|
 | 
						|
@property (nonatomic) BOOL isRequestInFlight;
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
@implementation OWSContactsSyncing
 | 
						|
 | 
						|
+ (instancetype)sharedManager
 | 
						|
{
 | 
						|
    static OWSContactsSyncing *instance = nil;
 | 
						|
    static dispatch_once_t onceToken;
 | 
						|
    dispatch_once(&onceToken, ^{
 | 
						|
        instance = [[self alloc] initDefault];
 | 
						|
    });
 | 
						|
    return instance;
 | 
						|
}
 | 
						|
 | 
						|
- (instancetype)initDefault
 | 
						|
{
 | 
						|
    return [self initWithContactsManager:Environment.current.contactsManager
 | 
						|
                         identityManager:OWSIdentityManager.sharedManager
 | 
						|
                           messageSender:Environment.current.messageSender
 | 
						|
                          profileManager:OWSProfileManager.sharedManager];
 | 
						|
}
 | 
						|
 | 
						|
- (instancetype)initWithContactsManager:(OWSContactsManager *)contactsManager
 | 
						|
                        identityManager:(OWSIdentityManager *)identityManager
 | 
						|
                          messageSender:(OWSMessageSender *)messageSender
 | 
						|
                         profileManager:(OWSProfileManager *)profileManager
 | 
						|
{
 | 
						|
    self = [super init];
 | 
						|
 | 
						|
    if (!self) {
 | 
						|
        return self;
 | 
						|
    }
 | 
						|
 | 
						|
    OWSAssert(contactsManager);
 | 
						|
    OWSAssert(messageSender);
 | 
						|
    OWSAssert(identityManager);
 | 
						|
 | 
						|
    _contactsManager = contactsManager;
 | 
						|
    _identityManager = identityManager;
 | 
						|
    _messageSender = messageSender;
 | 
						|
    _profileManager = profileManager;
 | 
						|
 | 
						|
    OWSSingletonAssert();
 | 
						|
 | 
						|
    [[NSNotificationCenter defaultCenter] addObserver:self
 | 
						|
                                             selector:@selector(signalAccountsDidChange:)
 | 
						|
                                                 name:OWSContactsManagerSignalAccountsDidChangeNotification
 | 
						|
                                               object:nil];
 | 
						|
 | 
						|
    return self;
 | 
						|
}
 | 
						|
 | 
						|
- (void)dealloc
 | 
						|
{
 | 
						|
    [[NSNotificationCenter defaultCenter] removeObserver:self];
 | 
						|
}
 | 
						|
 | 
						|
- (void)signalAccountsDidChange:(id)notification
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    [self sendSyncContactsMessageIfPossible];
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark - Methods
 | 
						|
 | 
						|
- (void)sendSyncContactsMessageIfNecessary
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
 | 
						|
    if (!self.serialQueue) {
 | 
						|
        _serialQueue = dispatch_queue_create("org.whispersystems.contacts.syncing", DISPATCH_QUEUE_SERIAL);
 | 
						|
    }
 | 
						|
 | 
						|
    dispatch_async(self.serialQueue, ^{
 | 
						|
 | 
						|
        if (self.isRequestInFlight) {
 | 
						|
            // De-bounce.  It's okay if we ignore some new changes;
 | 
						|
            // `sendSyncContactsMessageIfPossible` is called fairly
 | 
						|
            // often so we'll sync soon.
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        OWSSyncContactsMessage *syncContactsMessage =
 | 
						|
            [[OWSSyncContactsMessage alloc] initWithSignalAccounts:self.contactsManager.signalAccounts
 | 
						|
                                                   identityManager:self.identityManager
 | 
						|
                                                    profileManager:self.profileManager];
 | 
						|
 | 
						|
        NSData *messageData = [syncContactsMessage buildPlainTextAttachmentData];
 | 
						|
 | 
						|
        NSData *lastMessageData =
 | 
						|
            [TSStorageManager.dbReadConnection objectForKey:kTSStorageManagerOWSContactsSyncingLastMessageKey
 | 
						|
                                               inCollection:kTSStorageManagerOWSContactsSyncingCollection];
 | 
						|
 | 
						|
        if (lastMessageData && [lastMessageData isEqual:messageData]) {
 | 
						|
            // Ignore redundant contacts sync message.
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        self.isRequestInFlight = YES;
 | 
						|
 | 
						|
        DataSource *dataSource =
 | 
						|
            [DataSourceValue dataSourceWithSyncMessage:[syncContactsMessage buildPlainTextAttachmentData]];
 | 
						|
        [self.messageSender enqueueTemporaryAttachment:dataSource
 | 
						|
            contentType:OWSMimeTypeApplicationOctetStream
 | 
						|
            inMessage:syncContactsMessage
 | 
						|
            success:^{
 | 
						|
                DDLogInfo(@"%@ Successfully sent contacts sync message.", self.logTag);
 | 
						|
 | 
						|
                [TSStorageManager.dbReadWriteConnection setObject:messageData
 | 
						|
                                                           forKey:kTSStorageManagerOWSContactsSyncingLastMessageKey
 | 
						|
                                                     inCollection:kTSStorageManagerOWSContactsSyncingCollection];
 | 
						|
 | 
						|
                dispatch_async(self.serialQueue, ^{
 | 
						|
                    self.isRequestInFlight = NO;
 | 
						|
                });
 | 
						|
            }
 | 
						|
            failure:^(NSError *error) {
 | 
						|
                DDLogError(@"%@ Failed to send contacts sync message with error: %@", self.logTag, error);
 | 
						|
 | 
						|
                dispatch_async(self.serialQueue, ^{
 | 
						|
                    self.isRequestInFlight = NO;
 | 
						|
                });
 | 
						|
            }];
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
- (void)sendSyncContactsMessageIfPossible
 | 
						|
{
 | 
						|
    OWSAssertIsOnMainThread();
 | 
						|
    if (self.contactsManager.signalAccounts.count == 0) {
 | 
						|
        // Don't bother if the contacts manager has no contacts,
 | 
						|
        // e.g. if the contacts manager hasn't finished setup.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ([TSAccountManager sharedInstance]) {
 | 
						|
        [self sendSyncContactsMessageIfNecessary];
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_END
 |