diff --git a/Podfile.lock b/Podfile.lock index 7e7dfff5f..7f3048c85 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -43,7 +43,7 @@ PODS: - ProtocolBuffers (1.9.10) - Reachability (3.2) - SCWaveformView (1.0.0) - - SignalServiceKit (0.0.4): + - SignalServiceKit (0.0.5): - '25519' - AFNetworking - AxolotlKit @@ -137,7 +137,7 @@ CHECKOUT OPTIONS: :commit: 225b1baa11125ea84d4b960d700834b5b0a40ee1 :git: https://github.com/WhisperSystems/JSQMessagesViewController SignalServiceKit: - :commit: 8058951b08a9fb0c610c56bdb50c403132da2089 + :commit: 80671b247f616c3bd6264eccce5f806a4a538e68 :git: https://github.com/WhisperSystems/SignalServiceKit.git SocketRocket: :commit: 587ad297eb63eb0d64d4caeb32a7da646ad1132b @@ -160,7 +160,7 @@ SPEC CHECKSUMS: ProtocolBuffers: d088180c10072b3d24a9939a6314b7b9bcc2340b Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 SCWaveformView: 52a96750255d817e300565a80c81fb643e233e07 - SignalServiceKit: e27a3025c2d5c61696386e44a50ac8d2fe83151e + SignalServiceKit: f52bc6e17f717540d93b4247a93246648bf4085e SocketRocket: 3f77ec2104cc113add553f817ad90a77114f5d43 SQLCipher: 4c768761421736a247ed6cf412d9045615d53dff SSKeychain: c71293fa57216a40ab06c23f4085387583293de4 diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index fd4595d24..49efdecbb 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -9,6 +9,9 @@ /* Begin PBXBuildFile section */ 0DD55B166906AF3368995978 /* libPods-Signal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 80CD5E19DD23200E7926EEA7 /* libPods-Signal.a */; }; 30209C98DABCE82064B4EAF5 /* libPods-SignalTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A33D3C7EB4B17BDBD47F0FCC /* libPods-SignalTests.a */; }; + 45843D1F1D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; }; + 45843D201D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; }; + 45843D221D223BA10013E85A /* OWSContactsSearcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */; }; 45CB2FA81CB7146C00E1B343 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 45CB2FA71CB7146C00E1B343 /* Launch Screen.storyboard */; }; 4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */; }; 701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; }; @@ -24,7 +27,7 @@ 76EB054018170B33006006FC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB03C318170B33006006FC /* AppDelegate.m */; }; 76EB057218170B33006006FC /* RecentCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040018170B33006006FC /* RecentCall.m */; }; 76EB057418170B33006006FC /* RecentCallManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040218170B33006006FC /* RecentCallManager.m */; }; - 76EB057A18170B33006006FC /* ContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* ContactsManager.m */; }; + 76EB057A18170B33006006FC /* OWSContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* OWSContactsManager.m */; }; 76EB058218170B33006006FC /* Environment.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041318170B33006006FC /* Environment.m */; }; 76EB058418170B33006006FC /* LocalizableText.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041518170B33006006FC /* LocalizableText.m */; }; 76EB058618170B33006006FC /* PreferencesUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041718170B33006006FC /* PreferencesUtil.m */; }; @@ -172,7 +175,7 @@ B660F6B81C29868000687D6E /* JitterQueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6711C29867F00687D6E /* JitterQueueTest.m */; }; B660F6B91C29868000687D6E /* SpeexCodecTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6721C29867F00687D6E /* SpeexCodecTest.m */; }; B660F6BA1C29868000687D6E /* RecentCallTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6741C29867F00687D6E /* RecentCallTest.m */; }; - B660F6BB1C29868000687D6E /* ContactManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6761C29867F00687D6E /* ContactManagerTest.m */; }; + B660F6BB1C29868000687D6E /* OWSContactsManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6761C29867F00687D6E /* OWSContactsManagerTest.m */; }; B660F6BC1C29868000687D6E /* DnsManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6791C29867F00687D6E /* DnsManagerTest.m */; }; B660F6BD1C29868000687D6E /* HttpRequestResponseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67B1C29867F00687D6E /* HttpRequestResponseTest.m */; }; B660F6BE1C29868000687D6E /* IpAddressTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67C1C29867F00687D6E /* IpAddressTest.m */; }; @@ -232,7 +235,7 @@ B660F7141C29988E00687D6E /* RecentCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040018170B33006006FC /* RecentCall.m */; }; B660F7151C29988E00687D6E /* RecentCallManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040218170B33006006FC /* RecentCallManager.m */; }; B660F7161C29988E00687D6E /* GroupContactsResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B671B2451A93B238002BBD9D /* GroupContactsResult.m */; }; - B660F7171C29988E00687D6E /* ContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* ContactsManager.m */; }; + B660F7171C29988E00687D6E /* OWSContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* OWSContactsManager.m */; }; B660F7181C29988E00687D6E /* CryptoTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632418F70C0700D4A43F /* CryptoTools.m */; }; B660F7191C29988E00687D6E /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; }; B660F71A1C29988E00687D6E /* EvpSymetricUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632618F70C0700D4A43F /* EvpSymetricUtil.m */; }; @@ -489,6 +492,9 @@ /* Begin PBXFileReference section */ 453CC0361D08E1A60040EBA3 /* sn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sn; path = translations/sn.lproj/Localizable.strings; sourceTree = ""; }; 454B35071D08EED80026D658 /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = translations/mk.lproj/Localizable.strings; sourceTree = ""; }; + 45843D1D1D2236B30013E85A /* OWSContactsSearcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSearcher.h; sourceTree = ""; }; + 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcher.m; sourceTree = ""; }; + 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcherTest.m; sourceTree = ""; }; 45CB2FA71CB7146C00E1B343 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = "Launch Screen.storyboard"; path = "Signal/src/util/Launch Screen.storyboard"; sourceTree = SOURCE_ROOT; }; 45E282DE1D08E67800ADD4C8 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = translations/gl.lproj/Localizable.strings; sourceTree = ""; }; 45E282DF1D08E6CC00ADD4C8 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = translations/id.lproj/Localizable.strings; sourceTree = ""; }; @@ -515,8 +521,8 @@ 76EB040018170B33006006FC /* RecentCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCall.m; sourceTree = ""; }; 76EB040118170B33006006FC /* RecentCallManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentCallManager.h; sourceTree = ""; }; 76EB040218170B33006006FC /* RecentCallManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCallManager.m; sourceTree = ""; }; - 76EB040818170B33006006FC /* ContactsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsManager.h; sourceTree = ""; }; - 76EB040918170B33006006FC /* ContactsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsManager.m; sourceTree = ""; }; + 76EB040818170B33006006FC /* OWSContactsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsManager.h; sourceTree = ""; }; + 76EB040918170B33006006FC /* OWSContactsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsManager.m; sourceTree = ""; }; 76EB041218170B33006006FC /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = ""; }; 76EB041318170B33006006FC /* Environment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Environment.m; sourceTree = ""; }; 76EB041418170B33006006FC /* LocalizableText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalizableText.h; sourceTree = ""; }; @@ -786,7 +792,7 @@ B660F6711C29867F00687D6E /* JitterQueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitterQueueTest.m; sourceTree = ""; }; B660F6721C29867F00687D6E /* SpeexCodecTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpeexCodecTest.m; sourceTree = ""; }; B660F6741C29867F00687D6E /* RecentCallTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCallTest.m; sourceTree = ""; }; - B660F6761C29867F00687D6E /* ContactManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactManagerTest.m; sourceTree = ""; }; + B660F6761C29867F00687D6E /* OWSContactsManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsManagerTest.m; sourceTree = ""; }; B660F6791C29867F00687D6E /* DnsManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DnsManagerTest.m; sourceTree = ""; }; B660F67B1C29867F00687D6E /* HttpRequestResponseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequestResponseTest.m; sourceTree = ""; }; B660F67C1C29867F00687D6E /* IpAddressTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IpAddressTest.m; sourceTree = ""; }; @@ -1180,8 +1186,10 @@ isa = PBXGroup; children = ( 76EB04A818170B33006006FC /* number directory */, - 76EB040818170B33006006FC /* ContactsManager.h */, - 76EB040918170B33006006FC /* ContactsManager.m */, + 76EB040818170B33006006FC /* OWSContactsManager.h */, + 76EB040918170B33006006FC /* OWSContactsManager.m */, + 45843D1D1D2236B30013E85A /* OWSContactsSearcher.h */, + 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */, ); path = contact; sourceTree = ""; @@ -1781,7 +1789,8 @@ B660F6751C29867F00687D6E /* contact */ = { isa = PBXGroup; children = ( - B660F6761C29867F00687D6E /* ContactManagerTest.m */, + B660F6761C29867F00687D6E /* OWSContactsManagerTest.m */, + 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */, ); path = contact; sourceTree = ""; @@ -2587,13 +2596,14 @@ 76EB061018170B33006006FC /* EventWindow.m in Sources */, E197B62718BBF63B00F073E5 /* SoundBoard.m in Sources */, 76EB058418170B33006006FC /* LocalizableText.m in Sources */, - 76EB057A18170B33006006FC /* ContactsManager.m in Sources */, + 76EB057A18170B33006006FC /* OWSContactsManager.m in Sources */, E197B61918BBEC1A00F073E5 /* RemoteIOBufferListWrapper.m in Sources */, 76EB05A618170B33006006FC /* RtpPacket.m in Sources */, 76EB064218170B33006006FC /* StringUtil.m in Sources */, A547DD741A70A87800103EC7 /* DJWActionSheet+OWS.m in Sources */, 76EB062618170B33006006FC /* Queue.m in Sources */, D221A09A169C9E5E00537ABF /* main.m in Sources */, + 45843D1F1D2236B30013E85A /* OWSContactsSearcher.m in Sources */, 76EB061618170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, B6258B331C29E2E60014138E /* NotificationsManager.m in Sources */, 76EB063018170B33006006FC /* Conversions.m in Sources */, @@ -2743,7 +2753,7 @@ B660F7141C29988E00687D6E /* RecentCall.m in Sources */, B660F7151C29988E00687D6E /* RecentCallManager.m in Sources */, B660F7161C29988E00687D6E /* GroupContactsResult.m in Sources */, - B660F7171C29988E00687D6E /* ContactsManager.m in Sources */, + B660F7171C29988E00687D6E /* OWSContactsManager.m in Sources */, B660F7181C29988E00687D6E /* CryptoTools.m in Sources */, B660F7191C29988E00687D6E /* EvpMessageDigest.m in Sources */, B660F71A1C29988E00687D6E /* EvpSymetricUtil.m in Sources */, @@ -2793,6 +2803,7 @@ B660F7461C29988E00687D6E /* HelloAckPacket.m in Sources */, B660F7471C29988E00687D6E /* HelloPacket.m in Sources */, B660F7481C29988E00687D6E /* RecipientUnavailable.m in Sources */, + 45843D201D2236B30013E85A /* OWSContactsSearcher.m in Sources */, B660F7491C29988E00687D6E /* ShortAuthenticationStringGenerator.m in Sources */, B660F74A1C29988E00687D6E /* ZrtpHandshakeResult.m in Sources */, B660F74B1C29988E00687D6E /* ZrtpHandshakeSocket.m in Sources */, @@ -2806,6 +2817,7 @@ B660F7531C29988E00687D6E /* NetworkStream.m in Sources */, B660F7541C29988E00687D6E /* SecureEndPoint.m in Sources */, B660F7551C29988E00687D6E /* UdpSocket.m in Sources */, + 45843D221D223BA10013E85A /* OWSContactsSearcherTest.m in Sources */, B660F7561C29988E00687D6E /* PushManager.m in Sources */, B660F7571C29988E00687D6E /* NotificationTracker.m in Sources */, B660F7581C29988E00687D6E /* RPAccountManager.m in Sources */, @@ -2893,7 +2905,7 @@ B660F6D51C29868000687D6E /* TestUtil.m in Sources */, B660F6B81C29868000687D6E /* JitterQueueTest.m in Sources */, B660F6DF1C29868000687D6E /* QueueTest.m in Sources */, - B660F6BB1C29868000687D6E /* ContactManagerTest.m in Sources */, + B660F6BB1C29868000687D6E /* OWSContactsManagerTest.m in Sources */, B660F6CE1C29868000687D6E /* PhoneNumberTest.m in Sources */, B660F6C41C29868000687D6E /* HandshakePacketTest.m in Sources */, B660F6CD1C29868000687D6E /* UdpSocketTest.m in Sources */, diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 40fbe5520..f7552348c 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -2,7 +2,7 @@ #import "AppStoreRating.h" #import "CategorizingLogger.h" #import "CodeVerificationViewController.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "DebugLogger.h" #import "Environment.h" #import "NotificationsManager.h" diff --git a/Signal/src/call/RecentCall.h b/Signal/src/call/RecentCall.h index 361857db0..968191c5a 100644 --- a/Signal/src/call/RecentCall.h +++ b/Signal/src/call/RecentCall.h @@ -2,7 +2,7 @@ #import #import #import "Contact.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "PhoneNumber.h" /** diff --git a/Signal/src/contact/ContactsManager.h b/Signal/src/contact/OWSContactsManager.h similarity index 57% rename from Signal/src/contact/ContactsManager.h rename to Signal/src/contact/OWSContactsManager.h index 911f30d8e..4a3f89191 100644 --- a/Signal/src/contact/ContactsManager.h +++ b/Signal/src/contact/OWSContactsManager.h @@ -7,13 +7,7 @@ #import "ObservableValue.h" /** - * - * ContactsManager provides access to an updated list of contacts with optional categorizations - - * such as searching and favourite-attributed contacts (favourites are also managed through this class) - * Others can subscribe for contact and/or favourite updates - * Contacts can be grouped by first letter into an NSDictionary in order to display in individual sections- - * in the ContactBrowseViewController. - * + Get latest Signal contacts, and be notified when they change. */ #define SIGNAL_LIST_UPDATED @"Signal_AB_UPDATED" @@ -21,7 +15,7 @@ typedef void (^ABAccessRequestCompletionBlock)(BOOL hasAccess); typedef void (^ABReloadRequestCompletionBlock)(NSArray *contacts); -@interface ContactsManager : NSObject +@interface OWSContactsManager : NSObject @property CNContactStore *contactStore; @@ -29,14 +23,11 @@ typedef void (^ABReloadRequestCompletionBlock)(NSArray *contacts); - (NSArray *)getContactsFromAddressBook:(ABAddressBookRef)addressBook; - (Contact *)latestContactForPhoneNumber:(PhoneNumber *)phoneNumber; -- (NSArray *)latestContactsWithSearchString:(NSString *)searchString; - -+ (NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString; - (void)verifyABPermission; - (NSArray *)allContacts; -- (NSArray *)signalContacts; +- (NSArray *)signalContacts; - (NSArray *)textSecureContacts; - (void)doAfterEnvironmentInitSetup; diff --git a/Signal/src/contact/ContactsManager.m b/Signal/src/contact/OWSContactsManager.m similarity index 81% rename from Signal/src/contact/ContactsManager.m rename to Signal/src/contact/OWSContactsManager.m index af1b957b9..91f19c403 100644 --- a/Signal/src/contact/ContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -1,4 +1,4 @@ -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "ContactsUpdater.h" #import "Environment.h" #import "Util.h" @@ -7,7 +7,7 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL *); -@interface ContactsManager () +@interface OWSContactsManager () @property id addressBookReference; @property TOCFuture *futureAddressBook; @@ -17,7 +17,7 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL *); @end -@implementation ContactsManager +@implementation OWSContactsManager - (void)dealloc { [_life cancel]; @@ -65,7 +65,7 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL *); void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef info, void *context); void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef info, void *context) { - ContactsManager *contactsManager = (__bridge ContactsManager *)context; + OWSContactsManager *contactsManager = (__bridge OWSContactsManager *)context; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [contactsManager pullLatestAddressBook]; [contactsManager intersectContacts]; @@ -76,7 +76,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in - (void)setupAddressBook { dispatch_async(ADDRESSBOOK_QUEUE, ^{ - [[ContactsManager asyncGetAddressBook] thenDo:^(id addressBook) { + [[OWSContactsManager asyncGetAddressBook] thenDo:^(id addressBook) { self.addressBookReference = addressBook; ABAddressBookRef cfAddressBook = (__bridge ABAddressBookRef)addressBook; ABAddressBookRegisterExternalChangeCallback(cfAddressBook, onAddressBookChanged, (__bridge void *)self); @@ -107,7 +107,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in checkOperationDescribe(nil == creationError, [((__bridge NSError *)creationError)localizedDescription]); ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { if (!granted) { - [ContactsManager blockingContactDialog]; + [OWSContactsManager blockingContactDialog]; } }); [self.observableContactsController updateValue:[self getContactsFromAddressBook:addressBookRef]]; @@ -115,7 +115,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in - (void)setupLatestContacts:(NSArray *)contacts { if (contacts) { - self.latestContactsById = [ContactsManager keyContactsById:contacts]; + self.latestContactsById = [OWSContactsManager keyContactsById:contacts]; } } @@ -248,12 +248,6 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in }]; } -- (NSArray *)latestContactsWithSearchString:(NSString *)searchString { - return [self.latestContactsById.allValues filter:^int(Contact *contact) { - return searchString.length == 0 || [ContactsManager name:contact.fullName matchesQuery:searchString]; - }]; -} - #pragma mark - Contact/Phone Number util - (Contact *)contactForRecord:(ABRecordRef)record { @@ -335,58 +329,6 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } -+ (NSArray *)emailsForRecord:(ABRecordRef)record { - ABMultiValueRef emailRefs = ABRecordCopyValue(record, kABPersonEmailProperty); - - @try { - NSArray *emails = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(emailRefs); - - if (emails == nil) - emails = @[]; - - return emails; - - } @finally { - if (emailRefs) { - CFRelease(emailRefs); - } - } -} - -+ (NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString { - assert(contacts != nil); - - NSArray *matchingContacts = [contacts filter:^int(Contact *contact) { - return optionalSearchString.length == 0 || [self name:contact.fullName matchesQuery:optionalSearchString]; - }]; - - return [matchingContacts groupBy:^id(Contact *contact) { - NSString *nameToUse = @""; - - BOOL firstNameOrdering = ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst ? YES : NO; - - if (firstNameOrdering && contact.firstName != nil && contact.firstName.length > 0) { - nameToUse = contact.firstName; - } else if (!firstNameOrdering && contact.lastName != nil && contact.lastName.length > 0) { - nameToUse = contact.lastName; - } else if (contact.lastName == nil) { - if (contact.fullName.length > 0) { - nameToUse = contact.fullName; - } else { - return nameToUse; - } - } else { - nameToUse = contact.lastName; - } - - if (nameToUse.length >= 1) { - return [[[nameToUse substringToIndex:1] uppercaseString] decomposedStringWithCompatibilityMapping]; - } else { - return @" "; - } - }]; -} - + (NSDictionary *)keyContactsById:(NSArray *)contacts { return [contacts keyedBy:^id(Contact *contact) { return @((int)contact.recordID); @@ -406,11 +348,6 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in return allContacts; } -- (NSArray *)recordsForContacts:(NSArray *)contacts { - return [contacts map:^id(Contact *contact) { - return @([contact recordID]); - }]; -} + (BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString { NSCharacterSet *whitespaceSet = NSCharacterSet.whitespaceCharacterSet; @@ -427,21 +364,11 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in }]; } -+ (BOOL)phoneNumber:(PhoneNumber *)phoneNumber matchesQuery:(NSString *)queryString { - NSString *phoneNumberString = phoneNumber.localizedDescriptionForUser; - NSString *searchString = phoneNumberString.digitsOnly; - - if (queryString.length == 0) - return YES; - NSStringCompareOptions searchOpts = NSCaseInsensitiveSearch | NSAnchoredSearch; - return [searchString rangeOfString:queryString options:searchOpts].location != NSNotFound; -} - #pragma mark - Whisper User Management - (NSArray *)getSignalUsersFromContactsArray:(NSArray *)contacts { return [[contacts filter:^int(Contact *contact) { - return contact.isRedPhoneContact || contact.isTextSecureContact; + return [contact isSignalContact]; }] sortedArrayUsingComparator:[[self class] contactComparator]]; } @@ -460,25 +387,16 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in }; } -- (NSArray *)signalContacts { - return [self getSignalUsersFromContactsArray:self.allContacts]; +- (NSArray *)signalContacts { + return [self getSignalUsersFromContactsArray:[self allContacts]]; } - (NSArray *)textSecureContacts { return [[self.allContacts filter:^int(Contact *contact) { - return [contact isTextSecureContact]; + return [contact isSignalContact]; }] sortedArrayUsingComparator:[[self class] contactComparator]]; } -- (NSArray *)getNewItemsFrom:(NSArray *)newArray comparedTo:(NSArray *)oldArray { - NSMutableSet *newSet = [NSMutableSet setWithArray:newArray]; - NSSet *oldSet = [NSSet setWithArray:oldArray]; - - [newSet minusSet:oldSet]; - return newSet.allObjects; -} - - - (NSString *)nameStringForPhoneIdentifier:(NSString *)identifier { for (Contact *contact in self.allContacts) { for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { diff --git a/Signal/src/contact/OWSContactsSearcher.h b/Signal/src/contact/OWSContactsSearcher.h new file mode 100644 index 000000000..09f96e0d2 --- /dev/null +++ b/Signal/src/contact/OWSContactsSearcher.h @@ -0,0 +1,16 @@ +// +// OWSContactsSearcher.h +// Signal +// +// Created by Michael Kirk on 6/27/16. +// Copyright © 2016 Open Whisper Systems. All rights reserved. +// + +#import "Contact.h" + +@interface OWSContactsSearcher : NSObject + +- (instancetype)initWithContacts:(NSArray *)contacts; +- (NSArray *)filterWithString:(NSString *)string; + +@end diff --git a/Signal/src/contact/OWSContactsSearcher.m b/Signal/src/contact/OWSContactsSearcher.m new file mode 100644 index 000000000..9c44693fe --- /dev/null +++ b/Signal/src/contact/OWSContactsSearcher.m @@ -0,0 +1,42 @@ +// +// OWSContactsSearcher.m +// Signal +// +// Created by Michael Kirk on 6/27/16. +// Copyright © 2016 Open Whisper Systems. All rights reserved. +// + +#import "OWSContactsSearcher.h" +#import + +@interface OWSContactsSearcher () + +@property (copy) NSArray *contacts; + +@end + +@implementation OWSContactsSearcher + +- (instancetype)initWithContacts:(NSArray *)contacts { + self = [super init]; + if (!self) return self; + + _contacts = contacts; + return self; +} + +- (NSArray *)filterWithString:(NSString *)string { + NSString *searchTerm = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + if ([searchTerm isEqualToString:@""]) { + return self.contacts; + } + + NSString *formattedNumber = [PhoneNumber removeFormattingCharacters:searchTerm]; + + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(fullName contains[c] %@) OR (ANY parsedPhoneNumbers.toE164 contains[c] %@)", searchTerm, formattedNumber]; + + return [self.contacts filteredArrayUsingPredicate:predicate]; +} + +@end diff --git a/Signal/src/environment/Environment.h b/Signal/src/environment/Environment.h index 806e67ddb..5779f06b8 100644 --- a/Signal/src/environment/Environment.h +++ b/Signal/src/environment/Environment.h @@ -25,7 +25,7 @@ static NSString *const kCallSegue = @"2.0_6.0_Call_Segue"; #define TESTING_OPTION_USE_DH_FOR_HANDSHAKE @"DhKeyAgreementOnly" @class RecentCallManager; -@class ContactsManager; +@class OWSContactsManager; @class PhoneManager; @class SignalsViewController; @class TSGroupThread; @@ -44,7 +44,7 @@ static NSString *const kCallSegue = @"2.0_6.0_Call_Segue"; @property (nonatomic, readonly) NSArray *testingAndLegacyOptions; @property (nonatomic, readonly) NSData *zrtpClientId; @property (nonatomic, readonly) NSData *zrtpVersionId; -@property (nonatomic, readonly) ContactsManager *contactsManager; +@property (nonatomic, readonly) OWSContactsManager *contactsManager; @property (nonatomic, readonly) SignalsViewController *signalsViewController; @property (nonatomic, readonly, weak) UINavigationController *signUpFlowNavigationController; @@ -66,7 +66,7 @@ static NSString *const kCallSegue = @"2.0_6.0_Call_Segue"; andTestingAndLegacyOptions:(NSArray *)testingAndLegacyOptions andZrtpClientId:(NSData *)zrtpClientId andZrtpVersionId:(NSData *)zrtpVersionId - andContactsManager:(ContactsManager *)contactsManager; + andContactsManager:(OWSContactsManager *)contactsManager; + (Environment *)getCurrent; + (void)setCurrent:(Environment *)curEnvironment; diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index 7c43fd6fd..01f1d00a9 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -67,7 +67,7 @@ static Environment *environment = nil; andTestingAndLegacyOptions:(NSArray *)testingAndLegacyOptions andZrtpClientId:(NSData *)zrtpClientId andZrtpVersionId:(NSData *)zrtpVersionId - andContactsManager:(ContactsManager *)contactsManager { + andContactsManager:(OWSContactsManager *)contactsManager { ows_require(errorNoter != nil); ows_require(zrtpClientId != nil); ows_require(zrtpVersionId != nil); diff --git a/Signal/src/environment/Release.m b/Signal/src/environment/Release.m index ef241cb8e..45ccb9c28 100644 --- a/Signal/src/environment/Release.m +++ b/Signal/src/environment/Release.m @@ -58,7 +58,7 @@ static unsigned char DH3K_PRIME[] = { ] andZrtpClientId:RELEASE_ZRTP_CLIENT_ID andZrtpVersionId:RELEASE_ZRTP_VERSION_ID - andContactsManager:[ContactsManager new]]; + andContactsManager:[OWSContactsManager new]]; } + (Environment *)stagingEnvironmentWithLogging:(id)logging { @@ -82,7 +82,7 @@ static unsigned char DH3K_PRIME[] = { ] andZrtpClientId:RELEASE_ZRTP_CLIENT_ID andZrtpVersionId:RELEASE_ZRTP_VERSION_ID - andContactsManager:[ContactsManager new]]; + andContactsManager:[OWSContactsManager new]]; } + (Environment *)unitTestEnvironment:(NSArray *)testingAndLegacyOptions { diff --git a/Signal/src/environment/VersionMigrations.m b/Signal/src/environment/VersionMigrations.m index 9a9453b02..e6b45ecf7 100644 --- a/Signal/src/environment/VersionMigrations.m +++ b/Signal/src/environment/VersionMigrations.m @@ -169,7 +169,7 @@ __block BOOL success; - TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithUpdatedAttributesWithVoice:YES]; + TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithUpdatedAttributesWithVoice]; [[TSNetworkManager sharedManager] makeRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { success = YES; diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index 601be9791..0791ed3a3 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -9,7 +9,7 @@ #import #import "AppDelegate.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "InCallViewController.h" #import "NSData+ows_StripToken.h" #import "NSDate+millisecondTimeStamp.h" diff --git a/Signal/src/phone/signaling/number directory/GroupContactsResult.m b/Signal/src/phone/signaling/number directory/GroupContactsResult.m index 159764233..4798cab53 100644 --- a/Signal/src/phone/signaling/number directory/GroupContactsResult.m +++ b/Signal/src/phone/signaling/number directory/GroupContactsResult.m @@ -10,7 +10,7 @@ #import #import "Contact.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "Environment.h" #import "SignalKeyingStorage.h" @@ -28,7 +28,7 @@ - (instancetype)initWithMembersId:(NSArray *)memberIdentifiers without:(NSArray *)removeIds { self = [super init]; - ContactsManager *manager = [Environment.getCurrent contactsManager]; + OWSContactsManager *manager = [Environment.getCurrent contactsManager]; NSMutableSet *remainingNumbers = [NSMutableSet setWithArray:memberIdentifiers]; diff --git a/Signal/src/view controllers/CodeVerificationViewController.m b/Signal/src/view controllers/CodeVerificationViewController.m index 2564c694f..f6ea59321 100644 --- a/Signal/src/view controllers/CodeVerificationViewController.m +++ b/Signal/src/view controllers/CodeVerificationViewController.m @@ -9,7 +9,7 @@ #import "CodeVerificationViewController.h" #import -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "Environment.h" #import "LocalizableText.h" #import "PushManager.h" @@ -132,7 +132,6 @@ [TSAccountManager verifyAccountWithCode:[self validationCodeFromTextField] pushToken:pushTokens[0] voipToken:([pushTokens count] == 2) ? pushTokens.lastObject : nil - supportsVoice:YES success:^{ [textsecureRegistration trySetResult:@YES]; } diff --git a/Signal/src/view controllers/MessageComposeTableViewController.m b/Signal/src/view controllers/MessageComposeTableViewController.m index e0b4b3a79..21a1014fe 100644 --- a/Signal/src/view controllers/MessageComposeTableViewController.m +++ b/Signal/src/view controllers/MessageComposeTableViewController.m @@ -12,24 +12,24 @@ #import "ContactTableViewCell.h" #import "ContactsUpdater.h" +#import "OWSContactsSearcher.h" #import "Environment.h" #import "UIColor+OWS.h" #import "UIUtil.h" @interface MessageComposeTableViewController () { - UIButton *sendTextButton; - NSString *currentSearchTerm; - NSArray *contacts; - NSArray *searchResults; -} + MFMessageComposeViewControllerDelegate> +@property (nonatomic) UIButton *sendTextButton; @property (nonatomic, strong) UISearchController *searchController; @property (nonatomic, strong) UIActivityIndicatorView *activityIndicator; @property (nonatomic, strong) UIBarButtonItem *addGroup; @property (nonatomic, strong) UIView *loadingBackgroundView; @property (nonatomic, strong) UIView *emptyBackgroundView; +@property (nonatomic) NSString *currentSearchTerm; +@property (copy) NSArray *contacts; +@property (copy) NSArray *searchResults; @end @@ -39,8 +39,8 @@ [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - contacts = [[Environment getCurrent] contactsManager].signalContacts; - searchResults = contacts; + self.contacts = [[[Environment getCurrent] contactsManager] signalContacts]; + self.searchResults = self.contacts; [self initializeSearch]; self.searchController.searchBar.hidden = NO; @@ -54,7 +54,7 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - if ([contacts count] == 0) { + if ([self.contacts count] == 0) { [self showEmptyBackgroundView:YES]; } } @@ -218,17 +218,17 @@ self.searchController.searchBar.delegate = self; self.searchController.searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @""); - sendTextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; - [sendTextButton setBackgroundColor:[UIColor ows_materialBlueColor]]; - [sendTextButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - sendTextButton.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, - self.searchController.searchBar.frame.origin.y + 44.0, - self.searchController.searchBar.frame.size.width, - 44.0); - [self.view addSubview:sendTextButton]; - sendTextButton.hidden = YES; - - [sendTextButton addTarget:self action:@selector(sendText) forControlEvents:UIControlEventTouchUpInside]; + self.sendTextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + [self.sendTextButton setBackgroundColor:[UIColor ows_materialBlueColor]]; + [self.sendTextButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + self.sendTextButton.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, + self.searchController.searchBar.frame.origin.y + 44.0, + self.searchController.searchBar.frame.size.width, + 44.0); + [self.view addSubview:self.sendTextButton]; + self.sendTextButton.hidden = YES; + + [self.sendTextButton addTarget:self action:@selector(sendText) forControlEvents:UIControlEventTouchUpInside]; [self initializeRefreshControl]; } @@ -257,31 +257,26 @@ } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { - sendTextButton.hidden = YES; + self.sendTextButton.hidden = YES; } #pragma mark - Filter - (void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope { - // search by contact name or number - NSPredicate *resultPredicate = [NSPredicate - predicateWithFormat:@"(fullName contains[c] %@) OR (allPhoneNumbers contains[c] %@)", searchText, searchText]; - searchResults = [contacts filteredArrayUsingPredicate:resultPredicate]; - if (!searchResults.count && _searchController.searchBar.text.length == 0) { - searchResults = contacts; - } - NSString *formattedNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:searchText].toE164; + OWSContactsSearcher *contactsSearcher = [[OWSContactsSearcher alloc] initWithContacts: self.contacts]; + self.searchResults = [contactsSearcher filterWithString:searchText]; + NSString *formattedNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:searchText].toE164; // text to a non-signal number if we have no results and a valid phone # - if (searchResults.count == 0 && searchText.length > 8 && formattedNumber) { + if (self.searchResults.count == 0 && searchText.length > 8 && formattedNumber) { NSString *sendTextTo = NSLocalizedString(@"SEND_SMS_BUTTON", @""); sendTextTo = [sendTextTo stringByAppendingString:formattedNumber]; - [sendTextButton setTitle:sendTextTo forState:UIControlStateNormal]; - sendTextButton.hidden = NO; - currentSearchTerm = formattedNumber; + [self.sendTextButton setTitle:sendTextTo forState:UIControlStateNormal]; + self.sendTextButton.hidden = NO; + self.currentSearchTerm = formattedNumber; } else { - sendTextButton.hidden = YES; + self.sendTextButton.hidden = YES; } } @@ -290,9 +285,9 @@ - (void)sendText { NSString *confirmMessage = NSLocalizedString(@"SEND_SMS_CONFIRM_TITLE", @""); - if ([currentSearchTerm length] > 0) { + if ([self.currentSearchTerm length] > 0) { confirmMessage = NSLocalizedString(@"SEND_SMS_INVITE_TITLE", @""); - confirmMessage = [confirmMessage stringByAppendingString:currentSearchTerm]; + confirmMessage = [confirmMessage stringByAppendingString:self.currentSearchTerm]; confirmMessage = [confirmMessage stringByAppendingString:NSLocalizedString(@"QUESTIONMARK_PUNCTUATION", @"")]; } @@ -318,7 +313,7 @@ picker.messageComposeDelegate = self; picker.recipients = - [currentSearchTerm length] > 0 ? [NSArray arrayWithObject:currentSearchTerm] : nil; + [self.currentSearchTerm length] > 0 ? [NSArray arrayWithObject:self.currentSearchTerm] : nil; picker.body = [NSLocalizedString(@"SMS_INVITE_BODY", @"") stringByAppendingString: @" https://itunes.apple.com/us/app/signal-private-messenger/id874139669?mt=8"]; @@ -336,7 +331,7 @@ [alertController addAction:cancelAction]; [alertController addAction:okAction]; - sendTextButton.hidden = YES; + self.sendTextButton.hidden = YES; self.searchController.searchBar.text = @""; //must dismiss search controller before presenting alert. @@ -396,9 +391,9 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (self.searchController.active) { - return (NSInteger)[searchResults count]; + return (NSInteger)[self.searchResults count]; } else { - return (NSInteger)[contacts count]; + return (NSInteger)[self.contacts count]; } } @@ -426,11 +421,6 @@ } #pragma mark - Table View delegate -- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { - Contact *person = [self contactForIndexPath:indexPath]; - return person.isTextSecureContact ? indexPath : nil; -} - - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [[[self contactForIndexPath:indexPath] textSecureIdentifiers] firstObject]; @@ -441,7 +431,6 @@ }]; } - - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { ContactTableViewCell *cell = (ContactTableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryNone; @@ -451,9 +440,9 @@ Contact *contact = nil; if (self.searchController.active) { - contact = [searchResults objectAtIndex:(NSUInteger)indexPath.row]; + contact = [self.searchResults objectAtIndex:(NSUInteger)indexPath.row]; } else { - contact = [contacts objectAtIndex:(NSUInteger)indexPath.row]; + contact = [self.contacts objectAtIndex:(NSUInteger)indexPath.row]; } return contact; @@ -465,7 +454,7 @@ [self.refreshControl endRefreshing]; [self showLoadingBackgroundView:NO]; - if ([contacts count] == 0) { + if ([self.contacts count] == 0) { [self showEmptyBackgroundView:YES]; } else { [self showEmptyBackgroundView:NO]; @@ -476,7 +465,7 @@ [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:[Environment getCurrent].contactsManager.allContacts success:^{ - contacts = [[Environment getCurrent] contactsManager].signalContacts; + self.contacts = [[[Environment getCurrent] contactsManager] signalContacts]; dispatch_async(dispatch_get_main_queue(), ^{ [self updateSearchResultsForSearchController:self.searchController]; [self.tableView reloadData]; @@ -495,7 +484,7 @@ }); }]; - if ([contacts count] == 0) { + if ([self.contacts count] == 0) { [self showLoadingBackgroundView:YES]; } } diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m index 88e91352a..573272bae 100644 --- a/Signal/src/view controllers/MessagesViewController.m +++ b/Signal/src/view controllers/MessagesViewController.m @@ -14,7 +14,7 @@ #import #import #import -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "DJWActionSheet+OWS.h" #import "Environment.h" #import "FingerprintViewController.h" @@ -437,9 +437,7 @@ typedef enum : NSUInteger { target:self action:@selector(callAction)]; self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(0, -10, 0, 10); - } else if (!_thread.isGroupThread) { - self.navigationItem.rightBarButtonItem = nil; - } else { + } else if ([self.thread isGroupThread]) { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"contact-options-action"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] @@ -447,6 +445,9 @@ typedef enum : NSUInteger { target:self action:@selector(didSelectShow:)]; self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(10, 20, 10, 0); + } else { + self.navigationItem.rightBarButtonItem = nil; + DDLogError(@"Thread was neither group thread nor callable"); } [self hideInputIfNeeded]; @@ -627,17 +628,8 @@ typedef enum : NSUInteger { return recipient; } -- (BOOL)isRedPhoneReachable { - return [self signalRecipient].supportsVoice; -} - - - (BOOL)isTextSecureReachable { - if (isGroupConversation) { - return YES; - } else { - return [self signalRecipient]; - } + return isGroupConversation || [self signalRecipient]; } - (PhoneNumber *)phoneNumberForThread { @@ -646,18 +638,17 @@ typedef enum : NSUInteger { } - (void)callAction { - if ([self isRedPhoneReachable]) { + if ([self canCall]) { PhoneNumber *number = [self phoneNumberForThread]; Contact *contact = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:number]; [Environment.phoneManager initiateOutgoingCallToContact:contact atRemoteNumber:number]; } else { - DDLogWarn(@"Tried to initiate a call but contact has no RedPhone identifier"); + DDLogWarn(@"Tried to initiate a call but thread is not callable."); } } - (BOOL)canCall { - return !isGroupConversation && [self isRedPhoneReachable] && - ![((TSContactThread *)_thread).contactIdentifier isEqualToString:[TSAccountManager localNumber]]; + return !(isGroupConversation || [((TSContactThread *)self.thread).contactIdentifier isEqualToString:[TSAccountManager localNumber]]); } - (void)textViewDidChange:(UITextView *)textView { diff --git a/Signal/src/view controllers/NewGroupViewController.m b/Signal/src/view controllers/NewGroupViewController.m index 62e10aeda..00e6d6b68 100644 --- a/Signal/src/view controllers/NewGroupViewController.m +++ b/Signal/src/view controllers/NewGroupViewController.m @@ -11,7 +11,7 @@ #import #import #import -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "DJWActionSheet+OWS.h" #import "Environment.h" #import "FunctionalUtil.h" diff --git a/Signal/src/view controllers/SettingsTableViewController.m b/Signal/src/view controllers/SettingsTableViewController.m index 319cb1c87..c38034960 100644 --- a/Signal/src/view controllers/SettingsTableViewController.m +++ b/Signal/src/view controllers/SettingsTableViewController.m @@ -17,7 +17,7 @@ #import "TSSocketManager.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "AboutTableViewController.h" #import "AdvancedSettingsTableViewController.h" diff --git a/Signal/src/view controllers/ShowGroupMembersViewController.m b/Signal/src/view controllers/ShowGroupMembersViewController.m index 3fb083c49..14bc20476 100644 --- a/Signal/src/view controllers/ShowGroupMembersViewController.m +++ b/Signal/src/view controllers/ShowGroupMembersViewController.m @@ -11,7 +11,7 @@ #import "SignalsViewController.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "Environment.h" #import "GroupContactsResult.h" diff --git a/Signal/src/view controllers/SignalsViewController.m b/Signal/src/view controllers/SignalsViewController.m index 3862eb04c..15116f40b 100644 --- a/Signal/src/view controllers/SignalsViewController.m +++ b/Signal/src/view controllers/SignalsViewController.m @@ -9,7 +9,7 @@ #import "InboxTableViewCell.h" #import "UIUtil.h" -#import "ContactsManager.h" +#import "OWSContactsManager.h" #import "InCallViewController.h" #import "MessagesViewController.h" #import "NSDate+millisecondTimeStamp.h" diff --git a/Signal/src/views/ContactTableViewCell.h b/Signal/src/views/ContactTableViewCell.h index d2c19873e..80e5fe842 100644 --- a/Signal/src/views/ContactTableViewCell.h +++ b/Signal/src/views/ContactTableViewCell.h @@ -1,5 +1,5 @@ #import -#import "ContactsManager.h" +#import "OWSContactsManager.h" /** * diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index 2e652e850..6ab3929a4 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -4,11 +4,10 @@ #import "Environment.h" #import "PhoneManager.h" -#define CONTACT_TABLE_CELL_BORDER_WIDTH 1.0f +@interface ContactTableViewCell () -@interface ContactTableViewCell () { -} @property (strong, nonatomic) Contact *associatedContact; + @end @implementation ContactTableViewCell @@ -22,17 +21,9 @@ return NSStringFromClass(self.class); } - - (void)configureWithContact:(Contact *)contact { - if (!contact.isTextSecureContact) { - self.selectionStyle = UITableViewCellSelectionStyleNone; - } - _associatedContact = contact; - - _nameLabel.attributedText = [self attributedStringForContact:contact]; - if (!contact.isTextSecureContact) { - _nameLabel.textColor = [UIColor lightGrayColor]; - } + self.associatedContact = contact; + self.nameLabel.attributedText = [self attributedStringForContact:contact]; } - (NSAttributedString *)attributedStringForContact:(Contact *)contact { diff --git a/Signal/test/contact/ContactManagerTest.m b/Signal/test/contact/ContactManagerTest.m deleted file mode 100644 index c7740f248..000000000 --- a/Signal/test/contact/ContactManagerTest.m +++ /dev/null @@ -1,29 +0,0 @@ -#import -#import "TestUtil.h" -#import "ContactsManager.h" - -@interface ContactManagerTest : XCTestCase - -@end - -@implementation ContactManagerTest - -- (void)testQueryMatching { - test([ContactsManager name:@"big dave" matchesQuery:@"big dave"]); - test([ContactsManager name:@"big dave" matchesQuery:@"dave big"]); - test([ContactsManager name:@"big dave" matchesQuery:@"dave"]); - test([ContactsManager name:@"big dave" matchesQuery:@"big"]); - test([ContactsManager name:@"big dave" matchesQuery:@"big "]); - test([ContactsManager name:@"big dave" matchesQuery:@" big "]); - test([ContactsManager name:@"big dave" matchesQuery:@"dav"]); - test([ContactsManager name:@"big dave" matchesQuery:@"bi dav"]); - test([ContactsManager name:@"big dave" matchesQuery:@"big big big big big big big big big big dave dave dave dave dave"]); - - test(![ContactsManager name:@"big dave" matchesQuery:@"ave"]); - test(![ContactsManager name:@"big dave" matchesQuery:@"dare"]); - test(![ContactsManager name:@"big dave" matchesQuery:@"mike"]); - test(![ContactsManager name:@"big dave" matchesQuery:@"mike"]); - test(![ContactsManager name:@"dave" matchesQuery:@"big"]); -} - -@end diff --git a/Signal/test/contact/OWSContactsManagerTest.m b/Signal/test/contact/OWSContactsManagerTest.m new file mode 100644 index 000000000..9efc7ab55 --- /dev/null +++ b/Signal/test/contact/OWSContactsManagerTest.m @@ -0,0 +1,30 @@ +#import +#import "TestUtil.h" +#import "OWSContactsManager.h" + +@interface OWSContactsManagerTest : XCTestCase + +@end + + +@implementation OWSContactsManagerTest + +- (void)testQueryMatching { + test([OWSContactsManager name:@"big dave" matchesQuery:@"big dave"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"dave big"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"dave"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"big"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"big "]); + test([OWSContactsManager name:@"big dave" matchesQuery:@" big "]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"dav"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"bi dav"]); + test([OWSContactsManager name:@"big dave" matchesQuery:@"big big big big big big big big big big dave dave dave dave dave"]); + + test(![OWSContactsManager name:@"big dave" matchesQuery:@"ave"]); + test(![OWSContactsManager name:@"big dave" matchesQuery:@"dare"]); + test(![OWSContactsManager name:@"big dave" matchesQuery:@"mike"]); + test(![OWSContactsManager name:@"big dave" matchesQuery:@"mike"]); + test(![OWSContactsManager name:@"dave" matchesQuery:@"big"]); +} + +@end diff --git a/Signal/test/contact/OWSContactsSearcherTest.m b/Signal/test/contact/OWSContactsSearcherTest.m new file mode 100644 index 000000000..1223992ef --- /dev/null +++ b/Signal/test/contact/OWSContactsSearcherTest.m @@ -0,0 +1,69 @@ +// +// OWSContactSearcherTest.m +// Signal +// +// Created by Michael Kirk on 6/27/16. +// Copyright © 2016 Open Whisper Systems. All rights reserved. +// + +#import + +#import "OWSContactsSearcher.h" + +@interface OWSContactsSearcherTest : XCTestCase + +@property Contact *meow; +@property Contact *clement; +@property OWSContactsSearcher *contactsSearcher; + +@end + +@implementation OWSContactsSearcherTest + +- (void)setUp { + [super setUp]; + + self.meow = [[Contact alloc] initWithContactWithFirstName:@"Chairman" + andLastName:@"Meow" + andUserTextPhoneNumbers:@[ @"1-323-555-1234", @"+86 10 1111 2222" ] + andImage:nil + andContactID:1]; + + self.clement = [[Contact alloc] initWithContactWithFirstName:@"Clément" + andLastName:@"Duval" + andUserTextPhoneNumbers:@[ @"33 123456789" ] + andImage:nil + andContactID:2]; + + self.contactsSearcher = [[OWSContactsSearcher alloc] initWithContacts:@[self.meow, self.clement]]; +} + +- (void)testFilterWithStringMatchAllOnEmtpy { + XCTAssertEqualObjects((@[self.meow, self.clement]), [self.contactsSearcher filterWithString:@""]); + XCTAssertEqualObjects((@[self.meow, self.clement]), [self.contactsSearcher filterWithString:@" "]); +} + +- (void)testFilterWithStringMatchByName { + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"Chairman"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"Chair"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"Meow"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"Chairman Meow"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@" Chairman Meow "]); + XCTAssertEqualObjects((@[self.meow, self.clement]), ([self.contactsSearcher filterWithString:@"C"])); + XCTAssertEqualObjects(@[], [self.contactsSearcher filterWithString:@"Chairman Meowww"]); +} + +- (void)testFilterWithStringByNumber { + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"1-323-555-1234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"+86 10 1111 2222"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"323-555-1234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"323.555.1234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"3235551234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"323"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"323 555 1234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"+1 323 555 1234"]); + XCTAssertEqualObjects(@[self.meow], [self.contactsSearcher filterWithString:@"+13235551234"]); + XCTAssertEqualObjects((@[self.meow, self.clement]), [self.contactsSearcher filterWithString:@"1234"]); +} + +@end