Added session restore message sending

pull/71/head
Mikunj 5 years ago
parent 58a260aac5
commit 770d8b2f3d

@ -1 +1 @@
Subproject commit 79eaca77d2f8b7aee0907f0610804682c41c8a4c Subproject commit fd594cfe7694dd9b568254eaa9551ed18366ae0e

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
2400888E239F30A600305217 /* SessionRestoreBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2400888D239F30A600305217 /* SessionRestoreBannerView.swift */; };
241C6314231F64C000B4198E /* JazzIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C630E231F5AAC00B4198E /* JazzIcon.swift */; }; 241C6314231F64C000B4198E /* JazzIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C630E231F5AAC00B4198E /* JazzIcon.swift */; };
241C6315231F64CE00B4198E /* CGFloat+Rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C6312231F5F1D00B4198E /* CGFloat+Rounding.swift */; }; 241C6315231F64CE00B4198E /* CGFloat+Rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C6312231F5F1D00B4198E /* CGFloat+Rounding.swift */; };
241C6316231F64CE00B4198E /* UIColor+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C6310231F5C4400B4198E /* UIColor+Helper.swift */; }; 241C6316231F64CE00B4198E /* UIColor+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241C6310231F5C4400B4198E /* UIColor+Helper.swift */; };
@ -681,6 +682,7 @@
0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1C93CF3971B64E8B6C1F9AC1 /* Pods-SignalShareExtension.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.test.xcconfig"; sourceTree = "<group>"; }; 1C93CF3971B64E8B6C1F9AC1 /* Pods-SignalShareExtension.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.test.xcconfig"; sourceTree = "<group>"; };
1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.test.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.test.xcconfig"; sourceTree = "<group>"; }; 1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.test.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.test.xcconfig"; sourceTree = "<group>"; };
2400888D239F30A600305217 /* SessionRestoreBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionRestoreBannerView.swift; sourceTree = "<group>"; };
241C630E231F5AAC00B4198E /* JazzIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JazzIcon.swift; sourceTree = "<group>"; }; 241C630E231F5AAC00B4198E /* JazzIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JazzIcon.swift; sourceTree = "<group>"; };
241C6310231F5C4400B4198E /* UIColor+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Helper.swift"; sourceTree = "<group>"; }; 241C6310231F5C4400B4198E /* UIColor+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Helper.swift"; sourceTree = "<group>"; };
241C6312231F5F1D00B4198E /* CGFloat+Rounding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGFloat+Rounding.swift"; sourceTree = "<group>"; }; 241C6312231F5F1D00B4198E /* CGFloat+Rounding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGFloat+Rounding.swift"; sourceTree = "<group>"; };
@ -2717,6 +2719,7 @@
B89841E222B7579F00B1BDC6 /* NewConversationVC.swift */, B89841E222B7579F00B1BDC6 /* NewConversationVC.swift */,
24BD2608234DA2050008EB0A /* NewPublicChatVC.swift */, 24BD2608234DA2050008EB0A /* NewPublicChatVC.swift */,
B893063E2383961A005EAA8E /* ScanQRCodeWrapperVC.swift */, B893063E2383961A005EAA8E /* ScanQRCodeWrapperVC.swift */,
2400888D239F30A600305217 /* SessionRestoreBannerView.swift */,
); );
path = Messaging; path = Messaging;
sourceTree = "<group>"; sourceTree = "<group>";
@ -3850,6 +3853,7 @@
B8162F0322891AD600D46544 /* FriendRequestView.swift in Sources */, B8162F0322891AD600D46544 /* FriendRequestView.swift in Sources */,
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */, 458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
34B6A905218B4C91007C4606 /* TypingIndicatorInteraction.swift in Sources */, 34B6A905218B4C91007C4606 /* TypingIndicatorInteraction.swift in Sources */,
2400888E239F30A600305217 /* SessionRestoreBannerView.swift in Sources */,
4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */, 4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */,
34EA69402194933900702471 /* MediaDownloadView.swift in Sources */, 34EA69402194933900702471 /* MediaDownloadView.swift in Sources */,
340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */, 340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */,

@ -0,0 +1,83 @@
@objc(LKSessionRestoreBannerView)
final class SessionRestoreBannerView : UIView {
private let thread: TSThread
@objc public var onRestore: (() -> Void)?
@objc public var onDismiss: (() -> Void)?
private lazy var bannerView: UIView = {
let bannerView = UIView.container()
bannerView.backgroundColor = UIColor.lokiGray()
bannerView.layer.cornerRadius = 2.5;
// Use a shadow to "pop" the indicator above the other views.
bannerView.layer.shadowColor = UIColor.black.cgColor
bannerView.layer.shadowOffset = CGSize(width: 2, height: 3)
bannerView.layer.shadowRadius = 2
bannerView.layer.shadowOpacity = 0.35
return bannerView
}()
private lazy var label: UILabel = {
let result = UILabel()
result.textColor = UIColor.white
result.font = UIFont.ows_dynamicTypeSubheadlineClamped
result.numberOfLines = 0
result.textAlignment = .center
result.lineBreakMode = .byWordWrapping
return result
}()
private lazy var buttonStackView: UIStackView = {
let result = UIStackView()
result.axis = .horizontal
result.distribution = .fillEqually
return result
}()
private lazy var buttonFont = UIFont.ows_dynamicTypeBodyClamped.ows_mediumWeight()
private lazy var buttonHeight = buttonFont.pointSize * 48 / 17
// MARK: Lifecycle
@objc init(thread: TSThread) {
self.thread = thread;
super.init(frame: CGRect.zero)
initialize()
}
required init?(coder: NSCoder) { fatalError("Using SessionRestoreBannerView.init(coder:) isn't allowed. Use SessionRestoreBannerView.init(thread:) instead.") }
override init(frame: CGRect) { fatalError("Using SessionRestoreBannerView.init(frame:) isn't allowed. Use SessionRestoreBannerView.init(thread:) instead.") }
private func initialize() {
// Set up UI
let mainStackView = UIStackView()
mainStackView.axis = .vertical
mainStackView.distribution = .fill
mainStackView.addArrangedSubview(label)
mainStackView.addArrangedSubview(buttonStackView)
let restoreButton = OWSFlatButton.button(title: NSLocalizedString("Restore session", comment: ""), font: buttonFont, titleColor: .ows_materialBlue, backgroundColor: .white, target: self, selector:#selector(restore))
restoreButton.setBackgroundColors(upColor: .clear, downColor: .clear)
restoreButton.autoSetDimension(.height, toSize: buttonHeight)
buttonStackView.addArrangedSubview(restoreButton)
let dismissButton = OWSFlatButton.button(title: NSLocalizedString("DISMISS_BUTTON_TEXT", comment: ""), font: buttonFont, titleColor: .ows_white, backgroundColor: .white, target: self, selector:#selector(dismiss))
dismissButton.setBackgroundColors(upColor: .clear, downColor: .clear)
dismissButton.autoSetDimension(.height, toSize: buttonHeight)
buttonStackView.addArrangedSubview(dismissButton)
bannerView.addSubview(mainStackView)
mainStackView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 16, left: 16, bottom: 8, right: 16))
addSubview(bannerView)
bannerView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
if let contactID = thread.contactIdentifier() {
let displayName = Environment.shared.contactsManager.profileName(forRecipientId: contactID) ?? contactID
label.text = String(format: NSLocalizedString("Would you like to start a new session with %@?", comment: ""), displayName)
}
}
@objc private func restore() { onRestore?() }
@objc private func dismiss() { onDismiss?() }
}

@ -431,12 +431,8 @@ typedef void (^SystemMessageActionBlock)(void);
}]; }];
case TSErrorMessageMissingKeyId: case TSErrorMessageMissingKeyId:
case TSErrorMessageNoSession: case TSErrorMessageNoSession:
return nil;
case TSErrorMessageInvalidMessage: case TSErrorMessageInvalidMessage:
return [SystemMessageAction actionWithTitle:NSLocalizedString(@"FINGERPRINT_SHRED_KEYMATERIAL_BUTTON", @"") return nil;
block:^{
[weakSelf.delegate tappedCorruptedMessage:message];
}];
case TSErrorMessageDuplicateMessage: case TSErrorMessageDuplicateMessage:
case TSErrorMessageInvalidVersion: case TSErrorMessageInvalidVersion:
return nil; return nil;

@ -803,6 +803,7 @@ typedef enum : NSUInteger {
OWSLogDebug(@"viewWillAppear"); OWSLogDebug(@"viewWillAppear");
[self ensureBannerState]; [self ensureBannerState];
[self updateSessionRestoreBanner];
[super viewWillAppear:animated]; [super viewWillAppear:animated];
@ -967,8 +968,20 @@ typedef enum : NSUInteger {
if (isContactThread) { if (isContactThread) {
TSContactThread *thread = (TSContactThread *)self.thread; TSContactThread *thread = (TSContactThread *)self.thread;
if (thread.sessionRestoreDevices.count > 0) { if (thread.sessionRestoreDevices.count > 0) {
if (self.restoreSessionBannerView) { if (!self.restoreSessionBannerView) {
// TODO: Create banner here LKSessionRestoreBannerView *bannerView = [[LKSessionRestoreBannerView alloc] initWithThread:thread];
[self.view addSubview:bannerView];
[bannerView autoPinEdgeToSuperviewEdge:ALEdgeTop];
[bannerView autoPinEdgeToSuperviewEdge:ALEdgeLeft];
[bannerView autoPinEdgeToSuperviewEdge:ALEdgeRight];
[self.view layoutSubviews];
self.restoreSessionBannerView = bannerView;
[bannerView setOnRestore:^{
[self restoreSession];
}];
[bannerView setOnDismiss:^{
[thread removeAllRessionRestoreDevicesWithTransaction:nil];
}];
} }
} else { } else {
shouldRemoveBanner = true; shouldRemoveBanner = true;
@ -1154,10 +1167,21 @@ typedef enum : NSUInteger {
- (void)restoreSession { - (void)restoreSession {
if ([self.thread isKindOfClass:[TSContactThread class]]) { if ([self.thread isKindOfClass:[TSContactThread class]]) {
OWSMessageSender *messageSender = SSKEnvironment.shared.messageSender;
TSContactThread *thread = (TSContactThread *)self.thread; TSContactThread *thread = (TSContactThread *)self.thread;
NSArray *devices = thread.sessionRestoreDevices; NSArray *devices = thread.sessionRestoreDevices;
// TODO: Send session restore to all devices for (NSString *device in devices) {
// TODO: Add message saying session restore was sent if (device.length == 0) { continue; }
OWSMessageSend *sessionRestoreMessage = [messageSender getSessionRestoreMessageForHexEncodedPublicKey:device];
if (sessionRestoreMessage) {
dispatch_async(OWSDispatch.sendingQueue, ^{
[messageSender sendMessage:sessionRestoreMessage];
});
}
}
[[[TSInfoMessage alloc] initWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageType:TSInfoMessageTypeLokiSessionResetInProgress] save];
thread.sessionResetState = TSContactThreadSessionResetStateRequestReceived;
[thread save];
[thread removeAllRessionRestoreDevicesWithTransaction:nil]; [thread removeAllRessionRestoreDevicesWithTransaction:nil];
} }
} }

@ -2672,3 +2672,5 @@
"Your device was unlinked successfully" = "Your device was unlinked successfully"; "Your device was unlinked successfully" = "Your device was unlinked successfully";
"Unnamed Device" = "Unnamed Device"; "Unnamed Device" = "Unnamed Device";
"Linked device (%@)" = "Linked device (%@)"; "Linked device (%@)" = "Linked device (%@)";
"Restore session" = "Restore session";
"Would you like to start a new session with %@?" = "Would you like to start a new session with %@?";

@ -0,0 +1,8 @@
#import "LKFriendRequestMessage.h"
NS_SWIFT_NAME(FriendRequestMessage)
@interface LKSessionRestoreMessage : LKFriendRequestMessage
- (instancetype)initWithThread:(TSThread *)thread;
@end

@ -0,0 +1,23 @@
#import "LKSessionRestoreMessage.h"
#import <SignalCoreKit/NSDate+OWS.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
@implementation LKSessionRestoreMessage
#pragma mark Initialization
- (instancetype)initWithThread:(TSThread *)thread {
return [self initOutgoingMessageWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageBody:@"" attachmentIds:[NSMutableArray<NSString *> new]
expiresInSeconds:0 expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMetaMessageUnspecified quotedMessage:nil contactShare:nil linkPreview:nil];
}
#pragma mark Building
- (nullable SSKProtoDataMessageBuilder *)dataMessageBuilder
{
SSKProtoDataMessageBuilder *builder = super.dataMessageBuilder;
if (builder == nil) { return nil; }
[builder setFlags:SSKProtoDataMessageFlagsSessionRestore];
return builder;
}
@end

@ -89,8 +89,9 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
withTransaction:(YapDatabaseReadWriteTransaction *)transaction withTransaction:(YapDatabaseReadWriteTransaction *)transaction
failedMessageType:(TSErrorMessageType)errorMessageType failedMessageType:(TSErrorMessageType)errorMessageType
{ {
NSString *source = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:envelope.source in:transaction] ?: envelope.source;
TSContactThread *contactThread = TSContactThread *contactThread =
[TSContactThread getOrCreateThreadWithContactId:envelope.source transaction:transaction]; [TSContactThread getOrCreateThreadWithContactId:source transaction:transaction];
// Legit usage of senderTimestamp. We don't actually currently surface it in the UI, but it serves as // Legit usage of senderTimestamp. We don't actually currently surface it in the UI, but it serves as
// a reference to the envelope which we failed to process. // a reference to the envelope which we failed to process.

@ -688,15 +688,15 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
envelope:(SSKProtoEnvelope *)envelope envelope:(SSKProtoEnvelope *)envelope
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:envelope.source in:transaction]; NSString *hexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:envelope.source in:transaction] ?: envelope.source;
NSString *hexEncodedPublicKey = masterHexEncodedPublicKey ?: envelope.source;
TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction]; TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction];
// Trigger a session restore prompt if we get specific errors // Trigger a session restore prompt if we get specific errors
if (errorMessage.errorType == TSErrorMessageNoSession || if (errorMessage.errorType == TSErrorMessageNoSession ||
errorMessage.errorType == TSErrorMessageInvalidMessage || errorMessage.errorType == TSErrorMessageInvalidMessage ||
errorMessage.errorType == TSErrorMessageInvalidKeyException) { errorMessage.errorType == TSErrorMessageInvalidKeyException) {
[((TSContactThread *) contactThread) addSessionRestoreDevice:hexEncodedPublicKey transaction:transaction]; // We want to store the source device pubkey into the session restore incase it's a secondary device message
[((TSContactThread *) contactThread) addSessionRestoreDevice:envelope.source transaction:transaction];
} }
} }
@ -704,8 +704,7 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
envelope:(SSKProtoEnvelope *)envelope envelope:(SSKProtoEnvelope *)envelope
transaction:(YapDatabaseReadWriteTransaction *)transaction transaction:(YapDatabaseReadWriteTransaction *)transaction
{ {
NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:envelope.source in:transaction]; NSString *hexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:envelope.source in:transaction] ?: envelope.source;
NSString *hexEncodedPublicKey = masterHexEncodedPublicKey ?: envelope.source;
TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction]; TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction];
[SSKEnvironment.shared.notificationsManager notifyUserForErrorMessage:errorMessage [SSKEnvironment.shared.notificationsManager notifyUserForErrorMessage:errorMessage
thread:contactThread thread:contactThread

@ -1723,10 +1723,6 @@ NS_ASSUME_NONNULL_BEGIN
}]; }];
} }
message.friendRequestStatus = LKMessageFriendRequestStatusPending; // Don't save yet. This is done in finalizeIncomingMessage:thread:masterThread:envelope:transaction. message.friendRequestStatus = LKMessageFriendRequestStatusPending; // Don't save yet. This is done in finalizeIncomingMessage:thread:masterThread:envelope:transaction.
} else {
// This can happen if Alice and Bob have a session, Bob deletes his app, restores from seed, and then sends a friend request to Alice again.
// TODO: Re-enable when seed restoration is done
// [self handleEndSessionMessageWithEnvelope:envelope dataMessage:data transaction:transaction];
} }
} }

@ -97,6 +97,7 @@ NS_SWIFT_NAME(MessageSender)
success:(void (^)(void))successHandler success:(void (^)(void))successHandler
failure:(void (^)(NSError *error))failureHandler; failure:(void (^)(NSError *error))failureHandler;
- (OWSMessageSend *)getSessionRestoreMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey;
- (OWSMessageSend *)getMultiDeviceFriendRequestMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey; - (OWSMessageSend *)getMultiDeviceFriendRequestMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey;
- (void)sendMessage:(OWSMessageSend *)messageSend; - (void)sendMessage:(OWSMessageSend *)messageSend;

@ -45,6 +45,7 @@
#import "TSThread.h" #import "TSThread.h"
#import "TSContactThread.h" #import "TSContactThread.h"
#import "LKFriendRequestMessage.h" #import "LKFriendRequestMessage.h"
#import "LKSessionRestoreMessage.h"
#import "LKDeviceLinkMessage.h" #import "LKDeviceLinkMessage.h"
#import "LKAddressMessage.h" #import "LKAddressMessage.h"
#import <AxolotlKit/AxolotlExceptions.h> #import <AxolotlKit/AxolotlExceptions.h>
@ -915,15 +916,32 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
return deviceMessages; return deviceMessages;
} }
- (OWSMessageSend *)getSessionRestoreMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey
{
__block TSContactThread *thread;
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction];
// Force hide secondary device thread
NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:hexEncodedPublicKey in:transaction];
thread.isForceHidden = masterHexEncodedPublicKey != nil && ![masterHexEncodedPublicKey isEqualToString:hexEncodedPublicKey];
[thread saveWithTransaction:transaction];
}];
if (!thread) { return nil; }
LKSessionRestoreMessage *message = [[LKSessionRestoreMessage alloc] initWithThread:thread];
message.skipSave = YES;
SignalRecipient *recipient = [[SignalRecipient alloc] initWithUniqueId:hexEncodedPublicKey];
NSString *userHexEncodedPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
return [[OWSMessageSend alloc] initWithMessage:message thread:thread recipient:recipient senderCertificate:nil udAccess:nil localNumber:userHexEncodedPublicKey success:^{ } failure:^(NSError *error) { }];
}
- (OWSMessageSend *)getMultiDeviceFriendRequestMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey - (OWSMessageSend *)getMultiDeviceFriendRequestMessageForHexEncodedPublicKey:(NSString *)hexEncodedPublicKey
{ {
__block TSContactThread *thread; __block TSContactThread *thread;
[OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [OWSPrimaryStorage.sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSContactThread fetchObjectWithUniqueID:[TSContactThread threadIdFromContactId:hexEncodedPublicKey] transaction:transaction]; thread = [TSContactThread getOrCreateThreadWithContactId:hexEncodedPublicKey transaction:transaction];
if (thread == nil) { // Force hide secondary device thread
thread = [[TSContactThread alloc] initWithContactId:hexEncodedPublicKey]; NSString *masterHexEncodedPublicKey = [LKDatabaseUtilities getMasterHexEncodedPublicKeyFor:hexEncodedPublicKey in:transaction];
} thread.isForceHidden = masterHexEncodedPublicKey != nil && ![masterHexEncodedPublicKey isEqualToString:hexEncodedPublicKey];
thread.isForceHidden = YES;
[thread saveWithTransaction:transaction]; [thread saveWithTransaction:transaction];
}]; }];
LKFriendRequestMessage *message = [[LKFriendRequestMessage alloc] initOutgoingMessageWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageBody:@"Please accept to enable messages to be synced across devices" attachmentIds:[NSMutableArray new] LKFriendRequestMessage *message = [[LKFriendRequestMessage alloc] initOutgoingMessageWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageBody:@"Please accept to enable messages to be synced across devices" attachmentIds:[NSMutableArray new]

Loading…
Cancel
Save