Initial Message UI

This commit is contained in:
dtsbourg 2014-10-29 21:58:58 +01:00 committed by Frederic Jacobs
parent 7e555c6c20
commit a60bc8be92
121 changed files with 8048 additions and 559 deletions

View file

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

View file

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

View file

@ -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 = "<group>"; };
E1CD329418BCFF9900B1A496 /* SoundInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundInstance.h; sourceTree = "<group>"; };
E1CD329518BCFF9900B1A496 /* SoundInstance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SoundInstance.m; sourceTree = "<group>"; };
FC3196281A067D8F0094C78E /* MessageComposeTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageComposeTableViewController.h; sourceTree = "<group>"; };
FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessageComposeTableViewController.m; sourceTree = "<group>"; };
FC31962B1A06A2190094C78E /* FingerprintViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FingerprintViewController.h; sourceTree = "<group>"; };
FC31962C1A06A2190094C78E /* FingerprintViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FingerprintViewController.m; sourceTree = "<group>"; };
FC31962E1A0814130094C78E /* SettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewController.h; sourceTree = "<group>"; };
FC31962F1A0814130094C78E /* SettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewController.m; sourceTree = "<group>"; };
FC4F9FE41A16258C00DA100A /* logo_intro@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "logo_intro@2x.png"; sourceTree = "<group>"; };
FC4F9FEC1A1658EE00DA100A /* call@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call@2x.png"; sourceTree = "<group>"; };
FC4F9FEE1A1664EA00DA100A /* mute_off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_off@2x.png"; sourceTree = "<group>"; };
FC4F9FEF1A1664EA00DA100A /* speaker_off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "speaker_off@2x.png"; sourceTree = "<group>"; };
FC4F9FF01A1664EA00DA100A /* speaker_on@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "speaker_on@2x.png"; sourceTree = "<group>"; };
FC4F9FF11A1664EA00DA100A /* mute_on@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_on@2x.png"; sourceTree = "<group>"; };
FC4F9FF21A1664EA00DA100A /* endcall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "endcall@2x.png"; sourceTree = "<group>"; };
FC4F9FFC1A179FCF00DA100A /* lock@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock@2x.png"; sourceTree = "<group>"; };
FC4F9FFE1A17A39E00DA100A /* photo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "photo@2x.png"; sourceTree = "<group>"; };
FC4FA0061A18BDAE00DA100A /* info@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "info@2x.png"; sourceTree = "<group>"; };
FC4FA0081A18BF3100DA100A /* lock_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_white@2x.png"; sourceTree = "<group>"; };
FC4FA00C1A18CC4300DA100A /* shred@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "shred@2x.png"; sourceTree = "<group>"; };
FC4FA0131A1A180D00DA100A /* red-delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "red-delete@2x.png"; sourceTree = "<group>"; };
FC4FA0141A1A180D00DA100A /* delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delete@2x.png"; sourceTree = "<group>"; };
FC4FA0151A1A180D00DA100A /* archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "archive@2x.png"; sourceTree = "<group>"; };
FC4FA0161A1A180D00DA100A /* blue-archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "blue-archive@2x.png"; sourceTree = "<group>"; };
FC4FA0211A1B8A8D00DA100A /* Socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = "<group>"; };
FC4FA0221A1B8A8D00DA100A /* Socket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Socket.m; sourceTree = "<group>"; };
FC4FA0241A1B9DC600DA100A /* SignalsNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsNavigationController.h; sourceTree = "<group>"; };
FC4FA0251A1B9DC600DA100A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = "<group>"; };
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 = "<group>"; };
FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SignalsViewController.m; path = UITests/SignalsViewController.m; sourceTree = "<group>"; };
FCAC963D19FEF99A0046DFC5 /* TableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewCell.h; sourceTree = "<group>"; };
FCAC963E19FEF99A0046DFC5 /* TableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewCell.m; sourceTree = "<group>"; };
FCAC963F19FEF99A0046DFC5 /* TableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCell.xib; sourceTree = "<group>"; };
FCAC964219FEFD8B0046DFC5 /* DemoDataFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoDataFactory.h; sourceTree = "<group>"; };
FCAC964319FEFD8B0046DFC5 /* DemoDataFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoDataFactory.m; sourceTree = "<group>"; };
FCAC964519FEFE1A0046DFC5 /* DemoDataModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoDataModel.h; sourceTree = "<group>"; };
FCAC964619FEFE1A0046DFC5 /* DemoDataModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoDataModel.m; sourceTree = "<group>"; };
FCAC964F19FF0A6E0046DFC5 /* MessagesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagesViewController.h; sourceTree = "<group>"; };
FCAC965019FF0A6E0046DFC5 /* MessagesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessagesViewController.m; sourceTree = "<group>"; };
FCAFC2EB1A0C469C00AE5136 /* checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkmark.png; sourceTree = "<group>"; };
FCAFC2ED1A0C472200AE5136 /* reply.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reply.png; sourceTree = "<group>"; };
FCAFC2EF1A0C4ACF00AE5136 /* received.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = received.png; sourceTree = "<group>"; };
FCAFC2F01A0C4ACF00AE5136 /* missed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = missed.png; sourceTree = "<group>"; };
FCAFC3091A0C560E00AE5136 /* signals.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = signals.png; sourceTree = "<group>"; };
FCAFC30A1A0C560E00AE5136 /* settings.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = settings.png; sourceTree = "<group>"; };
FCAFC3201A0D394300AE5136 /* favourite.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = favourite.png; sourceTree = "<group>"; };
FCAFC3251A0D466F00AE5136 /* delete_history@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "delete_history@2x.png"; sourceTree = "<group>"; };
FCAFC3261A0D466F00AE5136 /* signal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "signal@2x.png"; sourceTree = "<group>"; };
FCAFC3271A0D466F00AE5136 /* call_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_dark@2x.png"; sourceTree = "<group>"; };
FCAFC32D1A0D46D500AE5136 /* settings_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings_dark@2x.png"; sourceTree = "<group>"; };
FCAFC32F1A0D5E3000AE5136 /* share@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "share@2x.png"; sourceTree = "<group>"; };
FCAFC3331A0D656100AE5136 /* contacts_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "contacts_tab@2x.png"; sourceTree = "<group>"; };
FCAFC3351A0D680100AE5136 /* keypad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keypad@2x.png"; sourceTree = "<group>"; };
FCAFC33D1A0F948F00AE5136 /* ActionContactDetailCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionContactDetailCell.h; sourceTree = "<group>"; };
FCAFC33E1A0F948F00AE5136 /* ActionContactDetailCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionContactDetailCell.m; sourceTree = "<group>"; };
FCB11D881A1284BB002F93FB /* SettingsTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewCell.h; sourceTree = "<group>"; };
FCB11D891A1284BB002F93FB /* SettingsTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewCell.m; sourceTree = "<group>"; };
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 = "<group>"; };
FCB11D8E1A12A388002F93FB /* quit@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "quit@2x.png"; sourceTree = "<group>"; };
FCB11D911A12A4AA002F93FB /* FullImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullImageViewController.h; sourceTree = "<group>"; };
FCB11D921A12A4AA002F93FB /* FullImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FullImageViewController.m; sourceTree = "<group>"; };
FCF72A061A01A765006BC849 /* ContactsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsTableViewController.h; sourceTree = "<group>"; };
FCF72A071A01A765006BC849 /* ContactsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsTableViewController.m; sourceTree = "<group>"; };
FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailTableViewController.m; sourceTree = "<group>"; };
FCF72A121A02D27F006BC849 /* ContactDetailTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailTableViewController.h; sourceTree = "<group>"; };
FCF72A141A02D2BB006BC849 /* ContactDetailCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailCell.h; sourceTree = "<group>"; };
FCF72A151A02D2BB006BC849 /* ContactDetailCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactDetailCell.m; sourceTree = "<group>"; };
FCFD256D1A151BCB00F4C644 /* NewGroupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewGroupViewController.h; sourceTree = "<group>"; };
FCFD256E1A151BCB00F4C644 /* NewGroupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewGroupViewController.m; sourceTree = "<group>"; };
FCFD25701A1524DB00F4C644 /* GroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupModel.h; sourceTree = "<group>"; };
FCFD25711A1524DB00F4C644 /* GroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupModel.m; sourceTree = "<group>"; };
FCFD257D1A154B2C00F4C644 /* RegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationViewController.h; sourceTree = "<group>"; };
FCFD257E1A154B2C00F4C644 /* RegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RegistrationViewController.m; sourceTree = "<group>"; };
FCFD25801A154B3800F4C644 /* CodeVerificationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeVerificationViewController.h; sourceTree = "<group>"; };
FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodeVerificationViewController.m; sourceTree = "<group>"; };
/* 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 = "<group>";
};
FC3196311A08141D0094C78E /* Settings */ = {
isa = PBXGroup;
children = (
FC31962E1A0814130094C78E /* SettingsTableViewController.h */,
FC31962F1A0814130094C78E /* SettingsTableViewController.m */,
);
name = Settings;
sourceTree = "<group>";
};
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 = "<group>";
};
FC3196331A0814360094C78E /* Contacts */ = {
isa = PBXGroup;
children = (
FCF72A121A02D27F006BC849 /* ContactDetailTableViewController.h */,
FCF72A111A02D27F006BC849 /* ContactDetailTableViewController.m */,
FCF72A061A01A765006BC849 /* ContactsTableViewController.h */,
FCF72A071A01A765006BC849 /* ContactsTableViewController.m */,
);
name = Contacts;
sourceTree = "<group>";
};
FCAC963919FEF8A00046DFC5 /* UI Tests */ = {
isa = PBXGroup;
children = (
FCAC964819FEFE210046DFC5 /* DemoData */,
FCAC964E19FF061C0046DFC5 /* ViewControllers */,
FCAC964D19FF06110046DFC5 /* Views */,
);
name = "UI Tests";
path = "view controllers";
sourceTree = "<group>";
};
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 = "<group>";
};
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 = "<group>";
};
FCAC964E19FF061C0046DFC5 /* ViewControllers */ = {
isa = PBXGroup;
children = (
FCFD25791A1543D500F4C644 /* Signup */,
FC3196321A08142D0094C78E /* Signals */,
FC3196331A0814360094C78E /* Contacts */,
FC3196311A08141D0094C78E /* Settings */,
);
name = ViewControllers;
sourceTree = "<group>";
};
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 = "<group>";
};
FCFD25791A1543D500F4C644 /* Signup */ = {
isa = PBXGroup;
children = (
FCFD257D1A154B2C00F4C644 /* RegistrationViewController.h */,
FCFD257E1A154B2C00F4C644 /* RegistrationViewController.m */,
FCFD25801A154B3800F4C644 /* CodeVerificationViewController.h */,
FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */,
);
name = Signup;
sourceTree = "<group>";
};
/* 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)",

@ -0,0 +1 @@
Subproject commit 585c9e6ca1b55e99fb5c09aa31a6d590c2be5c58

View file

@ -1 +1,10 @@
<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:Signal.xcodeproj'/><FileRef location='group:Pods/Pods.xcodeproj'/></Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Signal.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View file

@ -13,7 +13,7 @@
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
<string>org.whispersystems.signal</string>
<string>org.whispersystems.signal.branch</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@ -48,6 +48,10 @@
<string>remote-notification</string>
<string>voip</string>
</array>
<key>UILaunchStoryboardName</key>
<string>Storyboard</string>
<key>UIMainStoryboardFile</key>
<string>Storyboard</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>

BIN
Signal/archive@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
Signal/blue-archive@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
Signal/call@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
Signal/call_dark@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
Signal/checkmark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Signal/contacts.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

BIN
Signal/contacts@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

BIN
Signal/contacts_tab@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Signal/delete@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
Signal/endcall@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

BIN
Signal/favourite.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
Signal/info@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
Signal/keypad@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

BIN
Signal/lock@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
Signal/lock_white@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
Signal/logo_intro@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
Signal/missed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
Signal/mute_off@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
Signal/mute_on@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Signal/photo@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
Signal/quit@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
Signal/received.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
Signal/red-delete@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
Signal/reply.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
Signal/savephoto@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
Signal/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
Signal/settings_dark@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
Signal/share@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Signal/shred@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
Signal/signal@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
Signal/signals.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

BIN
Signal/speaker_off@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
Signal/speaker_on@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,7 +1,11 @@
#import <UIKit/UIKit.h>
#import "SignalsViewController.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) SignalsViewController *signalVC;
@end

View file

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

View file

@ -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 <UIKit/UIKit.h>
@interface ContactsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property(nonatomic,strong) IBOutlet UISearchBar* searchBar;
@property(nonatomic,strong) IBOutlet UITableView* tableView;
@property(nonatomic,strong) IBOutlet UILabel* phoneNumberLabel;
@end

View file

@ -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 <AddressBook/AddressBook.h>
#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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -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 <UIKit/UIKit.h>
@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

View file

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

View file

@ -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 <UIKit/UIKit.h>
@interface CodeVerificationViewController : UIViewController
@property(nonatomic, strong) IBOutlet UITextField* challengeTextField;
@end

View file

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

View file

@ -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 <UIKit/UIKit.h>
#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

View file

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

View file

@ -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 <UIKit/UIKit.h>
#import "Contact.h"
@interface ContactDetailTableViewController : UITableViewController
@property (nonatomic, strong) Contact *contact;
@end

View file

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

View file

@ -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 <UIKit/UIKit.h>
@interface ContactsTableViewController : UITableViewController
@end

View file

@ -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 <AddressBook/AddressBook.h>
static NSString *const CONTACT_BROWSE_TABLE_CELL_IDENTIFIER = @"ContactTableViewCell";
@interface ContactsTableViewController () <UISearchBarDelegate, UISearchResultsUpdating>
{
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

View file

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

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13A2093" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6243"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CountryCodeViewController">
@ -16,51 +17,68 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="Aec-ej-ccl">
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="Aec-ej-ccl">
<rect key="frame" x="0.0" y="106" width="320" height="462"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="dataSource" destination="-1" id="nKq-1s-Z6A"/>
<outlet property="delegate" destination="-1" id="GHU-1n-beB"/>
</connections>
</tableView>
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" fixedFrame="YES" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QFE-w4-1GR">
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QFE-w4-1GR">
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<items>
<barButtonItem width="242" style="plain" systemItem="fixedSpace" id="GRQ-uO-YiE"/>
<barButtonItem title="Cancel" id="OQ8-LL-GHF">
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<color key="tintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<action selector="cancelTapped:" destination="-1" id="XXB-Il-GTJ"/>
</connections>
</barButtonItem>
</items>
<color key="barTintColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="barTintColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
</toolbar>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Choose Country Code" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pWD-Rl-eq5" customClass="HelveticaNeueLTStdBoldLabel">
<rect key="frame" x="20" y="26" width="226" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="17"/>
<searchBar contentMode="redraw" placeholder="search" translatesAutoresizingMaskIntoConstraints="NO" id="LbU-Dq-i0S">
<rect key="frame" x="0.0" y="62" width="320" height="44"/>
<textInputTraits key="textInputTraits"/>
<connections>
<outlet property="delegate" destination="-1" id="KJu-gV-Y08"/>
</connections>
</searchBar>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Choose Country Code" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pWD-Rl-eq5" customClass="HelveticaNeueLTStdBoldLabel">
<rect key="frame" x="86" y="26" width="226" height="36"/>
<constraints>
<constraint firstAttribute="height" constant="36" id="RCx-aJ-Vgd"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.73333333329999995" blue="0.87058823529999996" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizationKey" value="CHOOSE_COUNTRY_CODE"/>
</userDefinedRuntimeAttributes>
</label>
<searchBar contentMode="redraw" fixedFrame="YES" placeholder="search" translatesAutoresizingMaskIntoConstraints="NO" id="LbU-Dq-i0S">
<rect key="frame" x="0.0" y="62" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<textInputTraits key="textInputTraits"/>
<connections>
<outlet property="delegate" destination="-1" id="KJu-gV-Y08"/>
</connections>
</searchBar>
</subviews>
<color key="backgroundColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Aec-ej-ccl" secondAttribute="trailing" id="7ri-1u-onT"/>
<constraint firstItem="LbU-Dq-i0S" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="9HY-c5-seR"/>
<constraint firstItem="Aec-ej-ccl" firstAttribute="top" secondItem="1" secondAttribute="top" constant="106" id="Gt2-oz-QpM"/>
<constraint firstItem="pWD-Rl-eq5" firstAttribute="top" secondItem="QFE-w4-1GR" secondAttribute="bottom" constant="-40" id="H2r-v2-Oe4"/>
<constraint firstAttribute="trailing" secondItem="pWD-Rl-eq5" secondAttribute="trailing" constant="8" id="Kj4-7v-juF"/>
<constraint firstAttribute="trailing" secondItem="QFE-w4-1GR" secondAttribute="trailing" id="MC4-oi-i61"/>
<constraint firstItem="QFE-w4-1GR" firstAttribute="top" secondItem="1" secondAttribute="top" constant="22" id="ODH-5B-qCb"/>
<constraint firstItem="pWD-Rl-eq5" firstAttribute="leading" secondItem="QFE-w4-1GR" secondAttribute="trailing" constant="-234" id="Xvy-83-8bb"/>
<constraint firstItem="pWD-Rl-eq5" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="86" id="fg1-iH-OkJ"/>
<constraint firstItem="Aec-ej-ccl" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="gaS-xN-W5n"/>
<constraint firstAttribute="bottom" secondItem="Aec-ej-ccl" secondAttribute="bottom" id="iqk-df-bOx"/>
<constraint firstAttribute="trailing" secondItem="LbU-Dq-i0S" secondAttribute="trailing" id="kJK-l1-VVq"/>
<constraint firstItem="QFE-w4-1GR" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="weB-fs-fpo"/>
<constraint firstItem="LbU-Dq-i0S" firstAttribute="top" secondItem="QFE-w4-1GR" secondAttribute="bottom" constant="-4" id="y5a-nh-JH0"/>
</constraints>
</view>
</objects>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -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 <Foundation/Foundation.h>
@interface DemoDataFactory : NSObject
+(NSArray*)data;
+(NSArray*)makeFakeContacts;
+(NSArray*)makeFakeCalls;
@end

View file

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

View file

@ -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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#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

View file

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

View file

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

View file

@ -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 <UIKit/UIKit.h>
@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

View file

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

View file

@ -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 <UIKit/UIKit.h>
@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

View file

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

View file

@ -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 <Foundation/Foundation.h>
@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

View file

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

View file

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

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5056" systemVersion="13C1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6249" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6243"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="InviteContactsViewController">
@ -19,7 +20,6 @@
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="Y27-8Q-Ao4">
<rect key="frame" x="0.0" y="43" width="320" height="461"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="separatorColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<connections>
@ -29,11 +29,9 @@
</tableView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="x7J-R5-Aoc" userLabel="Title Bar View" customClass="SearchBarTitleView">
<rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Invite Contacts" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aWP-1y-0OY" customClass="HelveticaNeueLTStdBoldLabel">
<rect key="frame" x="61" y="26" width="229" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@ -43,7 +41,6 @@
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cz3-CG-rX8" userLabel="Menu Button">
<rect key="frame" x="16" y="29" width="27" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" image="menu_icon.png">
<color key="titleColor" red="1" green="0.54845513059999995" blue="7.621079918e-05" alpha="1" colorSpace="calibratedRGB"/>
@ -52,16 +49,13 @@
</button>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rba-1W-PFE" userLabel="Search View">
<rect key="frame" x="267" y="0.0" width="320" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ugp-Ce-cP5" userLabel="Search Bar Underline View">
<rect key="frame" x="61" y="56" width="210" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.0" green="0.5450980392" blue="0.93725490199999995" alpha="1" colorSpace="calibratedRGB"/>
</view>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uyI-aT-0uk" userLabel="Search Button">
<rect key="frame" x="3" y="19" width="54" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" image="search_icon.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
@ -69,7 +63,6 @@
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fQW-ac-wlf" userLabel="Search Cancel Button">
<rect key="frame" x="275" y="24" width="45" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" image="search_cancel.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
@ -77,7 +70,6 @@
</button>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="search" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Rlq-MC-79h">
<rect key="frame" x="61" y="31" width="210" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="22"/>
<textInputTraits key="textInputTraits" autocapitalizationType="words" autocorrectionType="no" returnKeyType="search"/>
@ -99,9 +91,7 @@
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
<view contentMode="scaleToFill" id="8iO-99-83g" userLabel="New Whisper Users View">
<rect key="frame" x="0.0" y="0.0" width="320" height="52"/>
@ -109,7 +99,6 @@
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="209" translatesAutoresizingMaskIntoConstraints="NO" id="UtW-8T-yLz" customClass="HelveticaNeueLTStdMedLabel">
<rect key="frame" x="57" y="5" width="209" height="41"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<string key="text" base64-UTF8="YES">
U29tZSBvZiB5b3VyIGNvbnRhY3RzIGhhdmUgcmVjZW50bHkgA3JlZ2lzdGVyZWQgbnVtYmVycyB3aXRo
IFNpZ25hbCE
@ -123,7 +112,6 @@ IFNpZ25hbCE
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9dy-uC-NBb">
<rect key="frame" x="3" y="1" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" image="dismiss_notification_icon.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
@ -133,6 +121,8 @@ IFNpZ25hbCE
</button>
</subviews>
<color key="backgroundColor" red="0.22352941176470587" green="0.70980392156862748" blue="0.29019607843137252" alpha="1" colorSpace="calibratedRGB"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
<view contentMode="scaleToFill" id="DH4-s9-oCT" userLabel="Regular Contacts Header View">
<rect key="frame" x="0.0" y="0.0" width="320" height="29"/>
@ -140,13 +130,14 @@ IFNpZ25hbCE
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="You can invite the following users to use Signal" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="320" translatesAutoresizingMaskIntoConstraints="NO" id="dJX-lY-XWv">
<rect key="frame" x="0.0" y="0.0" width="320" height="29"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="12"/>
<color key="textColor" red="0.0" green="0.73333333329999995" blue="0.87058823529999996" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.8735351562" green="0.8735351562" blue="0.8735351562" alpha="1" colorSpace="calibratedRGB"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
@ -155,4 +146,9 @@ IFNpZ25hbCE
<image name="search_cancel.png" width="18" height="18"/>
<image name="search_icon.png" width="25" height="25"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -0,0 +1,24 @@
//
// MessageComposeTableViewController.h
//
//
// Created by Dylan Bourgeois on 02/11/14.
//
//
#import <UIKit/UIKit.h>
#import "DemoDataFactory.h"
#import "Contact.h"
#import "JSQMessagesToolbarContentView.h"
#import "JSQMessagesInputToolbar.h"
#import "JSQMessagesComposerTextView.h"
#import "JSQMessagesKeyboardController.h"
@interface MessageComposeTableViewController : UITableViewController
@end

View file

@ -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 () <UISearchBarDelegate, UISearchResultsUpdating>
{
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

View file

@ -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 <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (strong, nonatomic) DemoDataModel *demoData;
@property (strong, nonatomic) NSString* _senderTitleString;
-(void)initWithGroup:(NSArray*)group;
@end

View file

@ -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 <MobileCoreServices/UTCoreTypes.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>
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<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [self.demoData.messages objectAtIndex:(NSUInteger)indexPath.item];
}
- (id<JSQMessageBubbleImageDataSource>)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<JSQMessageAvatarImageDataSource>)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<JSQMessageData> messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
BOOL isMediaMessage = [messageItem isMediaMessage];
if (isMediaMessage) {
id<JSQMessageMediaData> 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

View file

@ -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 <UIKit/UIKit.h>
@interface NewGroupViewController : UIViewController <UITableViewDelegate, UITabBarDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate>
@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

View file

@ -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 <MobileCoreServices/UTCoreTypes.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>
@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

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6249" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3746"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6243"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="PreferenceListViewController">
@ -17,7 +18,6 @@
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="iaf-8A-Gui">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="dataSource" destination="-1" id="tHd-A5-v0y"/>
@ -26,8 +26,11 @@
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
</objects>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -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 <UIKit/UIKit.h>
#import "CountryCodeViewController.h"
@interface RegistrationViewController : UIViewController<CountryCodeViewControllerDelegate, UITextFieldDelegate>
// 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

View file

@ -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 <Pastelog.h>
#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

View file

@ -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 <UIKit/UIKit.h>
@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

View file

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

View file

@ -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 <UIKit/UIKit.h>
@interface SettingsTableViewController : UITableViewController
@end

View file

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

View file

@ -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 <UIKit/UIKit.h>
#import "Socket.h"
@interface SignalsNavigationController : UINavigationController
@property (nonatomic, strong) Socket * socket;
@property (nonatomic, strong) UIProgressView* socketStatusView;
@end

View file

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

View file

@ -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 <Foundation/Foundation.h>
@interface Socket : NSObject
@property (nonatomic) SocketStatus status;
@end

View file

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

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4510" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6249" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6243"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TabBarParentViewController">
@ -24,7 +25,6 @@
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TxK-UA-SMw">
<rect key="frame" x="0.0" y="504" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490196078433" green="0.12156862745098039" blue="0.12549019607843137" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="Esv-J1-3fb"/>
@ -40,7 +40,6 @@
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TEC-kG-R8z">
<rect key="frame" x="64" y="504" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490196078433" green="0.12156862745098039" blue="0.12549019607843137" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="64" id="bOG-hx-3TL"/>
@ -57,7 +56,6 @@
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UaS-5R-mL2">
<rect key="frame" x="128" y="504" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490196078433" green="0.12156862745098039" blue="0.12549019607843137" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="Jhu-0r-7dg"/>
@ -74,7 +72,6 @@
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Yv9-Bj-1YZ">
<rect key="frame" x="192" y="504" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490196078433" green="0.12156862745098039" blue="0.12549019607843137" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="BP0-IJ-0NY"/>
@ -92,7 +89,6 @@
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fjJ-JY-NGI">
<rect key="frame" x="256" y="504" width="64" height="64"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490196078433" green="0.12156862745098039" blue="0.12549019607843137" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="78C-ec-QrH"/>
@ -109,7 +105,6 @@
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EuB-DL-7PE">
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
@ -118,7 +113,6 @@
</view>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B7o-32-9AW">
<rect key="frame" x="128" y="557" width="64" height="11"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.0" green="0.5450980392" blue="0.93725490199999995" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="5N0-Nd-wG3"/>
@ -129,7 +123,6 @@
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="notification_mini_icon.png" translatesAutoresizingMaskIntoConstraints="NO" id="TNS-1q-kpu">
<rect key="frame" x="232" y="512" width="24" height="24"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
@ -152,8 +145,6 @@
<constraint firstItem="fjJ-JY-NGI" firstAttribute="top" secondItem="EuB-DL-7PE" secondAttribute="bottom" id="wyn-Ek-AKc"/>
<constraint firstAttribute="bottom" secondItem="Yv9-Bj-1YZ" secondAttribute="bottom" id="yXh-ay-seH"/>
</constraints>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
</objects>
<resources>
@ -164,4 +155,9 @@
<image name="tab_icon_keypad.png" width="24" height="24"/>
<image name="tab_icon_menu.png" width="36" height="27"/>
</resources>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -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 <UIKit/UIKit.h>
#import "DemoDataModel.h"
#import "NextResponderScrollView.h"
typedef enum : NSUInteger {
kArchiveState,
kInboxState,
} CellState;
@class TableViewCell;
@protocol TableViewCellDelegate <NSObject>
- (void)tableViewCellTappedDelete:(TableViewCell *)cell;
- (void)tableViewCellTappedArchive:(TableViewCell *)cell;
@end
@interface TableViewCell : UITableViewCell <UIScrollViewDelegate>
@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<TableViewCellDelegate> delegate;
-(void)configureWithTestMessage:(DemoDataModel*)testMessage;
-(void)configureForState:(CellState)state;
-(void)animateDisappear;
@end

View file

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

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="TableViewCell" rowHeight="72" id="axX-Rb-kiK" customClass="TableViewCell">
<rect key="frame" x="0.0" y="0.0" width="400" height="72"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" multipleTouchEnabled="YES" contentMode="center" tableViewCell="axX-Rb-kiK" id="BRG-hJ-lRa">
<rect key="frame" x="0.0" y="0.0" width="318" height="71"/>
<autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3rD-4i-EKG" userLabel="Delete View">
<rect key="frame" x="299" y="0.0" width="102" height="71"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="delete.png" translatesAutoresizingMaskIntoConstraints="NO" id="TBw-ud-Ysk">
<rect key="frame" x="50" y="23" width="19" height="25"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="102" id="sEr-Wb-h8b"/>
</constraints>
</view>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="yBY-TS-2tI" userLabel="Archive View">
<rect key="frame" x="0.0" y="0.0" width="102" height="71"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="archive.png" translatesAutoresizingMaskIntoConstraints="NO" id="WyX-Hb-Mpn">
<rect key="frame" x="40" y="25" width="22" height="22"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
</view>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceHorizontal="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bG5-iK-ql3" customClass="NextResponderScrollView">
<rect key="frame" x="0.0" y="0.0" width="400" height="72"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kq8-RD-txC" userLabel="Container View">
<rect key="frame" x="0.0" y="0.0" width="604" height="72"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wco-u2-Bz6">
<rect key="frame" x="92" y="0.0" width="410" height="72"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="contact_default_feed.png" translatesAutoresizingMaskIntoConstraints="NO" id="p9o-x6-nT5">
<rect key="frame" x="115" y="10" width="52" height="53"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qgj-EY-BWC">
<rect key="frame" x="180" y="31" width="200" height="35"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" fixedFrame="YES" text="Name Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gWV-cB-qZe">
<rect key="frame" x="180" y="8" width="180" height="30"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="highlightedColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Thursday" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bp6-EC-9eP">
<rect key="frame" x="426" y="15" width="56" height="17"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.13725490200000001" green="0.1215686275" blue="0.12549019610000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="highlightedColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="reply.png" translatesAutoresizingMaskIntoConstraints="NO" id="BV6-Tp-SmZ">
<rect key="frame" x="459" y="35" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="FZI-2j-0TT"/>
</constraints>
</imageView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dGa-iy-WtH" userLabel="Archive View">
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HWq-U9-n0t" userLabel="Delete View">
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="Wco-u2-Bz6" secondAttribute="centerX" constant="-10" id="3FF-mP-SEU"/>
<constraint firstItem="Wco-u2-Bz6" firstAttribute="leading" secondItem="kq8-RD-txC" secondAttribute="leading" constant="92" id="7CN-Mr-Ecm"/>
<constraint firstItem="BV6-Tp-SmZ" firstAttribute="top" secondItem="Wco-u2-Bz6" secondAttribute="bottom" constant="-37" id="AoW-bB-S5N"/>
<constraint firstItem="Wco-u2-Bz6" firstAttribute="centerY" secondItem="bp6-EC-9eP" secondAttribute="centerY" constant="12.5" id="EGs-nA-2nC"/>
<constraint firstAttribute="centerY" secondItem="Wco-u2-Bz6" secondAttribute="centerY" id="GZX-5M-GH9"/>
<constraint firstAttribute="bottom" secondItem="Wco-u2-Bz6" secondAttribute="bottom" id="IZD-iJ-o1H"/>
<constraint firstItem="Wco-u2-Bz6" firstAttribute="centerY" secondItem="BV6-Tp-SmZ" secondAttribute="centerY" constant="-9" id="aMK-6Q-s3n"/>
<constraint firstAttribute="trailing" secondItem="Wco-u2-Bz6" secondAttribute="trailing" constant="102" id="bSf-ft-rxR"/>
<constraint firstItem="Wco-u2-Bz6" firstAttribute="top" secondItem="kq8-RD-txC" secondAttribute="top" id="dXQ-dR-4SK"/>
<constraint firstItem="Wco-u2-Bz6" firstAttribute="trailing" secondItem="bp6-EC-9eP" secondAttribute="trailing" constant="20" id="jDm-3D-SbD"/>
<constraint firstItem="BV6-Tp-SmZ" firstAttribute="centerX" secondItem="bp6-EC-9eP" secondAttribute="centerX" constant="15" id="nLR-lQ-dJH"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="3FF-mP-SEU"/>
</mask>
</variation>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="kq8-RD-txC" secondAttribute="trailing" id="3iz-A6-N93"/>
<constraint firstItem="kq8-RD-txC" firstAttribute="top" secondItem="bG5-iK-ql3" secondAttribute="top" id="An4-9G-IYU"/>
<constraint firstItem="kq8-RD-txC" firstAttribute="leading" secondItem="bG5-iK-ql3" secondAttribute="leading" id="HqR-mX-M8E"/>
<constraint firstAttribute="centerX" secondItem="kq8-RD-txC" secondAttribute="centerX" constant="-102" id="LkM-VZ-WRa"/>
<constraint firstAttribute="bottom" secondItem="kq8-RD-txC" secondAttribute="bottom" id="nsI-NR-f3Y"/>
<constraint firstAttribute="centerY" secondItem="kq8-RD-txC" secondAttribute="centerY" id="q6R-fT-3Qv"/>
<constraint firstAttribute="height" constant="72" id="s7n-Dd-n3b"/>
</constraints>
<connections>
<outlet property="delegate" destination="axX-Rb-kiK" id="TMe-oF-FQE"/>
</connections>
</scrollView>
</subviews>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="bG5-iK-ql3" secondAttribute="centerX" id="1eG-bp-0aH"/>
<constraint firstItem="bG5-iK-ql3" firstAttribute="leading" secondItem="BRG-hJ-lRa" secondAttribute="leadingMargin" constant="-8" id="Dmq-W5-Xkr"/>
<constraint firstAttribute="centerY" secondItem="bG5-iK-ql3" secondAttribute="centerY" constant="-0.25" id="IQe-4d-baG"/>
<constraint firstAttribute="trailingMargin" secondItem="3rD-4i-EKG" secondAttribute="trailing" constant="23" id="LCr-QP-vla"/>
<constraint firstAttribute="bottomMargin" secondItem="3rD-4i-EKG" secondAttribute="bottom" constant="-7.5" id="SPU-lp-rQv"/>
<constraint firstAttribute="trailingMargin" secondItem="3rD-4i-EKG" secondAttribute="trailing" constant="-9" id="SbS-PB-jL2"/>
<constraint firstAttribute="trailingMargin" secondItem="bG5-iK-ql3" secondAttribute="trailing" constant="-8" id="ikW-Es-Ngp"/>
<constraint firstItem="3rD-4i-EKG" firstAttribute="top" secondItem="BRG-hJ-lRa" secondAttribute="topMargin" constant="-8" id="yxg-lB-7gK"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="LCr-QP-vla"/>
</mask>
</variation>
</tableViewCellContentView>
<connections>
<outlet property="archiveImageView" destination="WyX-Hb-Mpn" id="99i-j3-F49"/>
<outlet property="archiveView" destination="yBY-TS-2tI" id="Olb-KX-yw5"/>
<outlet property="contactPictureView" destination="p9o-x6-nT5" id="oUA-O3-JIc"/>
<outlet property="contentContainerView" destination="kq8-RD-txC" id="yaJ-z3-8sC"/>
<outlet property="deleteImageView" destination="TBw-ud-Ysk" id="a1T-GR-0cx"/>
<outlet property="deleteView" destination="3rD-4i-EKG" id="oak-Hh-6CC"/>
<outlet property="lastActionImageView" destination="BV6-Tp-SmZ" id="UvX-Wb-tWS"/>
<outlet property="nameLabel" destination="gWV-cB-qZe" id="drr-G2-EB6"/>
<outlet property="scrollView" destination="bG5-iK-ql3" id="wEp-AH-Pdu"/>
<outlet property="snippetLabel" destination="Qgj-EY-BWC" id="EIb-je-Cw5"/>
<outlet property="timeLabel" destination="bp6-EC-9eP" id="O4O-ST-o3v"/>
</connections>
</tableViewCell>
</objects>
<resources>
<image name="archive.png" width="100" height="100"/>
<image name="contact_default_feed.png" width="242" height="242"/>
<image name="delete.png" width="100" height="100"/>
<image name="reply.png" width="100" height="100"/>
</resources>
</document>

View file

@ -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 <UIKit/UIKit.h>
#import "GroupModel.h"
@interface SignalsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, TableViewCellDelegate>
@property (nonatomic) Contact* contactFromCompose;
@property (nonatomic) GroupModel* groupFromCompose;
@property (nonatomic,strong) IBOutlet UITableView* _tableView;
@property (strong, nonatomic) IBOutlet UISegmentedControl * segmentedControl;
@end

View file

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

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1552</int>
<string key="IBDocument.SystemVersion">12F37</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<int key="IBDocument.SystemTarget">1792</int>
<string key="IBDocument.SystemVersion">14A388a</string>
<string key="IBDocument.InterfaceBuilderVersion">6250</string>
<string key="IBDocument.AppKitVersion">1343.14</string>
<string key="IBDocument.HIToolboxVersion">755.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">2083</string>
<string key="NS.object.0">6244</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
@ -34,7 +34,7 @@
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="191373211">
<reference key="NSNextResponder"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIButton" id="627495493">
@ -49,21 +49,21 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Answer</string>
<object class="NSColor" key="IBUIHighlightedTitleColor" id="1030841825">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MCAwLjQ0ODMwNTg3NjQgMC4wMTQ0MjU2MDIyMQA</bytes>
</object>
<object class="NSColor" key="IBUIHighlightedTitleColor" id="1030841825">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<string key="IBUINormalTitle">Answer</string>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="973887861">
<int key="type">2</int>
<double key="pointSize">15</double>
</object>
<object class="NSFont" key="IBUIFont" id="533433202">
<string key="NSName">Helvetica-Bold</string>
<object class="NSFont" key="IBUIFont" id="791711818">
<string key="NSName">HelveticaNeue-Bold</string>
<double key="NSSize">15</double>
<int key="NSfFlags">16</int>
</object>
@ -80,14 +80,14 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Reject</string>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC40NDgzMDU4NzY0IDAuMDEwNTY4MjM3MjkgMAA</bytes>
</object>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<string key="IBUINormalTitle">Reject</string>
<reference key="IBUIFontDescription" ref="973887861"/>
<reference key="IBUIFont" ref="533433202"/>
<reference key="IBUIFont" ref="791711818"/>
</object>
<object class="IBUIButton" id="997104522">
<reference key="NSNextResponder" ref="191373211"/>
@ -101,14 +101,14 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Force Register</string>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC40NDgzMDU4NzY0IDAuMDEwNTY4MjM3MjkgMAA</bytes>
</object>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<string key="IBUINormalTitle">Force Register</string>
<reference key="IBUIFontDescription" ref="973887861"/>
<reference key="IBUIFont" ref="533433202"/>
<reference key="IBUIFont" ref="791711818"/>
</object>
<object class="IBUIButton" id="318920417">
<reference key="NSNextResponder" ref="191373211"/>
@ -122,14 +122,14 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Call ...</string>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MCAwLjQ0ODMwNTg3NjQgMC4wMTQ0MjU2MDIyMQA</bytes>
</object>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<string key="IBUINormalTitle">Call ...</string>
<reference key="IBUIFontDescription" ref="973887861"/>
<reference key="IBUIFont" ref="533433202"/>
<reference key="IBUIFont" ref="791711818"/>
</object>
<object class="IBUIButton" id="727423514">
<reference key="NSNextResponder" ref="191373211"/>
@ -143,14 +143,14 @@
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Hangup</string>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC41IDAgMAA</bytes>
</object>
<reference key="IBUIHighlightedTitleColor" ref="1030841825"/>
<string key="IBUINormalTitle">Hangup</string>
<reference key="IBUIFontDescription" ref="973887861"/>
<reference key="IBUIFont" ref="533433202"/>
<reference key="IBUIFont" ref="791711818"/>
</object>
<object class="IBUITableView" id="66560115">
<reference key="NSNextResponder" ref="191373211"/>
@ -195,8 +195,8 @@
<int key="type">1</int>
<double key="pointSize">17</double>
</object>
<object class="NSFont" key="IBUIFont" id="25549041">
<string key="NSName">Helvetica</string>
<object class="NSFont" key="IBUIFont" id="234669106">
<string key="NSName">HelveticaNeue</string>
<double key="NSSize">17</double>
<int key="NSfFlags">16</int>
</object>
@ -222,7 +222,7 @@
<int key="IBUINumberOfLines">10</int>
<int key="IBUILineBreakMode">0</int>
<reference key="IBUIFontDescription" ref="638011444"/>
<reference key="IBUIFont" ref="25549041"/>
<reference key="IBUIFont" ref="234669106"/>
<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
<double key="preferredMaxLayoutWidth">301</double>
</object>
@ -245,13 +245,12 @@
<int key="IBUINumberOfLines">10</int>
<int key="IBUILineBreakMode">0</int>
<reference key="IBUIFontDescription" ref="638011444"/>
<reference key="IBUIFont" ref="25549041"/>
<reference key="IBUIFont" ref="234669106"/>
<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
<double key="preferredMaxLayoutWidth">301</double>
</object>
</array>
<string key="NSFrame">{{0, 20}, {320, 548}}</string>
<reference key="NSSuperview"/>
<reference key="NSNextKeyView" ref="318920417"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
@ -263,6 +262,8 @@
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
<object class="IBUIScreenMetrics" key="IBUISimulatedDestinationMetrics">
<string key="IBUISimulatedSizeMetricsClass">IBUIScreenMetrics</string>
<string key="IBUITargetRuntime">IBCocoaTouchFramework</string>
<string key="IBUIDisplayName">iPhone 4-inch</string>
<object class="NSMutableDictionary" key="IBUINormalizedOrientationToSizeMap">
<bool key="EncodedWithXMLCoder">YES</bool>
<array key="dict.sortedKeys">
@ -274,15 +275,13 @@
<string>{568, 320}</string>
</array>
</object>
<string key="IBUITargetRuntime">IBCocoaTouchFramework</string>
<string key="IBUIDisplayName">Retina 4 Full Screen</string>
<int key="IBUIType">2</int>
</object>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<array key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
@ -532,8 +531,12 @@
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBDocument.previouslyAttemptedUpgradeToXcode5">NO</bool>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
<integer value="4600" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">2083</string>
</data>
</archive>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4510" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RecentCallsViewController">
@ -94,8 +95,6 @@
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
</objects>
<resources>
@ -103,4 +102,9 @@
<image name="search_cancel.png" width="18" height="18"/>
<image name="search_icon.png" width="25" height="25"/>
</resources>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4510" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ContactBrowseViewController">
@ -134,9 +135,7 @@ IFdoaXNwZXIhA
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics" translucent="NO"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
</objects>
<resources>
@ -146,4 +145,9 @@ IFdoaXNwZXIhA
<image name="search_icon.png" width="25" height="25"/>
<image name="whisper_notification_icon.png" width="28" height="17"/>
</resources>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13A2093" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
@ -14,7 +15,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="+1 (234)-567-8905" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rFC-L1-ZvO">
<rect key="frame" x="26" y="23" width="202" height="21"/>
<rect key="frame" x="26" y="23" width="202" height="22"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="16"/>
<nil key="highlightedColor"/>
@ -27,7 +28,7 @@
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" id="RXT-bl-LZn" userLabel="Seperator view">
<rect key="frame" x="9" y="47" width="300" height="1"/>
<rect key="frame" x="9" y="48" width="300" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
</view>
@ -39,4 +40,9 @@
</connections>
</tableViewCell>
</objects>
</document>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5056" systemVersion="13C1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ContactDetailViewController">
@ -20,7 +21,6 @@
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="none" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="jNG-R5-r0m">
<rect key="frame" x="0.0" y="0.0" width="320" height="519"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="dataSource" destination="-1" id="vyd-cy-GMS"/>
@ -34,10 +34,8 @@
<constraint firstItem="jNG-R5-r0m" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="rGH-rn-ki2"/>
<constraint firstAttribute="bottom" secondItem="jNG-R5-r0m" secondAttribute="bottom" id="rJn-Dd-NeH"/>
</constraints>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics" translucent="NO"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
<view contentMode="scaleToFill" id="rbM-xj-rv4" userLabel="Contact Detail Header View">
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
@ -45,24 +43,28 @@
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Moxie Marlinspike" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="201" translatesAutoresizingMaskIntoConstraints="NO" id="5qW-wL-wnI">
<rect key="frame" x="80" y="22" width="201" height="55"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="18"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="contact_default_feed.png" translatesAutoresizingMaskIntoConstraints="NO" id="zfe-la-xIb">
<rect key="frame" x="17" y="22" width="55" height="55"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZNu-c1-4Uj" userLabel="Seperator view">
<rect key="frame" x="0.0" y="98" width="320" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
<resources>
<image name="contact_default_feed.png" width="242" height="242"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

Some files were not shown because too many files have changed in this diff Show more