Merge branch 'nt/uuid'
This commit is contained in:
commit
1aa4fb747e
2
Pods
2
Pods
@ -1 +1 @@
|
||||
Subproject commit 7fcaa35aac69aa47443b920ef4c6553bd1f8d9d3
|
||||
Subproject commit 3d393009e3fded14568792745f55eb8faccf44a0
|
||||
@ -79,7 +79,7 @@ public class SessionResetOperation: OWSOperation, DurableOperation {
|
||||
|
||||
let contactThread: TSContactThread
|
||||
var recipientId: String {
|
||||
return contactThread.contactIdentifier()
|
||||
return contactThread.contactAddress.transitional_phoneNumber
|
||||
}
|
||||
|
||||
@objc public required init(contactThread: TSContactThread, jobRecord: OWSSessionResetJobRecord) {
|
||||
|
||||
@ -212,7 +212,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||
func presentIncomingCall(_ call: SignalCall, callerName: String) {
|
||||
|
||||
let remotePhoneNumber = call.remotePhoneNumber
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: remotePhoneNumber.transitional_signalServiceAddress)
|
||||
|
||||
let notificationTitle: String?
|
||||
let threadIdentifier: String?
|
||||
@ -250,7 +250,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||
func presentMissedCall(_ call: SignalCall, callerName: String) {
|
||||
|
||||
let remotePhoneNumber = call.remotePhoneNumber
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: remotePhoneNumber.transitional_signalServiceAddress)
|
||||
|
||||
let notificationTitle: String?
|
||||
let threadIdentifier: String?
|
||||
@ -289,7 +289,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||
public func presentMissedCallBecauseOfNoLongerVerifiedIdentity(call: SignalCall, callerName: String) {
|
||||
|
||||
let remotePhoneNumber = call.remotePhoneNumber
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: remotePhoneNumber.transitional_signalServiceAddress)
|
||||
|
||||
let notificationTitle: String?
|
||||
let threadIdentifier: String?
|
||||
@ -327,7 +327,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||
public func presentMissedCallBecauseOfNewIdentity(call: SignalCall, callerName: String) {
|
||||
|
||||
let remotePhoneNumber = call.remotePhoneNumber
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: remotePhoneNumber.transitional_signalServiceAddress)
|
||||
|
||||
let notificationTitle: String?
|
||||
let threadIdentifier: String?
|
||||
|
||||
@ -143,7 +143,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
||||
required init(call: SignalCall) {
|
||||
contactsManager = Environment.shared.contactsManager
|
||||
self.call = call
|
||||
self.thread = TSContactThread.getOrCreateThread(contactId: call.remotePhoneNumber)
|
||||
self.thread = TSContactThread.getOrCreateThread(contactAddress: call.remotePhoneNumber.transitional_signalServiceAddress)
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
allAudioSources = Set(callUIAdapter.audioService.availableInputs)
|
||||
|
||||
@ -51,10 +51,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)tappedAddToContactsOfferMessage:(OWSContactOffersInteraction *)interaction;
|
||||
- (void)tappedAddToProfileWhitelistOfferMessage:(OWSContactOffersInteraction *)interaction;
|
||||
|
||||
#pragma mark - Formatting
|
||||
|
||||
- (NSAttributedString *)attributedContactOrProfileNameForPhoneIdentifier:(NSString *)recipientId;
|
||||
|
||||
#pragma mark - Caching
|
||||
|
||||
- (NSCache *)cellMediaCache;
|
||||
|
||||
@ -1720,8 +1720,12 @@ typedef enum : NSUInteger {
|
||||
|
||||
- (BOOL)canCall
|
||||
{
|
||||
return !(self.isGroupConversation ||
|
||||
[((TSContactThread *)self.thread).contactIdentifier isEqualToString:self.tsAccountManager.localNumber]);
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([self.thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)self.thread;
|
||||
}
|
||||
|
||||
return !(self.isGroupConversation || contactThread.contactAddress.isLocalAddress);
|
||||
}
|
||||
|
||||
#pragma mark - Dynamic Text
|
||||
@ -1900,9 +1904,10 @@ typedef enum : NSUInteger {
|
||||
return;
|
||||
|
||||
} else {
|
||||
TSContactThread *thread = (TSContactThread *)self.thread;
|
||||
OWSLogInfo(@"Assuming tap on legacy nonblocking identity change corresponds to current contact thread: %@",
|
||||
self.thread.contactIdentifier);
|
||||
signalIdParam = self.thread.contactIdentifier;
|
||||
thread.contactAddress);
|
||||
signalIdParam = thread.contactAddress.transitional_phoneNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2271,15 +2276,6 @@ typedef enum : NSUInteger {
|
||||
[[OWSWindowManager sharedManager] showMenuActionsWindow:menuActionsViewController];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedContactOrProfileNameForPhoneIdentifier:(NSString *)recipientId
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssertDebug(recipientId.length > 0);
|
||||
|
||||
return
|
||||
[self.contactsManager attributedContactOrProfileNameForAddress:recipientId.transitional_signalServiceAddress];
|
||||
}
|
||||
|
||||
- (void)tappedUnknownContactBlockOfferMessage:(OWSContactOffersInteraction *)interaction
|
||||
{
|
||||
if (![self.thread isKindOfClass:[TSContactThread class]]) {
|
||||
@ -2334,9 +2330,10 @@ typedef enum : NSUInteger {
|
||||
return;
|
||||
}
|
||||
TSContactThread *contactThread = (TSContactThread *)self.thread;
|
||||
[self.contactsViewHelper presentContactViewControllerForRecipientId:contactThread.contactIdentifier
|
||||
fromViewController:self
|
||||
editImmediately:YES];
|
||||
[self.contactsViewHelper
|
||||
presentContactViewControllerForRecipientId:contactThread.contactAddress.transitional_phoneNumber
|
||||
fromViewController:self
|
||||
editImmediately:YES];
|
||||
|
||||
// Delete the offers.
|
||||
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
|
||||
@ -193,15 +193,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||
switch (self.interaction.interactionType) {
|
||||
case OWSInteractionType_TypingIndicator: {
|
||||
OWSTypingIndicatorInteraction *typingIndicator = (OWSTypingIndicatorInteraction *)self.interaction;
|
||||
_authorConversationColorName =
|
||||
[TSContactThread conversationColorNameForRecipientId:typingIndicator.recipientId
|
||||
transaction:transaction];
|
||||
_authorConversationColorName = [TSContactThread
|
||||
conversationColorNameForContactAddress:typingIndicator.recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction];
|
||||
break;
|
||||
}
|
||||
case OWSInteractionType_IncomingMessage: {
|
||||
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)self.interaction;
|
||||
_authorConversationColorName =
|
||||
[TSContactThread conversationColorNameForRecipientId:incomingMessage.authorId transaction:transaction];
|
||||
_authorConversationColorName = [TSContactThread
|
||||
conversationColorNameForContactAddress:incomingMessage.authorId.transitional_signalServiceAddress
|
||||
transaction:transaction];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@ -1205,7 +1205,7 @@ static const int kYapDatabaseRangeMaxLength = 25000;
|
||||
BOOL shouldHaveAddToContactsOffer = YES;
|
||||
BOOL shouldHaveAddToProfileWhitelistOffer = YES;
|
||||
|
||||
SignalServiceAddress *recipientAddress = ((TSContactThread *)thread).contactAddress;
|
||||
SignalServiceAddress *recipientAddress = contactThread.contactAddress;
|
||||
|
||||
if (recipientAddress.isLocalAddress) {
|
||||
// Don't add self to contacts.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -42,9 +42,9 @@ class DebugUICalling: DebugUIPage {
|
||||
let callMessage = OWSOutgoingCallMessage(thread: thread, hangupMessage: hangupMessage)
|
||||
|
||||
strongSelf.messageSender.sendPromise(message: callMessage).done {
|
||||
Logger.debug("Successfully sent hangup call message to \(thread.contactIdentifier())")
|
||||
Logger.debug("Successfully sent hangup call message to \(thread.contactAddress)")
|
||||
}.catch { error in
|
||||
Logger.error("failed to send hangup call message to \(thread.contactIdentifier()) with error: \(error)")
|
||||
Logger.error("failed to send hangup call message to \(thread.contactAddress) with error: \(error)")
|
||||
}.retainUntilComplete()
|
||||
},
|
||||
OWSTableItem(title: "Send 'busy' for old call") { [weak self] in
|
||||
@ -63,9 +63,9 @@ class DebugUICalling: DebugUIPage {
|
||||
let callMessage = OWSOutgoingCallMessage(thread: thread, busyMessage: busyMessage)
|
||||
|
||||
strongSelf.messageSender.sendPromise(message: callMessage).done {
|
||||
Logger.debug("Successfully sent busy call message to \(thread.contactIdentifier())")
|
||||
Logger.debug("Successfully sent busy call message to \(thread.contactAddress)")
|
||||
}.catch { error in
|
||||
Logger.error("failed to send busy call message to \(thread.contactIdentifier()) with error: \(error)")
|
||||
Logger.error("failed to send busy call message to \(thread.contactAddress) with error: \(error)")
|
||||
}.retainUntilComplete()
|
||||
}
|
||||
]
|
||||
|
||||
@ -107,7 +107,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (void)createUnregisteredContactThread
|
||||
{
|
||||
NSString *recipientId = [self unregisteredRecipientId];
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId];
|
||||
TSContactThread *thread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress];
|
||||
[SignalApp.sharedApp presentConversationForThread:thread animated:YES];
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +305,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
NSString *recipientId = contactThread.contactIdentifier;
|
||||
NSString *recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
[items addObject:[OWSTableItem itemWithTitle:@"Create 10 new groups"
|
||||
actionBlock:^{
|
||||
[DebugUIMessages createNewGroups:10 recipientId:recipientId];
|
||||
@ -381,7 +381,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (void)sendMessages:(NSUInteger)count toAllMembersOfGroup:(TSGroupThread *)groupThread
|
||||
{
|
||||
for (NSString *recipientId in groupThread.groupModel.groupMemberIds) {
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:recipientId];
|
||||
TSContactThread *contactThread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress];
|
||||
[[self sendTextMessagesActionInThread:contactThread] prepareAndPerformNTimes:count];
|
||||
}
|
||||
}
|
||||
@ -3457,7 +3458,7 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
|
||||
return gThread.groupModel.groupMemberIds[0];
|
||||
} else if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
return contactThread.contactIdentifier;
|
||||
return contactThread.contactAddress.transitional_phoneNumber;
|
||||
} else {
|
||||
OWSFailDebug(@"failure: unknown thread type");
|
||||
return @"unknown-source-id";
|
||||
@ -3760,7 +3761,8 @@ typedef OWSContact * (^OWSContactBlock)(SDSAnyWriteTransaction *transaction);
|
||||
OWSAssertDebug(phoneNumber);
|
||||
OWSAssertDebug(phoneNumber.toE164);
|
||||
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:phoneNumber.toE164];
|
||||
TSContactThread *contactThread = [TSContactThread
|
||||
getOrCreateThreadWithContactAddress:phoneNumber.toE164.transitional_signalServiceAddress];
|
||||
[self sendFakeMessages:messageCount thread:contactThread];
|
||||
[self.databaseStorage readWithBlock:^(SDSAnyReadTransaction *transaction) {
|
||||
NSUInteger interactionCount = [contactThread numberOfInteractionsWithTransaction:transaction];
|
||||
|
||||
@ -108,7 +108,7 @@ class DebugUINotifications: DebugUIPage {
|
||||
}
|
||||
|
||||
func delayedNotificationDispatchWithFakeCall(thread: TSContactThread, callBlock: @escaping (SignalCall) -> Void) -> Guarantee<Void> {
|
||||
let call = SignalCall.incomingCall(localId: UUID(), remotePhoneNumber: thread.contactIdentifier(), signalingId: 0)
|
||||
let call = SignalCall.incomingCall(localId: UUID(), remotePhoneNumber: thread.contactAddress.transitional_phoneNumber, signalingId: 0)
|
||||
|
||||
return delayedNotificationDispatch {
|
||||
callBlock(call)
|
||||
|
||||
@ -59,7 +59,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSLogError(@"Flipping identity Key. Flip again to return.");
|
||||
|
||||
OWSIdentityManager *identityManager = [OWSIdentityManager sharedManager];
|
||||
NSString *recipientId = [thread contactIdentifier];
|
||||
NSString *recipientId = thread.contactAddress.transitional_phoneNumber;
|
||||
|
||||
NSData *currentKey = [identityManager identityKeyForRecipientId:recipientId];
|
||||
NSMutableData *flippedKey = [NSMutableData new];
|
||||
|
||||
@ -479,7 +479,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return;
|
||||
}
|
||||
|
||||
if (![self.thread.contactIdentifier isEqualToString:recipientId]) {
|
||||
if (![self.thread.contactAddress.transitional_phoneNumber isEqualToString:recipientId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1078,7 +1078,7 @@ NSString *const kArchiveButtonPseudoGroup = @"kArchiveButtonPseudoGroup";
|
||||
cellName = [NSString stringWithFormat:@"cell-group-%@", groupThread.groupModel.groupName];
|
||||
} else {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread.threadRecord;
|
||||
cellName = [NSString stringWithFormat:@"cell-contact-%@", contactThread.contactIdentifier];
|
||||
cellName = [NSString stringWithFormat:@"cell-contact-%@", contactThread.contactAddress.stringForDisplay];
|
||||
}
|
||||
cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, cellName);
|
||||
|
||||
|
||||
@ -875,7 +875,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)newConversationWithRecipientId:(NSString *)recipientId
|
||||
{
|
||||
OWSAssertDebug(recipientId.length > 0);
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId];
|
||||
TSContactThread *thread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress];
|
||||
[self newConversationWithThread:thread];
|
||||
}
|
||||
|
||||
|
||||
@ -177,10 +177,15 @@ const CGFloat kIconViewLength = 24;
|
||||
- (NSString *)threadName
|
||||
{
|
||||
NSString *threadName = self.thread.name;
|
||||
if (self.thread.contactIdentifier &&
|
||||
[threadName isEqualToString:self.thread.contactIdentifier]) {
|
||||
threadName =
|
||||
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:self.thread.contactIdentifier];
|
||||
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([self.thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)self.thread;
|
||||
}
|
||||
|
||||
if (contactThread && [threadName isEqualToString:contactThread.contactAddress.phoneNumber]) {
|
||||
threadName = [PhoneNumber
|
||||
bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:contactThread.contactAddress.phoneNumber];
|
||||
} else if (threadName.length == 0 && [self isGroupThread]) {
|
||||
threadName = [MessageStrings newGroupDefaultTitle];
|
||||
}
|
||||
@ -367,7 +372,7 @@ const CGFloat kIconViewLength = 24;
|
||||
OWSConversationSettingsViewController *strongSelf = weakSelf;
|
||||
OWSCAssertDebug(strongSelf);
|
||||
TSContactThread *contactThread = (TSContactThread *)strongSelf.thread;
|
||||
NSString *recipientId = contactThread.contactIdentifier;
|
||||
NSString *recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
[strongSelf presentAddToContactViewControllerWithRecipientId:recipientId];
|
||||
}]];
|
||||
}
|
||||
@ -1108,7 +1113,9 @@ const CGFloat kIconViewLength = 24;
|
||||
|
||||
- (void)showVerificationView
|
||||
{
|
||||
NSString *recipientId = self.thread.contactIdentifier;
|
||||
OWSAssertDebug([self.thread isKindOfClass:[TSContactThread class]]);
|
||||
TSContactThread *contactThread = (TSContactThread *)self.thread;
|
||||
NSString *recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
OWSAssertDebug(recipientId.length > 0);
|
||||
|
||||
[FingerprintViewController presentFromViewController:self recipientId:recipientId];
|
||||
@ -1144,9 +1151,10 @@ const CGFloat kIconViewLength = 24;
|
||||
}
|
||||
|
||||
TSContactThread *contactThread = (TSContactThread *)self.thread;
|
||||
[self.contactsViewHelper presentContactViewControllerForRecipientId:contactThread.contactIdentifier
|
||||
fromViewController:self
|
||||
editImmediately:YES];
|
||||
[self.contactsViewHelper
|
||||
presentContactViewControllerForRecipientId:contactThread.contactAddress.transitional_phoneNumber
|
||||
fromViewController:self
|
||||
editImmediately:YES];
|
||||
}
|
||||
|
||||
- (void)presentAddToContactViewControllerWithRecipientId:(NSString *)recipientId
|
||||
@ -1469,8 +1477,13 @@ const CGFloat kIconViewLength = 24;
|
||||
NSString *recipientId = notification.userInfo[kNSNotificationKey_ProfileRecipientId];
|
||||
OWSAssertDebug(recipientId.length > 0);
|
||||
|
||||
if (recipientId.length > 0 && [self.thread isKindOfClass:[TSContactThread class]] &&
|
||||
[self.thread.contactIdentifier isEqualToString:recipientId]) {
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([self.thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)self.thread;
|
||||
}
|
||||
|
||||
if (recipientId.length > 0 && contactThread &&
|
||||
[contactThread.contactAddress.transitional_phoneNumber isEqualToString:recipientId]) {
|
||||
[self updateTableContents];
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,7 +569,7 @@ private class SignalCallData: NSObject {
|
||||
*/
|
||||
public func handleReceivedAnswer(thread: TSContactThread, callId: UInt64, sessionDescription: String) {
|
||||
AssertIsOnMainThread()
|
||||
Logger.info("received call answer for call: \(callId) thread: \(thread.contactIdentifier())")
|
||||
Logger.info("received call answer for call: \(callId) thread: \(thread.contactAddress)")
|
||||
|
||||
guard let call = self.call else {
|
||||
Logger.warn("ignoring obsolete call: \(callId)")
|
||||
@ -613,7 +613,7 @@ private class SignalCallData: NSObject {
|
||||
if call.callRecord == nil {
|
||||
// MJK TODO remove this timestamp param
|
||||
call.callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
withCallNumber: call.thread.contactIdentifier(),
|
||||
withCallNumber: call.thread.contactAddress.transitional_phoneNumber,
|
||||
callType: .incomingMissed,
|
||||
in: call.thread)
|
||||
}
|
||||
@ -646,7 +646,7 @@ private class SignalCallData: NSObject {
|
||||
*/
|
||||
private func handleLocalBusyCall(_ call: SignalCall) {
|
||||
AssertIsOnMainThread()
|
||||
Logger.info("for call: \(call.identifiersForLogs) thread: \(call.thread.contactIdentifier())")
|
||||
Logger.info("for call: \(call.identifiersForLogs) thread: \(call.thread.contactAddress)")
|
||||
|
||||
do {
|
||||
let busyBuilder = SSKProtoCallMessageBusy.builder(id: call.signalingId)
|
||||
@ -665,7 +665,7 @@ private class SignalCallData: NSObject {
|
||||
*/
|
||||
public func handleRemoteBusy(thread: TSContactThread, callId: UInt64) {
|
||||
AssertIsOnMainThread()
|
||||
Logger.info("for thread: \(thread.contactIdentifier())")
|
||||
Logger.info("for thread: \(thread.contactAddress)")
|
||||
|
||||
guard let call = self.call else {
|
||||
Logger.warn("ignoring obsolete call: \(callId)")
|
||||
@ -677,7 +677,7 @@ private class SignalCallData: NSObject {
|
||||
return
|
||||
}
|
||||
|
||||
guard thread.contactIdentifier() == call.remotePhoneNumber else {
|
||||
guard thread.contactAddress.transitional_phoneNumber == call.remotePhoneNumber else {
|
||||
Logger.warn("ignoring obsolete call")
|
||||
return
|
||||
}
|
||||
@ -699,11 +699,11 @@ private class SignalCallData: NSObject {
|
||||
|
||||
BenchEventStart(title: "Incoming Call Connection", eventId: "call-\(callId)")
|
||||
|
||||
let newCall = SignalCall.incomingCall(localId: UUID(), remotePhoneNumber: thread.contactIdentifier(), signalingId: callId)
|
||||
let newCall = SignalCall.incomingCall(localId: UUID(), remotePhoneNumber: thread.contactAddress.transitional_phoneNumber, signalingId: callId)
|
||||
|
||||
Logger.info("receivedCallOffer: \(newCall.identifiersForLogs)")
|
||||
|
||||
let untrustedIdentity = OWSIdentityManager.shared().untrustedIdentityForSending(toRecipientId: thread.contactIdentifier())
|
||||
let untrustedIdentity = OWSIdentityManager.shared().untrustedIdentityForSending(toRecipientId: thread.contactAddress.transitional_phoneNumber)
|
||||
|
||||
guard untrustedIdentity == nil else {
|
||||
Logger.warn("missed a call due to untrusted identity: \(newCall.identifiersForLogs)")
|
||||
@ -722,7 +722,7 @@ private class SignalCallData: NSObject {
|
||||
|
||||
// MJK TODO remove this timestamp param
|
||||
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
withCallNumber: thread.contactIdentifier(),
|
||||
withCallNumber: thread.contactAddress.transitional_phoneNumber,
|
||||
callType: .incomingMissedBecauseOfChangedIdentity,
|
||||
in: thread)
|
||||
assert(newCall.callRecord == nil)
|
||||
@ -901,7 +901,7 @@ private class SignalCallData: NSObject {
|
||||
return
|
||||
}
|
||||
|
||||
guard thread.contactIdentifier() == call.thread.contactIdentifier() else {
|
||||
guard thread.contactAddress.matchesAddress(call.thread.contactAddress) else {
|
||||
Logger.warn("ignoring remote ice update for thread: \(String(describing: thread.uniqueId)) due to thread mismatch. Call already ended?")
|
||||
return
|
||||
}
|
||||
@ -1070,10 +1070,10 @@ private class SignalCallData: NSObject {
|
||||
return
|
||||
}
|
||||
|
||||
guard thread.contactIdentifier() == call.thread.contactIdentifier() else {
|
||||
guard thread.contactAddress.matchesAddress(call.thread.contactAddress) else {
|
||||
// This can safely be ignored.
|
||||
// We don't want to fail the current call because an old call was slow to send us the hangup message.
|
||||
Logger.warn("ignoring hangup for thread: \(thread.contactIdentifier()) which is not the current call: \(call.identifiersForLogs)")
|
||||
Logger.warn("ignoring hangup for thread: \(thread.contactAddress) which is not the current call: \(call.identifiersForLogs)")
|
||||
return
|
||||
}
|
||||
|
||||
@ -1317,10 +1317,10 @@ private class SignalCallData: NSObject {
|
||||
|
||||
self.messageSender.sendPromise(message: callMessage)
|
||||
.done {
|
||||
Logger.debug("successfully sent hangup call message to \(call.thread.contactIdentifier())")
|
||||
Logger.debug("successfully sent hangup call message to \(call.thread.contactAddress)")
|
||||
}.catch { error in
|
||||
OWSProdInfo(OWSAnalyticsEvents.callServiceErrorHandleLocalHungupCall(), file: #file, function: #function, line: #line)
|
||||
Logger.error("failed to send hangup call message to \(call.thread.contactIdentifier()) with error: \(error)")
|
||||
Logger.error("failed to send hangup call message to \(call.thread.contactAddress) with error: \(error)")
|
||||
}.retainUntilComplete()
|
||||
|
||||
terminateCall()
|
||||
|
||||
@ -160,7 +160,7 @@ protocol CallObserver: class {
|
||||
self.signalingId = signalingId
|
||||
self.state = state
|
||||
self.remotePhoneNumber = remotePhoneNumber
|
||||
self.thread = TSContactThread.getOrCreateThread(contactId: remotePhoneNumber)
|
||||
self.thread = TSContactThread.getOrCreateThread(contactAddress: remotePhoneNumber.transitional_signalServiceAddress)
|
||||
self.audioActivity = AudioActivity(audioDescription: "[SignalCall] with \(remotePhoneNumber)", behavior: .call)
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -12,8 +12,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
|
||||
// MARK: Initializers
|
||||
|
||||
@objc
|
||||
public override init()
|
||||
{
|
||||
public override init() {
|
||||
super.init()
|
||||
|
||||
SwiftSingletons.register(self)
|
||||
@ -21,18 +20,15 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
|
||||
|
||||
// MARK: - Dependencies
|
||||
|
||||
private var messageSender : MessageSender
|
||||
{
|
||||
private var messageSender: MessageSender {
|
||||
return SSKEnvironment.shared.messageSender
|
||||
}
|
||||
|
||||
private var accountManager : AccountManager
|
||||
{
|
||||
private var accountManager: AccountManager {
|
||||
return AppEnvironment.shared.accountManager
|
||||
}
|
||||
|
||||
private var callService : CallService
|
||||
{
|
||||
private var callService: CallService {
|
||||
return AppEnvironment.shared.callService
|
||||
}
|
||||
|
||||
@ -41,21 +37,21 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
|
||||
public func receivedOffer(_ offer: SSKProtoCallMessageOffer, from callerId: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: callerId.transitional_signalServiceAddress)
|
||||
self.callService.handleReceivedOffer(thread: thread, callId: offer.id, sessionDescription: offer.sessionDescription)
|
||||
}
|
||||
|
||||
public func receivedAnswer(_ answer: SSKProtoCallMessageAnswer, from callerId: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: callerId.transitional_signalServiceAddress)
|
||||
self.callService.handleReceivedAnswer(thread: thread, callId: answer.id, sessionDescription: answer.sessionDescription)
|
||||
}
|
||||
|
||||
public func receivedIceUpdate(_ iceUpdate: SSKProtoCallMessageIceUpdate, from callerId: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: callerId.transitional_signalServiceAddress)
|
||||
|
||||
// Discrepency between our protobuf's sdpMlineIndex, which is unsigned,
|
||||
// while the RTC iOS API requires a signed int.
|
||||
@ -67,14 +63,14 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler {
|
||||
public func receivedHangup(_ hangup: SSKProtoCallMessageHangup, from callerId: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: callerId.transitional_signalServiceAddress)
|
||||
self.callService.handleRemoteHangup(thread: thread, callId: hangup.id)
|
||||
}
|
||||
|
||||
public func receivedBusy(_ busy: SSKProtoCallMessageBusy, from callerId: String) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(contactId: callerId)
|
||||
let thread = TSContactThread.getOrCreateThread(contactAddress: callerId.transitional_signalServiceAddress)
|
||||
self.callService.handleRemoteBusy(thread: thread, callId: busy.id)
|
||||
}
|
||||
|
||||
|
||||
@ -65,7 +65,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
__block TSThread *thread = nil;
|
||||
[OWSPrimaryStorage.dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
|
||||
thread = [TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
}];
|
||||
[self presentConversationForThread:thread action:action animated:(BOOL)isAnimated];
|
||||
}
|
||||
|
||||
@ -593,12 +593,13 @@ typedef void (^DebugLogUploadFailure)(DebugLogUploader *uploader, NSError *error
|
||||
if (![self.tsAccountManager isRegistered]) {
|
||||
return;
|
||||
}
|
||||
NSString *recipientId = [TSAccountManager localNumber];
|
||||
SignalServiceAddress *recipientAddress = TSAccountManager.sharedInstance.localAddress;
|
||||
|
||||
DispatchMainThreadSafe(^{
|
||||
__block TSThread *thread = nil;
|
||||
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
|
||||
thread = [TSContactThread getOrCreateThreadWithContactAddress:recipientAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
}];
|
||||
[self.databaseStorage readWithBlock:^(SDSAnyReadTransaction *transaction) {
|
||||
[ThreadUtil enqueueMessageWithText:url.absoluteString
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"+15555555"];
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactAddress:@"+15555555".transitional_signalServiceAddress];
|
||||
self.conversationStyle = [[ConversationStyle alloc] initWithThread:self.thread];
|
||||
}
|
||||
|
||||
|
||||
@ -91,10 +91,10 @@ class FullTextSearcherTest: SignalBaseTest {
|
||||
let snackClubGroupThread = TSGroupThread.getOrCreateThread(with: snackModel, transaction: transaction)
|
||||
self.snackClubThread = ThreadViewModel(thread: snackClubGroupThread, transaction: transaction.asAnyWrite)
|
||||
|
||||
let aliceContactThread = TSContactThread.getOrCreateThread(withContactId: aliceRecipientId, transaction: transaction)
|
||||
let aliceContactThread = TSContactThread.getOrCreateThread(withContactAddress: aliceRecipientId.transitional_signalServiceAddress, transaction: transaction.asAnyWrite)
|
||||
self.aliceThread = ThreadViewModel(thread: aliceContactThread, transaction: transaction.asAnyWrite)
|
||||
|
||||
let bobContactThread = TSContactThread.getOrCreateThread(withContactId: bobRecipientId, transaction: transaction)
|
||||
let bobContactThread = TSContactThread.getOrCreateThread(withContactAddress: bobRecipientId.transitional_signalServiceAddress, transaction: transaction.asAnyWrite)
|
||||
self.bobEmptyThread = ThreadViewModel(thread: bobContactThread, transaction: transaction.asAnyWrite)
|
||||
|
||||
let helloAlice = TSOutgoingMessage(in: aliceContactThread, messageBody: "Hello Alice", attachmentId: nil)
|
||||
|
||||
@ -328,8 +328,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
__block TSThread *thread = nil;
|
||||
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSContactThread getOrCreateThreadWithContactId:signalAccount.recipientAddress.transitional_phoneNumber
|
||||
transaction:transaction];
|
||||
thread = [TSContactThread getOrCreateThreadWithContactAddress:signalAccount.recipientAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
}];
|
||||
OWSAssertDebug(thread);
|
||||
|
||||
@ -354,7 +354,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
for (TSThread *thread in threads) {
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
[contactIdsToIgnore addObject:contactThread.contactIdentifier];
|
||||
[contactIdsToIgnore addObject:contactThread.contactAddress.transitional_phoneNumber];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ public class ThreadViewModel: NSObject {
|
||||
@objc public let isGroupThread: Bool
|
||||
@objc public let threadRecord: TSThread
|
||||
@objc public let unreadCount: UInt
|
||||
@objc public let contactIdentifier: String?
|
||||
@objc public let contactAddress: SignalServiceAddress?
|
||||
@objc public let name: String
|
||||
@objc public let isMuted: Bool
|
||||
@ -36,10 +35,8 @@ public class ThreadViewModel: NSObject {
|
||||
self.lastMessageDate = lastInteraction?.receivedAtDate()
|
||||
|
||||
if let contactThread = thread as? TSContactThread {
|
||||
self.contactIdentifier = contactThread.contactIdentifier()
|
||||
self.contactAddress = contactThread.contactAddress
|
||||
} else {
|
||||
self.contactIdentifier = nil
|
||||
self.contactAddress = nil
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ public class ConversationAvatarImageView: AvatarImageView {
|
||||
|
||||
switch thread {
|
||||
case let contactThread as TSContactThread:
|
||||
self.recipientId = contactThread.contactIdentifier()
|
||||
self.recipientId = contactThread.contactAddress.transitional_phoneNumber
|
||||
self.groupThreadId = nil
|
||||
case let groupThread as TSGroupThread:
|
||||
self.recipientId = nil
|
||||
|
||||
@ -137,7 +137,8 @@ const CGFloat kContactCellAvatarTextMargin = 12;
|
||||
self.recipientId = recipientId;
|
||||
|
||||
[self.primaryStorage.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
self.thread = [TSContactThread getThreadWithContactId:recipientId transaction:transaction];
|
||||
self.thread = [TSContactThread getThreadWithContactAddress:recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction.asAnyRead];
|
||||
}];
|
||||
|
||||
BOOL isNoteToSelf = (IsNoteToSelfEnabled() && [recipientId isEqualToString:self.tsAccountManager.localNumber]);
|
||||
@ -182,8 +183,12 @@ const CGFloat kContactCellAvatarTextMargin = 12;
|
||||
threadName = [MessageStrings newGroupDefaultTitle];
|
||||
}
|
||||
|
||||
BOOL isNoteToSelf
|
||||
= (!thread.isGroupThread && [thread.contactIdentifier isEqualToString:self.tsAccountManager.localNumber]);
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([self.thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)self.thread;
|
||||
}
|
||||
|
||||
BOOL isNoteToSelf = contactThread && contactThread.contactAddress.isLocalAddress;
|
||||
if (isNoteToSelf) {
|
||||
threadName = NSLocalizedString(@"NOTE_TO_SELF", @"Label for 1:1 conversation with yourself.");
|
||||
}
|
||||
@ -195,8 +200,8 @@ const CGFloat kContactCellAvatarTextMargin = 12;
|
||||
}];
|
||||
self.nameLabel.attributedText = attributedText;
|
||||
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
self.recipientId = thread.contactIdentifier;
|
||||
if (contactThread != nil) {
|
||||
self.recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(otherUsersProfileDidChange:)
|
||||
|
||||
@ -53,13 +53,13 @@ public class NewAccountDiscovery: NSObject {
|
||||
// Typically we'd never want to create a "new user" notification if the thread already existed
|
||||
// but for testing we disabled the `forNewThreadsOnly` flag.
|
||||
if forNewThreadsOnly {
|
||||
guard TSContactThread.getWithContactId(recipient.address.transitional_phoneNumber, anyTransaction: transaction) == nil else {
|
||||
guard TSContactThread.getWithContactAddress(recipient.address, transaction: transaction) == nil else {
|
||||
owsFailDebug("not creating notification for 'new' user in existing thread.")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
let thread = TSContactThread.getOrCreateThread(withContactId: recipient.address.transitional_phoneNumber, anyTransaction: transaction)
|
||||
let thread = TSContactThread.getOrCreateThread(withContactAddress: recipient.address, transaction: transaction)
|
||||
let message = TSInfoMessage(timestamp: NSDate.ows_millisecondTimeStamp(),
|
||||
in: thread,
|
||||
messageType: .userJoinedSignal)
|
||||
|
||||
@ -857,7 +857,8 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||
[self addUserToProfileWhitelist:recipientId];
|
||||
}
|
||||
} else {
|
||||
NSString *recipientId = thread.contactIdentifier;
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
NSString *recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
[self addUserToProfileWhitelist:recipientId];
|
||||
}
|
||||
}
|
||||
@ -890,7 +891,8 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||
NSData *groupId = groupThread.groupModel.groupId;
|
||||
return [self isGroupIdInProfileWhitelist:groupId];
|
||||
} else {
|
||||
NSString *recipientId = thread.contactIdentifier;
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
NSString *recipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
return [self isUserInProfileWhitelist:recipientId];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -86,7 +86,7 @@ public class BlockListCache: NSObject {
|
||||
switch thread {
|
||||
case let contactThread as TSContactThread:
|
||||
return serialQueue.sync {
|
||||
blockedRecipientIds.contains(contactThread.contactIdentifier())
|
||||
blockedRecipientIds.contains(contactThread.contactAddress.transitional_phoneNumber)
|
||||
}
|
||||
case let groupThread as TSGroupThread:
|
||||
return serialQueue.sync {
|
||||
|
||||
@ -29,7 +29,7 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
[self showBlockPhoneNumberActionSheet:contactThread.contactIdentifier
|
||||
[self showBlockPhoneNumberActionSheet:contactThread.contactAddress.transitional_phoneNumber
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
contactsManager:contactsManager
|
||||
@ -267,7 +267,7 @@ typedef void (^BlockAlertCompletionBlock)(UIAlertAction *action);
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
[self showUnblockPhoneNumberActionSheet:contactThread.contactIdentifier
|
||||
[self showUnblockPhoneNumberActionSheet:contactThread.contactAddress.transitional_phoneNumber
|
||||
fromViewController:fromViewController
|
||||
blockingManager:blockingManager
|
||||
contactsManager:contactsManager
|
||||
|
||||
@ -292,7 +292,7 @@ public class FullTextSearcher: NSObject {
|
||||
let searchResult = ConversationSearchResult(thread: threadViewModel, sortKey: sortKey)
|
||||
|
||||
if let contactThread = thread as? TSContactThread {
|
||||
let recipientId = contactThread.contactIdentifier()
|
||||
let recipientId = contactThread.contactAddress.transitional_phoneNumber!
|
||||
existingConversationRecipientIds.insert(recipientId)
|
||||
}
|
||||
|
||||
@ -416,7 +416,7 @@ public class FullTextSearcher: NSObject {
|
||||
}
|
||||
|
||||
private lazy var contactThreadSearcher: Searcher<TSContactThread> = Searcher { (contactThread: TSContactThread) in
|
||||
let recipientId = contactThread.contactIdentifier()
|
||||
let recipientId = contactThread.contactAddress.transitional_phoneNumber!
|
||||
return self.conversationIndexingString(recipientId: recipientId)
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSAvatarBuilder.h"
|
||||
@ -11,6 +11,7 @@
|
||||
#import "UIColor+OWS.h"
|
||||
#import "UIFont+OWS.h"
|
||||
#import "UIView+OWS.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -30,9 +31,10 @@ typedef void (^OWSAvatarDrawBlock)(CGContextRef context);
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
ConversationColorName colorName = thread.conversationColorName;
|
||||
avatarBuilder = [[OWSContactAvatarBuilder alloc] initWithSignalId:contactThread.contactIdentifier
|
||||
colorName:colorName
|
||||
diameter:diameter];
|
||||
avatarBuilder =
|
||||
[[OWSContactAvatarBuilder alloc] initWithSignalId:contactThread.contactAddress.transitional_phoneNumber
|
||||
colorName:colorName
|
||||
diameter:diameter];
|
||||
} else if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
avatarBuilder = [[OWSGroupAvatarBuilder alloc] initWithThread:(TSGroupThread *)thread diameter:diameter];
|
||||
} else {
|
||||
|
||||
48
SignalServiceKit/src/Contacts/AnyThreadFinder.swift
Normal file
48
SignalServiceKit/src/Contacts/AnyThreadFinder.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
class AnyContactThreadFinder: NSObject {
|
||||
let grdbAdapter = GRDBContactThreadFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnyContactThreadFinder {
|
||||
@objc(contactThreadForAddress:transaction:)
|
||||
func contactThread(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> TSContactThread? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.contactThread(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBContactThreadFinder: NSObject {
|
||||
func contactThread(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
if let thread = contactThreadForUUID(address.uuid, transaction: transaction) {
|
||||
return thread
|
||||
} else if let thread = contactThreadForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return thread
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func contactThreadForUUID(_ uuid: UUID?, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
let sql = "SELECT * FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .contactUUID) = ?"
|
||||
return TSContactThread.grdbFetchOne(sql: sql, arguments: [uuidString], transaction: transaction) as? TSContactThread
|
||||
}
|
||||
|
||||
private func contactThreadForPhoneNumber(_ phoneNumber: String?, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
let sql = "SELECT * FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .contactPhoneNumber) = ?"
|
||||
return TSContactThread.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction) as? TSContactThread
|
||||
}
|
||||
}
|
||||
@ -4,36 +4,26 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SignalAccountFinder {
|
||||
associatedtype ReadTransaction
|
||||
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: ReadTransaction) -> SignalAccount?
|
||||
}
|
||||
|
||||
@objc
|
||||
class AnySignalAccountFinder: NSObject {
|
||||
typealias ReadTransaction = SDSAnyReadTransaction
|
||||
|
||||
let grdbAdapter = GRDBSignalAccountFinder()
|
||||
let yapdbAdapter = YAPDBSignalAccountFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalAccountFinder: SignalAccountFinder {
|
||||
extension AnySignalAccountFinder {
|
||||
@objc(signalAccountForAddress:transaction:)
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> SignalAccount? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalAccount(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.signalAccount(for: address, transaction: transaction)
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
typealias ReadTransaction = GRDBReadTransaction
|
||||
|
||||
class GRDBSignalAccountFinder: NSObject {
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> SignalAccount? {
|
||||
if let account = signalAccountForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
@ -56,109 +46,3 @@ class GRDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
return SignalAccount.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
typealias ReadTransaction = YapDatabaseReadTransaction
|
||||
|
||||
private static let uuidColumn = "recipient_uuid"
|
||||
private static let phoneNumberColumn = "recipient_phone_number"
|
||||
private static let phoneNumberIndex = "index_signal_accounts_on_recipientPhoneNumber"
|
||||
private static let uuidIndex = "index_signal_accounts_on_recipientUUID"
|
||||
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
if let account = signalAccountForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
} else if let account = signalAccountForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return account
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func signalAccountForUUID(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalAccountFinder.uuidIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalAccountFinder.uuidColumn, uuidString)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalAccount?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? SignalAccount else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func signalAccountForPhoneNumber(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalAccountFinder.phoneNumberIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalAccountFinder.phoneNumberColumn, phoneNumber)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalAccount?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? SignalAccount else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndex)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndex)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let account = object as? SignalAccount else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidColumn] = account.recipientUUID
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let account = object as? SignalAccount else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberColumn] = account.recipientPhoneNumber
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,36 +4,26 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SignalRecipientFinder {
|
||||
associatedtype ReadTransaction
|
||||
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: ReadTransaction) -> SignalRecipient?
|
||||
}
|
||||
|
||||
@objc
|
||||
public class AnySignalRecipientFinder: NSObject {
|
||||
typealias ReadTransaction = SDSAnyReadTransaction
|
||||
|
||||
class AnySignalRecipientFinder: NSObject {
|
||||
let grdbAdapter = GRDBSignalRecipientFinder()
|
||||
let yapdbAdapter = YAPDBSignalRecipientFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalRecipientFinder: SignalRecipientFinder {
|
||||
extension AnySignalRecipientFinder {
|
||||
@objc(signalRecipientForAddress:transaction:)
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> SignalRecipient? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipient(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.signalRecipient(for: address, transaction: transaction)
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
typealias ReadTransaction = GRDBReadTransaction
|
||||
|
||||
class GRDBSignalRecipientFinder: NSObject {
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> SignalRecipient? {
|
||||
if let recipient = signalRecipientForUUID(address.uuid, transaction: transaction) {
|
||||
return recipient
|
||||
@ -56,109 +46,3 @@ class GRDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
return SignalRecipient.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
typealias ReadTransaction = YapDatabaseReadTransaction
|
||||
|
||||
private static let uuidColumn = "recipient_uuid"
|
||||
private static let phoneNumberColumn = "recipient_phone_number"
|
||||
private static let phoneNumberIndex = "index_signal_recipients_on_recipientPhoneNumber"
|
||||
private static let uuidIndex = "index_signal_recipients_on_recipientUUID"
|
||||
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
if let recipient = signalRecipientForUUID(address.uuid, transaction: transaction) {
|
||||
return recipient
|
||||
} else if let recipient = signalRecipientForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return recipient
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func signalRecipientForUUID(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalRecipientFinder.uuidIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalRecipientFinder.uuidColumn, uuidString)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalRecipient?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = recipient
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func signalRecipientForPhoneNumber(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalRecipientFinder.phoneNumberIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalRecipientFinder.phoneNumberColumn, phoneNumber)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalRecipient?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = recipient
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndex)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndex)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidColumn] = recipient.recipientUUID
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberColumn] = recipient.recipientPhoneNumber
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,9 @@ public struct ThreadRecord: SDSRecord {
|
||||
public let shouldThreadBeVisible: Bool
|
||||
|
||||
// Subclass properties
|
||||
public let contactPhoneNumber: String?
|
||||
public let contactThreadSchemaVersion: UInt?
|
||||
public let contactUUID: String?
|
||||
public let groupModel: Data?
|
||||
public let hasDismissedOffers: Bool?
|
||||
|
||||
@ -53,6 +56,9 @@ public struct ThreadRecord: SDSRecord {
|
||||
case messageDraft
|
||||
case mutedUntilDate
|
||||
case shouldThreadBeVisible
|
||||
case contactPhoneNumber
|
||||
case contactThreadSchemaVersion
|
||||
case contactUUID
|
||||
case groupModel
|
||||
case hasDismissedOffers
|
||||
}
|
||||
@ -99,6 +105,9 @@ extension TSThread {
|
||||
let messageDraft: String? = record.messageDraft
|
||||
let mutedUntilDate: Date? = record.mutedUntilDate
|
||||
let shouldThreadBeVisible: Bool = record.shouldThreadBeVisible
|
||||
let contactPhoneNumber: String? = record.contactPhoneNumber
|
||||
let contactThreadSchemaVersion: UInt = try SDSDeserialization.required(record.contactThreadSchemaVersion, name: "contactThreadSchemaVersion")
|
||||
let contactUUID: String? = record.contactUUID
|
||||
let hasDismissedOffers: Bool = try SDSDeserialization.required(record.hasDismissedOffers, name: "hasDismissedOffers")
|
||||
|
||||
return TSContactThread(uniqueId: uniqueId,
|
||||
@ -111,6 +120,9 @@ extension TSThread {
|
||||
messageDraft: messageDraft,
|
||||
mutedUntilDate: mutedUntilDate,
|
||||
shouldThreadBeVisible: shouldThreadBeVisible,
|
||||
contactPhoneNumber: contactPhoneNumber,
|
||||
contactThreadSchemaVersion: contactThreadSchemaVersion,
|
||||
contactUUID: contactUUID,
|
||||
hasDismissedOffers: hasDismissedOffers)
|
||||
|
||||
case .groupThread:
|
||||
@ -215,8 +227,11 @@ extension TSThreadSerializer {
|
||||
static let mutedUntilDateColumn = SDSColumnMetadata(columnName: "mutedUntilDate", columnType: .int64, isOptional: true, columnIndex: 10)
|
||||
static let shouldThreadBeVisibleColumn = SDSColumnMetadata(columnName: "shouldThreadBeVisible", columnType: .int, columnIndex: 11)
|
||||
// Subclass properties
|
||||
static let groupModelColumn = SDSColumnMetadata(columnName: "groupModel", columnType: .blob, isOptional: true, columnIndex: 12)
|
||||
static let hasDismissedOffersColumn = SDSColumnMetadata(columnName: "hasDismissedOffers", columnType: .int, isOptional: true, columnIndex: 13)
|
||||
static let contactPhoneNumberColumn = SDSColumnMetadata(columnName: "contactPhoneNumber", columnType: .unicodeString, isOptional: true, columnIndex: 12)
|
||||
static let contactThreadSchemaVersionColumn = SDSColumnMetadata(columnName: "contactThreadSchemaVersion", columnType: .int64, isOptional: true, columnIndex: 13)
|
||||
static let contactUUIDColumn = SDSColumnMetadata(columnName: "contactUUID", columnType: .unicodeString, isOptional: true, columnIndex: 14)
|
||||
static let groupModelColumn = SDSColumnMetadata(columnName: "groupModel", columnType: .blob, isOptional: true, columnIndex: 15)
|
||||
static let hasDismissedOffersColumn = SDSColumnMetadata(columnName: "hasDismissedOffers", columnType: .int, isOptional: true, columnIndex: 16)
|
||||
|
||||
// TODO: We should decide on a naming convention for
|
||||
// tables that store models.
|
||||
@ -233,6 +248,9 @@ extension TSThreadSerializer {
|
||||
messageDraftColumn,
|
||||
mutedUntilDateColumn,
|
||||
shouldThreadBeVisibleColumn,
|
||||
contactPhoneNumberColumn,
|
||||
contactThreadSchemaVersionColumn,
|
||||
contactUUIDColumn,
|
||||
groupModelColumn,
|
||||
hasDismissedOffersColumn
|
||||
])
|
||||
@ -571,9 +589,12 @@ class TSThreadSerializer: SDSSerializer {
|
||||
let shouldThreadBeVisible: Bool = model.shouldThreadBeVisible
|
||||
|
||||
// Subclass properties
|
||||
let contactPhoneNumber: String? = nil
|
||||
let contactThreadSchemaVersion: UInt? = nil
|
||||
let contactUUID: String? = nil
|
||||
let groupModel: Data? = nil
|
||||
let hasDismissedOffers: Bool? = nil
|
||||
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,12 +83,6 @@ NS_SWIFT_NAME(init(uniqueId:archivalDate:archivedAsOfMessageSortId:conversationC
|
||||
+ (ConversationColorName)stableColorNameForNewConversationWithString:(NSString *)colorSeed;
|
||||
@property (class, nonatomic, readonly) NSArray<ConversationColorName> *conversationColorNames;
|
||||
|
||||
/**
|
||||
* @returns
|
||||
* Signal Id (e164) of the contact if it's a contact thread.
|
||||
*/
|
||||
- (nullable NSString *)contactIdentifier;
|
||||
|
||||
/**
|
||||
* @returns recipientId for each recipient in the thread
|
||||
*/
|
||||
|
||||
@ -85,13 +85,10 @@ ConversationColorName const kConversationColorName_Default = ConversationColorNa
|
||||
_creationDate = [NSDate date];
|
||||
_messageDraft = nil;
|
||||
|
||||
NSString *_Nullable contactId = self.contactIdentifier;
|
||||
if (contactId.length > 0) {
|
||||
// To be consistent with colors synced to desktop
|
||||
_conversationColorName = [self.class stableColorNameForNewConversationWithString:contactId];
|
||||
} else {
|
||||
_conversationColorName = [self.class stableColorNameForNewConversationWithString:self.uniqueId];
|
||||
}
|
||||
// This is overriden in TSContactThread to use the phone number when available
|
||||
// We can't use self.colorSeed here because the subclass hasn't done its
|
||||
// initializing work yet to set it up.
|
||||
_conversationColorName = [self.class stableColorNameForNewConversationWithString:uniqueId];
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -154,14 +151,7 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin
|
||||
}
|
||||
|
||||
if (_conversationColorName.length == 0) {
|
||||
NSString *_Nullable colorSeed = self.contactIdentifier;
|
||||
if (colorSeed.length > 0) {
|
||||
// group threads
|
||||
colorSeed = self.uniqueId;
|
||||
}
|
||||
|
||||
// To be consistent with colors synced to desktop
|
||||
ConversationColorName colorName = [self.class stableColorNameForLegacyConversationWithString:colorSeed];
|
||||
ConversationColorName colorName = [self.class stableColorNameForLegacyConversationWithString:self.colorSeed];
|
||||
OWSAssertDebug(colorName);
|
||||
|
||||
_conversationColorName = colorName;
|
||||
@ -246,11 +236,12 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin
|
||||
|
||||
- (BOOL)isNoteToSelf
|
||||
{
|
||||
if (!IsNoteToSelfEnabled()) {
|
||||
return NO;
|
||||
}
|
||||
return (!self.isGroupThread && self.contactIdentifier != nil &&
|
||||
[self.contactIdentifier isEqualToString:self.tsAccountManager.localNumber]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *)colorSeed
|
||||
{
|
||||
return self.uniqueId;
|
||||
}
|
||||
|
||||
#pragma mark - To be subclassed.
|
||||
@ -261,12 +252,6 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Override in ContactThread
|
||||
- (nullable NSString *)contactIdentifier
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)name {
|
||||
OWSAbstractMethod();
|
||||
|
||||
|
||||
@ -43,9 +43,12 @@ class TSContactThreadSerializer: SDSSerializer {
|
||||
let shouldThreadBeVisible: Bool = model.shouldThreadBeVisible
|
||||
|
||||
// Subclass properties
|
||||
let contactPhoneNumber: String? = model.contactPhoneNumber
|
||||
let contactThreadSchemaVersion: UInt? = model.contactThreadSchemaVersion
|
||||
let contactUUID: String? = model.contactUUID
|
||||
let groupModel: Data? = nil
|
||||
let hasDismissedOffers: Bool? = model.hasDismissedOffers
|
||||
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const TSContactThreadPrefix;
|
||||
|
||||
@class SignalServiceAddress;
|
||||
|
||||
@interface TSContactThread : TSThread
|
||||
@ -28,48 +26,45 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin
|
||||
messageDraft:(nullable NSString *)messageDraft
|
||||
mutedUntilDate:(nullable NSDate *)mutedUntilDate
|
||||
shouldThreadBeVisible:(BOOL)shouldThreadBeVisible
|
||||
contactPhoneNumber:(nullable NSString *)contactPhoneNumber
|
||||
contactThreadSchemaVersion:(NSUInteger)contactThreadSchemaVersion
|
||||
contactUUID:(nullable NSString *)contactUUID
|
||||
hasDismissedOffers:(BOOL)hasDismissedOffers
|
||||
NS_SWIFT_NAME(init(uniqueId:archivalDate:archivedAsOfMessageSortId:conversationColorName:creationDate:isArchivedByLegacyTimestampForSorting:lastMessageDate:messageDraft:mutedUntilDate:shouldThreadBeVisible:hasDismissedOffers:));
|
||||
NS_SWIFT_NAME(init(uniqueId:archivalDate:archivedAsOfMessageSortId:conversationColorName:creationDate:isArchivedByLegacyTimestampForSorting:lastMessageDate:messageDraft:mutedUntilDate:shouldThreadBeVisible:contactPhoneNumber:contactThreadSchemaVersion:contactUUID:hasDismissedOffers:));
|
||||
|
||||
// clang-format on
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
// TODO: We might want to make this initializer private once we
|
||||
// convert getOrCreateThreadWithContactId to take "any" transaction.
|
||||
- (instancetype)initWithContactId:(NSString *)contactId;
|
||||
|
||||
@property (nonatomic) BOOL hasDismissedOffers;
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId NS_SWIFT_NAME(getOrCreateThread(contactId:));
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId
|
||||
anyTransaction:(SDSAnyWriteTransaction *)transaction;
|
||||
|
||||
// Unlike getOrCreateThreadWithContactId, this will _NOT_ create a thread if one does not already exist.
|
||||
+ (nullable instancetype)getThreadWithContactId:(NSString *)contactId transaction:(YapDatabaseReadTransaction *)transaction;
|
||||
+ (nullable instancetype)getThreadWithContactId:(NSString *)contactId
|
||||
anyTransaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
- (NSString *)contactIdentifier;
|
||||
// convert getOrCreateThreadWithContactAddress to take "any" transaction.
|
||||
- (instancetype)initWithContactAddress:(SignalServiceAddress *)contactAddress;
|
||||
|
||||
@property (nonatomic, readonly) SignalServiceAddress *contactAddress;
|
||||
|
||||
+ (NSString *)contactIdFromThreadId:(NSString *)threadId;
|
||||
@property (nonatomic) BOOL hasDismissedOffers;
|
||||
|
||||
// This is only exposed for tests.
|
||||
#ifdef DEBUG
|
||||
+ (NSString *)threadIdFromContactId:(NSString *)contactId;
|
||||
#endif
|
||||
+ (instancetype)getOrCreateThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
NS_SWIFT_NAME(getOrCreateThread(contactAddress:));
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
transaction:(SDSAnyWriteTransaction *)transaction;
|
||||
|
||||
// Unlike getOrCreateThreadWithContactAddress, this will _NOT_ create a thread if one does not already exist.
|
||||
+ (nullable instancetype)getThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
+ (nullable SignalServiceAddress *)contactAddressFromThreadId:(NSString *)threadId
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
// This is only ever used from migration from a pre-UUID world to a UUID world
|
||||
+ (nullable NSString *)legacyContactPhoneNumberFromThreadId:(NSString *)threadId;
|
||||
|
||||
// This method can be used to get the conversation color for a given
|
||||
// recipient without using a read/write transaction to create a
|
||||
// contact thread.
|
||||
+ (NSString *)conversationColorNameForRecipientId:(NSString *)recipientId
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
+ (NSString *)conversationColorNameForContactAddress:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -9,15 +9,40 @@
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "SSKEnvironment.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
#import <YapDatabase/YapDatabaseConnection.h>
|
||||
#import <YapDatabase/YapDatabaseTransaction.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSString *const TSContactThreadPrefix = @"c";
|
||||
NSString *const TSContactThreadLegacyPrefix = @"c";
|
||||
NSUInteger const TSContactThreadSchemaVersion = 1;
|
||||
|
||||
@interface TSContactThread ()
|
||||
|
||||
@property (nonatomic, nullable, readonly) NSString *contactPhoneNumber;
|
||||
@property (nonatomic, nullable, readonly) NSString *contactUUID;
|
||||
@property (nonatomic, readonly) NSUInteger contactThreadSchemaVersion;
|
||||
|
||||
// From TSThread
|
||||
@property (nonatomic) NSString *conversationColorName;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TSContactThread
|
||||
|
||||
#pragma mark - Dependencies
|
||||
|
||||
+ (SDSDatabaseStorage *)databaseStorage
|
||||
{
|
||||
return SDSDatabaseStorage.shared;
|
||||
}
|
||||
|
||||
+ (AnyContactThreadFinder *)threadFinder
|
||||
{
|
||||
return [AnyContactThreadFinder new];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
// This snippet is generated by /Scripts/sds_codegen/sds_generate.py. Do not manually edit it, instead run `sds_codegen.sh`.
|
||||
@ -34,6 +59,9 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin
|
||||
messageDraft:(nullable NSString *)messageDraft
|
||||
mutedUntilDate:(nullable NSDate *)mutedUntilDate
|
||||
shouldThreadBeVisible:(BOOL)shouldThreadBeVisible
|
||||
contactPhoneNumber:(nullable NSString *)contactPhoneNumber
|
||||
contactThreadSchemaVersion:(NSUInteger)contactThreadSchemaVersion
|
||||
contactUUID:(nullable NSString *)contactUUID
|
||||
hasDismissedOffers:(BOOL)hasDismissedOffers
|
||||
{
|
||||
self = [super initWithUniqueId:uniqueId
|
||||
@ -51,6 +79,9 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
return self;
|
||||
}
|
||||
|
||||
_contactPhoneNumber = contactPhoneNumber;
|
||||
_contactThreadSchemaVersion = contactThreadSchemaVersion;
|
||||
_contactUUID = contactUUID;
|
||||
_hasDismissedOffers = hasDismissedOffers;
|
||||
|
||||
return self;
|
||||
@ -60,93 +91,108 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
|
||||
- (instancetype)initWithContactId:(NSString *)contactId {
|
||||
NSString *uniqueIdentifier = [[self class] threadIdFromContactId:contactId];
|
||||
- (nullable instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
self = [super initWithCoder:coder];
|
||||
if (self) {
|
||||
// Migrate legacy threads to store phone number and UUID
|
||||
if (_contactThreadSchemaVersion < 1) {
|
||||
_contactPhoneNumber = [[self class] legacyContactPhoneNumberFromThreadId:self.uniqueId];
|
||||
}
|
||||
|
||||
OWSAssertDebug(contactId.length > 0);
|
||||
_contactThreadSchemaVersion = TSContactThreadSchemaVersion;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
self = [super initWithUniqueId:uniqueIdentifier];
|
||||
- (instancetype)initWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
{
|
||||
OWSAssertDebug(contactAddress.isValid);
|
||||
|
||||
if (self = [super init]) {
|
||||
_contactUUID = contactAddress.uuidString;
|
||||
_contactPhoneNumber = contactAddress.phoneNumber;
|
||||
_contactThreadSchemaVersion = TSContactThreadSchemaVersion;
|
||||
|
||||
// Reset the conversation color to use our phone number, if available. The super initializer just uses the
|
||||
// uniqueId
|
||||
self.conversationColorName =
|
||||
[[self class] stableColorNameForNewConversationWithString:contactAddress.stringForDisplay];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId
|
||||
transaction:(YapDatabaseReadWriteTransaction *)transaction {
|
||||
OWSAssertDebug(contactId.length > 0);
|
||||
|
||||
TSContactThread *thread =
|
||||
[self fetchObjectWithUniqueID:[self threadIdFromContactId:contactId] transaction:transaction];
|
||||
|
||||
if (!thread) {
|
||||
thread = [[TSContactThread alloc] initWithContactId:contactId];
|
||||
[thread saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId
|
||||
anyTransaction:(SDSAnyWriteTransaction *)transaction
|
||||
+ (instancetype)getOrCreateThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
transaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(contactId.length > 0);
|
||||
OWSAssertDebug(contactAddress.isValid);
|
||||
|
||||
NSString *uniqueId = [self threadIdFromContactId:contactId];
|
||||
TSContactThread *thread = (TSContactThread *)[self anyFetchWithUniqueId:uniqueId transaction:transaction];
|
||||
TSContactThread *thread = [self.threadFinder contactThreadForAddress:contactAddress transaction:transaction];
|
||||
|
||||
if (!thread) {
|
||||
thread = [[TSContactThread alloc] initWithContactId:contactId];
|
||||
thread = [[TSContactThread alloc] initWithContactAddress:contactAddress];
|
||||
[thread anyInsertWithTransaction:transaction];
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
+ (instancetype)getOrCreateThreadWithContactId:(NSString *)contactId
|
||||
+ (instancetype)getOrCreateThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
{
|
||||
OWSAssertDebug(contactId.length > 0);
|
||||
OWSAssertDebug(contactAddress.isValid);
|
||||
|
||||
__block TSContactThread *thread;
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [self getOrCreateThreadWithContactId:contactId transaction:transaction];
|
||||
[self.databaseStorage writeWithBlock:^(SDSAnyWriteTransaction *transaction) {
|
||||
thread = [self getOrCreateThreadWithContactAddress:contactAddress transaction:transaction];
|
||||
}];
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)getThreadWithContactId:(NSString *)contactId
|
||||
transaction:(YapDatabaseReadTransaction *)transaction
|
||||
+ (nullable instancetype)getThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return [TSContactThread fetchObjectWithUniqueID:[self threadIdFromContactId:contactId] transaction:transaction];
|
||||
}
|
||||
|
||||
+ (nullable instancetype)getThreadWithContactId:(NSString *)contactId
|
||||
anyTransaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return (TSContactThread *)[TSContactThread anyFetchWithUniqueId:[self threadIdFromContactId:contactId]
|
||||
transaction:transaction];
|
||||
}
|
||||
|
||||
- (NSString *)contactIdentifier {
|
||||
return [[self class] contactIdFromThreadId:self.uniqueId];
|
||||
return [self.threadFinder contactThreadForAddress:contactAddress transaction:transaction];
|
||||
}
|
||||
|
||||
- (SignalServiceAddress *)contactAddress
|
||||
{
|
||||
return [[SignalServiceAddress alloc] initWithPhoneNumber:self.contactIdentifier];
|
||||
return [[SignalServiceAddress alloc] initWithUuidString:self.contactUUID phoneNumber:self.contactPhoneNumber];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)recipientIdentifiers
|
||||
{
|
||||
return @[self.contactIdentifier];
|
||||
return @[ self.contactAddress.transitional_phoneNumber ];
|
||||
}
|
||||
|
||||
- (BOOL)isGroupThread {
|
||||
return false;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isNoteToSelf
|
||||
{
|
||||
if (!IsNoteToSelfEnabled()) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return self.contactAddress.isLocalAddress;
|
||||
}
|
||||
|
||||
- (NSString *)colorSeed
|
||||
{
|
||||
NSString *_Nullable phoneNumber = self.contactAddress.phoneNumber;
|
||||
if (!phoneNumber) {
|
||||
phoneNumber = [[self class] legacyContactPhoneNumberFromThreadId:self.uniqueId];
|
||||
}
|
||||
|
||||
return phoneNumber ?: self.uniqueId;
|
||||
}
|
||||
|
||||
- (BOOL)hasSafetyNumbers
|
||||
{
|
||||
return !![[OWSIdentityManager sharedManager] identityKeyForRecipientId:self.contactIdentifier];
|
||||
return !!
|
||||
[[OWSIdentityManager sharedManager] identityKeyForRecipientId:self.contactAddress.transitional_phoneNumber];
|
||||
}
|
||||
|
||||
// TODO deprecate this? seems weird to access the displayName in the DB model
|
||||
@ -155,25 +201,34 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
return [SSKEnvironment.shared.contactsManager displayNameForAddress:self.contactAddress];
|
||||
}
|
||||
|
||||
+ (NSString *)threadIdFromContactId:(NSString *)contactId {
|
||||
return [TSContactThreadPrefix stringByAppendingString:contactId];
|
||||
+ (nullable SignalServiceAddress *)contactAddressFromThreadId:(NSString *)threadId
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
TSContactThread *_Nullable contactThread = (TSContactThread *)[TSContactThread anyFetchWithUniqueId:threadId
|
||||
transaction:transaction];
|
||||
return contactThread.contactAddress;
|
||||
}
|
||||
|
||||
+ (NSString *)contactIdFromThreadId:(NSString *)threadId {
|
||||
+ (nullable NSString *)legacyContactPhoneNumberFromThreadId:(NSString *)threadId
|
||||
{
|
||||
if (![threadId hasPrefix:TSContactThreadLegacyPrefix]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [threadId substringWithRange:NSMakeRange(1, threadId.length - 1)];
|
||||
}
|
||||
|
||||
+ (NSString *)conversationColorNameForRecipientId:(NSString *)recipientId
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
+ (NSString *)conversationColorNameForContactAddress:(SignalServiceAddress *)address
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
OWSAssertDebug(recipientId.length > 0);
|
||||
OWSAssertDebug(address);
|
||||
|
||||
TSContactThread *_Nullable contactThread =
|
||||
[TSContactThread getThreadWithContactId:recipientId anyTransaction:transaction];
|
||||
TSContactThread *_Nullable contactThread = [TSContactThread getThreadWithContactAddress:address
|
||||
transaction:transaction];
|
||||
if (contactThread) {
|
||||
return contactThread.conversationColorName;
|
||||
}
|
||||
return [self stableColorNameForNewConversationWithString:recipientId];
|
||||
return [self stableColorNameForNewConversationWithString:address.stringForDisplay];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -43,9 +43,12 @@ class TSGroupThreadSerializer: SDSSerializer {
|
||||
let shouldThreadBeVisible: Bool = model.shouldThreadBeVisible
|
||||
|
||||
// Subclass properties
|
||||
let contactPhoneNumber: String? = nil
|
||||
let contactThreadSchemaVersion: UInt? = nil
|
||||
let contactUUID: String? = nil
|
||||
let groupModel: Data? = optionalArchive(model.groupModel)
|
||||
let hasDismissedOffers: Bool? = nil
|
||||
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
return ThreadRecord(id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, archivedAsOfMessageSortId: archivedAsOfMessageSortId, conversationColorName: conversationColorName, creationDate: creationDate, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,151 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol YAPDBSignalServiceAddressIndexable: class {
|
||||
var indexableUUIDValue: String? { get }
|
||||
var indexablePhoneNumberValue: String? { get }
|
||||
}
|
||||
|
||||
extension SignalAccount: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension SignalRecipient: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension TSContactThread: YAPDBSignalServiceAddressIndexable {
|
||||
var indexableUUIDValue: String? { return contactUUID }
|
||||
var indexablePhoneNumberValue: String? { return contactPhoneNumber }
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalServiceAddressIndex: NSObject {
|
||||
private static let indexableTypes: [YAPDBSignalServiceAddressIndexable.Type] = [
|
||||
SignalAccount.self,
|
||||
SignalRecipient.self,
|
||||
TSContactThread.self
|
||||
]
|
||||
|
||||
private static let uuidKey = "uuidKey"
|
||||
private static let phoneNumberKey = "phoneNumberKey"
|
||||
private static let classNameKey = "classNameKey"
|
||||
|
||||
private static let phoneNumberIndexName = "index_on_recipientPhoneNumber"
|
||||
private static let uuidIndexName = "index_on_recipientUUID"
|
||||
|
||||
func fetchOne<T: YAPDBSignalServiceAddressIndexable>(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
if let result: T = fetchOneForUUID(address.uuid, transaction: transaction) {
|
||||
return result
|
||||
} else if let result: T = fetchOneForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return result
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchOneForUUID<T: YAPDBSignalServiceAddressIndexable>(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.uuidIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(
|
||||
format: "WHERE %@ = \"%@\" AND %@ = \"%@\"",
|
||||
YAPDBSignalServiceAddressIndex.uuidKey,
|
||||
uuidString,
|
||||
YAPDBSignalServiceAddressIndex.classNameKey,
|
||||
NSStringFromClass(T.self)
|
||||
)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func fetchOneForPhoneNumber<T: YAPDBSignalServiceAddressIndexable>(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.phoneNumberIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(
|
||||
format: "WHERE %@ = \"%@\" AND %@ = \"%@\"",
|
||||
YAPDBSignalServiceAddressIndex.phoneNumberKey,
|
||||
phoneNumber,
|
||||
YAPDBSignalServiceAddressIndex.classNameKey,
|
||||
NSStringFromClass(T.self)
|
||||
)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndexName)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndexName)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidKey, with: .text)
|
||||
setup.addColumn(classNameKey, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidKey] = indexableObject.indexableUUIDValue
|
||||
dict[classNameKey] = NSStringFromClass(type(of: indexableObject))
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberKey, with: .text)
|
||||
setup.addColumn(classNameKey, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberKey] = indexableObject.indexablePhoneNumberValue
|
||||
dict[classNameKey] = NSStringFromClass(type(of: indexableObject))
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (self.dataMessage.group) {
|
||||
_thread = [TSGroupThread getOrCreateThreadWithGroupId:_dataMessage.group.id transaction:transaction];
|
||||
} else {
|
||||
_thread = [TSContactThread getOrCreateThreadWithContactId:_recipientId transaction:transaction];
|
||||
_thread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:_recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
}
|
||||
|
||||
_quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage
|
||||
|
||||
@ -52,10 +52,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
|
||||
_message = message;
|
||||
// This will be nil for groups.
|
||||
_sentRecipientId = message.thread.contactIdentifier;
|
||||
_isRecipientUpdate = isRecipientUpdate;
|
||||
|
||||
if ([message.thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)message.thread;
|
||||
_sentRecipientId = contactThread.contactAddress.transitional_phoneNumber;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@ -129,8 +129,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSString *conversationColorName;
|
||||
|
||||
TSContactThread *_Nullable contactThread =
|
||||
[TSContactThread getThreadWithContactId:signalAccount.recipientAddress.transitional_phoneNumber
|
||||
transaction:transaction];
|
||||
[TSContactThread getThreadWithContactAddress:signalAccount.recipientAddress
|
||||
transaction:transaction.asAnyRead];
|
||||
if (contactThread) {
|
||||
conversationColorName = contactThread.conversationColorName;
|
||||
disappearingMessagesConfiguration = [contactThread disappearingMessagesConfigurationWithTransaction:transaction];
|
||||
|
||||
@ -91,8 +91,8 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
|
||||
withTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
failedMessageType:(TSErrorMessageType)errorMessageType
|
||||
{
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164
|
||||
transaction:transaction];
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
|
||||
// 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.
|
||||
|
||||
@ -37,8 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
|
||||
if (_authorId == nil) {
|
||||
OWSAssertDebug([self.uniqueThreadId hasPrefix:TSContactThreadPrefix]);
|
||||
_authorId = [TSContactThread contactIdFromThreadId:self.uniqueThreadId];
|
||||
_authorId = [TSContactThread legacyContactPhoneNumberFromThreadId:self.uniqueThreadId];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@ -237,9 +237,10 @@ perMessageExpirationDurationSeconds:perMessageExpirationDurationSeconds
|
||||
case TSInfoMessageUserJoinedSignal: {
|
||||
NSString *recipientName;
|
||||
if (transaction.transitional_yapReadTransaction != nil) {
|
||||
NSString *contactId = [TSContactThread contactIdFromThreadId:self.uniqueThreadId];
|
||||
SignalServiceAddress *address = [TSContactThread contactAddressFromThreadId:self.uniqueThreadId
|
||||
transaction:transaction];
|
||||
recipientName =
|
||||
[self.contactsManager displayNameForAddress:contactId.transitional_signalServiceAddress
|
||||
[self.contactsManager displayNameForAddress:address
|
||||
transaction:transaction.transitional_yapReadTransaction];
|
||||
}
|
||||
NSString *format = NSLocalizedString(@"INFO_MESSAGE_USER_JOINED_SIGNAL_BODY_FORMAT",
|
||||
|
||||
@ -41,8 +41,8 @@ __attribute__((deprecated)) @interface TSInvalidIdentityKeyReceivingErrorMessage
|
||||
+ (nullable instancetype)untrustedKeyWithEnvelope:(SSKProtoEnvelope *)envelope
|
||||
withTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164
|
||||
transaction:transaction];
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction.asAnyWrite];
|
||||
|
||||
// Legit usage of senderTimestamp, references message which failed to decrypt
|
||||
TSInvalidIdentityKeyReceivingErrorMessage *errorMessage =
|
||||
|
||||
@ -95,7 +95,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
|
||||
{
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
return [self isRecipientIdBlocked:contactThread.contactIdentifier];
|
||||
return [self isRecipientIdBlocked:contactThread.contactAddress.transitional_phoneNumber];
|
||||
} else if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
TSGroupThread *groupThread = (TSGroupThread *)thread;
|
||||
return [self isGroupIdBlocked:groupThread.groupModel.groupId];
|
||||
|
||||
@ -550,7 +550,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
NSMutableArray<TSMessage *> *messages = [NSMutableArray new];
|
||||
|
||||
TSContactThread *contactThread =
|
||||
[TSContactThread getOrCreateThreadWithContactId:recipientId anyTransaction:transaction];
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction];
|
||||
OWSAssertDebug(contactThread != nil);
|
||||
|
||||
TSErrorMessage *errorMessage =
|
||||
@ -652,8 +653,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
OWSAssertDebug(message);
|
||||
OWSAssertDebug(message.verificationForRecipientId.length > 0);
|
||||
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:message.verificationForRecipientId];
|
||||
|
||||
TSContactThread *contactThread = [TSContactThread
|
||||
getOrCreateThreadWithContactAddress:message.verificationForRecipientId.transitional_signalServiceAddress];
|
||||
|
||||
// Send null message to appear as though we're sending a normal message to cover the sync messsage sent
|
||||
// subsequently
|
||||
OWSOutgoingNullMessage *nullMessage = [[OWSOutgoingNullMessage alloc] initWithContactThread:contactThread
|
||||
@ -876,7 +878,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
NSMutableArray<TSMessage *> *messages = [NSMutableArray new];
|
||||
|
||||
TSContactThread *contactThread =
|
||||
[TSContactThread getOrCreateThreadWithContactId:recipientId anyTransaction:transaction];
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress
|
||||
transaction:transaction];
|
||||
OWSAssertDebug(contactThread);
|
||||
// MJK TODO - should be safe to remove senderTimestamp
|
||||
[messages addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
|
||||
@ -653,8 +653,8 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
|
||||
envelope:(SSKProtoEnvelope *)envelope
|
||||
transaction:(SDSAnyWriteTransaction *)transaction
|
||||
{
|
||||
TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164
|
||||
anyTransaction:transaction];
|
||||
TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction];
|
||||
[SSKEnvironment.shared.notificationsManager notifyUserForErrorMessage:errorMessage
|
||||
thread:contactThread
|
||||
transaction:transaction];
|
||||
|
||||
@ -581,9 +581,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// FIXME: https://github.com/signalapp/Signal-iOS/issues/1340
|
||||
OWSLogInfo(@"Sending group info request: %@", envelopeAddress(envelope));
|
||||
|
||||
NSString *recipientId = envelope.sourceE164;
|
||||
|
||||
TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId anyTransaction:transaction];
|
||||
TSThread *thread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction];
|
||||
|
||||
OWSSyncGroupsRequestMessage *syncGroupsRequestMessage =
|
||||
[[OWSSyncGroupsRequestMessage alloc] initWithThread:thread groupId:groupId];
|
||||
@ -719,7 +718,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
thread = groupThread;
|
||||
} else {
|
||||
thread = [TSContactThread getThreadWithContactId:envelope.sourceE164 anyTransaction:transaction];
|
||||
thread = [TSContactThread getThreadWithContactAddress:envelope.sourceAddress transaction:transaction];
|
||||
}
|
||||
|
||||
if (!thread) {
|
||||
@ -1029,8 +1028,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return;
|
||||
}
|
||||
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164
|
||||
anyTransaction:transaction];
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction];
|
||||
|
||||
// MJK TODO - safe to remove senderTimestamp
|
||||
[[[TSInfoMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
@ -1379,8 +1378,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164
|
||||
anyTransaction:transaction];
|
||||
TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress
|
||||
transaction:transaction];
|
||||
|
||||
if (dataMessage.hasRequiredProtocolVersion
|
||||
&& dataMessage.requiredProtocolVersion > SSKProtos.currentProtocolVersion) {
|
||||
@ -1661,7 +1660,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSAssertDebug(groupThread);
|
||||
return groupThread;
|
||||
} else {
|
||||
return [TSContactThread getOrCreateThreadWithContactId:envelope.sourceE164 anyTransaction:transaction];
|
||||
return [TSContactThread getOrCreateThreadWithContactAddress:envelope.sourceAddress transaction:transaction];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -557,23 +557,24 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
OWSFailDebug(@"Message send recipients should not include self.");
|
||||
}
|
||||
} else if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
NSString *recipientContactId = ((TSContactThread *)thread).contactIdentifier;
|
||||
TSContactThread *contactThread = (TSContactThread *)thread;
|
||||
SignalServiceAddress *recipientAddress = contactThread.contactAddress;
|
||||
|
||||
// Treat 1:1 sends to blocked contacts as failures.
|
||||
// If we block a user, don't send 1:1 messages to them. The UI
|
||||
// should prevent this from occurring, but in some edge cases
|
||||
// you might, for example, have a pending outgoing message when
|
||||
// you block them.
|
||||
OWSAssertDebug(recipientContactId.length > 0);
|
||||
if ([self.blockingManager isRecipientIdBlocked:recipientContactId]) {
|
||||
OWSLogInfo(@"skipping 1:1 send to blocked contact: %@", recipientContactId);
|
||||
OWSAssertDebug(recipientAddress);
|
||||
if ([self.blockingManager isRecipientIdBlocked:recipientAddress.transitional_phoneNumber]) {
|
||||
OWSLogInfo(@"skipping 1:1 send to blocked contact: %@", recipientAddress);
|
||||
NSError *error = OWSErrorMakeMessageSendFailedDueToBlockListError();
|
||||
[error setIsRetryable:NO];
|
||||
*errorHandle = error;
|
||||
return nil;
|
||||
}
|
||||
|
||||
[recipientIds addObject:recipientContactId];
|
||||
[recipientIds addObject:recipientAddress.transitional_phoneNumber];
|
||||
|
||||
if ([recipientIds containsObject:self.tsAccountManager.localNumber]) {
|
||||
OWSFailDebug(@"Message send recipients should not include self.");
|
||||
@ -715,9 +716,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)thread;
|
||||
}
|
||||
|
||||
// In the "self-send" special case, we ony need to send a sync message with a delivery receipt.
|
||||
if ([thread isKindOfClass:[TSContactThread class]] &&
|
||||
[((TSContactThread *)thread).contactIdentifier isEqualToString:self.tsAccountManager.localNumber]) {
|
||||
if (contactThread && contactThread.contactAddress.isLocalAddress) {
|
||||
// Send to self.
|
||||
OWSAssertDebug(message.recipientIds.count == 1);
|
||||
// Don't mark self-sent messages as read (or sent) until the sync transcript is sent.
|
||||
@ -1411,8 +1416,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
{
|
||||
dispatch_block_t success = ^{
|
||||
TSThread *_Nullable thread = message.thread;
|
||||
if (thread && [thread isKindOfClass:[TSContactThread class]] &&
|
||||
[thread.contactIdentifier isEqualToString:self.tsAccountManager.localNumber]) {
|
||||
|
||||
TSContactThread *_Nullable contactThread;
|
||||
if ([thread isKindOfClass:[TSContactThread class]]) {
|
||||
contactThread = (TSContactThread *)thread;
|
||||
}
|
||||
|
||||
if (contactThread && contactThread.contactAddress.isLocalAddress) {
|
||||
OWSAssertDebug(message.recipientIds.count == 1);
|
||||
// Don't mark self-sent messages as read (or sent) until the sync transcript is sent.
|
||||
[self.databaseStorage writeWithBlock:^(SDSAnyWriteTransaction *transaction) {
|
||||
|
||||
@ -172,7 +172,8 @@ NSString *const kOutgoingReadReceiptManagerCollection = @"kOutgoingReadReceiptMa
|
||||
continue;
|
||||
}
|
||||
|
||||
TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:recipientId];
|
||||
TSThread *thread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:recipientId.transitional_signalServiceAddress];
|
||||
OWSReceiptsForSenderMessage *message;
|
||||
NSString *receiptName;
|
||||
switch (receiptType) {
|
||||
|
||||
@ -502,6 +502,32 @@ public class GRDBDatabaseStorageAdapter: NSObject {
|
||||
on: SignalAccountRecord.databaseTableName,
|
||||
columns: [SignalAccountRecord.columnName(.recipientUUID)]
|
||||
)
|
||||
|
||||
// Signal Recipient Indices
|
||||
try db.create(
|
||||
index: "index_signal_recipients_on_recipientPhoneNumber",
|
||||
on: SignalRecipientRecord.databaseTableName,
|
||||
columns: [SignalRecipientRecord.columnName(.recipientPhoneNumber)]
|
||||
)
|
||||
|
||||
try db.create(
|
||||
index: "index_signal_recipients_on_recipientUUID",
|
||||
on: SignalRecipientRecord.databaseTableName,
|
||||
columns: [SignalRecipientRecord.columnName(.recipientUUID)]
|
||||
)
|
||||
|
||||
// Thread Indices
|
||||
try db.create(
|
||||
index: "index_thread_on_contactPhoneNumber",
|
||||
on: ThreadRecord.databaseTableName,
|
||||
columns: [ThreadRecord.columnName(.contactPhoneNumber)]
|
||||
)
|
||||
|
||||
try db.create(
|
||||
index: "index_tsthread_on_contactUUID",
|
||||
on: ThreadRecord.databaseTableName,
|
||||
columns: [ThreadRecord.columnName(.contactUUID)]
|
||||
)
|
||||
}
|
||||
return migrator
|
||||
}()
|
||||
|
||||
@ -166,4 +166,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface TSContactThread (SDS)
|
||||
|
||||
@property (nonatomic, nullable, readonly) NSString *contactPhoneNumber;
|
||||
@property (nonatomic, nullable, readonly) NSString *contactUUID;
|
||||
@property (nonatomic, readonly) NSUInteger contactThreadSchemaVersion;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -169,12 +169,12 @@ public class FullTextSearchFinder: NSObject {
|
||||
}
|
||||
|
||||
private static let contactThreadIndexer: SearchIndexer<TSContactThread> = SearchIndexer { (contactThread: TSContactThread, transaction: YapDatabaseReadTransaction) in
|
||||
let recipientId = contactThread.contactIdentifier()
|
||||
var result = recipientIndexer.index(recipientId, transaction: transaction)
|
||||
let recipientAddress = contactThread.contactAddress
|
||||
var result = recipientIndexer.index(recipientAddress.transitional_phoneNumber, transaction: transaction)
|
||||
|
||||
if IsNoteToSelfEnabled(),
|
||||
let localNumber = tsAccountManager.storedOrCachedLocalNumber(transaction.asAnyRead),
|
||||
localNumber == recipientId {
|
||||
localNumber == recipientAddress.transitional_phoneNumber {
|
||||
|
||||
let noteToSelfLabel = NSLocalizedString("NOTE_TO_SELF", comment: "Label for 1:1 conversation with yourself.")
|
||||
result += " \(noteToSelfLabel)"
|
||||
|
||||
@ -230,8 +230,7 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage, dispatch_block_t
|
||||
[YAPDBMediaGalleryFinder asyncRegisterDatabaseExtensionsWithPrimaryStorage:self];
|
||||
[TSDatabaseView asyncRegisterLazyRestoreAttachmentsDatabaseView:self];
|
||||
[YAPDBJobRecordFinderSetup asyncRegisterDatabaseExtensionObjCWithStorage:self];
|
||||
[YAPDBSignalAccountFinder asyncRegisterDatabaseExtensions:self];
|
||||
[YAPDBSignalRecipientFinder asyncRegisterDatabaseExtensions:self];
|
||||
[YAPDBSignalServiceAddressIndex asyncRegisterDatabaseExtensions:self];
|
||||
|
||||
[self.database
|
||||
flushExtensionRequestsWithCompletionQueue:dispatch_get_global_queue(
|
||||
|
||||
@ -97,7 +97,7 @@ public class ContactThreadFactory: NSObject, Factory {
|
||||
@objc
|
||||
public func create(transaction: SDSAnyWriteTransaction) -> TSContactThread {
|
||||
let threadId = generateContactThreadId()
|
||||
let thread = TSContactThread.getOrCreateThread(withContactId: threadId, anyTransaction: transaction)
|
||||
let thread = TSContactThread.getOrCreateThread(withContactAddress: SignalServiceAddress(phoneNumber: threadId), transaction: transaction)
|
||||
|
||||
let incomingMessageFactory = IncomingMessageFactory()
|
||||
incomingMessageFactory.threadCreator = { _ in return thread }
|
||||
@ -301,7 +301,7 @@ public class IncomingMessageFactory: NSObject, Factory {
|
||||
public var authorIdBuilder: (TSThread) -> String = { thread in
|
||||
switch thread {
|
||||
case let contactThread as TSContactThread:
|
||||
return contactThread.contactIdentifier()
|
||||
return contactThread.contactAddress.transitional_phoneNumber
|
||||
case let groupThread as TSGroupThread:
|
||||
return groupThread.recipientIdentifiers.ows_randomElement() ?? CommonGenerator.contactId
|
||||
default:
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MockSSKEnvironment.h"
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "SSKBaseTestObjC.h"
|
||||
#import "TSContactThread.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -21,7 +22,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
self.contactThread = [TSContactThread getOrCreateThreadWithContactId:@"fake-contact-id"];
|
||||
self.contactThread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:@"fake-contact-id".transitional_signalServiceAddress];
|
||||
}
|
||||
|
||||
- (void)testHasSafetyNumbersWithoutRemoteIdentity
|
||||
@ -31,8 +33,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)testHasSafetyNumbersWithRemoteIdentity
|
||||
{
|
||||
[[OWSIdentityManager sharedManager] saveRemoteIdentity:[[NSMutableData alloc] initWithLength:kStoredIdentityKeyLength]
|
||||
recipientId:self.contactThread.contactIdentifier];
|
||||
[[OWSIdentityManager sharedManager]
|
||||
saveRemoteIdentity:[[NSMutableData alloc] initWithLength:kStoredIdentityKeyLength]
|
||||
recipientId:self.contactThread.contactAddress.transitional_phoneNumber];
|
||||
XCTAssert(self.contactThread.hasSafetyNumbers);
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
- (void)testDeletingThreadDeletesInteractions
|
||||
{
|
||||
TSContactThread *thread =
|
||||
[[TSContactThread alloc] initWithUniqueId:[TSContactThread threadIdFromContactId:@"+13334445555"]];
|
||||
[[TSContactThread alloc] initWithContactAddress:@"+13334445555".transitional_signalServiceAddress];
|
||||
[thread save];
|
||||
|
||||
[self readWithBlock:^(SDSAnyReadTransaction *_Nonnull transaction) {
|
||||
@ -89,7 +89,7 @@
|
||||
- (void)testDeletingThreadDeletesAttachmentFiles
|
||||
{
|
||||
TSContactThread *thread =
|
||||
[[TSContactThread alloc] initWithUniqueId:[TSContactThread threadIdFromContactId:@"+13334445555"]];
|
||||
[[TSContactThread alloc] initWithContactAddress:@"+13334445555".transitional_signalServiceAddress];
|
||||
[thread save];
|
||||
|
||||
// Sanity check
|
||||
|
||||
@ -2,11 +2,12 @@
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSMessage.h"
|
||||
#import "SSKBaseTestObjC.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSMessage.h"
|
||||
#import <SignalCoreKit/NSDate+OWS.h>
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -20,7 +21,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"fake-thread-id"];
|
||||
self.thread =
|
||||
[TSContactThread getOrCreateThreadWithContactAddress:@"fake-thread-id".transitional_signalServiceAddress];
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
|
||||
@ -86,7 +86,7 @@ class MessageProcessingIntegrationTest: SSKBaseTestSwift {
|
||||
XCTFail("thread was unexpetedly nil")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(thread.contactIdentifier(), self.bobClient.e164Identifier)
|
||||
XCTAssertEqual(thread.contactAddress.transitional_phoneNumber, self.bobClient.e164Identifier)
|
||||
expectMessageProcessed.fulfill()
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ class MessageProcessingIntegrationTest: SSKBaseTestSwift {
|
||||
XCTFail("thread was unexpetedly nil")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(thread.contactIdentifier(), self.bobClient.e164Identifier)
|
||||
XCTAssertEqual(thread.contactAddress.transitional_phoneNumber, self.bobClient.e164Identifier)
|
||||
expectMessageProcessed.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#import "SSKBaseTestObjC.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSIncomingMessage.h"
|
||||
#import <SignalServiceKit/SignalServiceKit-Swift.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -31,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
{
|
||||
[super setUp];
|
||||
self.sourceId = @"+19999999999";
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactId:self.sourceId];
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactAddress:self.sourceId.transitional_signalServiceAddress];
|
||||
self.finder = [OWSIncomingMessageFinder new];
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ class SDSDatabaseStorageTest: SSKBaseTestSwift {
|
||||
XCTAssertEqual(0, TSThread.anyFetchAll(databaseStorage: storage).count)
|
||||
|
||||
let contactId = "+13213214321"
|
||||
let contactThread = TSContactThread(contactId: contactId)
|
||||
let contactThread = TSContactThread(contactAddress: contactId.transitional_signalServiceAddress)
|
||||
|
||||
storage.write { (transaction) in
|
||||
XCTAssertEqual(0, TSThread.anyFetchAll(transaction: transaction).count)
|
||||
@ -111,7 +111,7 @@ class SDSDatabaseStorageTest: SSKBaseTestSwift {
|
||||
XCTAssertEqual(0, TSInteraction.anyFetchAll(databaseStorage: storage).count)
|
||||
|
||||
let contactId = "+13213214321"
|
||||
let contactThread = TSContactThread(contactId: contactId)
|
||||
let contactThread = TSContactThread(contactAddress: contactId.transitional_signalServiceAddress)
|
||||
|
||||
storage.write { (transaction) in
|
||||
XCTAssertEqual(0, TSThread.anyFetchAll(transaction: transaction).count)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user