Merge branch 'nt/uuid'

This commit is contained in:
Nora Trapp 2019-06-27 13:14:12 -07:00
commit 1aa4fb747e
69 changed files with 643 additions and 544 deletions

2
Pods

@ -1 +1 @@
Subproject commit 7fcaa35aac69aa47443b920ef4c6553bd1f8d9d3
Subproject commit 3d393009e3fded14568792745f55eb8faccf44a0

View File

@ -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) {

View File

@ -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?

View File

@ -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)

View File

@ -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;

View File

@ -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) {

View File

@ -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:

View File

@ -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.

View File

@ -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()
}
]

View File

@ -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];
}

View File

@ -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];

View File

@ -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)

View File

@ -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];

View File

@ -479,7 +479,7 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
if (![self.thread.contactIdentifier isEqualToString:recipientId]) {
if (![self.thread.contactAddress.transitional_phoneNumber isEqualToString:recipientId]) {
return;
}

View File

@ -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);

View File

@ -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];
}

View File

@ -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];
}
}

View File

@ -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()

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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];
}

View File

@ -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

View File

@ -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];
}

View File

@ -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)

View File

@ -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];
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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:)

View File

@ -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)

View File

@ -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];
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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)
}

View File

@ -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 {

View 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
}
}

View File

@ -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")
}
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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
*/

View File

@ -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();

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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)
}
}

View File

@ -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")
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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];

View File

@ -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.

View File

@ -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;

View File

@ -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",

View File

@ -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 =

View File

@ -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];

View File

@ -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]

View File

@ -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];

View File

@ -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];
}
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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
}()

View File

@ -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

View File

@ -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)"

View File

@ -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(

View File

@ -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:

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -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()
}
}

View File

@ -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];
}

View File

@ -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)