Addresses multiple UI issues.

- New Contact spacing to let user tap call/message icons
- Handeling error messages, delivery receipts, timestamps
This commit is contained in:
dtsbourg 2014-11-29 19:54:33 +01:00 committed by Frederic Jacobs
parent d4f5675a58
commit 91e0b66424
33 changed files with 548 additions and 136 deletions

View file

@ -83,7 +83,7 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
JSQMessagesViewController:
:commit: b22b7a4caf2d36ff9965b1970fea968a46898f4c
:commit: 4049f547891ffa18eaf11f9c15092de38821a590
:git: https://github.com/dtsbourg/JSQMessagesViewController
SocketRocket:
:commit: d0585af165

View file

@ -293,7 +293,6 @@
B633C5851A1D190B0059AC12 /* blue-archive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5031A1D190B0059AC12 /* blue-archive@2x.png */; };
B633C5861A1D190B0059AC12 /* call@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5041A1D190B0059AC12 /* call@2x.png */; };
B633C5871A1D190B0059AC12 /* call_dark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5051A1D190B0059AC12 /* call_dark@2x.png */; };
B633C58C1A1D190B0059AC12 /* checkmark.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C50A1A1D190B0059AC12 /* checkmark.png */; };
B633C58D1A1D190B0059AC12 /* contact_default_feed.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C50B1A1D190B0059AC12 /* contact_default_feed.png */; };
B633C58F1A1D190B0059AC12 /* contacts@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C50D1A1D190B0059AC12 /* contacts@2x.png */; };
B633C5921A1D190B0059AC12 /* contacts_tab@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5101A1D190B0059AC12 /* contacts_tab@2x.png */; };
@ -307,14 +306,11 @@
B633C5B71A1D190B0059AC12 /* logo_intro@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5351A1D190B0059AC12 /* logo_intro@2x.png */; };
B633C5BB1A1D190B0059AC12 /* message_bubble.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5391A1D190B0059AC12 /* message_bubble.png */; };
B633C5BC1A1D190B0059AC12 /* message_bubble@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C53A1A1D190B0059AC12 /* message_bubble@2x.png */; };
B633C5BE1A1D190B0059AC12 /* missed.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C53C1A1D190B0059AC12 /* missed.png */; };
B633C5C31A1D190B0059AC12 /* mute_off@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5411A1D190B0059AC12 /* mute_off@2x.png */; };
B633C5C41A1D190B0059AC12 /* mute_on@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5421A1D190B0059AC12 /* mute_on@2x.png */; };
B633C5CD1A1D190B0059AC12 /* photo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C54B1A1D190B0059AC12 /* photo@2x.png */; };
B633C5CE1A1D190B0059AC12 /* quit@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C54C1A1D190B0059AC12 /* quit@2x.png */; };
B633C5CF1A1D190B0059AC12 /* received.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C54D1A1D190B0059AC12 /* received.png */; };
B633C5D01A1D190B0059AC12 /* red-delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C54E1A1D190B0059AC12 /* red-delete@2x.png */; };
B633C5D11A1D190B0059AC12 /* reply.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C54F1A1D190B0059AC12 /* reply.png */; };
B633C5D21A1D190B0059AC12 /* savephoto@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5501A1D190B0059AC12 /* savephoto@2x.png */; };
B633C5DA1A1D190B0059AC12 /* settings_dark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5581A1D190B0059AC12 /* settings_dark@2x.png */; };
B633C5DB1A1D190B0059AC12 /* share@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5591A1D190B0059AC12 /* share@2x.png */; };
@ -492,8 +488,19 @@
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 */; };
FC3BD97B1A2CD385005B96BB /* call_dotted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC3BD9791A2CD385005B96BB /* call_dotted@2x.png */; };
FC3BD97C1A2CD385005B96BB /* signal_dotted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC3BD97A1A2CD385005B96BB /* signal_dotted@2x.png */; };
FC4FA0261A1B9DC600DA100A /* SignalsNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0251A1B9DC600DA100A /* SignalsNavigationController.m */; };
FC4FA0331A1D46AE00DA100A /* InitialViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0321A1D46AE00DA100A /* InitialViewController.m */; };
FCA52AE61A2B676C00CCADFA /* call_canceled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52ADE1A2B676C00CCADFA /* call_canceled@2x.png */; };
FCA52AE71A2B676C00CCADFA /* call_failed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52ADF1A2B676C00CCADFA /* call_failed@2x.png */; };
FCA52AE81A2B676C00CCADFA /* call_incoming@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE01A2B676C00CCADFA /* call_incoming@2x.png */; };
FCA52AE91A2B676C00CCADFA /* call_missed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE11A2B676C00CCADFA /* call_missed@2x.png */; };
FCA52AEA1A2B676C00CCADFA /* call_outgoing@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE21A2B676C00CCADFA /* call_outgoing@2x.png */; };
FCA52AEB1A2B676C00CCADFA /* checkmark_light@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE31A2B676C00CCADFA /* checkmark_light@2x.png */; };
FCA52AEC1A2B676C00CCADFA /* message_error@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE41A2B676C00CCADFA /* message_error@2x.png */; };
FCA52AED1A2B676C00CCADFA /* reply@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AE51A2B676C00CCADFA /* reply@2x.png */; };
FCA52B071A2BBAE400CCADFA /* call_tab@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52B061A2BBAE400CCADFA /* call_tab@2x.png */; };
FCAC963519FEF4E20046DFC5 /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FCAC963419FEF4E20046DFC5 /* Storyboard.storyboard */; };
FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963B19FEF9280046DFC5 /* SignalsViewController.m */; };
FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCAC963E19FEF99A0046DFC5 /* InboxTableViewCell.m */; };
@ -868,7 +875,6 @@
B633C5031A1D190B0059AC12 /* blue-archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "blue-archive@2x.png"; sourceTree = "<group>"; };
B633C5041A1D190B0059AC12 /* call@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call@2x.png"; sourceTree = "<group>"; };
B633C5051A1D190B0059AC12 /* call_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_dark@2x.png"; sourceTree = "<group>"; };
B633C50A1A1D190B0059AC12 /* checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkmark.png; sourceTree = "<group>"; };
B633C50B1A1D190B0059AC12 /* contact_default_feed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = contact_default_feed.png; sourceTree = "<group>"; };
B633C50D1A1D190B0059AC12 /* contacts@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "contacts@2x.png"; sourceTree = "<group>"; };
B633C5101A1D190B0059AC12 /* contacts_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "contacts_tab@2x.png"; sourceTree = "<group>"; };
@ -882,14 +888,11 @@
B633C5351A1D190B0059AC12 /* logo_intro@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "logo_intro@2x.png"; sourceTree = "<group>"; };
B633C5391A1D190B0059AC12 /* message_bubble.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = message_bubble.png; sourceTree = "<group>"; };
B633C53A1A1D190B0059AC12 /* message_bubble@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "message_bubble@2x.png"; sourceTree = "<group>"; };
B633C53C1A1D190B0059AC12 /* missed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = missed.png; sourceTree = "<group>"; };
B633C5411A1D190B0059AC12 /* mute_off@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_off@2x.png"; sourceTree = "<group>"; };
B633C5421A1D190B0059AC12 /* mute_on@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mute_on@2x.png"; sourceTree = "<group>"; };
B633C54B1A1D190B0059AC12 /* photo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "photo@2x.png"; sourceTree = "<group>"; };
B633C54C1A1D190B0059AC12 /* quit@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "quit@2x.png"; sourceTree = "<group>"; };
B633C54D1A1D190B0059AC12 /* received.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = received.png; sourceTree = "<group>"; };
B633C54E1A1D190B0059AC12 /* red-delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "red-delete@2x.png"; sourceTree = "<group>"; };
B633C54F1A1D190B0059AC12 /* reply.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reply.png; sourceTree = "<group>"; };
B633C5501A1D190B0059AC12 /* savephoto@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "savephoto@2x.png"; sourceTree = "<group>"; };
B633C5581A1D190B0059AC12 /* settings_dark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings_dark@2x.png"; sourceTree = "<group>"; };
B633C5591A1D190B0059AC12 /* share@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "share@2x.png"; sourceTree = "<group>"; };
@ -1155,10 +1158,21 @@
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>"; };
FC3BD9791A2CD385005B96BB /* call_dotted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_dotted@2x.png"; sourceTree = "<group>"; };
FC3BD97A1A2CD385005B96BB /* signal_dotted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "signal_dotted@2x.png"; 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>"; };
FC4FA0311A1D46AE00DA100A /* InitialViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitialViewController.h; sourceTree = "<group>"; };
FC4FA0321A1D46AE00DA100A /* InitialViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InitialViewController.m; sourceTree = "<group>"; };
FCA52ADE1A2B676C00CCADFA /* call_canceled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_canceled@2x.png"; sourceTree = "<group>"; };
FCA52ADF1A2B676C00CCADFA /* call_failed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_failed@2x.png"; sourceTree = "<group>"; };
FCA52AE01A2B676C00CCADFA /* call_incoming@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_incoming@2x.png"; sourceTree = "<group>"; };
FCA52AE11A2B676C00CCADFA /* call_missed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_missed@2x.png"; sourceTree = "<group>"; };
FCA52AE21A2B676C00CCADFA /* call_outgoing@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_outgoing@2x.png"; sourceTree = "<group>"; };
FCA52AE31A2B676C00CCADFA /* checkmark_light@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "checkmark_light@2x.png"; sourceTree = "<group>"; };
FCA52AE41A2B676C00CCADFA /* message_error@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "message_error@2x.png"; sourceTree = "<group>"; };
FCA52AE51A2B676C00CCADFA /* reply@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "reply@2x.png"; sourceTree = "<group>"; };
FCA52B061A2BBAE400CCADFA /* call_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_tab@2x.png"; 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>"; };
@ -2086,37 +2100,44 @@
B633C5011A1D190B0059AC12 /* backspace.png */,
B633C5021A1D190B0059AC12 /* backspace@2x.png */,
B633C5031A1D190B0059AC12 /* blue-archive@2x.png */,
B633C5041A1D190B0059AC12 /* call@2x.png */,
FCA52ADE1A2B676C00CCADFA /* call_canceled@2x.png */,
B633C5051A1D190B0059AC12 /* call_dark@2x.png */,
B633C50A1A1D190B0059AC12 /* checkmark.png */,
FC3BD9791A2CD385005B96BB /* call_dotted@2x.png */,
FCA52ADF1A2B676C00CCADFA /* call_failed@2x.png */,
FCA52AE01A2B676C00CCADFA /* call_incoming@2x.png */,
FCA52AE11A2B676C00CCADFA /* call_missed@2x.png */,
FCA52AE21A2B676C00CCADFA /* call_outgoing@2x.png */,
FCA52B061A2BBAE400CCADFA /* call_tab@2x.png */,
B633C5041A1D190B0059AC12 /* call@2x.png */,
FCA52AE31A2B676C00CCADFA /* checkmark_light@2x.png */,
B633C50B1A1D190B0059AC12 /* contact_default_feed.png */,
B633C50D1A1D190B0059AC12 /* contacts@2x.png */,
B633C5101A1D190B0059AC12 /* contacts_tab@2x.png */,
B633C5141A1D190B0059AC12 /* DefaultContactImage.png */,
B633C50D1A1D190B0059AC12 /* contacts@2x.png */,
FC15B7BE1A1F80F200F59801 /* defaultConctact_light@2x.png */,
B633C5151A1D190B0059AC12 /* delete@2x.png */,
B633C5141A1D190B0059AC12 /* DefaultContactImage.png */,
B633C5161A1D190B0059AC12 /* delete_history@2x.png */,
B633C5151A1D190B0059AC12 /* delete@2x.png */,
B633C51B1A1D190B0059AC12 /* endcall@2x.png */,
FC1F90BF1A22342B004F8253 /* group_photo@2x.png */,
B633C5321A1D190B0059AC12 /* keypad@2x.png */,
B633C5331A1D190B0059AC12 /* lock@2x.png */,
B633C5341A1D190B0059AC12 /* lock_white@2x.png */,
B633C5331A1D190B0059AC12 /* lock@2x.png */,
B633C5351A1D190B0059AC12 /* logo_intro@2x.png */,
B633C5391A1D190B0059AC12 /* message_bubble.png */,
B633C53A1A1D190B0059AC12 /* message_bubble@2x.png */,
B633C53C1A1D190B0059AC12 /* missed.png */,
FCA52AE41A2B676C00CCADFA /* message_error@2x.png */,
B633C5411A1D190B0059AC12 /* mute_off@2x.png */,
B633C5421A1D190B0059AC12 /* mute_on@2x.png */,
B633C54B1A1D190B0059AC12 /* photo@2x.png */,
B633C54C1A1D190B0059AC12 /* quit@2x.png */,
B633C54D1A1D190B0059AC12 /* received.png */,
B633C54E1A1D190B0059AC12 /* red-delete@2x.png */,
B633C54F1A1D190B0059AC12 /* reply.png */,
FCA52AE51A2B676C00CCADFA /* reply@2x.png */,
B633C5501A1D190B0059AC12 /* savephoto@2x.png */,
B633C5581A1D190B0059AC12 /* settings_dark@2x.png */,
FC1F90C41A223991004F8253 /* settings_tab@2x.png */,
B633C5591A1D190B0059AC12 /* share@2x.png */,
B633C55A1A1D190B0059AC12 /* shred@2x.png */,
FC3BD97A1A2CD385005B96BB /* signal_dotted@2x.png */,
B633C55E1A1D190B0059AC12 /* signal@2x.png */,
FC1F90C51A223991004F8253 /* signals_tab@2x.png */,
B633C5641A1D190B0059AC12 /* speaker_off@2x.png */,
@ -2696,7 +2717,6 @@
ORGANIZATIONNAME = "Open Whisper Systems";
TargetAttributes = {
D221A088169C9E5E00537ABF = {
DevelopmentTeam = U68MSDN6DR;
SystemCapabilities = {
com.apple.DataProtection = {
enabled = 1;
@ -2813,32 +2833,33 @@
B633C5E61A1D190B0059AC12 /* speaker_on@2x.png in Resources */,
B633C5BB1A1D190B0059AC12 /* message_bubble.png in Resources */,
B633C5B51A1D190B0059AC12 /* lock@2x.png in Resources */,
FCA52AE81A2B676C00CCADFA /* call_incoming@2x.png in Resources */,
FC1F90C01A22342B004F8253 /* group_photo@2x.png in Resources */,
FCA52AE91A2B676C00CCADFA /* call_missed@2x.png in Resources */,
E148750518A06966002CC4F3 /* CountryCodeViewController.xib in Resources */,
B633C5C41A1D190B0059AC12 /* mute_on@2x.png in Resources */,
E148750618A06966002CC4F3 /* DialerViewController.xib in Resources */,
B633C5CE1A1D190B0059AC12 /* quit@2x.png in Resources */,
E148750A18A06966002CC4F3 /* InCallViewController.xib in Resources */,
FCA52AEB1A2B676C00CCADFA /* checkmark_light@2x.png in Resources */,
B633C5D01A1D190B0059AC12 /* red-delete@2x.png in Resources */,
B633C59D1A1D190B0059AC12 /* endcall@2x.png in Resources */,
B633C5CF1A1D190B0059AC12 /* received.png in Resources */,
B633C5B41A1D190B0059AC12 /* keypad@2x.png in Resources */,
B633C5DA1A1D190B0059AC12 /* settings_dark@2x.png in Resources */,
FCA52AEC1A2B676C00CCADFA /* message_error@2x.png in Resources */,
E14874F818A06951002CC4F3 /* ContactTableViewCell.xib in Resources */,
B633C5BC1A1D190B0059AC12 /* message_bubble@2x.png in Resources */,
B633C5D11A1D190B0059AC12 /* reply.png in Resources */,
FC15B7BF1A1F80F200F59801 /* defaultConctact_light@2x.png in Resources */,
E14874F918A06951002CC4F3 /* CountryCodeTableViewCell.xib in Resources */,
B633C5871A1D190B0059AC12 /* call_dark@2x.png in Resources */,
B633C5BE1A1D190B0059AC12 /* missed.png in Resources */,
B633C5851A1D190B0059AC12 /* blue-archive@2x.png in Resources */,
B633C5D21A1D190B0059AC12 /* savephoto@2x.png in Resources */,
B633C58C1A1D190B0059AC12 /* checkmark.png in Resources */,
B633C5921A1D190B0059AC12 /* contacts_tab@2x.png in Resources */,
B6416FB8199A0478003C5699 /* Localizable.strings in Resources */,
B633C5971A1D190B0059AC12 /* delete@2x.png in Resources */,
FCAC964119FEF99A0046DFC5 /* InboxTableViewCell.xib in Resources */,
B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */,
FCA52AE71A2B676C00CCADFA /* call_failed@2x.png in Resources */,
70B8FEE21909FE360042E3F0 /* 171756__nenadsimic__picked-coin-echo-2.wav in Resources */,
B633C5801A1D190B0059AC12 /* archive@2x.png in Resources */,
E1370BEA18A0689000826894 /* AppIcon29x29.jpg in Resources */,
@ -2850,6 +2871,7 @@
FC1F90C61A223991004F8253 /* settings_tab@2x.png in Resources */,
E1370BEE18A0689000826894 /* AppIcon40x40@2x.png in Resources */,
E1370BEF18A0689000826894 /* AppIcon60x60.png in Resources */,
FCA52AEA1A2B676C00CCADFA /* call_outgoing@2x.png in Resources */,
E1370BF018A0689000826894 /* AppIcon60x60@2x.png in Resources */,
E1370BF118A0689000826894 /* AppIcon76x76.png in Resources */,
E1370BF218A0689000826894 /* AppIcon76x76@2x.png in Resources */,
@ -2861,7 +2883,9 @@
E1370BE218A0686C00826894 /* failure.mp3 in Resources */,
B633C5DB1A1D190B0059AC12 /* share@2x.png in Resources */,
E1370BE318A0686C00826894 /* handshake.mp3 in Resources */,
FCA52B071A2BBAE400CCADFA /* call_tab@2x.png in Resources */,
B633C58D1A1D190B0059AC12 /* contact_default_feed.png in Resources */,
FC3BD97C1A2CD385005B96BB /* signal_dotted@2x.png in Resources */,
B633C5CD1A1D190B0059AC12 /* photo@2x.png in Resources */,
B633C5861A1D190B0059AC12 /* call@2x.png in Resources */,
FCAC963519FEF4E20046DFC5 /* Storyboard.storyboard in Resources */,
@ -2871,14 +2895,17 @@
B633C5B71A1D190B0059AC12 /* logo_intro@2x.png in Resources */,
E1370BE518A0686C00826894 /* r.caf in Resources */,
B633C5981A1D190B0059AC12 /* delete_history@2x.png in Resources */,
FCA52AED1A2B676C00CCADFA /* reply@2x.png in Resources */,
B633C5E51A1D190B0059AC12 /* speaker_off@2x.png in Resources */,
B633C58F1A1D190B0059AC12 /* contacts@2x.png in Resources */,
E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */,
B633C5961A1D190B0059AC12 /* DefaultContactImage.png in Resources */,
E148751218A06AFD002CC4F3 /* HelveticaNeueLTStd-Bd.otf in Resources */,
FCA52AE61A2B676C00CCADFA /* call_canceled@2x.png in Resources */,
E148751318A06AFD002CC4F3 /* HelveticaNeueLTStd-Th.otf in Resources */,
E148751418A06AFD002CC4F3 /* HelveticaNeueLTStd-Lt.otf in Resources */,
E148751518A06AFD002CC4F3 /* HelveticaNeueLTStd-Md.otf in Resources */,
FC3BD97B1A2CD385005B96BB /* call_dotted@2x.png in Resources */,
E1370BF618A068A600826894 /* whisperReal.cer in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -3473,7 +3500,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "-fobjc-arc-exceptions";
PROVISIONING_PROFILE = "87a69a1c-864f-4e05-8d48-b9268ace6179";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
@ -3644,7 +3671,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fobjc-arc-exceptions";
PROVISIONING_PROFILE = "87a69a1c-864f-4e05-8d48-b9268ace6179";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
@ -3709,7 +3736,7 @@
"-DNS_BLOCK_ASSERTIONS=1",
"-fobjc-arc-exceptions",
);
PROVISIONING_PROFILE = "87a69a1c-864f-4e05-8d48-b9268ace6179";
PROVISIONING_PROFILE = "";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
Signal/Images/reply@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -15,7 +15,7 @@
<viewControllerLayoutGuide type="bottom" id="7uh-gm-z8v"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="EFA-Fu-XJm">
<rect key="frame" x="0.0" y="0.0" width="600" height="551"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="PaA-ol-uQT">
@ -114,7 +114,7 @@
<viewControllerLayoutGuide type="bottom" id="stV-ob-KSQ"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="5r3-kq-bbI">
<rect key="frame" x="0.0" y="0.0" width="600" height="551"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@ -1435,7 +1435,7 @@ Lorem ipsum : Quick explanation of Fingerprints</string>
<objects>
<tableViewController id="6mY-1Q-YBT" customClass="ContactsTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="GqA-oC-CJa">
<rect key="frame" x="0.0" y="0.0" width="600" height="551"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
@ -1464,7 +1464,7 @@ Lorem ipsum : Quick explanation of Fingerprints</string>
<objects>
<tableViewController id="0XE-hu-8cu" customClass="ContactDetailTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="default" showsSelectionImmediatelyOnTouchBegin="NO" rowHeight="150" sectionHeaderHeight="22" sectionFooterHeight="22" id="RoU-YO-d5P">
<rect key="frame" x="0.0" y="0.0" width="600" height="551"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
@ -2324,7 +2324,7 @@ Lorem ipsum : Quick explanation of Fingerprints</string>
<objects>
<tableViewController id="n1f-7Y-906" customClass="SettingsTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="FhQ-dM-1mj">
<rect key="frame" x="0.0" y="0.0" width="600" height="551"/>
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<view key="tableFooterView" contentMode="scaleToFill" id="Ezq-Cw-na2">

View file

@ -18,5 +18,11 @@
+ (UIColor *) ows_darkGrayColor;
+ (UIColor *) ows_yellowColor;
+ (UIColor *) ows_greenColor;
+ (UIColor *) ows_redColor;
@end

View file

@ -13,22 +13,37 @@
+ (UIColor*) ows_blueColor
{
return [UIColor colorWithRed:0.f/255.f green:122.f/255.f blue:255.f/255.f alpha:1.0f];
return [UIColor colorWithRed:0 green:122.f/255.f blue:255.f/255.f alpha:1.f];
}
+ (UIColor*) ows_darkGrayColor
{
return [UIColor colorWithRed:81.f/255.f green:81.f/255.f blue:81.f/255.f alpha:1.0f];
return [UIColor colorWithRed:81.f/255.f green:81.f/255.f blue:81.f/255.f alpha:1.f];
}
+ (UIColor*) ows_darkBackgroundColor
{
return [UIColor colorWithRed:35.0f/255.0f green:31.0f/255.0f blue:32.0f/255.0f alpha:1.0f];
return [UIColor colorWithRed:35.f/255.f green:31.f/255.f blue:32.f/255.f alpha:1.f];
}
+ (UIColor *) ows_fadedBlueColor
{
return [UIColor colorWithRed:110.f/255.f green:178.f/255.f blue:1.0f alpha:1.0f];
return [UIColor colorWithRed:110.f/255.f green:178.f/255.f blue:1.f alpha:1.f];
}
+ (UIColor *) ows_yellowColor
{
return [UIColor colorWithRed:239.f/255.f green:189.f/255.f blue:88.f/255.f alpha:1.f];
}
+ (UIColor *) ows_greenColor
{
return [UIColor colorWithRed:55.f/255.f green:212.f/255.f blue:69.f/255.f alpha:1.f];
}
+ (UIColor *) ows_redColor
{
return [UIColor colorWithRed:195.f/255.f green:0 blue:22.f/255.f alpha:1.f];
}
@end

View file

@ -11,6 +11,24 @@
#import "TSYapDatabaseObject.h"
typedef NS_ENUM(NSInteger, TSLastActionType) {
TSLastActionNone,
TSLastActionCallIncoming,
TSLastActionCallIncomingMissed,
TSLastActionCallOutgoing,
TSLastActionCallOutgoingMissed,
TSLastActionCallOutgoingFailed,
TSLastActionMessageAttemptingOut,
TSLastActionMessageUnsent,
TSLastActionMessageSent,
TSLastActionMessageDelivered,
TSLastActionMessageIncoming
};
/**
* TSThread is the superclass of TSContactThread and TSGroupThread
*/
@ -48,6 +66,8 @@
- (NSString*)lastMessageLabel;
- (TSLastActionType)lastAction;
- (int)unreadMessages;
@end

View file

@ -13,6 +13,10 @@
#import "TSStorageManager.h"
#import "TSGroup.h"
#import "TSCall.h"
#import "TSOutgoingMessage.h"
#import "TSIncomingMessage.h"
@implementation TSThread
+ (NSString *)collection{
@ -64,6 +68,69 @@
return interaction.description;
}
- (TSLastActionType)lastAction
{
__block TSInteraction *interaction;
[[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
interaction = [TSInteraction fetchObjectWithUniqueID:[TSInteraction stringFromTimeStamp:_lastMessageId] transaction:transaction];
}];
return [self lastActionForInteraction:interaction];
}
- (TSLastActionType)lastActionForInteraction:(TSInteraction*)interaction
{
if ([interaction isKindOfClass:[TSCall class]])
{
TSCall * callInteraction = (TSCall*)interaction;
BOOL isOutgoing = callInteraction.wasCaller;
switch (callInteraction.callType) {
case TSCallTypeSuccess:
return isOutgoing ? TSLastActionCallOutgoing : TSLastActionCallIncoming;
break;
case TSCallTypeMissed:
return isOutgoing ? TSLastActionCallOutgoingMissed : TSLastActionCallIncomingMissed;
break;
case TSCallTypeBusy:
return isOutgoing ? TSLastActionCallOutgoingMissed : TSLastActionCallIncomingMissed;
break;
case TSCallTypeFailed:
return isOutgoing ? TSLastActionCallOutgoingFailed : TSLastActionNone;
break;
default:
return TSLastActionNone;
break;
}
} else if ([interaction isKindOfClass:[TSOutgoingMessage class]]) {
TSOutgoingMessage * outgoingMessageInteraction = (TSOutgoingMessage*)interaction;
switch (outgoingMessageInteraction.messageState) {
case TSOutgoingMessageStateAttemptingOut:
return TSLastActionNone;
break;
case TSOutgoingMessageStateUnsent:
return TSLastActionMessageUnsent;
break;
case TSOutgoingMessageStateSent:
return TSLastActionMessageSent;
break;
case TSOutgoingMessageStateDelivered:
return TSLastActionMessageDelivered;
break;
default:
return TSLastActionNone;
break;
}
} else if ([interaction isKindOfClass:[TSIncomingMessage class]]) {
return TSLastActionNone;
} else {
return TSLastActionNone;
}
}
- (int)unreadMessages{
return 0;
}

View file

@ -50,7 +50,6 @@
[Environment.getCurrent.phoneDirectoryManager forceUpdate];
[self performSegueWithIdentifier:@"verifiedSegue" sender:self];
} failure:^(NSError *error) {
NSLog(@"Failed to register");
[self showAlertForError:error];
[_challengeButton setEnabled:YES];
}];

View file

@ -166,24 +166,24 @@ static NSString *const kContactDetailSegue = @"DetailSegue";
UIImage *clearImage = [[UIImage imageNamed:@"delete_history"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[cell.contactShredButton setImage:clearImage forState:UIControlStateNormal];
cell.contactShredButton.tintColor = [UIColor redColor];
cell.contactShredButton.tintColor = [UIColor ows_redColor];
if (c.isRedPhoneContact)
{
cell.contactCallButton.tintColor = [UIColor colorWithRed:0.f/255.f green:122.f/255.f blue:255.f/255.f alpha:1.0f];
cell.contactCallButton.tintColor = [UIColor ows_blueColor];
[cell.contactCallButton addTarget:self action:@selector(initiateRedPhoneCall) forControlEvents:UIControlEventTouchUpInside];
} else {
cell.contactCallButton.tintColor = [UIColor colorWithRed:81.f/255.f green:81.f/255.f blue:81.f/255.f alpha:1.0f];
cell.contactCallButton.tintColor = [UIColor ows_darkGrayColor];
cell.contactCallButton.enabled = NO;
}
if (c.isTextSecureContact)
{
cell.contactTextButton.tintColor = [UIColor colorWithRed:0.f/255.f green:122.f/255.f blue:255.f/255.f alpha:1.0f];
cell.contactTextButton.tintColor = [UIColor ows_blueColor];
[cell.contactTextButton addTarget:self action:@selector(openTextSecureConversation) forControlEvents:UIControlEventTouchUpInside];
} else {
cell.contactTextButton.tintColor = [UIColor colorWithRed:81.f/255.f green:81.f/255.f blue:81.f/255.f alpha:1.0f];
cell.contactTextButton.tintColor = [UIColor ows_darkGrayColor];
cell.contactTextButton.enabled = NO;
}
}

View file

@ -246,7 +246,7 @@ static NSString *const CONTACT_BROWSE_TABLE_CELL_IDENTIFIER = @"ContactTableView
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44.0f;
return 55.0f;
}
#pragma mark - Segue

View file

@ -292,7 +292,7 @@ static NSInteger connectingFlashCounter = 0;
message = [message stringByAppendingString:[serverMessage text]];
}
_callStatusLabel.textColor = [UIColor redColor];
_callStatusLabel.textColor = [UIColor ows_redColor];
[self showConnectingError];
_callStatusLabel.text = message;

View file

@ -48,7 +48,7 @@
_timeLabel.attributedText = [self dateAttributedString:thread.lastMessageDate];
self.separatorInset = UIEdgeInsetsMake(0,_contactPictureView.frame.size.width*1.5f, 0, 0);
[self setUpLastAction:@"read"]; // TODO: Change
[self setUpLastActionForThread:thread];
}
-(void)configureForState:(CellState)state
@ -66,24 +66,48 @@
}
}
-(void)setUpLastAction:(NSString*)lastAction {
-(void)setUpLastActionForThread:(TSThread*)thread
{
TSLastActionType lastAction = [thread 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:122.f/255.f blue:1.0f alpha:1.0f];
switch (lastAction) {
case TSLastActionNone:
_lastActionImageView.image = nil;
break;
case TSLastActionCallIncoming:
_lastActionImageView.image = [UIImage imageNamed:@"call_incoming"];
break;
case TSLastActionCallIncomingMissed:
_lastActionImageView.image = [UIImage imageNamed:@"call_missed"];
break;
case TSLastActionCallOutgoing:
_lastActionImageView.image = [UIImage imageNamed:@"call_outgoing"];
break;
case TSLastActionCallOutgoingMissed:
_lastActionImageView.image = [UIImage imageNamed:@"call_canceled"];
break;
case TSLastActionCallOutgoingFailed:
_lastActionImageView.image = [UIImage imageNamed:@"call_failed"];
break;
case TSLastActionMessageAttemptingOut:
_lastActionImageView.image = nil;
break;
case TSLastActionMessageUnsent:
_lastActionImageView.image = [UIImage imageNamed:@"message_error"];
break;
case TSLastActionMessageSent:
_lastActionImageView.image = [UIImage imageNamed:@"reply"];
break;
case TSLastActionMessageDelivered:
_lastActionImageView.image = [UIImage imageNamed:@"checkmark_light"];
break;
case TSLastActionMessageIncoming:
_lastActionImageView.image = nil;
break;
default:
_lastActionImageView.image = nil;
break;
}
}
#pragma mark - Date formatting
@ -95,7 +119,7 @@
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:timeString];
[attributedString addAttribute:NSForegroundColorAttributeName
value:[UIColor darkGrayColor]
value:[UIColor ows_darkGrayColor]
range:NSMakeRange(0, timeString.length)];

View file

@ -14,6 +14,10 @@
#import "JSQCallCollectionViewCell.h"
#import "JSQCall.h"
#import "JSQDisplayedMessageCollectionViewCell.h"
#import "JSQInfoMessage.h"
#import "JSQErrorMessage.h"
#import "UIUtil.h"
#import "DJWActionSheet.h"
#import <MobileCoreServices/UTCoreTypes.h>
@ -32,6 +36,11 @@
#import "TSMessagesManager+sendMessages.h"
#import "NSDate+millisecondTimeStamp.h"
#import "PhoneNumber.h"
#import "Environment.h"
#import "PhoneManager.h"
#import "ContactsManager.h"
static NSTimeInterval const kTSMessageSentDateShowTimeInterval = 5 * 60;
typedef enum : NSUInteger {
@ -67,15 +76,10 @@ typedef enum : NSUInteger {
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
isGroupConversation = NO; // TODO: Support Group Conversations
JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init];
self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
self.outgoingMessageFailedImageData = [bubbleFactory outgoingMessageFailedBubbleImageWithColor:[UIColor ows_fadedBlueColor]];
[self initializeBubbles];
self.messageMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[self.thread.uniqueId] view:TSMessageDatabaseViewExtensionName];
@ -83,33 +87,15 @@ typedef enum : NSUInteger {
[self.messageMappings updateWithTransaction:transaction];
}];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"lock.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showFingerprint)];
[self.collectionView.collectionViewLayout setMessageBubbleFont:[UIFont ows_lightFontWithSize:16.0f]];
self.collectionView.showsVerticalScrollIndicator = NO;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.title = self.thread.name;
[self initializeNavigationBar];
[self initializeCollectionViewLayout];
self.senderId = ME_MESSAGE_IDENTIFIER
self.senderDisplayName = ME_MESSAGE_IDENTIFIER;
self.automaticallyScrollsToMostRecentMessage = YES;
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
self.senderDisplayName = ME_MESSAGE_IDENTIFIER
if (!isGroupConversation)
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
[self initializeObservers];
}
}
@ -131,6 +117,65 @@ typedef enum : NSUInteger {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
#pragma mark - Initiliazers
-(void)initializeNavigationBar
{
self.title = self.thread.name;
UIBarButtonItem * lockButton = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"lock"] style:UIBarButtonItemStylePlain target:self action:@selector(showFingerprint)];
if (!isGroupConversation && [self isRedPhoneReachable]) {
UIBarButtonItem * callButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"call_tab"] style:UIBarButtonItemStylePlain target:self action:@selector(callAction)];
[callButton setImageInsets:UIEdgeInsetsMake(0, -10, 0, -50)];
UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -8;
self.navigationItem.rightBarButtonItems = @[negativeSeparator, lockButton, callButton];
} else {
self.navigationItem.rightBarButtonItem = lockButton;
}
}
-(void)initializeBubbles
{
JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init];
self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor ows_blueColor]];
self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
self.outgoingMessageFailedImageData = [bubbleFactory outgoingMessageFailedBubbleImageWithColor:[UIColor ows_fadedBlueColor]];
}
-(void)initializeCollectionViewLayout
{
[self.collectionView.collectionViewLayout setMessageBubbleFont:[UIFont ows_lightFontWithSize:16.0f]];
self.collectionView.showsVerticalScrollIndicator = NO;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.automaticallyScrollsToMostRecentMessage = YES;
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
}
-(void)initializeObservers
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
#pragma mark - Keyboard Handlers
-(void)keyboardWillShow:(id)sender
@ -150,6 +195,29 @@ typedef enum : NSUInteger {
[self performSegueWithIdentifier:@"fingerprintSegue" sender:self];
}
#pragma mark - Calls
-(BOOL)isRedPhoneReachable
{
return [[Environment getCurrent].contactsManager isPhoneNumberRegisteredWithRedPhone:[self phoneNumberForThread]];
}
-(PhoneNumber*)phoneNumberForThread
{
NSString * contactId = [(TSContactThread*)self.thread contactIdentifier];
PhoneNumber * phoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:contactId];
return phoneNumber;
}
-(void)callAction
{
if ([self isRedPhoneReachable]) {
[Environment.phoneManager initiateOutgoingCallToRemoteNumber:[self phoneNumberForThread]];
} else {
DDLogWarn(@"Tried to initiate a call but contact has no RedPhone identifier");
}
}
#pragma mark - JSQMessage custom methods
-(void)updateMessageStatus:(JSQMessage*)message {
@ -211,27 +279,77 @@ typedef enum : NSUInteger {
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
/**
* Override point for customizing cells
*/
id<JSQMessageData> msg = [self messageAtIndexPath:indexPath];
TSMessageAdapter * msg = [self messageAtIndexPath:indexPath];
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
if (!msg.isMediaMessage) {
if ([msg.senderId isEqualToString:self.senderId]) {
cell.textView.textColor = [UIColor whiteColor];
}
else {
cell.textView.textColor = [UIColor blackColor];
}
switch (msg.messageType) {
case TSIncomingMessageAdapter:
return [self loadIncomingMessageCellForMessage:msg atIndexPath:indexPath];
break;
case TSOutgoingMessageAdapter:
return [self loadOutgoingCellForMessage:msg atIndexPath:indexPath];
break;
case TSCallAdapter:
return [self loadCallCellForCall:msg atIndexPath:indexPath];
break;
case TSInfoMessageAdapter:
return [self loadInfoMessageCellForMessage:msg atIndexPath:indexPath];
break;
case TSErrorMessageAdapter:
return [self loadErrorMessageCellForMessage:msg atIndexPath:indexPath];
break;
default:
NSLog(@"Something went wrong");
return nil;
break;
}
}
#pragma mark - Loading message cells
-(JSQMessagesCollectionViewCell*)loadIncomingMessageCellForMessage:(id<JSQMessageData>)message atIndexPath:(NSIndexPath*)indexPath
{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
if (!message.isMediaMessage)
{
cell.textView.textColor = [UIColor blackColor];
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
}
return cell;
}
-(JSQMessagesCollectionViewCell*)loadOutgoingCellForMessage:(id<JSQMessageData>)message atIndexPath:(NSIndexPath*)indexPath
{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
if (!message.isMediaMessage)
{
cell.textView.textColor = [UIColor whiteColor];
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
}
return cell;
}
-(JSQCallCollectionViewCell*)loadCallCellForCall:(id<JSQMessageData>)call atIndexPath:(NSIndexPath*)indexPath
{
JSQCallCollectionViewCell *cell = (JSQCallCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
return cell;
}
-(JSQDisplayedMessageCollectionViewCell *)loadInfoMessageCellForMessage:(id<JSQMessageData>)message atIndexPath:(NSIndexPath*)indexPath
{
JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
return cell;
}
-(JSQDisplayedMessageCollectionViewCell *)loadErrorMessageCellForMessage:(id<JSQMessageData>)message atIndexPath:(NSIndexPath*)indexPath
{
JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
return cell;
}
#pragma mark - Adjusting cell label heights
@ -239,16 +357,6 @@ typedef enum : NSUInteger {
- (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 ([self showDateAtIndexPath:indexPath]) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
@ -274,10 +382,64 @@ typedef enum : NSUInteger {
return showDate;
}
-(NSAttributedString*)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
TSMessageAdapter * msg = [self messageAtIndexPath:indexPath];
if ([self showDateAtIndexPath:indexPath])
{
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:msg.date];
}
return nil;
}
-(BOOL)shouldShowMessageStatusAtIndexPath:(NSIndexPath*)indexPath
{
TSMessageAdapter * currentMessage = [self messageAtIndexPath:indexPath];
if (indexPath.item == [self.collectionView numberOfItemsInSection:indexPath.section]-1)
{
return [self isMessageOutgoingAndDelivered:currentMessage];
}
TSMessageAdapter * nextMessage = [self messageAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]];
return ![self isMessageOutgoingAndDelivered:nextMessage] && [self isMessageOutgoingAndDelivered:currentMessage];
}
-(BOOL)isMessageOutgoingAndDelivered:(TSMessageAdapter*)message
{
return message.messageType == TSOutgoingMessageAdapter && message.messageState == TSOutgoingMessageStateDelivered;
}
-(NSAttributedString*)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
if ([self shouldShowMessageStatusAtIndexPath:indexPath])
{
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.bounds = CGRectMake(0, 0, 11.0f, 10.0f);
NSMutableAttributedString * attrStr = [[NSMutableAttributedString alloc]initWithString:@"Delivered"];
[attrStr appendAttributedString:[NSAttributedString attributedStringWithAttachment:textAttachment]];
return (NSAttributedString*)attrStr;
}
return nil;
}
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath
{
return 16.0f;
TSMessageAdapter * msg = [self messageAtIndexPath:indexPath];
if (msg.messageType == TSOutgoingMessageAdapter)
{
return 16.0f;
}
return 0.0f;
}
@ -285,9 +447,11 @@ typedef enum : NSUInteger {
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath
{
id<JSQMessageData> messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
TSMessageAdapter * messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
BOOL isMediaMessage = [messageItem isMediaMessage];
BOOL isMessage = (messageItem.messageType == TSIncomingMessageAdapter) || (messageItem.messageType == TSOutgoingMessageAdapter);
BOOL isMediaMessage = isMessage ? [messageItem isMediaMessage] : NO;
if (isMediaMessage) {
id<JSQMessageMediaData> messageMedia = [messageItem media];
@ -300,7 +464,38 @@ typedef enum : NSUInteger {
} else if ([messageMedia isKindOfClass:JSQVideoMediaItem.class]) {
//is a video
}
}
BOOL isUnsent = messageItem.messageState == TSOutgoingMessageStateUnsent || messageItem.messageState == TSOutgoingMessageStateAttemptingOut;
if (isMessage && isUnsent)
{
[DJWActionSheet showInView:self.tabBarController.view withTitle:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete" otherButtonTitles:@[@"Send again"] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
NSLog(@"User Cancelled");
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
[self.uiDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){
TSOutgoingMessage * message = (TSOutgoingMessage*)messageItem;
[message removeWithTransaction:transaction];
[self finishSendingMessage];
}];
}else {
switch (tappedButtonIndex) {
case 0:
{
TSOutgoingMessage * message = (TSOutgoingMessage*)messageItem;
[[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread];
[self finishSendingMessage];
break;
}
default:
break;
}
}
}];
}
}
@ -366,8 +561,9 @@ typedef enum : NSUInteger {
}
/*
* Fetch data from UIImagePickerController
* Fetching data from UIImagePickerController
*/
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage];
@ -380,7 +576,6 @@ typedef enum : NSUInteger {
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;

View file

@ -8,6 +8,8 @@
#import "SignalsNavigationController.h"
#import "UIUtil.h"
@interface SignalsNavigationController ()
@end
@ -33,7 +35,7 @@
CGRect bar = self.navigationBar.frame;
_socketStatusView.frame = CGRectMake(0, bar.size.height-1.0f, self.view.frame.size.width, 1.0f);
_socketStatusView.progressTintColor = [UIColor redColor];
_socketStatusView.progressTintColor = [UIColor ows_redColor];
_socketStatusView.progress = 1.0f;
[self.navigationBar addSubview:_socketStatusView];
}
@ -56,18 +58,18 @@
-(void)socketDidOpen
{
_socketStatusView.progressTintColor = [UIColor greenColor];
_socketStatusView.progressTintColor = [UIColor ows_greenColor];
}
-(void)socketDidClose
{
_socketStatusView.progressTintColor = [UIColor redColor];
_socketStatusView.progressTintColor = [UIColor ows_redColor];
}
-(void)socketIsConnecting
{
_socketStatusView.progressTintColor = [UIColor yellowColor];
_socketStatusView.progressTintColor = [UIColor ows_yellowColor];
}

View file

@ -15,8 +15,18 @@
#define ME_MESSAGE_IDENTIFIER @"Me";
typedef NS_ENUM(NSInteger, TSMessageAdapterType) {
TSIncomingMessageAdapter,
TSOutgoingMessageAdapter,
TSCallAdapter,
TSInfoMessageAdapter,
TSErrorMessageAdapter
};
@interface TSMessageAdapter : NSObject <JSQMessageData>
+ (instancetype)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread;
@property TSMessageAdapterType messageType;
@end

View file

@ -24,13 +24,24 @@
@property (nonatomic, retain) NSString *senderId;
@property (nonatomic, retain) NSString *senderDisplayName;
// for InfoMessages
@property NSInteger infoMessageType;
// for ErrorMessages
@property NSInteger errorMessageType;
// for outgoing Messages only
@property NSInteger outgoingMessageStatus;
// ---
@property (nonatomic, copy) NSDate *messageDate;
@property (nonatomic, retain) NSString *messageBody;
@property NSUInteger identifier;
@property NSInteger outgoingMessageStatus;
@end
@ -49,16 +60,18 @@
NSString *contactId = ((TSContactThread*)thread).contactIdentifier;
adapter.senderId = contactId;
adapter.senderDisplayName = contactId;
} else{
adapter.messageType = TSIncomingMessageAdapter;
} else {
adapter.senderId = ME_MESSAGE_IDENTIFIER;
adapter.senderDisplayName = @"Me";
adapter.messageType = TSOutgoingMessageAdapter;
}
} else if ([thread isKindOfClass:[TSGroupThread class]]){
if ([interaction isKindOfClass:[TSIncomingMessage class]]) {
TSIncomingMessage *message = (TSIncomingMessage*)interaction;
adapter.senderId = message.authorId;
adapter.senderDisplayName = message.authorId;
} else{
} else {
adapter.senderId = ME_MESSAGE_IDENTIFIER;
adapter.senderDisplayName = @"Me";
}
@ -69,10 +82,17 @@
adapter.messageBody = message.body;
} else if ([interaction isKindOfClass:[TSCall class]]){
adapter.messageBody = @"Placeholder for TSCalls";
adapter.messageType = TSCallAdapter;
} else if ([interaction isKindOfClass:[TSInfoMessage class]]){
TSInfoMessage * infoMessage = (TSInfoMessage*)interaction;
adapter.infoMessageType = infoMessage.messageType;
adapter.messageBody = @"Placeholder for InfoMessage";
} else{
adapter.messageType = TSInfoMessageAdapter;
} else {
TSErrorMessage * errorMessage = (TSErrorMessage*)interaction;
adapter.infoMessageType = errorMessage.errorType;
adapter.messageBody = @"Placeholder for ErrorMessage";
adapter.messageType = TSErrorMessageAdapter;
}
if ([interaction isKindOfClass:[TSOutgoingMessage class]]) {

View file

@ -1,6 +1,10 @@
#import "ContactTableViewCell.h"
#import "UIUtil.h"
#import "Environment.h"
#import "PhoneManager.h"
#import "DJWActionSheet.h"
#define CONTACT_TABLE_CELL_BORDER_WIDTH 1.0f
@interface ContactTableViewCell() {
@ -53,18 +57,20 @@
if (contact.isRedPhoneContact && _shouldShowContactButtons)
{
_callButton.imageView.image = [[UIImage imageNamed:@"call_dark"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_callButton.tintColor = [UIColor colorWithRed:0.f/255.f green:122.f/255.f blue:255.f/255.f alpha:1.0f];
UIImage * callImage = [[UIImage imageNamed:@"call_dark"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[_callButton setImage:callImage forState:UIControlStateNormal];
_callButton.tintColor = [UIColor ows_blueColor];
} else {
_callButton.hidden = YES;
[_callButton setImage:[UIImage imageNamed:@"call_dotted"] forState:UIControlStateNormal];
}
if (contact.isTextSecureContact && _shouldShowContactButtons)
{
_messageButton.imageView.image = [[UIImage imageNamed:@"signal"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_messageButton.tintColor = [UIColor colorWithRed:0.f/255.f green:122.f/255.f blue:255.f/255.f alpha:1.0f];
UIImage * messageImage = [[UIImage imageNamed:@"signal"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[_messageButton setImage:messageImage forState:UIControlStateNormal];
_messageButton.tintColor = [UIColor ows_blueColor];
} else {
_messageButton.hidden = YES;
[_messageButton setImage:[UIImage imageNamed:@"signal_dotted"] forState:UIControlStateNormal];
}
}
@ -95,12 +101,23 @@
-(IBAction)callContact:(id)sender
{
//Initiate Call to _associatedContact
if (_associatedContact.isRedPhoneContact) {
NSArray *redPhoneIdentifiers = [_associatedContact redPhoneIdentifiers];
[Environment.phoneManager initiateOutgoingCallToContact:_associatedContact atRemoteNumber:[redPhoneIdentifiers firstObject]];
} else{
DDLogWarn(@"Tried to intiate a call but contact has no RedPhone identifier");
}
}
-(IBAction)messageContact:(id)sender
{
//Load messages to _associatedContact
if (_associatedContact.isTextSecureContact) {
NSArray *textSecureIdentifiers = [_associatedContact textSecureIdentifiers];
[Environment messageIdentifier:[textSecureIdentifiers firstObject]];
} else{
DDLogWarn(@"Tried to intiate a call but contact has no RedPhone identifier");
}
}
@end

View file

@ -1,5 +1,5 @@
<?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">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14C68k" 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"/>
@ -59,7 +59,10 @@
<constraint firstItem="U3p-TB-rKO" firstAttribute="leading" secondItem="ecr-fm-JY4" secondAttribute="trailing" constant="7" id="7Ud-iJ-x8c">
<variation key="heightClass=regular-widthClass=compact" constant="14"/>
</constraint>
<constraint firstItem="ecr-fm-JY4" firstAttribute="centerY" secondItem="3" secondAttribute="centerY" constant="0.5" id="7ZG-hL-NmI"/>
<constraint firstItem="ecr-fm-JY4" firstAttribute="centerY" secondItem="U3p-TB-rKO" secondAttribute="centerY" id="AHF-1d-aoL"/>
<constraint firstItem="3" firstAttribute="top" secondItem="Ibd-RS-koG" secondAttribute="topMargin" constant="-4" id="H8v-R2-KWU"/>
<constraint firstItem="10" firstAttribute="centerY" secondItem="3" secondAttribute="centerY" id="Zfc-We-RZP"/>
<constraint firstAttribute="trailingMargin" secondItem="U3p-TB-rKO" secondAttribute="trailing" constant="5" id="beE-ap-SdR">
<variation key="heightClass=regular-widthClass=compact" constant="-2"/>
</constraint>
@ -70,6 +73,13 @@
<constraint firstAttribute="bottomMargin" secondItem="3" secondAttribute="bottom" constant="-4.5" id="vDP-VK-QhQ"/>
<constraint firstItem="ecr-fm-JY4" firstAttribute="top" secondItem="Ibd-RS-koG" secondAttribute="topMargin" constant="2" id="y3o-zx-jLL"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="3s2-cu-KLN"/>
<exclude reference="y3o-zx-jLL"/>
<exclude reference="qcJ-E0-XzW"/>
</mask>
</variation>
</tableViewCellContentView>
<connections>
<outlet property="callButton" destination="ecr-fm-JY4" id="zQa-g1-xnt"/>