diff --git a/Podfile b/Podfile index 1abd4d24d2..cc121e973b 100644 --- a/Podfile +++ b/Podfile @@ -10,3 +10,5 @@ pod 'libPhoneNumber-iOS', '~> 0.7' pod 'PastelogKit', '~> 1.2' pod 'AFNetworking', '~> 2.4.1' pod 'TwistedOakCollapsingFutures','~> 1.0' +pod 'JSQMessagesViewController', :git => 'https://github.com/dtsbourg/JSQMessagesViewController', :branch => 'JSignalQ' +pod 'DJWActionSheet' diff --git a/Podfile.lock b/Podfile.lock index bae2bb60e4..75330180ac 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -25,6 +25,10 @@ PODS: - CocoaLumberjack/Core (1.9.2) - CocoaLumberjack/Extensions (1.9.2): - CocoaLumberjack/Core + - DJWActionSheet (1.0.4) + - JSQMessagesViewController (6.0-beta6): + - JSQSystemSoundPlayer (~> 2.0.0) + - JSQSystemSoundPlayer (2.0.0) - libPhoneNumber-iOS (0.7.3) - MMDrawerController (0.5.7): - MMDrawerController/Core @@ -48,6 +52,8 @@ PODS: DEPENDENCIES: - AFNetworking (~> 2.4.1) + - DJWActionSheet + - JSQMessagesViewController (from `https://github.com/dtsbourg/JSQMessagesViewController`, branch `JSignalQ`) - libPhoneNumber-iOS (~> 0.7) - MMDrawerController (~> 0.5.7) - OpenSSL (~> 1.0.109) @@ -56,12 +62,18 @@ DEPENDENCIES: - UICKeyChainStore (from `Podspecs/UICKeyChainStore.podspec`) EXTERNAL SOURCES: + JSQMessagesViewController: + :branch: JSignalQ + :git: https://github.com/dtsbourg/JSQMessagesViewController UICKeyChainStore: :podspec: Podspecs/UICKeyChainStore.podspec SPEC CHECKSUMS: AFNetworking: 0aabc6fae66d6e5d039eeb21c315843c7aae51ab CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817 + DJWActionSheet: d88b302d7c29523e1e9fb9b62cfac46f59bb90d9 + JSQMessagesViewController: 960a09d11978bea52d1a676e97980838f8d98652 + JSQSystemSoundPlayer: c98443b1cbb3b45db09d0d3d6c2355cf78294981 libPhoneNumber-iOS: 98fc07d70c8fdb5e6a8e3442c37e97353065c20e MMDrawerController: c3ab7a318ddc7e2bcd133139c3161af08c6e1197 OpenSSL: 4810adf5c99b0e2cd20670a11a987c805e8a521c diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 6eafdd961d..fa90def763 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -406,7 +406,6 @@ D2179CFE16BB0B480006F3AB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */; }; D221A08E169C9E5E00537ABF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A08D169C9E5E00537ABF /* UIKit.framework */; }; D221A090169C9E5E00537ABF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A08F169C9E5E00537ABF /* Foundation.framework */; }; - D221A092169C9E5E00537ABF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A091169C9E5E00537ABF /* CoreGraphics.framework */; }; D221A09A169C9E5E00537ABF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D221A099169C9E5E00537ABF /* main.m */; }; D221A0AD169C9E5F00537ABF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A08D169C9E5E00537ABF /* UIKit.framework */; }; D221A0AE169C9E5F00537ABF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A08F169C9E5E00537ABF /* Foundation.framework */; }; @@ -576,6 +575,61 @@ E197B62718BBF63B00F073E5 /* SoundBoard.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62618BBF63B00F073E5 /* SoundBoard.m */; }; E1CD329618BCFF9900B1A496 /* SoundInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = E1CD329518BCFF9900B1A496 /* SoundInstance.m */; }; F995AC2FFD6D4442B012604A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; }; + FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */; }; + FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC31962C1A06A2190094C78E /* FingerprintViewController.m */; }; + FC3196301A0814130094C78E /* SettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC31962F1A0814130094C78E /* SettingsTableViewController.m */; }; + FC4F9FE51A16258C00DA100A /* logo_intro@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FE41A16258C00DA100A /* logo_intro@2x.png */; }; + FC4F9FED1A1658EE00DA100A /* call@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FEC1A1658EE00DA100A /* call@2x.png */; }; + FC4F9FF31A1664EA00DA100A /* mute_off@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FEE1A1664EA00DA100A /* mute_off@2x.png */; }; + FC4F9FF41A1664EA00DA100A /* speaker_off@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FEF1A1664EA00DA100A /* speaker_off@2x.png */; }; + FC4F9FF51A1664EA00DA100A /* speaker_on@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FF01A1664EA00DA100A /* speaker_on@2x.png */; }; + FC4F9FF61A1664EA00DA100A /* mute_on@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FF11A1664EA00DA100A /* mute_on@2x.png */; }; + FC4F9FF71A1664EA00DA100A /* endcall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FF21A1664EA00DA100A /* endcall@2x.png */; }; + FC4F9FFD1A179FCF00DA100A /* lock@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FFC1A179FCF00DA100A /* lock@2x.png */; }; + FC4F9FFF1A17A39E00DA100A /* photo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4F9FFE1A17A39E00DA100A /* photo@2x.png */; }; + FC4FA0071A18BDAE00DA100A /* info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0061A18BDAE00DA100A /* info@2x.png */; }; + FC4FA0091A18BF3100DA100A /* lock_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0081A18BF3100DA100A /* lock_white@2x.png */; }; + FC4FA00D1A18CC4300DA100A /* shred@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA00C1A18CC4300DA100A /* shred@2x.png */; }; + FC4FA0171A1A180D00DA100A /* red-delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0131A1A180D00DA100A /* red-delete@2x.png */; }; + FC4FA0181A1A180D00DA100A /* delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0141A1A180D00DA100A /* delete@2x.png */; }; + FC4FA0191A1A180D00DA100A /* archive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0151A1A180D00DA100A /* archive@2x.png */; }; + FC4FA01A1A1A180D00DA100A /* blue-archive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC4FA0161A1A180D00DA100A /* blue-archive@2x.png */; }; + FC4FA0231A1B8A8D00DA100A /* Socket.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0221A1B8A8D00DA100A /* Socket.m */; }; + FC4FA0261A1B9DC600DA100A /* SignalsNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0251A1B9DC600DA100A /* SignalsNavigationController.m */; }; + FCAC963519FEF4E20046DFC5 /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FCAC963419FEF4E20046DFC5 /* Storyboard.storyboard */; }; + FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */; }; + FCAC964019FEF99A0046DFC5 /* TableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963E19FEF99A0046DFC5 /* TableViewCell.m */; }; + FCAC964119FEF99A0046DFC5 /* TableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCAC963F19FEF99A0046DFC5 /* TableViewCell.xib */; }; + FCAC964419FEFD8B0046DFC5 /* DemoDataFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC964319FEFD8B0046DFC5 /* DemoDataFactory.m */; }; + FCAC964719FEFE1A0046DFC5 /* DemoDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC964619FEFE1A0046DFC5 /* DemoDataModel.m */; }; + FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */; }; + FCAFC2EC1A0C469C00AE5136 /* checkmark.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC2EB1A0C469C00AE5136 /* checkmark.png */; }; + FCAFC2EE1A0C472200AE5136 /* reply.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC2ED1A0C472200AE5136 /* reply.png */; }; + FCAFC2F11A0C4ACF00AE5136 /* received.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC2EF1A0C4ACF00AE5136 /* received.png */; }; + FCAFC2F21A0C4ACF00AE5136 /* missed.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC2F01A0C4ACF00AE5136 /* missed.png */; }; + FCAFC30C1A0C560E00AE5136 /* signals.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3091A0C560E00AE5136 /* signals.png */; }; + FCAFC30D1A0C560E00AE5136 /* settings.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC30A1A0C560E00AE5136 /* settings.png */; }; + FCAFC3211A0D394300AE5136 /* favourite.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3201A0D394300AE5136 /* favourite.png */; }; + FCAFC3281A0D466F00AE5136 /* delete_history@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3251A0D466F00AE5136 /* delete_history@2x.png */; }; + FCAFC3291A0D466F00AE5136 /* signal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3261A0D466F00AE5136 /* signal@2x.png */; }; + FCAFC32A1A0D466F00AE5136 /* call_dark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3271A0D466F00AE5136 /* call_dark@2x.png */; }; + FCAFC32E1A0D46D500AE5136 /* settings_dark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC32D1A0D46D500AE5136 /* settings_dark@2x.png */; }; + FCAFC3301A0D5E3000AE5136 /* share@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC32F1A0D5E3000AE5136 /* share@2x.png */; }; + FCAFC3341A0D656100AE5136 /* contacts_tab@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3331A0D656100AE5136 /* contacts_tab@2x.png */; }; + FCAFC3361A0D680100AE5136 /* keypad@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCAFC3351A0D680100AE5136 /* keypad@2x.png */; }; + FCAFC33F1A0F948F00AE5136 /* ActionContactDetailCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAFC33E1A0F948F00AE5136 /* ActionContactDetailCell.m */; }; + FCB11D8A1A1284BB002F93FB /* SettingsTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCB11D891A1284BB002F93FB /* SettingsTableViewCell.m */; }; + FCB11D8C1A129A76002F93FB /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB11D8B1A129A76002F93FB /* CoreMedia.framework */; }; + FCB11D8F1A12A388002F93FB /* savephoto@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCB11D8D1A12A388002F93FB /* savephoto@2x.png */; }; + FCB11D901A12A388002F93FB /* quit@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCB11D8E1A12A388002F93FB /* quit@2x.png */; }; + FCB11D931A12A4AA002F93FB /* FullImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCB11D921A12A4AA002F93FB /* FullImageViewController.m */; }; + FCF72A081A01A765006BC849 /* ContactsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF72A071A01A765006BC849 /* ContactsTableViewController.m */; }; + FCF72A131A02D27F006BC849 /* ContactDetailTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */; }; + FCF72A161A02D2BB006BC849 /* ContactDetailCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCF72A151A02D2BB006BC849 /* ContactDetailCell.m */; }; + FCFD256F1A151BCB00F4C644 /* NewGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFD256E1A151BCB00F4C644 /* NewGroupViewController.m */; }; + FCFD25721A1524DB00F4C644 /* GroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFD25711A1524DB00F4C644 /* GroupModel.m */; }; + FCFD257F1A154B2C00F4C644 /* RegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFD257E1A154B2C00F4C644 /* RegistrationViewController.m */; }; + FCFD25821A154B3800F4C644 /* CodeVerificationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1287,6 +1341,81 @@ E1C407C117F0C246007BEE65 /* whisperReal.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperReal.cer; sourceTree = ""; }; E1CD329418BCFF9900B1A496 /* SoundInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundInstance.h; sourceTree = ""; }; E1CD329518BCFF9900B1A496 /* SoundInstance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SoundInstance.m; sourceTree = ""; }; + FC3196281A067D8F0094C78E /* MessageComposeTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageComposeTableViewController.h; sourceTree = ""; }; + FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessageComposeTableViewController.m; sourceTree = ""; }; + FC31962B1A06A2190094C78E /* FingerprintViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewController.h; sourceTree = ""; }; + FC31962C1A06A2190094C78E /* FingerprintViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewController.m; sourceTree = ""; }; + FC31962E1A0814130094C78E /* SettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewController.h; sourceTree = ""; }; + FC31962F1A0814130094C78E /* SettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewController.m; sourceTree = ""; }; + FC4F9FE41A16258C00DA100A /* logo_intro@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "logo_intro@2x.png"; sourceTree = ""; }; + FC4F9FEC1A1658EE00DA100A /* call@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call@2x.png"; sourceTree = ""; }; + FC4F9FEE1A1664EA00DA100A /* mute_off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_off@2x.png"; sourceTree = ""; }; + FC4F9FEF1A1664EA00DA100A /* speaker_off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "speaker_off@2x.png"; sourceTree = ""; }; + FC4F9FF01A1664EA00DA100A /* speaker_on@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "speaker_on@2x.png"; sourceTree = ""; }; + FC4F9FF11A1664EA00DA100A /* mute_on@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_on@2x.png"; sourceTree = ""; }; + FC4F9FF21A1664EA00DA100A /* endcall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "endcall@2x.png"; sourceTree = ""; }; + FC4F9FFC1A179FCF00DA100A /* lock@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock@2x.png"; sourceTree = ""; }; + FC4F9FFE1A17A39E00DA100A /* photo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "photo@2x.png"; sourceTree = ""; }; + FC4FA0061A18BDAE00DA100A /* info@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "info@2x.png"; sourceTree = ""; }; + FC4FA0081A18BF3100DA100A /* lock_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_white@2x.png"; sourceTree = ""; }; + FC4FA00C1A18CC4300DA100A /* shred@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "shred@2x.png"; sourceTree = ""; }; + FC4FA0131A1A180D00DA100A /* red-delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "red-delete@2x.png"; sourceTree = ""; }; + FC4FA0141A1A180D00DA100A /* delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delete@2x.png"; sourceTree = ""; }; + FC4FA0151A1A180D00DA100A /* archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "archive@2x.png"; sourceTree = ""; }; + FC4FA0161A1A180D00DA100A /* blue-archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "blue-archive@2x.png"; sourceTree = ""; }; + FC4FA0211A1B8A8D00DA100A /* Socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = ""; }; + FC4FA0221A1B8A8D00DA100A /* Socket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Socket.m; sourceTree = ""; }; + FC4FA0241A1B9DC600DA100A /* SignalsNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsNavigationController.h; sourceTree = ""; }; + FC4FA0251A1B9DC600DA100A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = ""; }; + FCAC963419FEF4E20046DFC5 /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Storyboard.storyboard; path = Signal/src/Storyboard/Storyboard.storyboard; sourceTree = SOURCE_ROOT; }; + FCAC963A19FEF9280046DFC5 /* SignalsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SignalsViewController.h; path = UITests/SignalsViewController.h; sourceTree = ""; }; + FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SignalsViewController.m; path = UITests/SignalsViewController.m; sourceTree = ""; }; + FCAC963D19FEF99A0046DFC5 /* TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewCell.h; sourceTree = ""; }; + FCAC963E19FEF99A0046DFC5 /* TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewCell.m; sourceTree = ""; }; + FCAC963F19FEF99A0046DFC5 /* TableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCell.xib; sourceTree = ""; }; + FCAC964219FEFD8B0046DFC5 /* DemoDataFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoDataFactory.h; sourceTree = ""; }; + FCAC964319FEFD8B0046DFC5 /* DemoDataFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoDataFactory.m; sourceTree = ""; }; + FCAC964519FEFE1A0046DFC5 /* DemoDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoDataModel.h; sourceTree = ""; }; + FCAC964619FEFE1A0046DFC5 /* DemoDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoDataModel.m; sourceTree = ""; }; + FCAC964F19FF0A6E0046DFC5 /* MessagesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagesViewController.h; sourceTree = ""; }; + FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessagesViewController.m; sourceTree = ""; }; + FCAFC2EB1A0C469C00AE5136 /* checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkmark.png; sourceTree = ""; }; + FCAFC2ED1A0C472200AE5136 /* reply.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reply.png; sourceTree = ""; }; + FCAFC2EF1A0C4ACF00AE5136 /* received.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = received.png; sourceTree = ""; }; + FCAFC2F01A0C4ACF00AE5136 /* missed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = missed.png; sourceTree = ""; }; + FCAFC3091A0C560E00AE5136 /* signals.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = signals.png; sourceTree = ""; }; + FCAFC30A1A0C560E00AE5136 /* settings.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = settings.png; sourceTree = ""; }; + FCAFC3201A0D394300AE5136 /* favourite.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = favourite.png; sourceTree = ""; }; + FCAFC3251A0D466F00AE5136 /* delete_history@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delete_history@2x.png"; sourceTree = ""; }; + FCAFC3261A0D466F00AE5136 /* signal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "signal@2x.png"; sourceTree = ""; }; + FCAFC3271A0D466F00AE5136 /* call_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_dark@2x.png"; sourceTree = ""; }; + FCAFC32D1A0D46D500AE5136 /* settings_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings_dark@2x.png"; sourceTree = ""; }; + FCAFC32F1A0D5E3000AE5136 /* share@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "share@2x.png"; sourceTree = ""; }; + FCAFC3331A0D656100AE5136 /* contacts_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "contacts_tab@2x.png"; sourceTree = ""; }; + FCAFC3351A0D680100AE5136 /* keypad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keypad@2x.png"; sourceTree = ""; }; + FCAFC33D1A0F948F00AE5136 /* ActionContactDetailCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionContactDetailCell.h; sourceTree = ""; }; + FCAFC33E1A0F948F00AE5136 /* ActionContactDetailCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionContactDetailCell.m; sourceTree = ""; }; + FCB11D881A1284BB002F93FB /* SettingsTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewCell.h; sourceTree = ""; }; + FCB11D891A1284BB002F93FB /* SettingsTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewCell.m; sourceTree = ""; }; + FCB11D8B1A129A76002F93FB /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + FCB11D8D1A12A388002F93FB /* savephoto@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "savephoto@2x.png"; sourceTree = ""; }; + FCB11D8E1A12A388002F93FB /* quit@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "quit@2x.png"; sourceTree = ""; }; + FCB11D911A12A4AA002F93FB /* FullImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullImageViewController.h; sourceTree = ""; }; + FCB11D921A12A4AA002F93FB /* FullImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FullImageViewController.m; sourceTree = ""; }; + FCF72A061A01A765006BC849 /* ContactsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsTableViewController.h; sourceTree = ""; }; + FCF72A071A01A765006BC849 /* ContactsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsTableViewController.m; sourceTree = ""; }; + FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailTableViewController.m; sourceTree = ""; }; + FCF72A121A02D27F006BC849 /* ContactDetailTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailTableViewController.h; sourceTree = ""; }; + FCF72A141A02D2BB006BC849 /* ContactDetailCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailCell.h; sourceTree = ""; }; + FCF72A151A02D2BB006BC849 /* ContactDetailCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailCell.m; sourceTree = ""; }; + FCFD256D1A151BCB00F4C644 /* NewGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewGroupViewController.h; sourceTree = ""; }; + FCFD256E1A151BCB00F4C644 /* NewGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewGroupViewController.m; sourceTree = ""; }; + FCFD25701A1524DB00F4C644 /* GroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupModel.h; sourceTree = ""; }; + FCFD25711A1524DB00F4C644 /* GroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupModel.m; sourceTree = ""; }; + FCFD257D1A154B2C00F4C644 /* RegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationViewController.h; sourceTree = ""; }; + FCFD257E1A154B2C00F4C644 /* RegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RegistrationViewController.m; sourceTree = ""; }; + FCFD25801A154B3800F4C644 /* CodeVerificationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeVerificationViewController.h; sourceTree = ""; }; + FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodeVerificationViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1294,6 +1423,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + FCB11D8C1A129A76002F93FB /* CoreMedia.framework in Frameworks */, 70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */, 70B800AF190C548D0042E3F0 /* libspeex.a in Frameworks */, 70B800A6190C53180042E3F0 /* libspandsp.a in Frameworks */, @@ -1309,7 +1439,6 @@ D2179CFC16BB0B3A0006F3AB /* CoreTelephony.framework in Frameworks */, D221A08E169C9E5E00537ABF /* UIKit.framework in Frameworks */, D221A090169C9E5E00537ABF /* Foundation.framework in Frameworks */, - D221A092169C9E5E00537ABF /* CoreGraphics.framework in Frameworks */, D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */, D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */, F995AC2FFD6D4442B012604A /* libPods.a in Frameworks */, @@ -1556,6 +1685,8 @@ 76EB03C118170B33006006FC /* src */ = { isa = PBXGroup; children = ( + FCAC963419FEF4E20046DFC5 /* Storyboard.storyboard */, + FCAC963919FEF8A00046DFC5 /* UI Tests */, 76EB03C218170B33006006FC /* AppDelegate.h */, 76EB03C318170B33006006FC /* AppDelegate.m */, 76EB03D918170B33006006FC /* audio */, @@ -2800,7 +2931,7 @@ D221A08C169C9E5E00537ABF /* Frameworks */ = { isa = PBXGroup; children = ( - B60EDE031A05A01700D73516 /* AudioToolbox.framework */, + FCB11D8B1A129A76002F93FB /* CoreMedia.framework */, B69CD25019773E79005CE69A /* XCTest.framework */, 70377AAA1918450100CAF501 /* MobileCoreServices.framework */, B9EB5ABC1884C002007CBB57 /* MessageUI.framework */, @@ -2843,6 +2974,7 @@ D221A094169C9E5E00537ABF /* Supporting Files */ = { isa = PBXGroup; children = ( + FCAFC2F91A0C4E1700AE5136 /* icons8 */, B6B6C3C419193F5B00C0B76B /* Translations */, E18AB40618A05754001A532A /* AudioFiles */, E1370BDA18A066F600826894 /* Default-568h@2x.png */, @@ -2954,6 +3086,150 @@ path = utilities; sourceTree = ""; }; + FC3196311A08141D0094C78E /* Settings */ = { + isa = PBXGroup; + children = ( + FC31962E1A0814130094C78E /* SettingsTableViewController.h */, + FC31962F1A0814130094C78E /* SettingsTableViewController.m */, + ); + name = Settings; + sourceTree = ""; + }; + FC3196321A08142D0094C78E /* Signals */ = { + isa = PBXGroup; + children = ( + FC3196281A067D8F0094C78E /* MessageComposeTableViewController.h */, + FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */, + FCAC963A19FEF9280046DFC5 /* SignalsViewController.h */, + FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */, + FCAC964F19FF0A6E0046DFC5 /* MessagesViewController.h */, + FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */, + FC31962B1A06A2190094C78E /* FingerprintViewController.h */, + FC31962C1A06A2190094C78E /* FingerprintViewController.m */, + FCB11D911A12A4AA002F93FB /* FullImageViewController.h */, + FCB11D921A12A4AA002F93FB /* FullImageViewController.m */, + FCFD256D1A151BCB00F4C644 /* NewGroupViewController.h */, + FCFD256E1A151BCB00F4C644 /* NewGroupViewController.m */, + FC4FA0241A1B9DC600DA100A /* SignalsNavigationController.h */, + FC4FA0251A1B9DC600DA100A /* SignalsNavigationController.m */, + ); + name = Signals; + sourceTree = ""; + }; + FC3196331A0814360094C78E /* Contacts */ = { + isa = PBXGroup; + children = ( + FCF72A121A02D27F006BC849 /* ContactDetailTableViewController.h */, + FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */, + FCF72A061A01A765006BC849 /* ContactsTableViewController.h */, + FCF72A071A01A765006BC849 /* ContactsTableViewController.m */, + ); + name = Contacts; + sourceTree = ""; + }; + FCAC963919FEF8A00046DFC5 /* UI Tests */ = { + isa = PBXGroup; + children = ( + FCAC964819FEFE210046DFC5 /* DemoData */, + FCAC964E19FF061C0046DFC5 /* ViewControllers */, + FCAC964D19FF06110046DFC5 /* Views */, + ); + name = "UI Tests"; + path = "view controllers"; + sourceTree = ""; + }; + FCAC964819FEFE210046DFC5 /* DemoData */ = { + isa = PBXGroup; + children = ( + FCAC964219FEFD8B0046DFC5 /* DemoDataFactory.h */, + FCAC964319FEFD8B0046DFC5 /* DemoDataFactory.m */, + FCAC964519FEFE1A0046DFC5 /* DemoDataModel.h */, + FCAC964619FEFE1A0046DFC5 /* DemoDataModel.m */, + FCFD25701A1524DB00F4C644 /* GroupModel.h */, + FCFD25711A1524DB00F4C644 /* GroupModel.m */, + FC4FA0211A1B8A8D00DA100A /* Socket.h */, + FC4FA0221A1B8A8D00DA100A /* Socket.m */, + ); + name = DemoData; + sourceTree = ""; + }; + FCAC964D19FF06110046DFC5 /* Views */ = { + isa = PBXGroup; + children = ( + FCF72A141A02D2BB006BC849 /* ContactDetailCell.h */, + FCF72A151A02D2BB006BC849 /* ContactDetailCell.m */, + FCAC963D19FEF99A0046DFC5 /* TableViewCell.h */, + FCAC963E19FEF99A0046DFC5 /* TableViewCell.m */, + FCAC963F19FEF99A0046DFC5 /* TableViewCell.xib */, + FCAFC33D1A0F948F00AE5136 /* ActionContactDetailCell.h */, + FCAFC33E1A0F948F00AE5136 /* ActionContactDetailCell.m */, + FCB11D881A1284BB002F93FB /* SettingsTableViewCell.h */, + FCB11D891A1284BB002F93FB /* SettingsTableViewCell.m */, + ); + name = Views; + sourceTree = ""; + }; + FCAC964E19FF061C0046DFC5 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + FCFD25791A1543D500F4C644 /* Signup */, + FC3196321A08142D0094C78E /* Signals */, + FC3196331A0814360094C78E /* Contacts */, + FC3196311A08141D0094C78E /* Settings */, + ); + name = ViewControllers; + sourceTree = ""; + }; + FCAFC2F91A0C4E1700AE5136 /* icons8 */ = { + isa = PBXGroup; + children = ( + FC4FA0131A1A180D00DA100A /* red-delete@2x.png */, + FC4FA0141A1A180D00DA100A /* delete@2x.png */, + FC4FA0151A1A180D00DA100A /* archive@2x.png */, + FC4FA0161A1A180D00DA100A /* blue-archive@2x.png */, + FC4FA00C1A18CC4300DA100A /* shred@2x.png */, + FC4FA0081A18BF3100DA100A /* lock_white@2x.png */, + FC4FA0061A18BDAE00DA100A /* info@2x.png */, + FC4F9FFE1A17A39E00DA100A /* photo@2x.png */, + FC4F9FFC1A179FCF00DA100A /* lock@2x.png */, + FC4F9FEE1A1664EA00DA100A /* mute_off@2x.png */, + FC4F9FEF1A1664EA00DA100A /* speaker_off@2x.png */, + FC4F9FF01A1664EA00DA100A /* speaker_on@2x.png */, + FC4F9FF11A1664EA00DA100A /* mute_on@2x.png */, + FC4F9FF21A1664EA00DA100A /* endcall@2x.png */, + FC4F9FEC1A1658EE00DA100A /* call@2x.png */, + FC4F9FE41A16258C00DA100A /* logo_intro@2x.png */, + FCB11D8D1A12A388002F93FB /* savephoto@2x.png */, + FCB11D8E1A12A388002F93FB /* quit@2x.png */, + FCAFC3351A0D680100AE5136 /* keypad@2x.png */, + FCAFC3331A0D656100AE5136 /* contacts_tab@2x.png */, + FCAFC32F1A0D5E3000AE5136 /* share@2x.png */, + FCAFC32D1A0D46D500AE5136 /* settings_dark@2x.png */, + FCAFC3251A0D466F00AE5136 /* delete_history@2x.png */, + FCAFC3261A0D466F00AE5136 /* signal@2x.png */, + FCAFC3271A0D466F00AE5136 /* call_dark@2x.png */, + FCAFC3201A0D394300AE5136 /* favourite.png */, + FCAFC3091A0C560E00AE5136 /* signals.png */, + FCAFC30A1A0C560E00AE5136 /* settings.png */, + FCAFC2EF1A0C4ACF00AE5136 /* received.png */, + FCAFC2F01A0C4ACF00AE5136 /* missed.png */, + FCAFC2ED1A0C472200AE5136 /* reply.png */, + FCAFC2EB1A0C469C00AE5136 /* checkmark.png */, + ); + name = icons8; + sourceTree = ""; + }; + FCFD25791A1543D500F4C644 /* Signup */ = { + isa = PBXGroup; + children = ( + FCFD257D1A154B2C00F4C644 /* RegistrationViewController.h */, + FCFD257E1A154B2C00F4C644 /* RegistrationViewController.m */, + FCFD25801A154B3800F4C644 /* CodeVerificationViewController.h */, + FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */, + ); + name = Signup; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -3010,7 +3286,7 @@ ORGANIZATIONNAME = "Open Whisper Systems"; TargetAttributes = { D221A088169C9E5E00537ABF = { - DevelopmentTeam = U68MSDN6DR; + DevelopmentTeam = DRXTS3ZU8M; SystemCapabilities = { com.apple.DataProtection = { enabled = 1; @@ -3126,15 +3402,22 @@ E148750118A06966002CC4F3 /* CallLogViewController.xib in Resources */, E148750218A06966002CC4F3 /* ContactBrowseViewController.xib in Resources */, E148750318A06966002CC4F3 /* ContactDetailTableViewCell.xib in Resources */, + FCAFC3341A0D656100AE5136 /* contacts_tab@2x.png in Resources */, E148750418A06966002CC4F3 /* ContactDetailViewController.xib in Resources */, E148750518A06966002CC4F3 /* CountryCodeViewController.xib in Resources */, E148750618A06966002CC4F3 /* DialerViewController.xib in Resources */, E148750818A06966002CC4F3 /* FavouritesViewController.xib in Resources */, E148750918A06966002CC4F3 /* InboxFeedViewController.xib in Resources */, E148750A18A06966002CC4F3 /* InCallViewController.xib in Resources */, + FCAFC32E1A0D46D500AE5136 /* settings_dark@2x.png in Resources */, + B6416FD2199A0478003C5699 /* Localizable.strings in Resources */, E148750B18A06966002CC4F3 /* InviteContactsViewController.xib in Resources */, + FCB11D901A12A388002F93FB /* quit@2x.png in Resources */, + FC4FA00D1A18CC4300DA100A /* shred@2x.png in Resources */, E148750C18A06966002CC4F3 /* LeftSideMenuViewController.xib in Resources */, E148750D18A06966002CC4F3 /* PreferenceListViewController.xib in Resources */, + FCAFC3301A0D5E3000AE5136 /* share@2x.png in Resources */, + FC4F9FE51A16258C00DA100A /* logo_intro@2x.png in Resources */, E148750E18A06966002CC4F3 /* RegisterViewController.xib in Resources */, E148750F18A06966002CC4F3 /* SettingsViewController.xib in Resources */, E148751018A06966002CC4F3 /* TabBarParentViewController.xib in Resources */, @@ -3142,12 +3425,15 @@ E14874F818A06951002CC4F3 /* ContactTableViewCell.xib in Resources */, E14874F918A06951002CC4F3 /* CountryCodeTableViewCell.xib in Resources */, E14874FA18A06951002CC4F3 /* FavouriteTableViewCell.xib in Resources */, + FCAFC2EE1A0C472200AE5136 /* reply.png in Resources */, E14874FB18A06951002CC4F3 /* InboxFeedFooterCell.xib in Resources */, E14874FC18A06951002CC4F3 /* InboxFeedTableViewCell.xib in Resources */, E14874FD18A06951002CC4F3 /* LeftSideMenuCell.xib in Resources */, E14874FE18A06951002CC4F3 /* PreferenceListTableViewCell.xib in Resources */, E14874FF18A06951002CC4F3 /* UnseenWhisperUserCell.xib in Resources */, + FC4F9FFF1A17A39E00DA100A /* photo@2x.png in Resources */, E14874A218A0692F002CC4F3 /* archive_icon.png in Resources */, + FCAFC32A1A0D466F00AE5136 /* call_dark@2x.png in Resources */, E14874A318A0692F002CC4F3 /* archive_icon@2x.png in Resources */, E14874A418A0692F002CC4F3 /* backspace.png in Resources */, E14874A518A0692F002CC4F3 /* backspace@2x.png in Resources */, @@ -3162,6 +3448,9 @@ E14874AE18A0692F002CC4F3 /* dismiss_notification_icon.png in Resources */, E14874AF18A0692F002CC4F3 /* dismiss_notification_icon@2x.png in Resources */, E14874B018A0692F002CC4F3 /* drop_down_arrow_icon.png in Resources */, + FC4F9FF61A1664EA00DA100A /* mute_on@2x.png in Resources */, + FCAFC2F21A0C4ACF00AE5136 /* missed.png in Resources */, + FC4F9FF31A1664EA00DA100A /* mute_off@2x.png in Resources */, E14874B118A0692F002CC4F3 /* drop_down_arrow_icon@2x.png in Resources */, E14874B218A0692F002CC4F3 /* expanded_cell_icon.png in Resources */, E14874B318A0692F002CC4F3 /* expanded_cell_icon@2x.png in Resources */, @@ -3169,10 +3458,15 @@ E14874B518A0692F002CC4F3 /* favourite_false_icon@2x.png in Resources */, E14874B618A0692F002CC4F3 /* favourite_true_icon.png in Resources */, E14874B718A0692F002CC4F3 /* favourite_true_icon@2x.png in Resources */, + FCAFC3211A0D394300AE5136 /* favourite.png in Resources */, E14874B818A0692F002CC4F3 /* forward_button.png in Resources */, + B6416FD4199A0478003C5699 /* Localizable.strings in Resources */, + FCAFC2EC1A0C469C00AE5136 /* checkmark.png in Resources */, E14874B918A0692F002CC4F3 /* forward_button@2x.png in Resources */, + FCAFC3281A0D466F00AE5136 /* delete_history@2x.png in Resources */, E14874BA18A0692F002CC4F3 /* home_icon.png in Resources */, E14874BB18A0692F002CC4F3 /* icon_contacts.png in Resources */, + FC4FA0071A18BDAE00DA100A /* info@2x.png in Resources */, E14874BC18A0692F002CC4F3 /* icon_favourites.png in Resources */, E14874BD18A0692F002CC4F3 /* icon_keypad.png in Resources */, E14874BE18A0692F002CC4F3 /* icon_recents.png in Resources */, @@ -3182,6 +3476,7 @@ E16E5C1518AEDB5A00B7C403 /* phone_icon.png in Resources */, E14874C218A0692F002CC4F3 /* in_call_phrase_icon@2x.png in Resources */, E14874C318A0692F002CC4F3 /* incoming_call_icon.png in Resources */, + FC4F9FF51A1664EA00DA100A /* speaker_on@2x.png in Resources */, E14874C418A0692F002CC4F3 /* incoming_call_icon@2x.png in Resources */, E14874C518A0692F002CC4F3 /* menu_icon.png in Resources */, E14874C618A0692F002CC4F3 /* menu_icon@2x.png in Resources */, @@ -3201,27 +3496,36 @@ E14874D318A0692F002CC4F3 /* search_cancel.png in Resources */, E14874D418A0692F002CC4F3 /* search_cancel@2x.png in Resources */, E14874D518A0692F002CC4F3 /* search_icon.png in Resources */, + FC4F9FFD1A179FCF00DA100A /* lock@2x.png in Resources */, E14874D618A0692F002CC4F3 /* search_icon@2x.png in Resources */, E14874D718A0692F002CC4F3 /* send_code_icon.png in Resources */, + B6416FC8199A0478003C5699 /* Localizable.strings in Resources */, + FCAFC3361A0D680100AE5136 /* keypad@2x.png in Resources */, E14874D818A0692F002CC4F3 /* send_code_icon@2x.png in Resources */, E14874D918A0692F002CC4F3 /* speaker_icon_selected.png in Resources */, + FC4FA0191A1A180D00DA100A /* archive@2x.png in Resources */, E14874DA18A0692F002CC4F3 /* speaker_icon_selected@2x.png in Resources */, E14874DB18A0692F002CC4F3 /* speaker_icon.png in Resources */, + FC4FA0171A1A180D00DA100A /* red-delete@2x.png in Resources */, E14874DC18A0692F002CC4F3 /* speaker_icon@2x.png in Resources */, E14874DD18A0692F002CC4F3 /* spinner_connecting_flash.png in Resources */, E14874DE18A0692F002CC4F3 /* spinner_connecting_flash@2x.png in Resources */, E14874DF18A06930002CC4F3 /* spinner_connecting.png in Resources */, - E14874E018A06930002CC4F3 /* spinner_connecting@2x.png in Resources */, - E14874E118A06930002CC4F3 /* spinner_error.png in Resources */, + FCAC964119FEF99A0046DFC5 /* TableViewCell.xib in Resources */, + B6416FBF199A0478003C5699 /* Localizable.strings in Resources */, + B6416FB7199A0478003C5699 /* Localizable.strings in Resources */, B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */, E14874E218A06930002CC4F3 /* spinner_error@2x.png in Resources */, E14874E318A06930002CC4F3 /* spinner_ringing.png in Resources */, E14874E418A06930002CC4F3 /* spinner_ringing@2x.png in Resources */, E14874E518A06930002CC4F3 /* tab_icon_contacts.png in Resources */, E14874E618A06930002CC4F3 /* tab_icon_contacts@2x.png in Resources */, + FCAFC3291A0D466F00AE5136 /* signal@2x.png in Resources */, E14874E718A06930002CC4F3 /* tab_icon_favourites.png in Resources */, + FCAFC30C1A0C560E00AE5136 /* signals.png in Resources */, E14874E818A06930002CC4F3 /* tab_icon_favourites@2x.png in Resources */, E14874E918A06930002CC4F3 /* tab_icon_inbox.png in Resources */, + FC4FA01A1A1A180D00DA100A /* blue-archive@2x.png in Resources */, E14874EA18A06930002CC4F3 /* tab_icon_inbox@2x.png in Resources */, E14874EB18A06930002CC4F3 /* tab_icon_keypad.png in Resources */, E14874EC18A06930002CC4F3 /* tab_icon_keypad@2x.png in Resources */, @@ -3232,6 +3536,7 @@ E14874F118A06930002CC4F3 /* volume_high.png in Resources */, E14874F218A06930002CC4F3 /* volume_high@2x.png in Resources */, 70B8FEE21909FE360042E3F0 /* 171756__nenadsimic__picked-coin-echo-2.wav in Resources */, + FC4F9FF71A1664EA00DA100A /* endcall@2x.png in Resources */, E14874F318A06930002CC4F3 /* volume_low.png in Resources */, E14874F418A06930002CC4F3 /* volume_low@2x.png in Resources */, E14874F518A06930002CC4F3 /* whisper_notification_icon.png in Resources */, @@ -3243,18 +3548,27 @@ E1370BEE18A0689000826894 /* AppIcon40x40@2x.png in Resources */, E16E5C1418AEDB5A00B7C403 /* message_icon.png in Resources */, E1370BEF18A0689000826894 /* AppIcon60x60.png in Resources */, + FC4F9FED1A1658EE00DA100A /* call@2x.png in Resources */, E1370BF018A0689000826894 /* AppIcon60x60@2x.png in Resources */, + FC4FA0181A1A180D00DA100A /* delete@2x.png in Resources */, + FC4FA0091A18BF3100DA100A /* lock_white@2x.png in Resources */, E1370BF118A0689000826894 /* AppIcon76x76.png in Resources */, E1370BF218A0689000826894 /* AppIcon76x76@2x.png in Resources */, E1370BE718A0688300826894 /* Default-568h@2x.png in Resources */, E1370BE818A0688300826894 /* Default.png in Resources */, + FCAFC30D1A0C560E00AE5136 /* settings.png in Resources */, E1370BE918A0688300826894 /* Default@2x.png in Resources */, E1370BE018A0686600826894 /* busy.mp3 in Resources */, E1370BE118A0686C00826894 /* completed.mp3 in Resources */, E1370BE218A0686C00826894 /* failure.mp3 in Resources */, + FCAFC2F11A0C4ACF00AE5136 /* received.png in Resources */, E1370BE318A0686C00826894 /* handshake.mp3 in Resources */, + B6416FCA199A0478003C5699 /* Localizable.strings in Resources */, + FCAC963519FEF4E20046DFC5 /* Storyboard.storyboard in Resources */, B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */, E1370BE418A0686C00826894 /* outring.mp3 in Resources */, + FC4F9FF41A1664EA00DA100A /* speaker_off@2x.png in Resources */, + FCB11D8F1A12A388002F93FB /* savephoto@2x.png in Resources */, E1370BE518A0686C00826894 /* r.caf in Resources */, E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */, E148751218A06AFD002CC4F3 /* HelveticaNeueLTStd-Bd.otf in Resources */, @@ -3399,6 +3713,7 @@ 76EB068418170B34006006FC /* ContactDetailTableViewCell.m in Sources */, 76EB066218170B34006006FC /* SettingsViewController.m in Sources */, 76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */, + FCB11D931A12A4AA002F93FB /* FullImageViewController.m in Sources */, B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */, 76EB062A18170B33006006FC /* BadState.m in Sources */, B97940271832BD2400BD66CB /* UIUtil.m in Sources */, @@ -3420,6 +3735,7 @@ 70B8010F190C55660042E3F0 /* CodedOutputStream.m in Sources */, 70B8010C190C55660042E3F0 /* AbstractMessage.m in Sources */, E197B61618BBEC1A00F073E5 /* StretchFactorController.m in Sources */, + FCFD257F1A154B2C00F4C644 /* RegistrationViewController.m in Sources */, 76EB065018170B34006006FC /* DialerViewController.m in Sources */, 701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */, 76EB062218170B33006006FC /* CyclicalBuffer.m in Sources */, @@ -3446,6 +3762,7 @@ D221A09A169C9E5E00537ABF /* main.m in Sources */, 76EB061618170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, 76EB063018170B33006006FC /* Conversions.m in Sources */, + FCAFC33F1A0F948F00AE5136 /* ActionContactDetailCell.m in Sources */, 76EB065618170B34006006FC /* InCallViewController.m in Sources */, 76EB05FE18170B33006006FC /* InitiateSignal.pb.m in Sources */, 76EB064C18170B34006006FC /* ContactBrowseViewController.m in Sources */, @@ -3453,6 +3770,7 @@ 70B80115190C55660042E3F0 /* GeneratedMessage.m in Sources */, E197B61418BBEC1A00F073E5 /* DropoutTracker.m in Sources */, 76EB062C18170B33006006FC /* OperationFailed.m in Sources */, + FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */, 707E549218FF26E800C8649D /* SmsInvite.m in Sources */, 76EB05DA18170B33006006FC /* LowLatencyConnector.m in Sources */, 76EB05EE18170B33006006FC /* CallTermination.m in Sources */, @@ -3465,9 +3783,13 @@ 70B80114190C55660042E3F0 /* Field.m in Sources */, E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */, E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */, + FCF72A081A01A765006BC849 /* ContactsTableViewController.m in Sources */, + FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */, 76EB061418170B33006006FC /* AnonymousConditionLogger.m in Sources */, + FCF72A161A02D2BB006BC849 /* ContactDetailCell.m in Sources */, 76EB05C018170B33006006FC /* DhPacket.m in Sources */, 765052A1182945EF008313E1 /* LocalizableCustomFontLabel.m in Sources */, + FC3196301A0814130094C78E /* SettingsTableViewController.m in Sources */, 7038632818F70C0700D4A43F /* EvpSymetricUtil.m in Sources */, 76EB066418170B34006006FC /* TabBarParentViewController.m in Sources */, 76EB068618170B34006006FC /* ContactTableViewCell.m in Sources */, @@ -3475,10 +3797,13 @@ 76EB05A018170B33006006FC /* IpAddress.m in Sources */, 70B8011B190C55660042E3F0 /* UnknownFieldSet_Builder.m in Sources */, B9A578B1183D60EE00C17105 /* FavouriteTableViewCell.m in Sources */, + FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */, 76EB057618170B33006006FC /* Contact.m in Sources */, 70B80111190C55660042E3F0 /* ExtendableMessage.m in Sources */, + FCAC964719FEFE1A0046DFC5 /* DemoDataModel.m in Sources */, E197B61118BBEC1A00F073E5 /* AudioProcessor.m in Sources */, 76EB065818170B34006006FC /* LeftSideMenuViewController.m in Sources */, + FCAC964019FEF99A0046DFC5 /* TableViewCell.m in Sources */, 76EB05EA18170B33006006FC /* CallProgress.m in Sources */, 76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */, B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */, @@ -3491,6 +3816,7 @@ E197B61218BBEC1A00F073E5 /* AudioStretcher.m in Sources */, 76EB05A218170B33006006FC /* IpEndPoint.m in Sources */, 70B8010D190C55660042E3F0 /* AbstractMessage_Builder.m in Sources */, + FCFD25721A1524DB00F4C644 /* GroupModel.m in Sources */, E197B61A18BBEC1A00F073E5 /* SpeexCodec.m in Sources */, 70B80118190C55660042E3F0 /* MutableField.m in Sources */, 762D9DCF18281C7400A5E418 /* SettingsTableHeaderView.m in Sources */, @@ -3500,6 +3826,7 @@ 76D713E7182D3E3F00C9C9C8 /* PreferenceListTableViewCell.m in Sources */, 76EB061818170B33006006FC /* AnonymousValueLogger.m in Sources */, 76EB05E618170B33006006FC /* CallController.m in Sources */, + FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */, E16E5BEE18AAC40200B7C403 /* EC25KeyAgreementParticipant.m in Sources */, 76EB057418170B33006006FC /* RecentCallManager.m in Sources */, 76EB061C18170B33006006FC /* ArrayUtil.m in Sources */, @@ -3511,6 +3838,7 @@ B942EB0E183A9633000887BB /* SearchBarTitleView.m in Sources */, 765052AF182AC9B5008313E1 /* DialerButtonView.m in Sources */, 70B80110190C55660042E3F0 /* ConcreteExtensionField.m in Sources */, + FCAC964419FEFD8B0046DFC5 /* DemoDataFactory.m in Sources */, 70B80112190C55660042E3F0 /* ExtendableMessage_Builder.m in Sources */, 76EB05D418170B33006006FC /* ZrtpManager.m in Sources */, 76EB058E18170B33006006FC /* HostNameEndPoint.m in Sources */, @@ -3519,6 +3847,8 @@ 76EB065218170B34006006FC /* FavouritesViewController.m in Sources */, E16E5BF018AAC40200B7C403 /* EvpKeyAgreement.m in Sources */, 70B80113190C55660042E3F0 /* ExtensionRegistry.m in Sources */, + FCFD25821A154B3800F4C644 /* CodeVerificationViewController.m in Sources */, + FCF72A131A02D27F006BC849 /* ContactDetailTableViewController.m in Sources */, B9EB5AC61884D370007CBB57 /* UnseenWhisperUserCell.m in Sources */, B65EDA1219E1BE6400AAA7CB /* RPAPICall.m in Sources */, 76EB05DC18170B33006006FC /* StreamPair.m in Sources */, @@ -3527,6 +3857,7 @@ 70BAFD5D190584BE00FA5E0B /* NotificationTracker.m in Sources */, 76EB05A418170B33006006FC /* PacketHandler.m in Sources */, E197B62118BBF12700F073E5 /* AppAudioManager.m in Sources */, + FC4FA0261A1B9DC600DA100A /* SignalsNavigationController.m in Sources */, 76EB068C18170B34006006FC /* InboxFeedTableViewCell.m in Sources */, 76EB062018170B33006006FC /* BloomFilter.m in Sources */, 76EB063818170B33006006FC /* DictionaryUtil.m in Sources */, @@ -3536,14 +3867,17 @@ B63761EE19E1FBE8005735D1 /* HttpRequestUtil.m in Sources */, 76EB05B618170B33006006FC /* MasterSecret.m in Sources */, 76EB05F418170B33006006FC /* CallConnectResult.m in Sources */, + FCFD256F1A151BCB00F4C644 /* NewGroupViewController.m in Sources */, 76EB059E18170B33006006FC /* HttpSocket.m in Sources */, E197B60E18BBEC1A00F073E5 /* CallAudioManager.m in Sources */, 76EB065418170B34006006FC /* InboxFeedViewController.m in Sources */, + FC4FA0231A1B8A8D00DA100A /* Socket.m in Sources */, 76EB054018170B33006006FC /* AppDelegate.m in Sources */, 76EB05D018170B33006006FC /* ZrtpHandshakeSocket.m in Sources */, B63761EF19E1FBE8005735D1 /* HttpResponse.m in Sources */, E197B61518BBEC1A00F073E5 /* JitterQueue.m in Sources */, BFB074C919A5611000F2947C /* ObservableValue.m in Sources */, + FCB11D8A1A1284BB002F93FB /* SettingsTableViewCell.m in Sources */, 76EB05C818170B33006006FC /* HelloPacket.m in Sources */, BFB074C719A5611000F2947C /* FutureUtil.m in Sources */, 76EB057218170B33006006FC /* RecentCall.m in Sources */, @@ -4200,7 +4534,7 @@ "\"$(SRCROOT)/Libraries\"/**", ); INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -4432,7 +4766,7 @@ "\"$(SRCROOT)/Libraries\"/**", ); INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -4486,7 +4820,7 @@ "\"$(SRCROOT)/Libraries\"/**", ); INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", diff --git a/Signal.xcworkspace/..Pods b/Signal.xcworkspace/..Pods new file mode 160000 index 0000000000..585c9e6ca1 --- /dev/null +++ b/Signal.xcworkspace/..Pods @@ -0,0 +1 @@ +Subproject commit 585c9e6ca1b55e99fb5c09aa31a6d590c2be5c58 diff --git a/Signal.xcworkspace/contents.xcworkspacedata b/Signal.xcworkspace/contents.xcworkspacedata index c906952e4d..3f3596e9a9 100644 --- a/Signal.xcworkspace/contents.xcworkspacedata +++ b/Signal.xcworkspace/contents.xcworkspacedata @@ -1 +1,10 @@ - \ No newline at end of file + + + + + + + diff --git a/Signal/Signal-Info.plist b/Signal/Signal-Info.plist index 62a7793d0e..e2e1b395f3 100644 --- a/Signal/Signal-Info.plist +++ b/Signal/Signal-Info.plist @@ -13,7 +13,7 @@ CFBundleIcons~ipad CFBundleIdentifier - org.whispersystems.signal + org.whispersystems.signal.branch CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -48,6 +48,10 @@ remote-notification voip + UILaunchStoryboardName + Storyboard + UIMainStoryboardFile + Storyboard UIRequiredDeviceCapabilities armv7 diff --git a/Signal/archive@2x.png b/Signal/archive@2x.png new file mode 100644 index 0000000000..6140b2d518 Binary files /dev/null and b/Signal/archive@2x.png differ diff --git a/Signal/blue-archive@2x.png b/Signal/blue-archive@2x.png new file mode 100644 index 0000000000..b0a9a37d46 Binary files /dev/null and b/Signal/blue-archive@2x.png differ diff --git a/Signal/call@2x.png b/Signal/call@2x.png new file mode 100644 index 0000000000..952845c2d0 Binary files /dev/null and b/Signal/call@2x.png differ diff --git a/Signal/call_dark@2x.png b/Signal/call_dark@2x.png new file mode 100644 index 0000000000..0bdf09f5d4 Binary files /dev/null and b/Signal/call_dark@2x.png differ diff --git a/Signal/checkmark.png b/Signal/checkmark.png new file mode 100644 index 0000000000..1a7c35f622 Binary files /dev/null and b/Signal/checkmark.png differ diff --git a/Signal/contacts.png b/Signal/contacts.png new file mode 100644 index 0000000000..a4c3deeb11 Binary files /dev/null and b/Signal/contacts.png differ diff --git a/Signal/contacts@2x.png b/Signal/contacts@2x.png new file mode 100644 index 0000000000..c150f69cac Binary files /dev/null and b/Signal/contacts@2x.png differ diff --git a/Signal/contacts_tab@2x.png b/Signal/contacts_tab@2x.png new file mode 100644 index 0000000000..0b5de3d69e Binary files /dev/null and b/Signal/contacts_tab@2x.png differ diff --git a/Signal/delete@2x.png b/Signal/delete@2x.png new file mode 100644 index 0000000000..7d3a06c12f Binary files /dev/null and b/Signal/delete@2x.png differ diff --git a/Signal/delete_history@2x.png b/Signal/delete_history@2x.png new file mode 100644 index 0000000000..2f1cea2946 Binary files /dev/null and b/Signal/delete_history@2x.png differ diff --git a/Signal/endcall@2x.png b/Signal/endcall@2x.png new file mode 100644 index 0000000000..802cffe2eb Binary files /dev/null and b/Signal/endcall@2x.png differ diff --git a/Signal/favourite.png b/Signal/favourite.png new file mode 100644 index 0000000000..4e2e31def0 Binary files /dev/null and b/Signal/favourite.png differ diff --git a/Signal/info@2x.png b/Signal/info@2x.png new file mode 100644 index 0000000000..5fc14034ca Binary files /dev/null and b/Signal/info@2x.png differ diff --git a/Signal/keypad@2x.png b/Signal/keypad@2x.png new file mode 100644 index 0000000000..e8b8b28963 Binary files /dev/null and b/Signal/keypad@2x.png differ diff --git a/Signal/lock@2x.png b/Signal/lock@2x.png new file mode 100644 index 0000000000..53c8582df3 Binary files /dev/null and b/Signal/lock@2x.png differ diff --git a/Signal/lock_white@2x.png b/Signal/lock_white@2x.png new file mode 100644 index 0000000000..1e28851458 Binary files /dev/null and b/Signal/lock_white@2x.png differ diff --git a/Signal/logo_intro@2x.png b/Signal/logo_intro@2x.png new file mode 100644 index 0000000000..33c38aa566 Binary files /dev/null and b/Signal/logo_intro@2x.png differ diff --git a/Signal/missed.png b/Signal/missed.png new file mode 100644 index 0000000000..b1cacfa822 Binary files /dev/null and b/Signal/missed.png differ diff --git a/Signal/mute_off@2x.png b/Signal/mute_off@2x.png new file mode 100644 index 0000000000..c758cb6b6b Binary files /dev/null and b/Signal/mute_off@2x.png differ diff --git a/Signal/mute_on@2x.png b/Signal/mute_on@2x.png new file mode 100644 index 0000000000..45008acea1 Binary files /dev/null and b/Signal/mute_on@2x.png differ diff --git a/Signal/photo@2x.png b/Signal/photo@2x.png new file mode 100644 index 0000000000..3d02d0a433 Binary files /dev/null and b/Signal/photo@2x.png differ diff --git a/Signal/quit@2x.png b/Signal/quit@2x.png new file mode 100644 index 0000000000..e8fad44929 Binary files /dev/null and b/Signal/quit@2x.png differ diff --git a/Signal/received.png b/Signal/received.png new file mode 100644 index 0000000000..cc794bc6f1 Binary files /dev/null and b/Signal/received.png differ diff --git a/Signal/red-delete@2x.png b/Signal/red-delete@2x.png new file mode 100644 index 0000000000..dce4872025 Binary files /dev/null and b/Signal/red-delete@2x.png differ diff --git a/Signal/reply.png b/Signal/reply.png new file mode 100644 index 0000000000..0fa5260be3 Binary files /dev/null and b/Signal/reply.png differ diff --git a/Signal/savephoto@2x.png b/Signal/savephoto@2x.png new file mode 100644 index 0000000000..752e5dc10b Binary files /dev/null and b/Signal/savephoto@2x.png differ diff --git a/Signal/settings.png b/Signal/settings.png new file mode 100644 index 0000000000..cac25f6955 Binary files /dev/null and b/Signal/settings.png differ diff --git a/Signal/settings_dark@2x.png b/Signal/settings_dark@2x.png new file mode 100644 index 0000000000..4df135ea02 Binary files /dev/null and b/Signal/settings_dark@2x.png differ diff --git a/Signal/share@2x.png b/Signal/share@2x.png new file mode 100644 index 0000000000..ce183031d7 Binary files /dev/null and b/Signal/share@2x.png differ diff --git a/Signal/shred@2x.png b/Signal/shred@2x.png new file mode 100644 index 0000000000..aaa5fe2ae3 Binary files /dev/null and b/Signal/shred@2x.png differ diff --git a/Signal/signal@2x.png b/Signal/signal@2x.png new file mode 100644 index 0000000000..06f3d32441 Binary files /dev/null and b/Signal/signal@2x.png differ diff --git a/Signal/signals.png b/Signal/signals.png new file mode 100644 index 0000000000..a3eb26482a Binary files /dev/null and b/Signal/signals.png differ diff --git a/Signal/speaker_off@2x.png b/Signal/speaker_off@2x.png new file mode 100644 index 0000000000..9383bc7b04 Binary files /dev/null and b/Signal/speaker_off@2x.png differ diff --git a/Signal/speaker_on@2x.png b/Signal/speaker_on@2x.png new file mode 100644 index 0000000000..8b891715b9 Binary files /dev/null and b/Signal/speaker_on@2x.png differ diff --git a/Signal/src/AppDelegate.h b/Signal/src/AppDelegate.h index 8561612f13..c95e39340c 100644 --- a/Signal/src/AppDelegate.h +++ b/Signal/src/AppDelegate.h @@ -1,7 +1,11 @@ #import +#import "SignalsViewController.h" + @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) SignalsViewController *signalVC; + @end diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index ebafbd4327..084fa24dbb 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -126,7 +126,7 @@ [self performUpdateCheck]; [self protectPreferenceFiles]; - self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; + //self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; [self prepareScreenshotProtection]; @@ -142,8 +142,8 @@ LeftSideMenuViewController *leftSideMenuViewController = [LeftSideMenuViewController new]; self.drawerController = [[MMDrawerController alloc] initWithCenterViewController:leftSideMenuViewController.centerTabBarViewController leftDrawerViewController:leftSideMenuViewController]; - self.window.rootViewController = _drawerController; - [self.window makeKeyAndVisible]; + //self.window.rootViewController = _drawerController; + //[self.window makeKeyAndVisible]; //Accept push notification when app is not open NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; diff --git a/Signal/src/ContactsViewController.h b/Signal/src/ContactsViewController.h new file mode 100644 index 0000000000..50240eba13 --- /dev/null +++ b/Signal/src/ContactsViewController.h @@ -0,0 +1,15 @@ +// +// ContactsViewController.h +// Signal +// +// Created by Dylan Bourgeois on 29/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface ContactsViewController : UIViewController +@property(nonatomic,strong) IBOutlet UISearchBar* searchBar; +@property(nonatomic,strong) IBOutlet UITableView* tableView; +@property(nonatomic,strong) IBOutlet UILabel* phoneNumberLabel; +@end diff --git a/Signal/src/ContactsViewController.m b/Signal/src/ContactsViewController.m new file mode 100644 index 0000000000..09d25d65d0 --- /dev/null +++ b/Signal/src/ContactsViewController.m @@ -0,0 +1,165 @@ +// +// ContactsViewController.m +// Signal +// +// Created by Dylan Bourgeois on 29/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "Environment.h" +#import "Contact.h" +#import "ContactsManager.h" +#import "PhoneNumberDirectoryFilterManager.h" + +#import "DemoDataFactory.h" + +#import +#import "ContactsViewController.h" + +static NSString *const CONTACT_BROWSE_TABLE_CELL_IDENTIFIER = @"ContactTableViewCell"; + + +@interface ContactsViewController () { + NSMutableDictionary *_latestAlphabeticalContacts; + NSArray *_latestSortedAlphabeticalContactKeys; + NSArray *_latestContacts; +} + +@end + +@implementation ContactsViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + + [self.tableView setContentOffset:CGPointMake(0, self.searchBar.frame.size.height)]; + + [self setupContacts]; + [self.tableView reloadData]; + + + // Uncomment the following line to preserve selection between presentations. + // self.clearsSelectionOnViewWillAppear = NO; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Contact functions + +- (void)setupContacts { + // ObservableValue *observableContacts = Environment.getCurrent.contactsManager.getObservableWhisperUsers; + // + // [observableContacts watchLatestValue:^(NSArray *latestContacts) { + // _latestContacts = latestContacts; + // } onThread:NSThread.mainThread untilCancelled:nil]; + _latestContacts = [DemoDataFactory makeFakeContacts]; + + NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES]; + NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; + _latestSortedAlphabeticalContactKeys = [_latestContacts sortedArrayUsingDescriptors:sortDescriptors]; + + _latestAlphabeticalContacts = [self alphabetDictionaryInit]; + + for (Contact*contact in _latestContacts) + { + NSString * firstLetter = [contact.firstName substringToIndex:1]; + + NSMutableArray * mutArray = [[_latestAlphabeticalContacts objectForKey:firstLetter] mutableCopy]; + if (![mutArray containsObject:contact]) + [mutArray addObject:contact]; + [_latestAlphabeticalContacts setObject:mutArray forKey:firstLetter]; + + } + + _latestSortedAlphabeticalContactKeys = [[_latestAlphabeticalContacts allKeys]sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + +} + +- (NSArray *)contactsForSectionIndex:(NSUInteger)index { + return [_latestAlphabeticalContacts valueForKey:_latestSortedAlphabeticalContactKeys[index]]; +} + +-(NSMutableDictionary*)alphabetDictionaryInit +{ + NSDictionary * dic; + + dic = @{ + @"A": @[], + @"B": @[], + @"C": @[], + @"D": @[], + @"E": @[], + @"F": @[], + @"G": @[], + @"H": @[], + @"I": @[], + @"J": @[], + @"K": @[], + @"L": @[], + @"M": @[], + @"N": @[], + @"O": @[], + @"P": @[], + @"Q": @[], + @"R": @[], + @"S": @[], + @"T": @[], + @"U": @[], + @"V": @[], + @"W": @[], + @"X": @[], + @"Y": @[], + @"Z": @[], + + }; + + return [dic mutableCopy]; +} + + +#pragma mark - Table view data source +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return (NSInteger)[[self contactsForSectionIndex:(NSUInteger)section] count]; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + if ([[self contactsForSectionIndex:(NSUInteger)section] count]) + return _latestSortedAlphabeticalContactKeys[(NSUInteger)section]; + else return nil; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return (NSInteger)[[_latestAlphabeticalContacts allKeys] count]; +} + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView +{ + return _latestSortedAlphabeticalContactKeys; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CONTACT_BROWSE_TABLE_CELL_IDENTIFIER]; + + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CONTACT_BROWSE_TABLE_CELL_IDENTIFIER]; + } + + NSArray *contactSection = [self contactsForSectionIndex:(NSUInteger)indexPath.section]; + Contact *contact = contactSection[(NSUInteger)indexPath.row]; + + //TODO: real setup of custom cell + cell.textLabel.text = contact.firstName; + + return cell; +} + +@end diff --git a/Signal/src/Storyboard/Storyboard.storyboard b/Signal/src/Storyboard/Storyboard.storyboard new file mode 100644 index 0000000000..2a69adc4bd --- /dev/null +++ b/Signal/src/Storyboard/Storyboard.storyboard @@ -0,0 +1,3481 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Signal/src/contact/Contact.h b/Signal/src/contact/Contact.h index 886633d3ac..21fce8cb9a 100644 --- a/Signal/src/contact/Contact.h +++ b/Signal/src/contact/Contact.h @@ -18,6 +18,10 @@ @property (readonly,nonatomic) UIImage* image; @property (readonly,nonatomic) NSString *notes; @property (readonly,nonatomic) ABRecordID recordID; + +@property (nonatomic, assign) BOOL isTextSecureContact; +@property (nonatomic, assign) BOOL isRedPhoneContact; + @property (nonatomic, assign) BOOL isFavourite; + (Contact*)contactWithFirstName:(NSString*)firstName diff --git a/Signal/src/util/UIUtil.m b/Signal/src/util/UIUtil.m index 315331ffe5..04b6deed99 100644 --- a/Signal/src/util/UIUtil.m +++ b/Signal/src/util/UIUtil.m @@ -6,7 +6,7 @@ static NSString *const HELVETICA_NEUE_LTSTD_MEDIUM_NAME = @"HelveticaNeueLTStd-M static NSString *const HELVETICA_REGULAR_NAME = @"Helvetica"; static NSString *const HELVETICA_LIGHT_NAME = @"Helvetica-Light"; -#define CONTACT_PICTURE_VIEW_BORDER_WIDTH 2.0f +#define CONTACT_PICTURE_VIEW_BORDER_WIDTH 0.5f @implementation UIUtil diff --git a/Signal/src/view controllers/ActionContactDetailCell.h b/Signal/src/view controllers/ActionContactDetailCell.h new file mode 100644 index 0000000000..bc00597bd8 --- /dev/null +++ b/Signal/src/view controllers/ActionContactDetailCell.h @@ -0,0 +1,16 @@ +// +// ActionContactDetailCell.h +// Signal +// +// Created by Dylan Bourgeois on 09/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface ActionContactDetailCell : UITableViewCell +@property (strong, nonatomic) IBOutlet UIButton *contactTextButton; +@property (strong, nonatomic) IBOutlet UIButton *contactCallButton; +@property (strong, nonatomic) IBOutlet UIButton *contactShredButton; +@property (strong, nonatomic) IBOutlet UIButton *contactFavoriteButton; +@end diff --git a/Signal/src/view controllers/ActionContactDetailCell.m b/Signal/src/view controllers/ActionContactDetailCell.m new file mode 100644 index 0000000000..23061e40d3 --- /dev/null +++ b/Signal/src/view controllers/ActionContactDetailCell.m @@ -0,0 +1,28 @@ +// +// ActionContactDetailCell.m +// Signal +// +// Created by Dylan Bourgeois on 09/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "DJWActionSheet.h" +#import "ActionContactDetailCell.h" + +@implementation ActionContactDetailCell + +- (void)awakeFromNib { + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + + + + + +@end diff --git a/Signal/src/view controllers/CodeVerificationViewController.h b/Signal/src/view controllers/CodeVerificationViewController.h new file mode 100644 index 0000000000..64bd4619ce --- /dev/null +++ b/Signal/src/view controllers/CodeVerificationViewController.h @@ -0,0 +1,15 @@ +// +// CodeVerificationViewController.h +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface CodeVerificationViewController : UIViewController + +@property(nonatomic, strong) IBOutlet UITextField* challengeTextField; + +@end diff --git a/Signal/src/view controllers/CodeVerificationViewController.m b/Signal/src/view controllers/CodeVerificationViewController.m new file mode 100644 index 0000000000..7c53b14907 --- /dev/null +++ b/Signal/src/view controllers/CodeVerificationViewController.m @@ -0,0 +1,62 @@ +// +// CodeVerificationViewController.m +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "CodeVerificationViewController.h" + +@interface CodeVerificationViewController () + +@end + +@implementation CodeVerificationViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + [self initializeKeyboardHandlers]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +- (IBAction)verifyChallengeAction:(id)sender { + + [_challengeTextField resignFirstResponder]; + + //Perform verification + + [self performSegueWithIdentifier:@"verifiedSegue" sender:self]; +} + +#pragma mark - Keyboard notifications + +- (void)initializeKeyboardHandlers{ + UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; + [self.view addGestureRecognizer:outsideTabRecognizer]; + +} + +-(void) dismissKeyboardFromAppropriateSubView { + [self.view endEditing:NO]; +} + + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Signal/src/view controllers/ContactDetailCell.h b/Signal/src/view controllers/ContactDetailCell.h new file mode 100644 index 0000000000..080f04153f --- /dev/null +++ b/Signal/src/view controllers/ContactDetailCell.h @@ -0,0 +1,24 @@ +// +// ContactDetailCell.h +// Signal +// +// Created by Dylan Bourgeois on 30/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +#import "Contact.h" +#import "UIUtil.h" + +@interface ContactDetailCell : UITableViewCell + +@property (strong, nonatomic) IBOutlet UILabel *contactName; +@property (strong, nonatomic) IBOutlet UIImageView *contactImageView; +@property (strong, nonatomic) IBOutlet UIImageView *contactFavoriteImageView; +@property (strong, nonatomic) IBOutlet UILabel *contactPhoneNumber; +@property (strong, nonatomic) IBOutlet UITextView *contactNotesTextView; + + + +@end diff --git a/Signal/src/view controllers/ContactDetailCell.m b/Signal/src/view controllers/ContactDetailCell.m new file mode 100644 index 0000000000..bb50031192 --- /dev/null +++ b/Signal/src/view controllers/ContactDetailCell.m @@ -0,0 +1,28 @@ +// +// ContactDetailCell.m +// Signal +// +// Created by Dylan Bourgeois on 30/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "ContactDetailCell.h" +#import "DJWActionSheet.h" + + +@implementation ContactDetailCell + +- (void)awakeFromNib { + // Initialization code +} + + + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + + +@end diff --git a/Signal/src/view controllers/ContactDetailTableViewController.h b/Signal/src/view controllers/ContactDetailTableViewController.h new file mode 100644 index 0000000000..20ce181161 --- /dev/null +++ b/Signal/src/view controllers/ContactDetailTableViewController.h @@ -0,0 +1,17 @@ +// +// ContactDetailTableViewController.h +// Signal +// +// Created by Dylan Bourgeois on 30/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +#import "Contact.h" + +@interface ContactDetailTableViewController : UITableViewController + +@property (nonatomic, strong) Contact *contact; + +@end diff --git a/Signal/src/view controllers/ContactDetailTableViewController.m b/Signal/src/view controllers/ContactDetailTableViewController.m new file mode 100644 index 0000000000..cdc2c425ca --- /dev/null +++ b/Signal/src/view controllers/ContactDetailTableViewController.m @@ -0,0 +1,179 @@ +// +// ContactDetailTableViewController.m +// Signal +// +// Created by Dylan Bourgeois on 30/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "ContactDetailTableViewController.h" +#import "ContactDetailCell.h" +#import "ActionContactDetailCell.h" +#import "UIUtil.h" +#import "DJWActionSheet.h" + + +typedef enum { + kNameMainNumberCellIndexPath = 0, + kActionCellIndexPath = 1, + kShareCellIndexPath = 2, + kEmailCellIndexPath = 3, + kAnnexPhoneNumberCellIndexPath = 4, + kNotesCellIndexPath = 5, +} kCellIndexPath; + +typedef enum { + kNameMainNumberCellHeight = 180, + kActionCellHeight = 60, + kShareCellHeight = 60, + kEmailCellHeight = 60, + kAnnexPhoneNumberCellHeight = 60, + kNotesCellHeight = 165, +} kCellHeight; + +static NSString* const kNameMainNumberCell = @"NameMainNumberCell"; +static NSString* const kActionCell = @"ActionCell"; + +//Deprecated +static NSString* const kShareCell = @"ShareCell"; +static NSString* const kEmailCell = @"EmailCell"; +static NSString* const kAnnexPhoneNumberCell = @"AnnexPhoneNumberCell"; +static NSString *const kNotesCell = @"NotesCell"; +// + +static NSString *const kContactDetailSegue = @"DetailSegue"; + + + +@interface ContactDetailTableViewController () + +@end + +@implementation ContactDetailTableViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 6; +} + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell * cell; + + switch (indexPath.row) { + case kNameMainNumberCellIndexPath: + cell = (ContactDetailCell*)[tableView dequeueReusableCellWithIdentifier:kNameMainNumberCell forIndexPath:indexPath]; + [self setUpNameMainUserCell:(ContactDetailCell*)cell]; + break; + case kActionCellIndexPath: + cell = (ActionContactDetailCell*)[tableView dequeueReusableCellWithIdentifier:kActionCell forIndexPath:indexPath]; + break; + case kShareCellIndexPath: + cell = [tableView dequeueReusableCellWithIdentifier:kShareCell forIndexPath:indexPath]; + break; + case kEmailCellIndexPath: + cell = [tableView dequeueReusableCellWithIdentifier:kEmailCell forIndexPath:indexPath]; + break; + case kAnnexPhoneNumberCellIndexPath: + cell = [tableView dequeueReusableCellWithIdentifier:kAnnexPhoneNumberCell forIndexPath:indexPath]; + break; + case kNotesCellIndexPath: + cell = [tableView dequeueReusableCellWithIdentifier:kNotesCell forIndexPath:indexPath]; + break; + + default: + break; + } + + return cell; +} + + +-(void)setUpNameMainUserCell:(ContactDetailCell*)cell +{ + Contact* c = self.contact; + + cell.contactName.text = [c fullName]; + + cell.contactPhoneNumber.text = [c.userTextPhoneNumbers firstObject]; + + if (c.image) { + cell.contactImageView.image = c.image; + } + [cell.contactImageView.layer setCornerRadius:50.0f]; + [cell.contactImageView.layer setMasksToBounds:YES]; + + +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + CGFloat cellHeight = 44.0f; + + switch (indexPath.row) { + case kNameMainNumberCellIndexPath: + cellHeight = kNameMainNumberCellHeight; + break; + case kActionCellIndexPath: + cellHeight = kActionCellHeight; + break; + case kShareCellIndexPath: + cellHeight = kShareCellHeight; + break; + case kEmailCellIndexPath: + cellHeight = kEmailCellHeight; + break; + case kAnnexPhoneNumberCellIndexPath: + cellHeight = kAnnexPhoneNumberCellHeight; + break; + case kNotesCellIndexPath: + cellHeight = kNotesCellHeight; + break; + default: + break; + } + return cellHeight; +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + switch (indexPath.row) { + case kShareCellIndexPath: + [DJWActionSheet showInView:self.tabBarController.view + withTitle:nil + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@[@"Mail", @"Message", @"Airdrop", @"Other"] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + NSLog(@"The user tapped button at index: %li", (long)tappedButtonIndex); + } + }]; + + break; + + } +} + +@end diff --git a/Signal/src/view controllers/ContactsTableViewController.h b/Signal/src/view controllers/ContactsTableViewController.h new file mode 100644 index 0000000000..1ab476fdd8 --- /dev/null +++ b/Signal/src/view controllers/ContactsTableViewController.h @@ -0,0 +1,13 @@ +// +// ContactsTableViewController.h +// Signal +// +// Created by Dylan Bourgeois on 29/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface ContactsTableViewController : UITableViewController + +@end diff --git a/Signal/src/view controllers/ContactsTableViewController.m b/Signal/src/view controllers/ContactsTableViewController.m new file mode 100644 index 0000000000..fb3d6c1069 --- /dev/null +++ b/Signal/src/view controllers/ContactsTableViewController.m @@ -0,0 +1,313 @@ +// +// ContactsTableViewController.m +// Signal +// +// Created by Dylan Bourgeois on 29/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "ContactsTableViewController.h" +#import "ContactDetailTableViewController.h" +#import "DialerViewController.h" + +#import "ContactTableViewCell.h" + +#import "Environment.h" +#import "Contact.h" +#import "ContactsManager.h" +#import "PhoneNumberDirectoryFilterManager.h" + +#import "DemoDataFactory.h" + +#import + +static NSString *const CONTACT_BROWSE_TABLE_CELL_IDENTIFIER = @"ContactTableViewCell"; + + +@interface ContactsTableViewController () +{ + NSMutableDictionary *latestAlphabeticalContacts; + NSArray *latestSortedAlphabeticalContactKeys; + NSArray * latestContacts; + + NSArray * searchResults; +} + +@property (nonatomic, strong) UISearchController *searchController; + +@end + +@implementation ContactsTableViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + + //Hide search bar + self.tableView.contentOffset = CGPointMake(0, 44); + + [self initializeSearch]; + + [self setupContacts]; + searchResults = latestContacts; + + [self.tableView reloadData]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +#pragma mark - Initializers + +-(void)initializeSearch +{ + self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; + + self.searchController.searchResultsUpdater = self; + + self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0); + + self.tableView.tableHeaderView = self.searchController.searchBar; + + self.searchController.dimsBackgroundDuringPresentation = NO; + self.searchController.hidesNavigationBarDuringPresentation = NO; + + self.definesPresentationContext = YES; + + self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal; + + +} + +#pragma mark - UISearchResultsUpdating + +-(void)updateSearchResultsForSearchController:(UISearchController *)searchController { + + NSString *searchString = [self.searchController.searchBar text]; + + [self filterContentForSearchText:searchString scope:nil]; + + [self.tableView reloadData]; +} + + +#pragma mark - UISearchBarDelegate + +- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope { + [self updateSearchResultsForSearchController:self.searchController]; +} + + +#pragma mark - Filter + +- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope +{ + NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"fullName contains[c] %@", searchText]; + searchResults = [latestContacts filteredArrayUsingPredicate:resultPredicate]; + if (!searchResults.count && _searchController.searchBar.text.length == 0) searchResults = latestContacts; +} + + +#pragma mark - Contact functions + +- (void)setupContacts { + // ObservableValue *observableContacts = Environment.getCurrent.contactsManager.getObservableWhisperUsers; + // + // [observableContacts watchLatestValue:^(NSArray *latestContacts) { + // _latestContacts = latestContacts; + // } onThread:NSThread.mainThread untilCancelled:nil]; + + latestContacts = [DemoDataFactory makeFakeContacts]; + + NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES]; + NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; + latestSortedAlphabeticalContactKeys = [latestContacts sortedArrayUsingDescriptors:sortDescriptors]; + + latestAlphabeticalContacts = [self alphabetDictionaryInit]; + + for (Contact*contact in latestContacts) + { + NSString * firstLetter = [contact.firstName substringToIndex:1]; + + NSMutableArray * mutArray = [[latestAlphabeticalContacts objectForKey:firstLetter] mutableCopy]; + if (![mutArray containsObject:contact]) + [mutArray addObject:contact]; + [latestAlphabeticalContacts setObject:mutArray forKey:firstLetter]; + + } + + latestSortedAlphabeticalContactKeys = [[latestAlphabeticalContacts allKeys]sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + +} + +- (NSArray *)contactsForSectionIndex:(NSUInteger)index { + return [latestAlphabeticalContacts valueForKey:latestSortedAlphabeticalContactKeys[index]]; +} + + +-(NSMutableDictionary*)alphabetDictionaryInit +{ + NSDictionary * dic; + + dic = @{ + @"A": @[], + @"B": @[], + @"C": @[], + @"D": @[], + @"E": @[], + @"F": @[], + @"G": @[], + @"H": @[], + @"I": @[], + @"J": @[], + @"K": @[], + @"L": @[], + @"M": @[], + @"N": @[], + @"O": @[], + @"P": @[], + @"Q": @[], + @"R": @[], + @"S": @[], + @"T": @[], + @"U": @[], + @"V": @[], + @"W": @[], + @"X": @[], + @"Y": @[], + @"Z": @[], + + }; + + return [dic mutableCopy]; +} + + +#pragma mark - Table view data source + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (self.searchController.active) { + return (NSInteger)[searchResults count]; + } else { + return (NSInteger)[[self contactsForSectionIndex:(NSUInteger)section] count]; + } +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + + if ([[self contactsForSectionIndex:(NSUInteger)section] count]) { + return latestSortedAlphabeticalContactKeys[(NSUInteger)section]; + } else { + return nil; + } +} + +- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section +{ + UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; + [header.textLabel setTextColor:[UIColor blackColor]]; + [header.textLabel setFont:[UIFont fontWithName:@"HelveticaNeue-Thin" size:14.0f]]; + +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + if (self.searchController.active) { + return 1; + } else { + return (NSInteger)[[latestAlphabeticalContacts allKeys] count]; + } +} + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView +{ + tableView.sectionIndexBackgroundColor = [UIColor clearColor]; + return latestSortedAlphabeticalContactKeys; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + ContactTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CONTACT_BROWSE_TABLE_CELL_IDENTIFIER]; + + if (!cell) { + cell = [[ContactTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:CONTACT_BROWSE_TABLE_CELL_IDENTIFIER]; + } + + + [cell configureWithContact:[self contactForIndexPath:indexPath]]; + + return cell; +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + [self performSegueWithIdentifier:@"DetailSegue" sender:self]; + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +-(Contact*)contactForIndexPath:(NSIndexPath*)indexPath +{ + Contact *contact = nil; + + if (self.searchController.active) { + contact = [searchResults objectAtIndex:(NSUInteger)indexPath.row]; + } else { + NSArray *contactSection = [self contactsForSectionIndex:(NSUInteger)indexPath.section]; + contact = contactSection[(NSUInteger)indexPath.row]; + } + + return contact; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return 44.0f; +} + +#pragma mark - Segue + +-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + if ([segue.identifier isEqualToString:@"DetailSegue"]) + { + Contact *contact = nil; + ContactDetailTableViewController * detailvc = [segue destinationViewController]; + NSIndexPath * indexPath = [self.tableView indexPathForSelectedRow]; + + if (self.searchController.active) { + contact = [searchResults objectAtIndex:(NSUInteger)indexPath.row]; + } else { + NSArray *contactSection = [self contactsForSectionIndex:(NSUInteger)indexPath.section]; + contact = contactSection[(NSUInteger)indexPath.row]; + } + detailvc.contact = contact; + } +} + +#pragma mark - IBAction + +-(IBAction)presentDialer:(id)sender +{ + + DialerViewController * dialer = [DialerViewController new]; + + UINavigationController *navigationController = [[UINavigationController alloc] + initWithRootViewController:dialer]; + navigationController.tabBarController.hidesBottomBarWhenPushed = NO; + + dialer.phoneNumber = nil; + + self.tabBarController.providesPresentationContextTransitionStyle = YES; + self.tabBarController.definesPresentationContext = YES; + [navigationController setModalPresentationStyle:UIModalPresentationOverCurrentContext]; + navigationController.hidesBottomBarWhenPushed = YES; + navigationController.navigationBarHidden=YES; + + [self.tabBarController presentViewController:navigationController animated:YES completion:^(){ + + }]; +} + +@end + diff --git a/Signal/src/view controllers/CountryCodeViewController.m b/Signal/src/view controllers/CountryCodeViewController.m index 1ab7635514..66cc9962b6 100644 --- a/Signal/src/view controllers/CountryCodeViewController.m +++ b/Signal/src/view controllers/CountryCodeViewController.m @@ -21,7 +21,7 @@ static NSString *const CONTRY_CODE_TABLE_CELL_IDENTIFIER = @"CountryCodeTableVie } - (UIStatusBarStyle)preferredStatusBarStyle { - return UIStatusBarStyleLightContent; + return UIStatusBarStyleDefault; } #pragma mark - Actions @@ -64,6 +64,11 @@ static NSString *const CONTRY_CODE_TABLE_CELL_IDENTIFIER = @"CountryCodeTableVie forCountry:countryName]; } +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return 44.0f; +} + #pragma mark - UISearchBarDelegate - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { @@ -71,4 +76,7 @@ static NSString *const CONTRY_CODE_TABLE_CELL_IDENTIFIER = @"CountryCodeTableVie [_countryCodeTableView reloadData]; } + + + @end diff --git a/Signal/src/view controllers/CountryCodeViewController.xib b/Signal/src/view controllers/CountryCodeViewController.xib index 3c2bd13890..7a1cb82362 100644 --- a/Signal/src/view controllers/CountryCodeViewController.xib +++ b/Signal/src/view controllers/CountryCodeViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -16,51 +17,68 @@ - + - - + - - - + - + - - - - + + + + + + + + + + + + + + + + + - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/DemoDataFactory.h b/Signal/src/view controllers/DemoDataFactory.h new file mode 100644 index 0000000000..36cbed6263 --- /dev/null +++ b/Signal/src/view controllers/DemoDataFactory.h @@ -0,0 +1,19 @@ +// +// DemoDataFactory.h +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "DemoDataModel.h" +#import + +@interface DemoDataFactory : NSObject + ++(NSArray*)data; ++(NSArray*)makeFakeContacts; ++(NSArray*)makeFakeCalls; + + +@end diff --git a/Signal/src/view controllers/DemoDataFactory.m b/Signal/src/view controllers/DemoDataFactory.m new file mode 100644 index 0000000000..91d6b36258 --- /dev/null +++ b/Signal/src/view controllers/DemoDataFactory.m @@ -0,0 +1,41 @@ +// +// DemoDataFactory.m +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "DemoDataFactory.h" + +@implementation DemoDataFactory + ++(NSArray*)data { + NSMutableArray* _mutableArray = [[NSMutableArray alloc]init]; + + for (NSUInteger i=0;i<5;i++) + [_mutableArray addObject:[DemoDataModel initModel:i]]; + + return (NSArray*)_mutableArray; +} + ++(NSArray*)makeFakeContacts +{ + NSMutableArray* _mutableArray = [[NSMutableArray alloc]init]; + + for (NSUInteger i=0;i<5;i++) + [_mutableArray addObject:[DemoDataModel initFakeContacts:i]]; + + return (NSArray*)_mutableArray; +} + ++(NSArray*)makeFakeCalls +{ + NSMutableArray* _mutableArray = [[NSMutableArray alloc]init]; + + for (NSUInteger i=0;i<5;i++) + [_mutableArray addObject:[DemoDataModel initRecentCall:i]]; + + return (NSArray*)_mutableArray; +} +@end diff --git a/Signal/src/view controllers/DemoDataModel.h b/Signal/src/view controllers/DemoDataModel.h new file mode 100644 index 0000000000..29c2cbcbab --- /dev/null +++ b/Signal/src/view controllers/DemoDataModel.h @@ -0,0 +1,48 @@ +// +// DemoDataModel.h +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + + +#import +#import +#import + +#import "JSQMessages.h" +#import "Contact.h" +#import "RecentCall.h" + +static NSString * const kJSQDemoAvatarDisplayNameDylan = @"Dylan Bourgeois"; +static NSString * const kJSQDemoAvatarDisplayNameFred = @"Frederic Jacobs"; +static NSString * const kJSQDemoAvatarDisplayNameMoxie = @"Moxie Marlinspike"; + +static NSString * const kJSQDemoAvatarIdDylan = @"053496-4509-289"; +static NSString * const kJSQDemoAvatarIdFred = @"468-768355-23123"; +static NSString * const kJSQDemoAvatarIdMoxie = @"707-8956784-57"; + +@interface DemoDataModel : NSObject + +@property (strong, nonatomic) NSMutableArray *messages; + +@property (strong, nonatomic) JSQMessagesBubbleImage *outgoingBubbleImageData; + +@property (strong, nonatomic) JSQMessagesBubbleImage *incomingBubbleImageData; + +@property (strong, nonatomic) NSDictionary *users; + + +@property (nonatomic, strong) NSString * _sender ; +@property (nonatomic, strong) NSString * _snippet ; +@property (nonatomic, strong) NSArray * _conversation; +@property (nonatomic, strong) NSString * lastActionString; + ++(DemoDataModel*)initModel:(NSUInteger)modelNumber; ++(Contact*)initFakeContacts:(NSUInteger)modelNumber; ++(RecentCall*)initRecentCall:(NSUInteger)modelNumber; + + + +@end diff --git a/Signal/src/view controllers/DemoDataModel.m b/Signal/src/view controllers/DemoDataModel.m new file mode 100644 index 0000000000..452f564aec --- /dev/null +++ b/Signal/src/view controllers/DemoDataModel.m @@ -0,0 +1,171 @@ +// +// DemoDataModel.m +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "DemoDataModel.h" +#import "Contact.h" +#import "RecentCall.h" +#import "PhoneNumber.h" + +enum {kDemoDataModelCase0, kDemoDataModelCase1,kDemoDataModelCase2, kDemoDataModelCase3, kDemoDataModelCase4}; + +@implementation DemoDataModel + +- (instancetype)init +{ + self = [super init]; + if (self) + { + [self loadFakeMessages]; + + JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init]; + + self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]]; + self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]]; + } + return self; +} + +- (void)loadFakeMessages +{ + /** + * Load some fake messages for demo. + * + * You should have a mutable array or orderedSet, or something. + */ + self.messages = [[NSMutableArray alloc] initWithObjects: + [[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdDylan + senderDisplayName:kJSQDemoAvatarDisplayNameDylan + date:[NSDate distantPast] + text:@"Welcome to JSQMessages: A messaging UI framework for iOS."], + + [[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdDylan + senderDisplayName:kJSQDemoAvatarDisplayNameDylan + date:[NSDate distantPast] + text:@"It even has data detectors. You can call me tonight. My cell number is 123-456-7890. My website is www.hexedbits.com."], + + [[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdMoxie + senderDisplayName:kJSQDemoAvatarDisplayNameMoxie + date:[NSDate date] + text:@"JSQMessagesViewController is nearly an exact replica of the iOS Messages App. And perhaps, better."], + + [[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdFred + senderDisplayName:kJSQDemoAvatarDisplayNameFred + date:[NSDate date] + text:@"It is unit-tested, free, open-source, and documented."], + + [[JSQTextMessage alloc] initWithSenderId:kJSQDemoAvatarIdDylan + senderDisplayName:kJSQDemoAvatarDisplayNameDylan + date:[NSDate date] + text:@"Now with media messages!"], + nil]; +} + + ++(DemoDataModel*)initModel:(NSUInteger)modelNumber +{ + DemoDataModel * _demoModel = [[DemoDataModel alloc] init]; + + switch (modelNumber) { + case kDemoDataModelCase0: + _demoModel._sender = @"Dylan Bourgeois"; + _demoModel._snippet = @"OpenSSL takes forever to build dude."; + _demoModel.lastActionString = @"unread"; + break; + case kDemoDataModelCase1: + _demoModel._sender = @"Frederic Jacobs"; + _demoModel._snippet = @"Bro, you're such an artist."; + _demoModel.lastActionString = @"replied"; + break; + case kDemoDataModelCase2: + _demoModel._sender = @"Romain Ruetschi"; + _demoModel._snippet = @"Missed Call"; + _demoModel.lastActionString = @"missedCall"; + break; + case kDemoDataModelCase3: + _demoModel._sender = @"Stephen Colbert"; + _demoModel._snippet = @"Outgoing Call"; + _demoModel.lastActionString = @"outgoingCall"; + break; + case kDemoDataModelCase4: + _demoModel._sender = @"Johnny Ramone"; + _demoModel._snippet = @"Rock on..."; + _demoModel.lastActionString = @"read"; + break; + + default: + break; + } + + + return _demoModel; +} + ++(Contact*)initFakeContacts:(NSUInteger)modelNumber +{ + Contact * _demoContact; + + switch (modelNumber) { + case kDemoDataModelCase0: + _demoContact = [Contact contactWithFirstName:@"Dylan" andLastName:@"Bourgeois" andUserTextPhoneNumbers:@[@"954-736-9230"] andEmails:nil andContactID:0]; + _demoContact.isRedPhoneContact = YES; + _demoContact.isTextSecureContact = YES; + break; + case kDemoDataModelCase1: + _demoContact = [Contact contactWithFirstName:@"Frederic" andLastName:@"Jacobs" andUserTextPhoneNumbers:@[@"954-736-9231"] andEmails:nil andContactID:0]; + _demoContact.isRedPhoneContact = YES; + _demoContact.isTextSecureContact = NO; + break; + case kDemoDataModelCase2: + _demoContact = [Contact contactWithFirstName:@"Romain" andLastName:@"Ruetschi" andUserTextPhoneNumbers:@[@"954-736-9233"] andEmails:nil andContactID:0]; + _demoContact.isRedPhoneContact = NO; + _demoContact.isTextSecureContact = NO; + break; + case kDemoDataModelCase3: + _demoContact = [Contact contactWithFirstName:@"Stephen" andLastName:@"Colbert" andUserTextPhoneNumbers:@[@"954-736-9232"] andEmails:nil andContactID:0]; + _demoContact.isRedPhoneContact = NO; + _demoContact.isTextSecureContact = YES; + break; + case kDemoDataModelCase4: + _demoContact = [Contact contactWithFirstName:@"Johnny" andLastName:@"Ramone" andUserTextPhoneNumbers:@[@"954-736-9221"] andEmails:nil andContactID:0]; + _demoContact.isRedPhoneContact = YES; + _demoContact.isTextSecureContact = YES; + break; + default: + break; + } + return _demoContact; +} + ++(RecentCall*)initRecentCall:(NSUInteger)modelNumber +{ + RecentCall * _demoCall; + + switch (modelNumber) { + case kDemoDataModelCase0: + _demoCall = [RecentCall recentCallWithContactID:0 andNumber:[PhoneNumber phoneNumberFromUserSpecifiedText:@"954-394-9043"] andCallType:RPRecentCallTypeMissed]; + break; + case kDemoDataModelCase1: + _demoCall = [RecentCall recentCallWithContactID:0 andNumber:[PhoneNumber phoneNumberFromUserSpecifiedText:@"954-304-9043"] andCallType:RPRecentCallTypeIncoming]; + break; + case kDemoDataModelCase2: + _demoCall = [RecentCall recentCallWithContactID:0 andNumber:[PhoneNumber phoneNumberFromUserSpecifiedText:@"954-124-9043"] andCallType:RPRecentCallTypeOutgoing]; + break; + case kDemoDataModelCase3: + _demoCall = [RecentCall recentCallWithContactID:0 andNumber:[PhoneNumber phoneNumberFromUserSpecifiedText:@"954-454-9043"] andCallType:RPRecentCallTypeIncoming]; + break; + case kDemoDataModelCase4: + _demoCall = [RecentCall recentCallWithContactID:0 andNumber:[PhoneNumber phoneNumberFromUserSpecifiedText:@"954-394-9043"] andCallType:RPRecentCallTypeIncoming]; + break; + + default: + break; + } + + return _demoCall; +} +@end diff --git a/Signal/src/view controllers/DialerViewController.m b/Signal/src/view controllers/DialerViewController.m index 00f7e63703..1dbee1a1dd 100644 --- a/Signal/src/view controllers/DialerViewController.m +++ b/Signal/src/view controllers/DialerViewController.m @@ -36,13 +36,20 @@ [self setupPasteBehaviour]; self.title = KEYPAD_NAV_BAR_TITLE; _currentNumberMutable = [NSMutableString string]; - [self updateNumberLabel]; + //[self updateNumberLabel]; [self.navigationController setNavigationBarHidden:YES animated:NO]; [_callButton setTitle:CALL_BUTTON_TITLE forState:UIControlStateNormal]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + UIBlurEffect * effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + UIVisualEffectView * viewWithBlurredBackground = + [[UIVisualEffectView alloc] initWithEffect:effect]; + viewWithBlurredBackground.frame = self.view.frame; + + [self.view insertSubview:viewWithBlurredBackground atIndex:0]; + if (_phoneNumber) { _currentNumberMutable = _phoneNumber.toE164.mutableCopy; [self updateNumberLabel]; @@ -111,6 +118,7 @@ } - (void)callButtonTapped { + PhoneNumber *phoneNumber = self.phoneNumberForCurrentInput; BOOL shouldTryCall = [Environment.getCurrent.phoneDirectoryManager.getCurrentFilter containsPhoneNumber:phoneNumber] || [Environment.getCurrent.recentCallManager isPhoneNumberPresentInRecentCalls:phoneNumber]; @@ -122,6 +130,12 @@ } } + +-(IBAction)cancelButtonTapped:(id)sender +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + -(void) initiateCallToPhoneNumber:(PhoneNumber*) phoneNumber { if (_contact) { [Environment.phoneManager initiateOutgoingCallToContact:_contact @@ -142,7 +156,9 @@ } - (void)updateNumberLabel { + //DEBUG!!! NSString* numberText = [_currentNumberMutable copy]; + _numberLabel.text = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:numberText]; PhoneNumber* number = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:numberText]; [self tryUpdateContactForNumber:number]; diff --git a/Signal/src/view controllers/FingerprintViewController.h b/Signal/src/view controllers/FingerprintViewController.h new file mode 100644 index 0000000000..308260fe0c --- /dev/null +++ b/Signal/src/view controllers/FingerprintViewController.h @@ -0,0 +1,26 @@ +// +// FingerprintViewController.h +// Signal +// +// Created by Dylan Bourgeois on 02/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface FingerprintViewController : UIViewController + +@property (nonatomic, strong) IBOutlet UILabel * presentationLabel; + +@property (nonatomic, strong) IBOutlet UIImageView * contactImageView; +@property (nonatomic, strong) IBOutlet UILabel * contactFingerprintTitleLabel; +@property (nonatomic, strong) IBOutlet UILabel * contactFingerprintLabel; + +@property (nonatomic, strong) IBOutlet UIImageView * userImageView; +@property (nonatomic, strong) IBOutlet UILabel * userFingerprintTitleLabel; +@property (nonatomic, strong) IBOutlet UILabel * userFingerprintLabel; + +@property (nonatomic, strong) IBOutlet UIButton * closeButton; +@property (nonatomic, strong) IBOutlet UIButton * shredMessagesAndContactButton; + +@end diff --git a/Signal/src/view controllers/FingerprintViewController.m b/Signal/src/view controllers/FingerprintViewController.m new file mode 100644 index 0000000000..2d9dc83e83 --- /dev/null +++ b/Signal/src/view controllers/FingerprintViewController.m @@ -0,0 +1,85 @@ +// +// FingerprintViewController.m +// Signal +// +// Created by Dylan Bourgeois on 02/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "FingerprintViewController.h" + +#import "DJWActionSheet.h" + +@interface FingerprintViewController () + +@end + +@implementation FingerprintViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self initializeImageViews]; + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Initializers +-(void)initializeImageViews +{ + _contactImageView.image = [UIImage imageNamed:@"DefaultContactImage"]; + _contactImageView.layer.cornerRadius = 75.f/2; + _contactImageView.layer.masksToBounds = YES; + _contactImageView.layer.borderWidth = 2.0f; + _contactImageView.layer.borderColor = [[UIColor whiteColor] CGColor]; + + _userImageView.image = [UIImage imageNamed:@"DefaultContactImage"]; + _userImageView.layer.cornerRadius = 75.f/2; + _userImageView.layer.masksToBounds = YES; + _userImageView.layer.borderWidth = 2.0f; + _userImageView.layer.borderColor = [[UIColor whiteColor] CGColor]; +} + +#pragma mark - Action +-(IBAction)closeButtonAction:(id)sender +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + +-(IBAction)shredAndDelete:(id)sender +{ + [DJWActionSheet showInView:self.view withTitle:@"Are you sure wou want to shred all communications with this contact ? This action is irreversible." + cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@[@"Shred all communications & delete contact"] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + [self shredAndDelete]; + } + }]; +} + +#pragma mark - Shredding & Deleting + +-(void)shredAndDelete +{ + +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Signal/src/view controllers/FullImageViewController.h b/Signal/src/view controllers/FullImageViewController.h new file mode 100644 index 0000000000..56ca57e8b4 --- /dev/null +++ b/Signal/src/view controllers/FullImageViewController.h @@ -0,0 +1,20 @@ +// +// FullImageViewController.h +// Signal +// +// Created by Dylan Bourgeois on 11/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface FullImageViewController : UIViewController + +@property(nonatomic, strong) IBOutlet UIImageView* fullImageView; +@property(nonatomic, strong) IBOutlet UIButton* saveButton; +@property(nonatomic, strong) IBOutlet UIButton* closeButton; + +@property(nonatomic, strong) UIImage* image; + + +@end diff --git a/Signal/src/view controllers/FullImageViewController.m b/Signal/src/view controllers/FullImageViewController.m new file mode 100644 index 0000000000..08fc2c3d50 --- /dev/null +++ b/Signal/src/view controllers/FullImageViewController.m @@ -0,0 +1,67 @@ +// +// FullImageViewController.m +// Signal +// +// Created by Dylan Bourgeois on 11/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "FullImageViewController.h" +#import "DJWActionSheet.h" + +@interface FullImageViewController () + +@end + +@implementation FullImageViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + _fullImageView.image = _image; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +#pragma mark - IBAction + +-(IBAction)close:(id)sender +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + +-(IBAction)more:(id)sender +{ + [DJWActionSheet showInView:self.view + withTitle:@"Options" + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@[@"Save to Camera Roll", @"Delete"] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + NSLog(@"The user tapped button at index: %li", (long)tappedButtonIndex); + } + }]; + +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Signal/src/view controllers/GroupModel.h b/Signal/src/view controllers/GroupModel.h new file mode 100644 index 0000000000..f91968bb00 --- /dev/null +++ b/Signal/src/view controllers/GroupModel.h @@ -0,0 +1,20 @@ +// +// GroupModel.h +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface GroupModel : NSObject + +@property (nonatomic, strong) NSMutableArray * groupMembers; +@property (nonatomic, strong) UIImage * groupImage; +@property (nonatomic, strong) NSString * groupName; + + +-(instancetype)initWithTitle:(NSString*)title members:(NSMutableArray*)members image:(UIImage*)image; + +@end diff --git a/Signal/src/view controllers/GroupModel.m b/Signal/src/view controllers/GroupModel.m new file mode 100644 index 0000000000..39234d9dfe --- /dev/null +++ b/Signal/src/view controllers/GroupModel.m @@ -0,0 +1,22 @@ +// +// GroupModel.m +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "GroupModel.h" + +@implementation GroupModel + +-(instancetype)initWithTitle:(NSString*)title members:(NSMutableArray*)members image:(UIImage*)image +{ + _groupName=title; + _groupMembers = [members copy]; + _groupImage = image; + + return self; +} + +@end diff --git a/Signal/src/view controllers/InCallViewController.m b/Signal/src/view controllers/InCallViewController.m index c878fc5f1a..42d88f7327 100644 --- a/Signal/src/view controllers/InCallViewController.m +++ b/Signal/src/view controllers/InCallViewController.m @@ -248,10 +248,15 @@ static NSInteger connectingFlashCounter = 0; - (void)muteButtonTapped { _muteButton.selected = [Environment.phoneManager toggleMute]; + + NSString* newImageName = _muteButton.selected ? @"mute_on" : @"mute_off"; + [_muteButton.imageView setImage:[UIImage imageNamed:newImageName]]; } - (void)speakerButtonTapped { _speakerButton.selected = [AppAudioManager.sharedInstance toggleSpeakerPhone]; + NSString* newImageName = _speakerButton.selected ? @"speaker_on" : @"speaker_off"; + [_speakerButton.imageView setImage:[UIImage imageNamed:newImageName]]; } - (void)answerButtonTapped { @@ -295,6 +300,9 @@ static NSInteger connectingFlashCounter = 0; } -(void) displayAcceptRejectButtons:(BOOL) enable{ + + //TODO: if NO, animate reject button -> end call button + _answerButton.hidden = !enable; _rejectButton.hidden = !enable; _endButton.hidden = enable; diff --git a/Signal/src/view controllers/InviteContactsViewController.xib b/Signal/src/view controllers/InviteContactsViewController.xib index cb59e16c9e..a710eaed4b 100644 --- a/Signal/src/view controllers/InviteContactsViewController.xib +++ b/Signal/src/view controllers/InviteContactsViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -19,7 +20,6 @@ - @@ -29,11 +29,9 @@ - - - - @@ -99,9 +91,7 @@ - - @@ -109,7 +99,6 @@ + + @@ -140,13 +130,14 @@ IFNpZ25hbCE + + @@ -155,4 +146,9 @@ IFNpZ25hbCE + + + + + diff --git a/Signal/src/view controllers/MessageComposeTableViewController.h b/Signal/src/view controllers/MessageComposeTableViewController.h new file mode 100644 index 0000000000..b5b2c7edf6 --- /dev/null +++ b/Signal/src/view controllers/MessageComposeTableViewController.h @@ -0,0 +1,24 @@ +// +// MessageComposeTableViewController.h +// +// +// Created by Dylan Bourgeois on 02/11/14. +// +// + +#import + +#import "DemoDataFactory.h" +#import "Contact.h" + +#import "JSQMessagesToolbarContentView.h" +#import "JSQMessagesInputToolbar.h" +#import "JSQMessagesComposerTextView.h" + +#import "JSQMessagesKeyboardController.h" + + +@interface MessageComposeTableViewController : UITableViewController + + +@end diff --git a/Signal/src/view controllers/MessageComposeTableViewController.m b/Signal/src/view controllers/MessageComposeTableViewController.m new file mode 100644 index 0000000000..0747945f32 --- /dev/null +++ b/Signal/src/view controllers/MessageComposeTableViewController.m @@ -0,0 +1,183 @@ +// +// MessageComposeTableViewController.m +// +// +// Created by Dylan Bourgeois on 02/11/14. +// +// + +#import "MessageComposeTableViewController.h" +#import "MessagesViewController.h" +#import "SignalsViewController.h" + +#import "ContactTableViewCell.h" + +@interface MessageComposeTableViewController () +{ + NSArray* contacts; + NSArray* searchResults; +} + +@property (nonatomic, strong) UISearchController *searchController; + +@end + +@implementation MessageComposeTableViewController + + + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self initializeSearch]; + + contacts = [DemoDataFactory makeFakeContacts]; + searchResults = contacts; + + self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +#pragma mark - Initializers + +-(void)initializeSearch +{ + self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; + + self.searchController.searchResultsUpdater = self; + + self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0); + + self.tableView.tableHeaderView = self.searchController.searchBar; + + self.searchController.dimsBackgroundDuringPresentation = NO; + self.searchController.hidesNavigationBarDuringPresentation = NO; + + self.definesPresentationContext = YES; + + self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal; + +} + +#pragma mark - UISearchResultsUpdating + +-(void)updateSearchResultsForSearchController:(UISearchController *)searchController { + + NSString *searchString = [self.searchController.searchBar text]; + + [self filterContentForSearchText:searchString scope:nil]; + + [self.tableView reloadData]; +} + + +#pragma mark - UISearchBarDelegate + +- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope { + [self updateSearchResultsForSearchController:self.searchController]; +} + + +#pragma mark - Filter + +- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope +{ + NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"fullName contains[c] %@", searchText]; + searchResults = [contacts filteredArrayUsingPredicate:resultPredicate]; + if (!searchResults.count && _searchController.searchBar.text.length == 0) searchResults = contacts; +} + + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + + if (self.searchController.active) { + return (NSInteger)[searchResults count]; + } else { + return (NSInteger)[contacts count]; + } + +} + + +- (ContactTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + ContactTableViewCell *cell = (ContactTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"ContactTableViewCell"]; + + if (cell == nil) { + cell = [[ContactTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ContactTableViewCell"]; + } + + [cell configureWithContact:[self contactForIndexPath:indexPath]]; + + tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + + return cell; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return 44.0f; +} + +#pragma mark - Table View delegate + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + //HACK: This is horrible due to the view hierarchy, but gets the job done. Gets a reference to the SignalsVC so we can present the conversation from it. + + UITabBarController * tb = (UITabBarController*)self.parentViewController.presentingViewController; + UINavigationController* nav = (UINavigationController*)[tb.childViewControllers objectAtIndex:1]; + SignalsViewController* s = (SignalsViewController*)nav.topViewController; + + s.contactFromCompose = [self contactForIndexPath:indexPath]; + + [self.searchController dismissViewControllerAnimated:NO completion:nil]; + + [self dismissViewControllerAnimated:YES completion:^(){ + [s performSegueWithIdentifier:@"showSegue" sender:nil]; + }]; +} + + +-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + ContactTableViewCell * cell = (ContactTableViewCell*)[tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryNone; +} + +-(Contact*)contactForIndexPath:(NSIndexPath*)indexPath +{ + Contact *contact = nil; + + if (self.searchController.active) { + contact = [searchResults objectAtIndex:(NSUInteger)indexPath.row]; + } else { + contact = [contacts objectAtIndex:(NSUInteger)indexPath.row]; + } + + return contact; +} + + +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + +} + +-(IBAction)closeAction:(id)sender +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + + +@end diff --git a/Signal/src/view controllers/MessagesViewController.h b/Signal/src/view controllers/MessagesViewController.h new file mode 100644 index 0000000000..09fae497e5 --- /dev/null +++ b/Signal/src/view controllers/MessagesViewController.h @@ -0,0 +1,23 @@ +// +// MessagesViewController.h +// Signal +// +// Created by Dylan Bourgeois on 28/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "JSQMessagesViewController.h" +#import "JSQMessages.h" + +#import "DemoDataModel.h" + + +@interface MessagesViewController : JSQMessagesViewController +@property (strong, nonatomic) DemoDataModel *demoData; + +@property (strong, nonatomic) NSString* _senderTitleString; + +-(void)initWithGroup:(NSArray*)group; + + +@end diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m new file mode 100644 index 0000000000..4163496f00 --- /dev/null +++ b/Signal/src/view controllers/MessagesViewController.m @@ -0,0 +1,474 @@ +// +// MessagesViewController.m +// Signal +// +// Created by Dylan Bourgeois on 28/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "AppDelegate.h" + +#import "MessagesViewController.h" +#import "FullImageViewController.h" + +#import "DJWActionSheet.h" +#import +#import +#import + +typedef enum : NSUInteger { + kMediaTypePicture, + kMediaTypeVideo, +} kMediaTypes; + +@interface MessagesViewController () { + UIImage* tappedImage; + BOOL isGroupConversation; +} + +@end + +@implementation MessagesViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"lock.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showFingerprint)]; + + [self.collectionView.collectionViewLayout setMessageBubbleFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:16.0f]]; + + //DEBUG: + isGroupConversation = NO; + + self.title = self._senderTitleString; + + self.senderId = kJSQDemoAvatarIdDylan; + self.senderDisplayName = kJSQDemoAvatarDisplayNameDylan; + + self.demoData = [[DemoDataModel alloc] init]; + + self.automaticallyScrollsToMostRecentMessage = YES; + + self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero; + self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero; + + if (!isGroupConversation) + { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; + } + +} + +- (void)didPressBack{ + [self dismissViewControllerAnimated:YES completion:^{ + [self.navigationController.parentViewController.presentingViewController.navigationController pushViewController:self animated:NO]; + }]; +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +-(void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; +} + +-(void)initWithGroup:(NSArray *)group +{ + //Search for an existing group to set self.title & fetch messages for this identifier + //If none found, instantiate new group +} + +#pragma mark - Keyboard Handlers + +-(void)keyboardWillShow:(id)sender +{ + [self.inputToolbar.contentView setRightBarButtonItem:[JSQMessagesToolbarButtonFactory defaultSendButtonItem]]; +} + +-(void)keyboardWillHide:(id)sender +{ + [self.inputToolbar.contentView setRightBarButtonItem:[JSQMessagesToolbarButtonFactory signalCallButtonItem]]; +} + +#pragma mark - Fingerprints + +-(void)showFingerprint +{ + [self performSegueWithIdentifier:@"fingerprintSegue" sender:self]; +} + +#pragma mark - JSQMessage custom methods + +-(void)updateMessageStatus:(JSQMessage*)message { + if ([message.senderId isEqualToString:self.senderId]) + message.status = kMessageReceived; +} + +#pragma mark - JSQMessagesViewController method overrides + +- (void)didPressSendButton:(UIButton *)button + withMessageText:(NSString *)text + senderId:(NSString *)senderId + senderDisplayName:(NSString *)senderDisplayName + date:(NSDate *)date +{ + if ([button.titleLabel.text isEqualToString:@"Call"]) + { + NSLog(@"Let's call !"); + + } else if (text.length > 0) { + [JSQSystemSoundPlayer jsq_playMessageSentSound]; + + JSQTextMessage *message = [[JSQTextMessage alloc] initWithSenderId:senderId + senderDisplayName:senderDisplayName + date:date + text:text]; + + [self.demoData.messages addObject:message]; + [self finishSendingMessage]; + } +} + + +#pragma mark - JSQMessages CollectionView DataSource + +- (id)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath +{ + return [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; +} + +- (id)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath +{ + + JSQMessage *message = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + + if ([message.senderId isEqualToString:self.senderId]) { + return self.demoData.outgoingBubbleImageData; + } + + return self.demoData.incomingBubbleImageData; +} + +- (id)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath +{ + return nil; +} + +- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath +{ + /** + * This logic should be consistent with what you return from `heightForCellTopLabelAtIndexPath:` + * The other label text delegate methods should follow a similar pattern. + * + * Show a timestamp for every 3rd message + */ + if (indexPath.item % 3 == 0) { + JSQMessage *message = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date]; + } + + return nil; +} + +- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath +{ + JSQMessage *message = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + + + /** + * iOS7-style sender name labels + */ + if ([message.senderId isEqualToString:self.senderId]) { + [self updateMessageStatus:message]; + return nil; + } + + if (indexPath.item - 1 > 0) { + JSQMessage *previousMessage = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item - 1]; + if ([[previousMessage senderId] isEqualToString:message.senderId]) { + return nil; + } + } + + /** + * Don't specify attributes to use the defaults. + */ + return [[NSAttributedString alloc] initWithString:message.senderDisplayName]; +} + +- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath +{ + JSQMessage * message = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + + if (message.status == kMessageRead){ + return [[NSAttributedString alloc]initWithString:@"Read" attributes:nil]; + } else if (message.status == kMessageSent) { + return [[NSAttributedString alloc]initWithString:@"Sent" attributes:nil]; + } else if (message.status == kMessageReceived) { + return [[NSAttributedString alloc]initWithString:@"Received" attributes:nil]; + } else { + return nil; + } +} + +#pragma mark - UICollectionView DataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +{ + return (NSInteger)[self.demoData.messages count]; +} + +- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath +{ + /** + * Override point for customizing cells + */ + JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath]; + + + JSQMessage *msg = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + + if ([msg isKindOfClass:[JSQTextMessage class]]) { + + if ([msg.senderId isEqualToString:self.senderId]) { + cell.textView.textColor = [UIColor whiteColor]; + } + else { + cell.textView.textColor = [UIColor blackColor]; + } + + cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor, + NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) }; + } + + return cell; +} + +#pragma mark - Adjusting cell label heights + +- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView + layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath +{ + /** + * Each label in a cell has a `height` delegate method that corresponds to its text dataSource method + */ + + /** + * This logic should be consistent with what you return from `attributedTextForCellTopLabelAtIndexPath:` + * The other label height delegate methods should follow similarly + * + * Show a timestamp for every 3rd message + */ + if (indexPath.item % 3 == 0) { + return kJSQMessagesCollectionViewCellLabelHeightDefault; + } + + return 0.0f; +} + +- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView + layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath +{ + /** + * iOS7-style sender name labels + */ + JSQMessage *currentMessage = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item]; + if ([[currentMessage senderId] isEqualToString:self.senderId]) { + return 0.0f; + } + + if (indexPath.item - 1 > 0) { + JSQMessage *previousMessage = [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item - 1]; + if ([[previousMessage senderId] isEqualToString:[currentMessage senderId]]) { + return 0.0f; + } + } + + return kJSQMessagesCollectionViewCellLabelHeightDefault; +} + +- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView + layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath +{ + return 16.0f; +} + + +#pragma mark - Actions + +-(void)didPressAccessoryButton:(UIButton *)sender +{ + [self.inputToolbar.contentView.textView resignFirstResponder]; + + UIView *presenter = self.parentViewController.view; + + [DJWActionSheet showInView:presenter + withTitle:nil + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@[@"Take Photo or Video", @"Choose existing Photo", @"Choose existing Video", @"Send file"] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + switch (tappedButtonIndex) { + case 0: + [self takePictureOrVideo]; + break; + case 1: + [self chooseFromLibrary:kMediaTypePicture]; + break; + case 2: + [self chooseFromLibrary:kMediaTypeVideo]; + break; + + default: + break; + } + } + }]; +} + +- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath +{ + id messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath]; + + BOOL isMediaMessage = [messageItem isMediaMessage]; + + if (isMediaMessage) { + id messageMedia = [messageItem media]; + + + if ([messageMedia isKindOfClass:JSQPhotoMediaItem.class]) { + //is a photo + tappedImage = ((JSQPhotoMediaItem*)messageMedia).image ; + [self performSegueWithIdentifier:@"fullImage" sender:self]; + + } else if ([messageMedia isKindOfClass:JSQVideoMediaItem.class]) { + //is a video + } + + } + +} + +#pragma mark - Navigation + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + if ([segue.identifier isEqualToString:@"fullImage"]) + { + FullImageViewController* dest = [segue destinationViewController]; + dest.image = tappedImage; + + } +} + + +#pragma mark - UIImagePickerController + +/* + * Presenting UIImagePickerController + */ + +- (void)takePictureOrVideo +{ + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; + picker.delegate = self; + picker.allowsEditing = NO; + picker.sourceType = UIImagePickerControllerSourceTypeCamera; + + if ([UIImagePickerController isSourceTypeAvailable: + UIImagePickerControllerSourceTypeCamera]) + { + picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *)kUTTypeMovie, kUTTypeImage, kUTTypeVideo, nil]; + [self presentViewController:picker animated:YES completion:NULL]; + } + +} + +-(void)chooseFromLibrary:(kMediaTypes)mediaType +{ + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; + picker.delegate = self; + picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; + + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) + { + NSArray* pictureTypeArray = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil]; + + NSArray* videoTypeArray = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeMovie, (NSString*)kUTTypeVideo, nil]; + + picker.mediaTypes = (mediaType == kMediaTypePicture) ? pictureTypeArray : videoTypeArray; + + [self presentViewController:picker animated:YES completion:nil]; + } +} + +/* + * Dismissing UIImagePickerController + */ + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +/* + * Fetch data from UIImagePickerController + */ +-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info +{ + UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage]; + + NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType]; + + if (CFStringCompare ((__bridge_retained CFStringRef)mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) { + //Is a video + + NSURL* videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; + AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:videoURL options:nil]; + //Create a snapshot image + //NOTE: Might not be necessary as JSQMessages might do this automtically + AVAssetImageGenerator *generate1 = [[AVAssetImageGenerator alloc] initWithAsset:asset1]; + generate1.appliesPreferredTrackTransform = YES; + NSError *err = NULL; + CMTime time = CMTimeMake(2, 1); + CGImageRef snapshotRef = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err]; + UIImage *snapshot = [[UIImage alloc] initWithCGImage:snapshotRef]; + + JSQVideoMediaItem * videoItem = [[JSQVideoMediaItem alloc] initWithFileURL:videoURL isReadyToPlay:YES]; + JSQMediaMessage * videoMessage = [JSQMediaMessage messageWithSenderId:kJSQDemoAvatarIdDylan + displayName:kJSQDemoAvatarDisplayNameDylan + media:videoItem]; + [self.demoData.messages addObject:videoMessage]; + [self finishSendingMessage]; + + } else if (picture_camera) { + //Is a photo + + JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:picture_camera]; + JSQMediaMessage *photoMessage = [JSQMediaMessage messageWithSenderId:kJSQDemoAvatarIdDylan + displayName:kJSQDemoAvatarDisplayNameDylan + media:photoItem]; + [self.demoData.messages addObject:photoMessage]; + [self finishSendingMessage]; + + } + + [self dismissViewControllerAnimated:YES completion:nil]; + +} +@end diff --git a/Signal/src/view controllers/NewGroupViewController.h b/Signal/src/view controllers/NewGroupViewController.h new file mode 100644 index 0000000000..fa24c5dc1e --- /dev/null +++ b/Signal/src/view controllers/NewGroupViewController.h @@ -0,0 +1,19 @@ +// +// NewGroupViewController.h +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface NewGroupViewController : UIViewController + +@property(nonatomic, strong) IBOutlet UITableView* tableView; + +@property(nonatomic, strong) IBOutlet UITextField* nameGroupTextField; +@property(nonatomic, strong) IBOutlet UIButton* groupImageButton; +@property(nonatomic, strong) IBOutlet UIView* tapToDismissView; + +@end diff --git a/Signal/src/view controllers/NewGroupViewController.m b/Signal/src/view controllers/NewGroupViewController.m new file mode 100644 index 0000000000..77a73d992a --- /dev/null +++ b/Signal/src/view controllers/NewGroupViewController.m @@ -0,0 +1,250 @@ +// +// NewGroupViewController.m +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "NewGroupViewController.h" +#import "SignalsViewController.h" + +#import "Contact.h" +#import "DemoDataFactory.h" +#import "GroupModel.h" + +#import "DJWActionSheet.h" +#import +#import +#import + +@interface NewGroupViewController () { + NSArray* contacts; +} + +@end + +@implementation NewGroupViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"Create" style:UIBarButtonItemStylePlain target:self action:@selector(createGroup)]; + self.navigationItem.title = @"New Group"; + + contacts = [DemoDataFactory makeFakeContacts]; + + [self initializeDelegates]; + [self initializeTableView]; + [self initializeKeyboardHandlers]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Initializers + +-(void)initializeDelegates +{ + self.nameGroupTextField.delegate = self; +} + +-(void)initializeTableView +{ + self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +} + +#pragma mark - Keyboard notifications + +- (void)initializeKeyboardHandlers{ + UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; + [self.tapToDismissView addGestureRecognizer:outsideTabRecognizer]; +} + +-(void) dismissKeyboardFromAppropriateSubView { + [self.nameGroupTextField resignFirstResponder]; +} + + + +#pragma mark - Actions +-(void)createGroup { + SignalsViewController* s = (SignalsViewController*)((UINavigationController*)[((UITabBarController*)self.parentViewController.presentingViewController).childViewControllers objectAtIndex:1]).topViewController; + + s.groupFromCompose = [self makeGroup]; + + [self dismissViewControllerAnimated:YES completion:^(){ + [s performSegueWithIdentifier:@"showSegue" sender:nil]; + }]; +} + +-(GroupModel*)makeGroup { + + //TODO: Add it to Envirronment + + NSString* title = _nameGroupTextField.text; + UIImage* img = _groupImageButton.imageView.image; + NSMutableArray* mut = [[NSMutableArray alloc]init]; + + for (NSIndexPath* idx in _tableView.indexPathsForSelectedRows) { + [mut addObject:[contacts objectAtIndex:(NSUInteger)idx.row-1]]; + } + + return [[GroupModel alloc] initWithTitle:title members:mut image:img]; +} + +-(IBAction)addGroupPhoto:(id)sender +{ + [DJWActionSheet showInView:self.parentViewController.view withTitle:nil cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil otherButtonTitles:@[@"Take a Picture",@"Choose from Library"] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + switch (tappedButtonIndex) { + case 0: + [self takePicture]; + break; + case 1: + [self chooseFromLibrary]; + break; + default: + break; + } + } + }]; +} + +#pragma mark - Group Image + +-(void)takePicture +{ + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; + picker.delegate = self; + picker.allowsEditing = NO; + picker.sourceType = UIImagePickerControllerSourceTypeCamera; + + if ([UIImagePickerController isSourceTypeAvailable: + UIImagePickerControllerSourceTypeCamera]) + { + picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *)kUTTypeImage, nil]; + [self presentViewController:picker animated:YES completion:NULL]; + } + +} + +-(void)chooseFromLibrary +{ + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; + picker.delegate = self; + picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; + + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) + { + picker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil]; + [self presentViewController:picker animated:YES completion:nil]; + } + +} + +/* + * Dismissing UIImagePickerController + */ + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +/* + * Fetch data from UIImagePickerController + */ +-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info +{ + UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage]; + + if (picture_camera) { + //There is a photo + _groupImageButton.imageView.image = picture_camera; + _groupImageButton.imageView.layer.cornerRadius = 40.0f; + _groupImageButton.imageView.clipsToBounds = YES; + + } + + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return (NSInteger)[contacts count]+1; + +} + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell"]; + + if (cell == nil) { + + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: indexPath.row == 0 ? @"HeaderCell" : @"GroupSearchCell"]; + } + + if (indexPath.row > 0) { + NSUInteger row = (NSUInteger)indexPath.row; + Contact* contact = contacts[row-1]; + + cell.textLabel.text = contact.fullName; + + } else { + cell.textLabel.text = @"Add People:"; + cell.textLabel.textColor = [UIColor lightGrayColor]; + } + + tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + + return cell; +} + +#pragma mark - Table View delegate +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryCheckmark; + +} + + +-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryNone; +} + +#pragma mark - Text Field Delegate + +- (BOOL)textFieldShouldReturn:(UITextField *)textField{ + [self.nameGroupTextField resignFirstResponder]; + return NO; +} + + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Signal/src/view controllers/PreferenceListViewController.xib b/Signal/src/view controllers/PreferenceListViewController.xib index 4be5a1cb4e..9ec7d7b028 100644 --- a/Signal/src/view controllers/PreferenceListViewController.xib +++ b/Signal/src/view controllers/PreferenceListViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -17,7 +18,6 @@ - @@ -26,8 +26,11 @@ - - - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/RegistrationViewController.h b/Signal/src/view controllers/RegistrationViewController.h new file mode 100644 index 0000000000..9f01958ec7 --- /dev/null +++ b/Signal/src/view controllers/RegistrationViewController.h @@ -0,0 +1,25 @@ +// +// RegistrationViewController.h +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import +#import "CountryCodeViewController.h" + + +@interface RegistrationViewController : UIViewController + +// Country code +@property(nonatomic, strong) IBOutlet UIButton* countryCodeButton; +@property(nonatomic, strong) IBOutlet UILabel* countryNameLabel; +@property(nonatomic, strong) IBOutlet UILabel* countryCodeLabel; + +//Phone number +@property(nonatomic, strong) IBOutlet UITextField* phoneNumberTextField; + + + +@end diff --git a/Signal/src/view controllers/RegistrationViewController.m b/Signal/src/view controllers/RegistrationViewController.m new file mode 100644 index 0000000000..f9f82c2803 --- /dev/null +++ b/Signal/src/view controllers/RegistrationViewController.m @@ -0,0 +1,222 @@ +// +// RegistrationViewController.m +// Signal +// +// Created by Dylan Bourgeois on 13/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "RegistrationViewController.h" + + +#import "Environment.h" +#import "LocalizableText.h" +#import "NBAsYouTypeFormatter.h" +#import "PhoneNumber.h" +#import "PhoneNumberDirectoryFilterManager.h" +#import "PhoneNumberUtil.h" +#import "PreferencesUtil.h" +#import "PushManager.h" +#import "RPServerRequestsManager.h" +#import "SignalUtil.h" +#import "SGNKeychainUtil.h" +#import "ThreadManager.h" +#import "Util.h" + +#import + +#define kKeyboardPadding 10.0f + + +@interface RegistrationViewController () + +@end + +@implementation RegistrationViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + [self populateDefaultCountryNameAndCode]; + [self initializeKeyboardHandlers]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +#pragma mark - Locale + +- (void)populateDefaultCountryNameAndCode { + NSLocale *locale = NSLocale.currentLocale; + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + NSNumber *cc = [NBPhoneNumberUtil.sharedInstance getCountryCodeForRegion:countryCode]; + + _countryCodeLabel.text = [NSString stringWithFormat:@"%@%@",COUNTRY_CODE_PREFIX, cc]; + //_countryNameLabel.text = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; + _countryNameLabel.text = @"United States"; +} + + +#pragma mark - Actions + +- (IBAction)sendCodeAction:(id)sender { + NSString *phoneNumber = [NSString stringWithFormat:@"%@%@", _countryCodeLabel.text, _phoneNumberTextField.text]; + PhoneNumber* localNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber]; + if(localNumber==nil){ return; } + + [_phoneNumberTextField resignFirstResponder]; + + // perform RPServerRequest here + + +} + +- (IBAction)changeCountryCodeTapped { + CountryCodeViewController *countryCodeController = [CountryCodeViewController new]; + countryCodeController.delegate = self; + [self presentViewController:countryCodeController animated:YES completion:nil]; +} + +- (void)presentInvalidCountryCodeError { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:REGISTER_CC_ERR_ALERT_VIEW_TITLE + message:REGISTER_CC_ERR_ALERT_VIEW_MESSAGE + delegate:nil + cancelButtonTitle:REGISTER_CC_ERR_ALERT_VIEW_DISMISS + otherButtonTitles:nil]; + [alertView show]; +} + +#pragma mark - Keyboard notifications + +- (void)initializeKeyboardHandlers{ + UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; + [self.view addGestureRecognizer:outsideTabRecognizer]; + + [self observeKeyboardNotifications]; + +} + +-(void) dismissKeyboardFromAppropriateSubView { + [self.view endEditing:NO]; +} + +- (void)observeKeyboardNotifications { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; +} + +- (void)keyboardWillShow:(NSNotification *)notification { + double duration = [[notification userInfo][UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + [UIView animateWithDuration:duration animations:^{ + CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + self.view.frame = CGRectMake(CGRectGetMinX(self.view.frame), + CGRectGetMinY(self.view.frame)-keyboardSize.height+kKeyboardPadding, + CGRectGetWidth(self.view.frame), + CGRectGetHeight(self.view.frame)); + }]; +} + +- (void)keyboardWillHide:(NSNotification *)notification { + double duration = [[notification userInfo][UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + [UIView animateWithDuration:duration animations:^{ + CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + self.view.frame = CGRectMake(CGRectGetMinX(self.view.frame), + CGRectGetMinY(self.view.frame)+keyboardSize.height-kKeyboardPadding, + CGRectGetWidth(self.view.frame), + CGRectGetHeight(self.view.frame)); + }]; +} + + + +#pragma mark - CountryCodeViewControllerDelegate + +- (void)countryCodeViewController:(CountryCodeViewController *)vc + didSelectCountryCode:(NSString *)code + forCountry:(NSString *)country { + + //NOTE: It seems [PhoneNumberUtil countryNameFromCountryCode:] doesn't return the country at all. Will investigate. + _countryCodeLabel.text = code; + _countryNameLabel.text = country; + + // Reformat phone number + NSString* digits = _phoneNumberTextField.text.digitsOnly; + NSString* reformattedNumber = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:digits + withSpecifiedCountryCodeString:_countryCodeLabel.text]; + _phoneNumberTextField.text = reformattedNumber; + UITextPosition *pos = _phoneNumberTextField.endOfDocument; + [_phoneNumberTextField setSelectedTextRange:[_phoneNumberTextField textRangeFromPosition:pos toPosition:pos]]; + + // Done choosing country + [vc dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)countryCodeViewControllerDidCancel:(CountryCodeViewController *)vc { + [vc dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - UITextFieldDelegate + +-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + NSString* textBeforeChange = textField.text; + + // backspacing should skip over formatting characters + UITextPosition *posIfBackspace = [textField positionFromPosition:textField.beginningOfDocument + offset:(NSInteger)(range.location + range.length)]; + UITextRange *rangeIfBackspace = [textField textRangeFromPosition:posIfBackspace toPosition:posIfBackspace]; + bool isBackspace = string.length == 0 && range.length == 1 && [rangeIfBackspace isEqual:textField.selectedTextRange]; + if (isBackspace) { + NSString* digits = textBeforeChange.digitsOnly; + NSUInteger correspondingDeletePosition = [PhoneNumberUtil translateCursorPosition:range.location + range.length + from:textBeforeChange + to:digits + stickingRightward:true]; + if (correspondingDeletePosition > 0) { + textBeforeChange = digits; + range = NSMakeRange(correspondingDeletePosition - 1, 1); + } + } + + // make the proposed change + NSString* textAfterChange = [textBeforeChange withCharactersInRange:range replacedBy:string]; + NSUInteger cursorPositionAfterChange = range.location + string.length; + + // reformat the phone number, trying to keep the cursor beside the inserted or deleted digit + bool isJustDeletion = string.length == 0; + NSString* textAfterReformat = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange.digitsOnly + withSpecifiedCountryCodeString:_countryCodeLabel.text]; + NSUInteger cursorPositionAfterReformat = [PhoneNumberUtil translateCursorPosition:cursorPositionAfterChange + from:textAfterChange + to:textAfterReformat + stickingRightward:isJustDeletion]; + textField.text = textAfterReformat; + UITextPosition *pos = [textField positionFromPosition:textField.beginningOfDocument + offset:(NSInteger)cursorPositionAfterReformat]; + [textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]]; + + return NO; // inform our caller that we took care of performing the change +} + + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Signal/src/view controllers/SettingsTableViewCell.h b/Signal/src/view controllers/SettingsTableViewCell.h new file mode 100644 index 0000000000..eae4967418 --- /dev/null +++ b/Signal/src/view controllers/SettingsTableViewCell.h @@ -0,0 +1,21 @@ +// +// SettingsTableViewCell.h +// Signal +// +// Created by Dylan Bourgeois on 11/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface SettingsTableViewCell : UITableViewCell + +//Regular cell +@property(nonatomic, strong) IBOutlet UISwitch* toggle; +@property(nonatomic, strong) IBOutlet UILabel* state; + +//Header cell +@property(nonatomic, strong) IBOutlet UIImageView* profileImageView; +@property(nonatomic, strong) IBOutlet UIButton * changeProfileImageViewButton; + +@end diff --git a/Signal/src/view controllers/SettingsTableViewCell.m b/Signal/src/view controllers/SettingsTableViewCell.m new file mode 100644 index 0000000000..923dbf8b18 --- /dev/null +++ b/Signal/src/view controllers/SettingsTableViewCell.m @@ -0,0 +1,47 @@ +// +// SettingsTableViewCell.m +// Signal +// +// Created by Dylan Bourgeois on 11/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "SettingsTableViewCell.h" + +@implementation SettingsTableViewCell + +- (void)awakeFromNib { + // Initialization code + + [self.toggle addTarget:self action:@selector(toggleSetting:) forControlEvents:UIControlEventValueChanged]; + + [self.profileImageView.layer setCornerRadius:50.0f]; + [self.profileImageView.layer setMasksToBounds:YES]; + + [self.changeProfileImageViewButton addTarget:self action:@selector(changeImageView:) forControlEvents:UIControlEventTouchUpInside]; +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +#pragma mark - UISwitch + +-(void)toggleSetting:(id)sender +{ + if ([self.reuseIdentifier isEqualToString:@"hideContactImages"]) + { + self.state.text = self.toggle.isOn ? @"Yes" : @"No"; + } +} + +#pragma mark - Editing Profile +-(void)changeImageView:(id)sender +{ + NSLog(@"hi"); + +} + +@end diff --git a/Signal/src/view controllers/SettingsTableViewController.h b/Signal/src/view controllers/SettingsTableViewController.h new file mode 100644 index 0000000000..a81afb3c20 --- /dev/null +++ b/Signal/src/view controllers/SettingsTableViewController.h @@ -0,0 +1,13 @@ +// +// SettingsTableViewController.h +// Signal +// +// Created by Dylan Bourgeois on 03/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import + +@interface SettingsTableViewController : UITableViewController + +@end diff --git a/Signal/src/view controllers/SettingsTableViewController.m b/Signal/src/view controllers/SettingsTableViewController.m new file mode 100644 index 0000000000..4aced198b8 --- /dev/null +++ b/Signal/src/view controllers/SettingsTableViewController.m @@ -0,0 +1,131 @@ +// +// SettingsTableViewController.m +// Signal +// +// Created by Dylan Bourgeois on 03/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "SettingsTableViewController.h" +#import "DJWActionSheet.h" +#import "SettingsTableViewCell.h" + +#define kProfileCellHeight 180.0f +#define kStandardCellHeight 60.0f + +#define kNumberOfSections 2 + +#define kClearHistoryLogCellRow 4 +#define kSendDebugLogCellRow 6 + + +typedef enum { + kProfileRows = 1, + kSecurityRows = 7, +} kRowsForSection; + +typedef enum { + kProfileSection, + kSecuritySection, +} kSection; + +@interface SettingsTableViewController () + +@end + +@implementation SettingsTableViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return kNumberOfSections; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + + switch (section) { + case kProfileSection: + return kProfileRows; + break; + case kSecuritySection: + return kSecurityRows; + break; + default: + return 0; + break; + } +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + switch (indexPath.section) { + case kProfileSection: + return kProfileCellHeight; + break; + + default: + return kStandardCellHeight; + break; + } +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section==kSecuritySection) + { + switch (indexPath.row) { + case kClearHistoryLogCellRow: + { + //Present more info + [DJWActionSheet showInView:self.tabBarController.view + withTitle:@"Are you sure you want to delete all your history ? This action cannot be reverted." + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@[@"I'm sure."] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + NSLog(@"User Cancelled"); + + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + NSLog(@"Destructive button tapped"); + }else { + NSLog(@"The user tapped button at index: %li", (long)tappedButtonIndex); + } + }]; + + break; + } + + case kSendDebugLogCellRow: + //Send debug Log + break; + default: + break; + } + } + + else if (indexPath.section==kProfileSection) + { + //FIXME: self is to nil after this call o_x so can't show button + SettingsTableViewCell* profileCell = (SettingsTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath]; + profileCell.changeProfileImageViewButton.hidden = !profileCell.changeProfileImageViewButton.hidden; + profileCell.changeProfileImageViewButton.userInteractionEnabled = !profileCell.changeProfileImageViewButton.userInteractionEnabled; + NSLog(@"hello"); + + } +} + + + +@end diff --git a/Signal/src/view controllers/SignalsNavigationController.h b/Signal/src/view controllers/SignalsNavigationController.h new file mode 100644 index 0000000000..5d0063a8e4 --- /dev/null +++ b/Signal/src/view controllers/SignalsNavigationController.h @@ -0,0 +1,19 @@ +// +// SignalsNavigationController.h +// Signal +// +// Created by Dylan Bourgeois on 18/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import +#import "Socket.h" + +@interface SignalsNavigationController : UINavigationController + +@property (nonatomic, strong) Socket * socket; + +@property (nonatomic, strong) UIProgressView* socketStatusView; + + +@end diff --git a/Signal/src/view controllers/SignalsNavigationController.m b/Signal/src/view controllers/SignalsNavigationController.m new file mode 100644 index 0000000000..b8da37d690 --- /dev/null +++ b/Signal/src/view controllers/SignalsNavigationController.m @@ -0,0 +1,74 @@ +// +// SignalsNavigationController.m +// Signal +// +// Created by Dylan Bourgeois on 18/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "SignalsNavigationController.h" + +@interface SignalsNavigationController () + +@end + +@implementation SignalsNavigationController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + [self initializeSocketStatusBar]; + + _socket = [[Socket alloc]init]; + + [self initializeObserver]; + + _socket.status = kSocketStatusOpen; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +-(void)initializeSocketStatusBar +{ + _socketStatusView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault]; + + CGRect bar = self.navigationBar.frame; + _socketStatusView.frame = CGRectMake(0, bar.size.height-1.0f, self.view.frame.size.width, 1.0f); + _socketStatusView.progressTintColor = [UIColor greenColor]; + _socketStatusView.progress = 1.0f; + [self.navigationBar addSubview:_socketStatusView]; +} + +#pragma mark - Socket Status Notifications + +-(void)initializeObserver +{ + [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidOpen) name:SocketOpenedNotification object:nil]; + [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidClose) name:SocketClosedNotification object:nil]; + [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketIsConnecting) name:SocketConnectingNotification object:nil]; +} + +-(void)socketDidOpen +{ + _socketStatusView.progressTintColor = [UIColor greenColor]; +} + +-(void)socketDidClose +{ + _socketStatusView.progressTintColor = [UIColor redColor]; + +} + +-(void)socketIsConnecting +{ + _socketStatusView.progressTintColor = [UIColor yellowColor]; + +} + + + +@end diff --git a/Signal/src/view controllers/Socket.h b/Signal/src/view controllers/Socket.h new file mode 100644 index 0000000000..f0fed513dc --- /dev/null +++ b/Signal/src/view controllers/Socket.h @@ -0,0 +1,29 @@ +// +// Socket.h +// Signal +// +// Created by Dylan Bourgeois on 18/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +typedef enum : NSUInteger { + kSocketStatusOpen, + kSocketStatusClosed, + kSocketStatusConnecting, +} SocketStatus; + +static void *kSocketStatusObservationContext = &kSocketStatusObservationContext; + +extern NSString * const SocketOpenedNotification; +extern NSString * const SocketClosedNotification; +extern NSString * const SocketConnectingNotification; + + + +#import + +@interface Socket : NSObject + +@property (nonatomic) SocketStatus status; + +@end diff --git a/Signal/src/view controllers/Socket.m b/Signal/src/view controllers/Socket.m new file mode 100644 index 0000000000..a8718dd0df --- /dev/null +++ b/Signal/src/view controllers/Socket.m @@ -0,0 +1,52 @@ +// +// Socket.m +// Signal +// +// Created by Dylan Bourgeois on 18/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "Socket.h" + +NSString * const SocketOpenedNotification = @"SocketOpenedNotification"; +NSString * const SocketClosedNotification = @"SocketClosedNotification"; +NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; + +@implementation Socket + +-(instancetype)init +{ + if (self = [super init]) + { + _status = kSocketStatusConnecting; + [self addObserver:self forKeyPath:@"status" options:0 context:kSocketStatusObservationContext]; + } + return self; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + + if (context == kSocketStatusObservationContext) + { + switch (self.status) { + case kSocketStatusOpen: + [[NSNotificationCenter defaultCenter] postNotificationName:SocketOpenedNotification object:self]; + break; + case kSocketStatusClosed: + [[NSNotificationCenter defaultCenter] postNotificationName:SocketClosedNotification object:self]; + break; + case kSocketStatusConnecting: + [[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectingNotification object:self]; + break; + default: + break; + + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + + + +@end diff --git a/Signal/src/view controllers/TabBarParentViewController.xib b/Signal/src/view controllers/TabBarParentViewController.xib index f171108371..d74eeb275d 100644 --- a/Signal/src/view controllers/TabBarParentViewController.xib +++ b/Signal/src/view controllers/TabBarParentViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -24,7 +25,6 @@ - @@ -118,7 +113,6 @@ - @@ -152,8 +145,6 @@ - - @@ -164,4 +155,9 @@ - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/TableViewCell.h b/Signal/src/view controllers/TableViewCell.h new file mode 100644 index 0000000000..b8926d4b4a --- /dev/null +++ b/Signal/src/view controllers/TableViewCell.h @@ -0,0 +1,47 @@ +// +// TableViewCell.h +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import +#import "DemoDataModel.h" +#import "NextResponderScrollView.h" + +typedef enum : NSUInteger { + kArchiveState, + kInboxState, +} CellState; + +@class TableViewCell; +@protocol TableViewCellDelegate + +- (void)tableViewCellTappedDelete:(TableViewCell *)cell; +- (void)tableViewCellTappedArchive:(TableViewCell *)cell; + +@end + +@interface TableViewCell : UITableViewCell + + +@property (nonatomic, strong) IBOutlet UIImageView* lastActionImageView; +@property (nonatomic, strong) IBOutlet UILabel *nameLabel; +@property (nonatomic, strong) IBOutlet UILabel * snippetLabel; +@property (nonatomic, strong) IBOutlet UIImageView *contactPictureView; +@property (nonatomic, strong) IBOutlet UILabel *timeLabel; +@property (nonatomic, strong) IBOutlet NextResponderScrollView *scrollView; +@property (nonatomic, strong) IBOutlet UIView *contentContainerView; + +@property (nonatomic, strong) IBOutlet UIView *deleteView; +@property (nonatomic, strong) IBOutlet UIView *archiveView; +@property (nonatomic, strong) IBOutlet UIImageView *deleteImageView; +@property (nonatomic, strong) IBOutlet UIImageView *archiveImageView; +@property (nonatomic, assign) id delegate; + +-(void)configureWithTestMessage:(DemoDataModel*)testMessage; +-(void)configureForState:(CellState)state; +-(void)animateDisappear; + +@end diff --git a/Signal/src/view controllers/TableViewCell.m b/Signal/src/view controllers/TableViewCell.m new file mode 100644 index 0000000000..abcd14a611 --- /dev/null +++ b/Signal/src/view controllers/TableViewCell.m @@ -0,0 +1,181 @@ +// +// TableViewCell.m +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "TableViewCell.h" +#import "Util.h" + +#define ARCHIVE_IMAGE_VIEW_WIDTH 22.0f +#define DELETE_IMAGE_VIEW_WIDTH 19.0f +#define TIME_LABEL_SIZE 10 +#define DATE_LABEL_SIZE 13 + + +@implementation TableViewCell + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [NSBundle.mainBundle loadNibNamed:NSStringFromClass(self.class) + owner:self + options:nil][0]; + + + if (self) { + _scrollView.contentSize = CGSizeMake(CGRectGetWidth(_contentContainerView.bounds), + CGRectGetHeight(_scrollView.frame)); + + [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; + + _scrollView.contentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); + _deleteImageView.image = [_deleteImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + _archiveImageView.image = [_archiveImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + + + } + return self; +} + +- (NSString *)reuseIdentifier { + return NSStringFromClass(self.class); +} + +-(void)configureWithTestMessage:(DemoDataModel*)testMessage { + _nameLabel.text = testMessage._sender; + _snippetLabel.text = testMessage._snippet; + _contactPictureView.image = nil; + _timeLabel.attributedText = [self dateArrributedString:[NSDate date]]; + self.separatorInset = UIEdgeInsetsMake(0,_contactPictureView.frame.size.width*1.5f, 0, 0); + + [self setUpLastAction:testMessage.lastActionString]; + +} + +-(void)configureForState:(CellState)state +{ + switch (state) { + case kArchiveState: + _scrollView.userInteractionEnabled=NO; + break; + case kInboxState: + _scrollView.userInteractionEnabled=YES; + break; + + default: + break; + } +} + +-(void)setUpLastAction:(NSString*)lastAction { + + //TODO: Set up KVO + if ([lastAction isEqualToString:@"read"]) { + _lastActionImageView.image = [UIImage imageNamed:@"checkmark"]; + } else if ([lastAction isEqualToString:@"replied"]) { + _lastActionImageView.image = [UIImage imageNamed:@"reply"]; + } else if ([lastAction isEqualToString:@"missedCall"]) { + _lastActionImageView.image = [UIImage imageNamed:@"missed"]; + } else if ([lastAction isEqualToString:@"outgoingCall"]) { + _lastActionImageView.image = [UIImage imageNamed:@"received"]; + } else if ([lastAction isEqualToString:@"unread"]) { + _lastActionImageView.image = nil; + _snippetLabel.textColor = [UIColor blackColor]; + _nameLabel.font = [UIFont boldSystemFontOfSize:15]; + _timeLabel.textColor = [UIColor colorWithRed:0 green:91/255.f blue:1.0f alpha:1.0f]; + } + +} + +#pragma mark - Date formatting + +- (NSAttributedString *)dateArrributedString:(NSDate *)date { + + NSString *timeString = [[DateUtil timeFormatter] stringFromDate:date]; + + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:timeString]; + + [attributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor darkGrayColor] + range:NSMakeRange(0, timeString.length)]; + + + + [attributedString addAttribute:NSFontAttributeName + value:[UIUtil helveticaLightWithSize:TIME_LABEL_SIZE] + range:NSMakeRange(0, timeString.length)]; + + + return attributedString; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + if (_scrollView.contentOffset.x < 0) { + _archiveImageView.image = [UIImage imageNamed:@"blue-archive"]; + _archiveImageView.bounds = CGRectMake(_archiveImageView.bounds.origin.x, + _archiveImageView.bounds.origin.y, + ARCHIVE_IMAGE_VIEW_WIDTH, + _archiveImageView.bounds.size.height); + } else { + + double ratio = (_archiveView.frame.size.width/2.0f - _scrollView.contentOffset.x) / (_archiveView.frame.size.width/2.0f); + double newWidth = ARCHIVE_IMAGE_VIEW_WIDTH/2.0f + (ARCHIVE_IMAGE_VIEW_WIDTH * ratio)/2.0f; + _archiveImageView.bounds = CGRectMake(_archiveImageView.bounds.origin.x, + _archiveImageView.bounds.origin.y, + (CGFloat)newWidth, + _archiveImageView.bounds.size.height); + _archiveImageView.tintColor = UIColor.whiteColor; + + } + + if (scrollView.contentOffset.x > CGRectGetWidth(_archiveView.frame)*2) { + _deleteImageView.image = [UIImage imageNamed:@"red-delete"]; + _deleteImageView.bounds = CGRectMake(_deleteImageView.bounds.origin.x, + _deleteImageView.bounds.origin.y, + DELETE_IMAGE_VIEW_WIDTH, + _deleteImageView.bounds.size.height); + } else { + + double ratio = _scrollView.contentOffset.x / (CGRectGetWidth(_deleteView.frame)*2); + double newWidth = DELETE_IMAGE_VIEW_WIDTH/2.0f + (DELETE_IMAGE_VIEW_WIDTH * ratio)/2.0f; + + _deleteImageView.bounds = CGRectMake(_deleteImageView.bounds.origin.x, + _deleteImageView.bounds.origin.y, + (CGFloat)newWidth, + _deleteImageView.bounds.size.height); + _deleteImageView.tintColor = UIColor.whiteColor; + } +} + +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint *)targetContentOffset { + + if (_scrollView.contentOffset.x < 0) { + [_delegate tableViewCellTappedArchive:self]; + } else { + *targetContentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); + } + + if (scrollView.contentOffset.x > CGRectGetWidth(_archiveView.frame)*2) { + [_delegate tableViewCellTappedDelete:self]; + } else { + *targetContentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); + } +} + +#pragma mark - Animation + +-(void)animateDisappear +{ + [UIView animateWithDuration:1.0f animations:^(){ + self.alpha = 0; + }]; +} + + +@end diff --git a/Signal/src/view controllers/TableViewCell.xib b/Signal/src/view controllers/TableViewCell.xib new file mode 100644 index 0000000000..96a393ddcd --- /dev/null +++ b/Signal/src/view controllers/TableViewCell.xib @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Signal/src/view controllers/UITests/SignalsViewController.h b/Signal/src/view controllers/UITests/SignalsViewController.h new file mode 100644 index 0000000000..dd3e630da6 --- /dev/null +++ b/Signal/src/view controllers/UITests/SignalsViewController.h @@ -0,0 +1,25 @@ +// +// SignalsViewController.h +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#include "TableViewCell.h" +#import + +#import "GroupModel.h" + + +@interface SignalsViewController : UIViewController + +@property (nonatomic) Contact* contactFromCompose; +@property (nonatomic) GroupModel* groupFromCompose; + +@property (nonatomic,strong) IBOutlet UITableView* _tableView; + +@property (strong, nonatomic) IBOutlet UISegmentedControl * segmentedControl; + + +@end diff --git a/Signal/src/view controllers/UITests/SignalsViewController.m b/Signal/src/view controllers/UITests/SignalsViewController.m new file mode 100644 index 0000000000..20ed4020dd --- /dev/null +++ b/Signal/src/view controllers/UITests/SignalsViewController.m @@ -0,0 +1,157 @@ +// +// SignalsViewController.m +// Signal +// +// Created by Dylan Bourgeois on 27/10/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import "AppDelegate.h" +#import "DemoDataFactory.h" +#import "TableViewCell.h" + +#import "MessagesViewController.h" +#import "SignalsViewController.h" + + +#define CELL_HEIGHT 71.0f +#define HEADER_HEIGHT 44.0f + + +static NSString *const kCellNibName = @"TableViewCell"; +static NSString *const kSegueIndentifier = @"showSegue"; + + +@interface SignalsViewController () { + NSArray * _dataArray; + NSUInteger numberOfCells; + +} +@property (strong, nonatomic) DemoDataModel *demoData; + +@end + +@implementation SignalsViewController + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + + if (self) { + AppDelegate *delegate = [[UIApplication sharedApplication] delegate]; + delegate.signalVC = self; + } + + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _dataArray = [DemoDataFactory data]; + numberOfCells = _dataArray.count; + [self tableViewSetUp]; + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + + +-(void)tableViewSetUp +{ + self._tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; +} + + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return (NSInteger)numberOfCells; +} + + - (TableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + return [self inboxFeedCellForIndexPath:indexPath]; + } + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return CELL_HEIGHT; +} + +-(TableViewCell*)inboxFeedCellForIndexPath:(NSIndexPath *)indexPath { + + TableViewCell *cell = [self._tableView dequeueReusableCellWithIdentifier:kCellNibName]; + + + if (!cell) { + cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:kCellNibName]; + cell.delegate = self; + } + + DemoDataModel *recent = _dataArray[(NSUInteger)indexPath.row]; + [cell configureWithTestMessage:recent]; + [cell configureForState:_segmentedControl.selectedSegmentIndex == 0 ? kInboxState : kArchiveState]; + return cell; + +} + + +#pragma mark - HomeFeedTableViewCellDelegate + +- (void)tableViewCellTappedDelete:(TableViewCell *)cell { + NSLog(@"Delete"); +} + +- (void)tableViewCellTappedArchive:(TableViewCell *)cell { + NSLog(@"Archive"); +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + [self performSegueWithIdentifier:kSegueIndentifier sender:self]; + [tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + + + +#pragma mark - Navigation + +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + + if ([segue.identifier isEqualToString:kSegueIndentifier]) + { + MessagesViewController * vc = [segue destinationViewController]; + NSIndexPath *selectedIndexPath = [self._tableView indexPathForSelectedRow]; + if (selectedIndexPath) { + vc._senderTitleString = ((DemoDataModel*)_dataArray[(NSUInteger)selectedIndexPath.row])._sender; + } else if (_contactFromCompose) { + vc._senderTitleString = _contactFromCompose.fullName; + } else if (_groupFromCompose) { + vc._senderTitleString = _groupFromCompose.groupName; + } + + } +} + +#pragma mark - IBAction + +-(IBAction)segmentDidChange:(id)sender +{ + switch (_segmentedControl.selectedSegmentIndex) { + case 0: + numberOfCells=5; + [self._tableView reloadData]; + break; + + case 1: + numberOfCells=3; + [self._tableView reloadData]; + break; + + } +} +@end diff --git a/Signal/src/view controllers/xibs/CallAudioManagerDemo.xib b/Signal/src/view controllers/xibs/CallAudioManagerDemo.xib index 34c71d7ddb..83a38f15e1 100644 --- a/Signal/src/view controllers/xibs/CallAudioManagerDemo.xib +++ b/Signal/src/view controllers/xibs/CallAudioManagerDemo.xib @@ -1,14 +1,14 @@ - 1552 - 12F37 - 3084 - 1187.39 - 626.00 + 1792 + 14A388a + 6250 + 1343.14 + 755.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 2083 + 6244 IBProxyObject @@ -34,7 +34,7 @@ IBCocoaTouchFramework - + 274 @@ -49,21 +49,21 @@ 0 0 1 - Answer - - 3 - MQA - 1 MCAwLjQ0ODMwNTg3NjQgMC4wMTQ0MjU2MDIyMQA + + 3 + MQA + + Answer 2 15 - - Helvetica-Bold + + HelveticaNeue-Bold 15 16 @@ -80,14 +80,14 @@ 0 0 1 - Reject - 1 MC40NDgzMDU4NzY0IDAuMDEwNTY4MjM3MjkgMAA + + Reject - + @@ -101,14 +101,14 @@ 0 0 1 - Force Register - 1 MC40NDgzMDU4NzY0IDAuMDEwNTY4MjM3MjkgMAA + + Force Register - + @@ -122,14 +122,14 @@ 0 0 1 - Call ... - 1 MCAwLjQ0ODMwNTg3NjQgMC4wMTQ0MjU2MDIyMQA + + Call ... - + @@ -143,14 +143,14 @@ 0 0 1 - Hangup - 1 MC41IDAgMAA + + Hangup - + @@ -195,8 +195,8 @@ 1 17 - - Helvetica + + HelveticaNeue 17 16 @@ -222,7 +222,7 @@ 10 0 - + NO 301 @@ -245,13 +245,12 @@ 10 0 - + NO 301 {{0, 20}, {320, 548}} - 3 @@ -263,6 +262,8 @@ IBUIScreenMetrics + IBCocoaTouchFramework + iPhone 4-inch YES @@ -274,15 +275,13 @@ {568, 320} - IBCocoaTouchFramework - Retina 4 Full Screen 2 IBCocoaTouchFramework - + view @@ -532,8 +531,12 @@ 0 IBCocoaTouchFramework + NO + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + YES 3 - 2083 diff --git a/Signal/src/view controllers/xibs/CallLogViewController.xib b/Signal/src/view controllers/xibs/CallLogViewController.xib index 8de772697b..53454745df 100644 --- a/Signal/src/view controllers/xibs/CallLogViewController.xib +++ b/Signal/src/view controllers/xibs/CallLogViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -94,8 +95,6 @@ - - @@ -103,4 +102,9 @@ - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/xibs/ContactBrowseViewController.xib b/Signal/src/view controllers/xibs/ContactBrowseViewController.xib index 03535e74fd..37f0f01e45 100644 --- a/Signal/src/view controllers/xibs/ContactBrowseViewController.xib +++ b/Signal/src/view controllers/xibs/ContactBrowseViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -134,9 +135,7 @@ IFdoaXNwZXIhA - - @@ -146,4 +145,9 @@ IFdoaXNwZXIhA - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/xibs/ContactDetailTableViewCell.xib b/Signal/src/view controllers/xibs/ContactDetailTableViewCell.xib index 39a34b132c..26a4595332 100644 --- a/Signal/src/view controllers/xibs/ContactDetailTableViewCell.xib +++ b/Signal/src/view controllers/xibs/ContactDetailTableViewCell.xib @@ -1,7 +1,8 @@ - + - + + @@ -14,7 +15,7 @@ - + @@ -39,4 +40,9 @@ - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/xibs/ContactDetailViewController.xib b/Signal/src/view controllers/xibs/ContactDetailViewController.xib index ecf90e18cd..6604aac53c 100644 --- a/Signal/src/view controllers/xibs/ContactDetailViewController.xib +++ b/Signal/src/view controllers/xibs/ContactDetailViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -20,7 +21,6 @@ - @@ -34,10 +34,8 @@ - - @@ -45,24 +43,28 @@ - - + + + + + + + diff --git a/Signal/src/view controllers/xibs/DialerViewController.xib b/Signal/src/view controllers/xibs/DialerViewController.xib index 25b199e030..5d8223569e 100644 --- a/Signal/src/view controllers/xibs/DialerViewController.xib +++ b/Signal/src/view controllers/xibs/DialerViewController.xib @@ -1,7 +1,7 @@ - + - + @@ -32,14 +32,13 @@ - - - - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - + - - + - - + - - + + - + @@ -858,13 +817,13 @@ - + - + @@ -874,6 +833,7 @@ + @@ -882,6 +842,7 @@ + @@ -897,12 +858,13 @@ + - + - + @@ -927,12 +889,17 @@ - - + + + + + + + diff --git a/Signal/src/view controllers/xibs/FavouritesViewController.xib b/Signal/src/view controllers/xibs/FavouritesViewController.xib index e0b12a25c0..95a0623dad 100644 --- a/Signal/src/view controllers/xibs/FavouritesViewController.xib +++ b/Signal/src/view controllers/xibs/FavouritesViewController.xib @@ -1,5 +1,5 @@ - + diff --git a/Signal/src/view controllers/xibs/InCallViewController.xib b/Signal/src/view controllers/xibs/InCallViewController.xib index 1fccd410bb..13b95d5864 100644 --- a/Signal/src/view controllers/xibs/InCallViewController.xib +++ b/Signal/src/view controllers/xibs/InCallViewController.xib @@ -1,287 +1,191 @@ - + - + - - - - - - - - - - - - - - + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - + + + + - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/xibs/InboxFeedViewController.xib b/Signal/src/view controllers/xibs/InboxFeedViewController.xib index d0e49ff4e7..052478c846 100644 --- a/Signal/src/view controllers/xibs/InboxFeedViewController.xib +++ b/Signal/src/view controllers/xibs/InboxFeedViewController.xib @@ -1,5 +1,5 @@ - + diff --git a/Signal/src/view controllers/xibs/LeftSideMenuViewController.xib b/Signal/src/view controllers/xibs/LeftSideMenuViewController.xib index 641741eecc..5ef38807c6 100644 --- a/Signal/src/view controllers/xibs/LeftSideMenuViewController.xib +++ b/Signal/src/view controllers/xibs/LeftSideMenuViewController.xib @@ -1,7 +1,8 @@ - + - + + @@ -19,7 +20,6 @@ - @@ -28,13 +28,13 @@ - - + + @@ -42,7 +42,6 @@ + + - \ No newline at end of file + + + + + + diff --git a/Signal/src/view controllers/xibs/RegisterViewController.xib b/Signal/src/view controllers/xibs/RegisterViewController.xib index 6d013eaf33..f4a8dea53f 100644 --- a/Signal/src/view controllers/xibs/RegisterViewController.xib +++ b/Signal/src/view controllers/xibs/RegisterViewController.xib @@ -1,8 +1,7 @@ - + - - + diff --git a/Signal/src/view controllers/xibs/SettingsViewController.xib b/Signal/src/view controllers/xibs/SettingsViewController.xib index 94df607e40..70211cd64f 100644 --- a/Signal/src/view controllers/xibs/SettingsViewController.xib +++ b/Signal/src/view controllers/xibs/SettingsViewController.xib @@ -1,7 +1,8 @@ - + - + + diff --git a/Signal/src/views/ContactTableViewCell.h b/Signal/src/views/ContactTableViewCell.h index b8f4a4a790..6c1f30b430 100644 --- a/Signal/src/views/ContactTableViewCell.h +++ b/Signal/src/views/ContactTableViewCell.h @@ -11,6 +11,8 @@ @property (nonatomic, strong) IBOutlet UILabel *nameLabel; @property (nonatomic, strong) IBOutlet UIImageView *contactPictureView; +@property (nonatomic, strong) IBOutlet UIButton *callButton ; +@property (nonatomic, strong) IBOutlet UIButton *messageButton; - (void)configureWithContact:(Contact *)contact; diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index a479e0ae5a..05b9c67f96 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -2,6 +2,12 @@ #define CONTACT_TABLE_CELL_BORDER_WIDTH 1.0f +@interface ContactTableViewCell() { + +} +@property(strong,nonatomic) Contact* associatedContact; +@end + @implementation ContactTableViewCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { @@ -17,6 +23,8 @@ - (void)configureWithContact:(Contact *)contact { + _associatedContact = contact; + _nameLabel.attributedText = [self attributedStringForContact:contact]; UIImage *image = contact.image; @@ -27,6 +35,21 @@ _contactPictureView.image = image; } else { _contactPictureView.image = nil; + [_contactPictureView addConstraint:[NSLayoutConstraint constraintWithItem:_contactPictureView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:0]]; + } + + if (contact.isRedPhoneContact) + { + _callButton.imageView.image = [UIImage imageNamed:@"call_dark"]; + } else { + [_callButton addConstraint:[NSLayoutConstraint constraintWithItem:_callButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:0]]; + } + + if (contact.isTextSecureContact) + { + _messageButton.imageView.image = [UIImage imageNamed:@"signal"]; + } else { + [_messageButton addConstraint:[NSLayoutConstraint constraintWithItem:_messageButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1.0f constant:0]]; } } @@ -42,11 +65,11 @@ UIFont *lastNameFont; if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { - firstNameFont = [UIFont boldSystemFontOfSize:_nameLabel.font.pointSize]; + firstNameFont = [UIFont fontWithName:@"HelveticaNeue-Light" size:_nameLabel.font.pointSize]; lastNameFont = [UIFont systemFontOfSize:_nameLabel.font.pointSize]; } else{ - firstNameFont = [UIFont systemFontOfSize:_nameLabel.font.pointSize]; - lastNameFont = [UIFont boldSystemFontOfSize:_nameLabel.font.pointSize]; + firstNameFont = [UIFont fontWithName:@"HelveticaNeue-Light" size:_nameLabel.font.pointSize]; + lastNameFont = [UIFont systemFontOfSize:_nameLabel.font.pointSize]; } [fullNameAttributedString addAttribute:NSFontAttributeName value:firstNameFont range:NSMakeRange(0, contact.firstName.length)]; [fullNameAttributedString addAttribute:NSFontAttributeName value:lastNameFont range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; @@ -55,4 +78,14 @@ return fullNameAttributedString; } +-(IBAction)callContact:(id)sender +{ + //Initiate Call to _associatedContact +} + +-(IBAction)messageContact:(id)sender +{ + //Load messages to _associatedContact +} + @end diff --git a/Signal/src/views/DialerButtonView.m b/Signal/src/views/DialerButtonView.m index 40f0355630..fb05893c8b 100644 --- a/Signal/src/views/DialerButtonView.m +++ b/Signal/src/views/DialerButtonView.m @@ -7,15 +7,17 @@ [super awakeFromNib]; _numberLabel.text = NSLocalizedString(_numberLocalizationKey, @""); _letterLabel.text = NSLocalizedString(_letterLocalizationKey, @""); - self.layer.cornerRadius = 4.0f; + + self.layer.cornerRadius = CGRectGetHeight(self.layer.frame)/2.0f; + self.layer.borderColor = [[UIUtil darkBackgroundColor] CGColor]; } - (void)setSelected:(BOOL)isSelected { if (isSelected) { - self.backgroundColor = [UIUtil transparentLightGrayColor]; - self.layer.borderWidth = 0.5f; + //self.backgroundColor = [UIUtil transparentLightGrayColor]; + //self.layer.borderWidth = 0.5f; } else { self.backgroundColor = [UIColor clearColor]; self.layer.borderWidth = 0.0f; diff --git a/Signal/src/views/InboxFeedFooterCell.xib b/Signal/src/views/InboxFeedFooterCell.xib index d7c76bb3a9..59abff1da6 100644 --- a/Signal/src/views/InboxFeedFooterCell.xib +++ b/Signal/src/views/InboxFeedFooterCell.xib @@ -1,7 +1,8 @@ - + - + + @@ -15,29 +16,24 @@ - - \ No newline at end of file + + + + + + diff --git a/Signal/src/views/InboxFeedTableViewCell.h b/Signal/src/views/InboxFeedTableViewCell.h index fcc76b0f5d..beb6a759ab 100644 --- a/Signal/src/views/InboxFeedTableViewCell.h +++ b/Signal/src/views/InboxFeedTableViewCell.h @@ -2,6 +2,7 @@ #import "RecentCall.h" #import "ContactsManager.h" #import "NextResponderScrollView.h" +#import "DemoDataModel.h" /** * @@ -34,6 +35,7 @@ @property (nonatomic, strong) IBOutlet UIImageView *archiveImageView; @property (nonatomic, assign) id delegate; -- (void)configureWithRecentCall:(RecentCall *)recentCall; +-(void)configureWithRecentCall:(RecentCall *)recentCall; +-(void)configureWithTestMessage:(DemoDataModel*)testMessage; @end diff --git a/Signal/src/views/InboxFeedTableViewCell.m b/Signal/src/views/InboxFeedTableViewCell.m index 768235bdaf..5d7a979abd 100644 --- a/Signal/src/views/InboxFeedTableViewCell.m +++ b/Signal/src/views/InboxFeedTableViewCell.m @@ -3,6 +3,7 @@ #import "Environment.h" #import "Util.h" + #define ARCHIVE_IMAGE_VIEW_WIDTH 22.0f #define DELETE_IMAGE_VIEW_WIDTH 19.0f #define TIME_LABEL_SIZE 10 @@ -36,6 +37,18 @@ return NSStringFromClass(self.class); } +-(void)configureWithTestMessage:(DemoDataModel*)testMessage { + _nameLabel.text = testMessage._sender; + _contactPictureView.image = nil; + + _callTypeImageView.image = [UIImage imageNamed:CALL_TYPE_IMAGE_NAME_OUTGOING]; + + _missedCallView.hidden = NO; + _numberLabel.text = @"123-456-7890"; + _timeLabel.attributedText = [[NSAttributedString alloc] initWithString:@"21:58"]; + +} + - (void)configureWithRecentCall:(RecentCall *)recentCall { Contact *contact = [Environment.getCurrent.contactsManager latestContactWithRecordId:recentCall.contactRecordID]; diff --git a/Signal/src/views/PreferenceListTableViewCell.xib b/Signal/src/views/PreferenceListTableViewCell.xib index 6afc60d1bd..45e84e4a73 100644 --- a/Signal/src/views/PreferenceListTableViewCell.xib +++ b/Signal/src/views/PreferenceListTableViewCell.xib @@ -1,7 +1,8 @@ - + - + + @@ -15,7 +16,6 @@ - \ No newline at end of file + + + + + + diff --git a/Signal/src/views/xibs/CallLogTableViewCell.xib b/Signal/src/views/xibs/CallLogTableViewCell.xib index b0d7bf40cc..68ddf1a751 100644 --- a/Signal/src/views/xibs/CallLogTableViewCell.xib +++ b/Signal/src/views/xibs/CallLogTableViewCell.xib @@ -1,8 +1,8 @@ - + - + diff --git a/Signal/src/views/xibs/ContactTableViewCell.xib b/Signal/src/views/xibs/ContactTableViewCell.xib index 3f64b0dc7f..33f4790399 100644 --- a/Signal/src/views/xibs/ContactTableViewCell.xib +++ b/Signal/src/views/xibs/ContactTableViewCell.xib @@ -1,8 +1,8 @@ - + - - + + @@ -14,28 +14,74 @@ - + + + + + + + + + + + + + + + + + + + - - - - - + + + + diff --git a/Signal/src/views/xibs/CountryCodeTableViewCell.xib b/Signal/src/views/xibs/CountryCodeTableViewCell.xib index 61754ac47f..d0764fd826 100644 --- a/Signal/src/views/xibs/CountryCodeTableViewCell.xib +++ b/Signal/src/views/xibs/CountryCodeTableViewCell.xib @@ -1,7 +1,8 @@ - + - + + @@ -13,21 +14,30 @@ - + + + + + + + + @@ -35,4 +45,9 @@ - \ No newline at end of file + + + + + + diff --git a/Signal/src/views/xibs/FavouriteTableViewCell.xib b/Signal/src/views/xibs/FavouriteTableViewCell.xib index d04e41ff2c..b56ae3302b 100644 --- a/Signal/src/views/xibs/FavouriteTableViewCell.xib +++ b/Signal/src/views/xibs/FavouriteTableViewCell.xib @@ -1,7 +1,8 @@ - + - + + @@ -15,18 +16,15 @@ -