From 5be2014ec72be0b1283c61cd4588c0f27d269fce Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 12 Sep 2017 10:14:17 -0400 Subject: [PATCH] Create Flat UI rounded button class. // FREEBIE --- Signal.xcodeproj/project.pbxproj | 20 +- Signal/src/Signal-Bridging-Header.h | 2 +- .../AttachmentApprovalViewController.swift | 22 +-- .../ViewControllers/CallViewController.swift | 34 ++-- .../CodeVerificationViewController.m | 46 +++-- .../ConversationViewController.m | 10 +- .../RegistrationViewController.m | 19 +- ...UIImage+normalizeImage.h => UIImage+OWS.h} | 3 + ...UIImage+normalizeImage.m => UIImage+OWS.m} | 56 ++++-- Signal/src/util/UIUtil.h | 2 +- Signal/src/views/OWSFlatButton.swift | 174 ++++++++++++++++++ 11 files changed, 293 insertions(+), 95 deletions(-) rename Signal/src/util/{UIImage+normalizeImage.h => UIImage+OWS.h} (76%) rename Signal/src/util/{UIImage+normalizeImage.m => UIImage+OWS.m} (81%) create mode 100644 Signal/src/views/OWSFlatButton.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 36c2470a4..b3903807f 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -74,6 +74,7 @@ 34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */; }; 34B3F89F1E8DF5490035BE1A /* OWSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */; }; 34B3F8A21E8EA6040035BE1A /* ViewControllerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */; }; + 34C04D801F6195E6004308B3 /* OWSFlatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C04D7F1F6195E6004308B3 /* OWSFlatButton.swift */; }; 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */; }; 34C42D611F4734CA0072EC04 /* OWSContactOffersCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D601F4734CA0072EC04 /* OWSContactOffersCell.m */; }; 34C42D661F4734ED0072EC04 /* OWSContactOffersInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D631F4734ED0072EC04 /* OWSContactOffersInteraction.m */; }; @@ -324,7 +325,7 @@ B660F7721C29988E00687D6E /* AppStoreRating.m in Sources */ = {isa = PBXBuildFile; fileRef = B6DA6B061B8A2F9A00CA6F98 /* AppStoreRating.m */; }; B660F7751C29988E00687D6E /* UIColor+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA64B31A24F3880007FB87 /* UIColor+OWS.m */; }; B660F7761C29988E00687D6E /* UIFont+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA64B61A24F6730007FB87 /* UIFont+OWS.m */; }; - B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */; }; + B660F7771C29988E00687D6E /* UIImage+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+OWS.m */; }; B660F77B1C29988E00687D6E /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D518170B33006006FC /* Queue.m */; }; B660F77F1C29988E00687D6E /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; B660F7811C29988E00687D6E /* FunctionalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EB18170B33006006FC /* FunctionalUtil.m */; }; @@ -335,7 +336,7 @@ B660F78C1C29988E00687D6E /* UIDevice+TSHardwareVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */; }; B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; }; B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; }; - B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */; }; + B68112EA1A4D9EC400BA82FF /* UIImage+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+OWS.m */; }; B68EF9BA1C0B1EBD009C3DCD /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B71C0B1EBD009C3DCD /* FLAnimatedImage.m */; }; B68EF9BB1C0B1EBD009C3DCD /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B91C0B1EBD009C3DCD /* FLAnimatedImageView.m */; }; B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; }; @@ -519,6 +520,7 @@ 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = ""; }; 34B3F8A01E8EA6040035BE1A /* ViewControllerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewControllerUtils.h; sourceTree = ""; }; 34B3F8A11E8EA6040035BE1A /* ViewControllerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewControllerUtils.m; sourceTree = ""; }; + 34C04D7F1F6195E6004308B3 /* OWSFlatButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSFlatButton.swift; sourceTree = ""; }; 34C42D591F45F7A80072EC04 /* OWSNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSNavigationController.h; sourceTree = ""; }; 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSNavigationController.m; sourceTree = ""; }; 34C42D5F1F4734CA0072EC04 /* OWSContactOffersCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactOffersCell.h; sourceTree = ""; }; @@ -808,8 +810,8 @@ B676BCF01AA544F5009637B8 /* el_GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el_GR; path = translations/el_GR.lproj/Localizable.strings; sourceTree = ""; }; B676BCF11AA5451E009637B8 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = translations/es.lproj/Localizable.strings; sourceTree = ""; }; B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; }; - B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+normalizeImage.h"; path = "util/UIImage+normalizeImage.h"; sourceTree = ""; }; - B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+normalizeImage.m"; path = "util/UIImage+normalizeImage.m"; sourceTree = ""; }; + B68112E81A4D9EC400BA82FF /* UIImage+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+OWS.h"; path = "util/UIImage+OWS.h"; sourceTree = ""; }; + B68112E91A4D9EC400BA82FF /* UIImage+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+OWS.m"; path = "util/UIImage+OWS.m"; sourceTree = ""; }; B68CB7D71AA546B80065AC3F /* ko_KR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko_KR; path = translations/ko_KR.lproj/Localizable.strings; sourceTree = ""; }; B68CB7D81AA546C30065AC3F /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = translations/lv.lproj/Localizable.strings; sourceTree = ""; }; B68CB7D91AA546CE0065AC3F /* nb_NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb_NO; path = translations/nb_NO.lproj/Localizable.strings; sourceTree = ""; }; @@ -1498,6 +1500,7 @@ 450873C91D9D86F4006B54F2 /* OWSExpirableMessageView.h */, 450873C11D9D5149006B54F2 /* OWSExpirationTimerView.h */, 450873C21D9D5149006B54F2 /* OWSExpirationTimerView.m */, + 34C04D7F1F6195E6004308B3 /* OWSFlatButton.swift */, 450873C51D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.h */, 450873C61D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m */, 45F2B1951D9CA207000D2C69 /* OWSIncomingMessageCollectionViewCell.xib */, @@ -1807,8 +1810,8 @@ FCFA64B31A24F3880007FB87 /* UIColor+OWS.m */, FCFA64B51A24F6730007FB87 /* UIFont+OWS.h */, FCFA64B61A24F6730007FB87 /* UIFont+OWS.m */, - B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */, - B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */, + B68112E81A4D9EC400BA82FF /* UIImage+OWS.h */, + B68112E91A4D9EC400BA82FF /* UIImage+OWS.m */, 34535D801E256BE9008A4747 /* UIView+OWS.h */, 34535D811E256BE9008A4747 /* UIView+OWS.m */, EF764C331DB67CC5000D9A87 /* UIViewController+CameraPermissions.h */, @@ -2246,6 +2249,7 @@ FCFA64B71A24F6730007FB87 /* UIFont+OWS.m in Sources */, B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */, 45DF5DF21DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */, + 34C04D801F6195E6004308B3 /* OWSFlatButton.swift in Sources */, 458DE9D91DEE7B360071BB03 /* OWSWebRTCDataProtos.pb.m in Sources */, B62D53F71A23CCAD009AAF82 /* TSMessageAdapter.m in Sources */, 76EB063C18170B33006006FC /* NumberUtil.m in Sources */, @@ -2373,7 +2377,7 @@ 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */, BFB074C919A5611000F2947C /* ObservableValue.m in Sources */, B68EF9BA1C0B1EBD009C3DCD /* FLAnimatedImage.m in Sources */, - B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */, + B68112EA1A4D9EC400BA82FF /* UIImage+OWS.m in Sources */, B609597C1C2C0FC6004E8797 /* iRate.m in Sources */, 4574A5D61DD6704700C6B692 /* CallService.swift in Sources */, 34B3F8721E8DF1700035BE1A /* AdvancedSettingsTableViewController.m in Sources */, @@ -2463,7 +2467,7 @@ B660F7721C29988E00687D6E /* AppStoreRating.m in Sources */, B660F7751C29988E00687D6E /* UIColor+OWS.m in Sources */, B660F7761C29988E00687D6E /* UIFont+OWS.m in Sources */, - B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */, + B660F7771C29988E00687D6E /* UIImage+OWS.m in Sources */, 954AEE6A1DF33E01002E5410 /* ContactsPickerTest.swift in Sources */, B660F77B1C29988E00687D6E /* Queue.m in Sources */, 455AC69C1F4F79E500134004 /* ImageCache.swift in Sources */, diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index 130670cf0..7b2e1228c 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -34,7 +34,7 @@ #import "TSMessageAdapter.h" #import "UIColor+OWS.h" #import "UIFont+OWS.h" -#import "UIImage+normalizeImage.h" +#import "UIImage+OWS.h" #import "UIUtil.h" #import "UIView+OWS.h" #import "ViewControllerUtils.h" diff --git a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift index b98b7d8cd..3d8e384fa 100644 --- a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift +++ b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift @@ -370,23 +370,17 @@ class AttachmentApprovalViewController: OWSViewController, OWSAudioAttachmentPla sendButton.autoPinEdge(.left, to:.right, of:buttonSpacer) } - private func createButton(title: String, color: UIColor, action: Selector) -> UIButton { - let buttonFont = UIFont.ows_mediumFont(withSize:ScaleFromIPhone5To7Plus(18, 22)) - let buttonCornerRadius = ScaleFromIPhone5To7Plus(4, 5) + private func createButton(title: String, color: UIColor, action: Selector) -> UIView { let buttonWidth = ScaleFromIPhone5To7Plus(110, 140) let buttonHeight = ScaleFromIPhone5To7Plus(35, 45) - let button = UIButton() - button.setTitle(title, for:.normal) - button.setTitleColor(UIColor.white, for:.normal) - button.titleLabel!.font = buttonFont - button.backgroundColor = color - button.layer.cornerRadius = buttonCornerRadius - button.clipsToBounds = true - button.addTarget(self, action:action, for:.touchUpInside) - button.autoSetDimension(.width, toSize:buttonWidth) - button.autoSetDimension(.height, toSize:buttonHeight) - return button + return OWSFlatButton.button(title:title, + titleColor:UIColor.white, + backgroundColor:color, + width:buttonWidth, + height:buttonHeight, + target:target, + selector:action) } // MARK: - Event Handlers diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 053412e55..d4d944c91 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -285,33 +285,27 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, settingsNagDescriptionLabel.autoPinEdge(toSuperviewEdge:.top) let buttonHeight = ScaleFromIPhone5To7Plus(35, 45) - let buttonFont = UIFont.ows_regularFont(withSize:ScaleFromIPhone5To7Plus(14, 18)) - let buttonCornerRadius = CGFloat(4) let descriptionVSpacingHeight = ScaleFromIPhone5To7Plus(30, 60) - let callSettingsButton = UIButton() - callSettingsButton.setTitle(NSLocalizedString("CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS", - comment: "Label for button that shows the privacy settings"), for:.normal) - callSettingsButton.setTitleColor(UIColor.white, for:.normal) - callSettingsButton.titleLabel!.font = buttonFont - callSettingsButton.addTarget(self, action:#selector(didPressShowCallSettings), for:.touchUpInside) - callSettingsButton.backgroundColor = UIColor.ows_signalBrandBlue() - callSettingsButton.layer.cornerRadius = buttonCornerRadius - callSettingsButton.clipsToBounds = true + let callSettingsButton = OWSFlatButton.button(title:NSLocalizedString("CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS", + comment: "Label for button that shows the privacy settings."), + font:OWSFlatButton.fontForHeight(buttonHeight), + titleColor:UIColor.white, + backgroundColor:UIColor.ows_signalBrandBlue(), + target:self, + selector:#selector(didPressShowCallSettings)) viewStack.addSubview(callSettingsButton) callSettingsButton.autoSetDimension(.height, toSize:buttonHeight) callSettingsButton.autoPinWidthToSuperview() callSettingsButton.autoPinEdge(.top, to:.bottom, of:settingsNagDescriptionLabel, withOffset:descriptionVSpacingHeight) - let notNowButton = UIButton() - notNowButton.setTitle(NSLocalizedString("CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON", - comment: "Label for button that dismiss the call view's settings nag."), for:.normal) - notNowButton.setTitleColor(UIColor.white, for:.normal) - notNowButton.titleLabel!.font = buttonFont - notNowButton.addTarget(self, action:#selector(didPressDismissNag), for:.touchUpInside) - notNowButton.backgroundColor = UIColor.ows_signalBrandBlue() - notNowButton.layer.cornerRadius = buttonCornerRadius - notNowButton.clipsToBounds = true + let notNowButton = OWSFlatButton.button(title:NSLocalizedString("CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON", + comment: "Label for button that dismiss the call view's settings nag."), + font:OWSFlatButton.fontForHeight(buttonHeight), + titleColor:UIColor.white, + backgroundColor:UIColor.ows_signalBrandBlue(), + target:self, + selector:#selector(didPressDismissNag)) viewStack.addSubview(notNowButton) notNowButton.autoSetDimension(.height, toSize:buttonHeight) notNowButton.autoPinWidthToSuperview() diff --git a/Signal/src/ViewControllers/CodeVerificationViewController.m b/Signal/src/ViewControllers/CodeVerificationViewController.m index 3040e5224..4773697dd 100644 --- a/Signal/src/ViewControllers/CodeVerificationViewController.m +++ b/Signal/src/ViewControllers/CodeVerificationViewController.m @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) UILabel *phoneNumberLabel; //// User action buttons -@property (nonatomic) UIButton *challengeButton; +@property (nonatomic) OWSFlatButton *submitButton; @property (nonatomic) UIButton *sendCodeViaSMSAgainButton; @property (nonatomic) UIButton *sendCodeViaVoiceButton; @@ -154,28 +154,27 @@ NS_ASSUME_NONNULL_BEGIN withOffset:3]; [underscoreView autoPinWidthToSuperviewWithMargin:kHMargin]; [underscoreView autoSetDimension:ALDimensionHeight toSize:1.f]; - - _challengeButton = [UIButton buttonWithType:UIButtonTypeCustom]; - _challengeButton.backgroundColor = signalBlueColor; - [_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"button text during registration to submit your SMS verification code") - forState:UIControlStateNormal]; - [_challengeButton setTitleColor:[UIColor whiteColor] - forState:UIControlStateNormal]; - _challengeButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f]; - [_challengeButton addTarget:self - action:@selector(verifyChallengeAction:) - forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:_challengeButton]; - [_challengeButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:underscoreView - withOffset:15]; - [_challengeButton autoPinWidthToSuperviewWithMargin:kHMargin]; - [_challengeButton autoSetDimension:ALDimensionHeight toSize:47.f]; + + const CGFloat kSubmitButtonHeight = 47.f; + OWSFlatButton *submitButton = + [OWSFlatButton buttonWithTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", + @"button text during registration to submit your SMS verification code.") + font:[OWSFlatButton fontForHeight:kSubmitButtonHeight] + titleColor:[UIColor whiteColor] + backgroundColor:[UIColor ows_signalBrandBlueColor] + target:self + selector:@selector(submitVerificationCode)]; + self.submitButton = submitButton; + [self.view addSubview:_submitButton]; + [_submitButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:underscoreView withOffset:15]; + [_submitButton autoPinWidthToSuperviewWithMargin:kHMargin]; + [_submitButton autoSetDimension:ALDimensionHeight toSize:47.f]; const CGFloat kSpinnerSize = 20; const CGFloat kSpinnerSpacing = ScaleFromIPhone5To7Plus(5, 15); _submitCodeSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; - [_challengeButton addSubview:_submitCodeSpinner]; + [_submitButton addSubview:_submitCodeSpinner]; [_submitCodeSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize]; [_submitCodeSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize]; [_submitCodeSpinner autoVCenterInSuperview]; @@ -192,8 +191,7 @@ NS_ASSUME_NONNULL_BEGIN action:@selector(sendCodeViaSMSAction:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_sendCodeViaSMSAgainButton]; - [_sendCodeViaSMSAgainButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_challengeButton - withOffset:10]; + [_sendCodeViaSMSAgainButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_submitButton withOffset:10]; [_sendCodeViaSMSAgainButton autoPinWidthToSuperviewWithMargin:kHMargin]; [_sendCodeViaSMSAgainButton autoSetDimension:ALDimensionHeight toSize:35]; @@ -255,7 +253,7 @@ NS_ASSUME_NONNULL_BEGIN [self.submitCodeSpinner stopAnimating]; } -- (void)verifyChallengeAction:(nullable id)sender +- (void)submitVerificationCode { [self startActivityIndicator]; OWSProdInfo([OWSAnalyticsEvents registrationRegisteringCode]); @@ -368,7 +366,7 @@ NS_ASSUME_NONNULL_BEGIN } - (void)enableServerActions:(BOOL)enabled { - [_challengeButton setEnabled:enabled]; + [_submitButton setEnabled:enabled]; [_sendCodeViaSMSAgainButton setEnabled:enabled]; [_sendCodeViaVoiceButton setEnabled:enabled]; } @@ -452,7 +450,7 @@ NS_ASSUME_NONNULL_BEGIN } - (BOOL)textFieldShouldReturn:(UITextField *)textField { - [self verifyChallengeAction:nil]; + [self submitVerificationCode]; [textField resignFirstResponder]; return NO; } @@ -469,7 +467,7 @@ NS_ASSUME_NONNULL_BEGIN UITextPosition *newPosition = [self.challengeTextField endOfDocument]; self.challengeTextField.selectedTextRange = [self.challengeTextField textRangeFromPosition:newPosition toPosition:newPosition]; - [self verifyChallengeAction:nil]; + [self submitVerificationCode]; } #pragma mark - Logging diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 680abbaef..61d690744 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -1235,9 +1235,10 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { name = [[NSAttributedString alloc] initWithString:self.thread.name]; } } else { + OWSAssert(self.thread.contactIdentifier); name = [self.contactsManager attributedStringForConversationTitleWithPhoneIdentifier:self.thread.contactIdentifier - primaryFont:self.navigationBarTitleLabel.font + primaryFont:[self navigationBarTitleLabelFont] secondaryFont:[UIFont ows_footnoteFont]]; } self.title = nil; @@ -1282,7 +1283,7 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { self.navigationBarTitleLabel = [UILabel new]; self.navigationBarTitleView.titleLabel = self.navigationBarTitleLabel; self.navigationBarTitleLabel.textColor = [UIColor whiteColor]; - self.navigationBarTitleLabel.font = [UIFont ows_boldFontWithSize:20.f]; + self.navigationBarTitleLabel.font = [self navigationBarTitleLabelFont]; self.navigationBarTitleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [self.navigationBarTitleView addSubview:self.navigationBarTitleLabel]; @@ -1292,6 +1293,11 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { [self.navigationBarTitleView addSubview:self.navigationBarSubtitleLabel]; } +- (UIFont *)navigationBarTitleLabelFont +{ + return [UIFont ows_boldFontWithSize:20.f]; +} + - (CGFloat)unreadCountViewDiameter { return 16; diff --git a/Signal/src/ViewControllers/RegistrationViewController.m b/Signal/src/ViewControllers/RegistrationViewController.m index 49c6a1a18..f47cfa638 100644 --- a/Signal/src/ViewControllers/RegistrationViewController.m +++ b/Signal/src/ViewControllers/RegistrationViewController.m @@ -32,7 +32,7 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi @property (nonatomic) UILabel *countryCodeLabel; @property (nonatomic) UITextField *phoneNumberTextField; @property (nonatomic) UILabel *examplePhoneNumberLabel; -@property (nonatomic) UIButton *activateButton; +@property (nonatomic) OWSFlatButton *activateButton; @property (nonatomic) UIActivityIndicatorView *spinnerView; @end @@ -198,22 +198,21 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi [separatorView2 autoSetDimension:ALDimensionHeight toSize:kSeparatorHeight]; // Activate Button - UIButton *activateButton = [UIButton buttonWithType:UIButtonTypeCustom]; + const CGFloat kActivateButtonHeight = 47.f; + OWSFlatButton *activateButton = [OWSFlatButton buttonWithTitle:NSLocalizedString(@"REGISTRATION_VERIFY_DEVICE", @"") + font:[OWSFlatButton fontForHeight:kActivateButtonHeight] + titleColor:[UIColor whiteColor] + backgroundColor:[UIColor ows_signalBrandBlueColor] + target:self + selector:@selector(sendCodeAction)]; self.activateButton = activateButton; - activateButton.backgroundColor = [UIColor ows_signalBrandBlueColor]; - [activateButton setTitle:NSLocalizedString(@"REGISTRATION_VERIFY_DEVICE", @"") forState:UIControlStateNormal]; - [activateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - activateButton.titleLabel.font = [UIFont ows_boldFontWithSize:fontSizePoints]; - [activateButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter]; - [activateButton setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter]; [contentView addSubview:activateButton]; [activateButton autoPinLeadingAndTrailingToSuperview]; [activateButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:separatorView2 withOffset:ScaleFromIPhone5To7Plus(12.f, 15.f)]; - [activateButton autoSetDimension:ALDimensionHeight toSize:47.f]; - [activateButton addTarget:self action:@selector(sendCodeAction) forControlEvents:UIControlEventTouchUpInside]; + [activateButton autoSetDimension:ALDimensionHeight toSize:kActivateButtonHeight]; UIActivityIndicatorView *spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; diff --git a/Signal/src/util/UIImage+normalizeImage.h b/Signal/src/util/UIImage+OWS.h similarity index 76% rename from Signal/src/util/UIImage+normalizeImage.h rename to Signal/src/util/UIImage+OWS.h index 5a9f601f8..782d7fdeb 100644 --- a/Signal/src/util/UIImage+normalizeImage.h +++ b/Signal/src/util/UIImage+OWS.h @@ -12,4 +12,7 @@ - (UIImage *)resizedImageToSize:(CGSize)dstSize; - (UIImage *)resizedImageToFillPixelSize:(CGSize)boundingSize; ++ (UIImage *)imageWithColor:(UIColor *)color; ++ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size; + @end diff --git a/Signal/src/util/UIImage+normalizeImage.m b/Signal/src/util/UIImage+OWS.m similarity index 81% rename from Signal/src/util/UIImage+normalizeImage.m rename to Signal/src/util/UIImage+OWS.m index e5b25ffcd..1532f9f3a 100644 --- a/Signal/src/util/UIImage+normalizeImage.m +++ b/Signal/src/util/UIImage+OWS.m @@ -2,26 +2,28 @@ // Copyright (c) 2017 Open Whisper Systems. All rights reserved. // -#import "UIImage+normalizeImage.h" +#import "UIImage+OWS.h" @implementation UIImage (normalizeImage) -- (UIImage *)normalizedImage { +- (UIImage *)normalizedImage +{ if (self.imageOrientation == UIImageOrientationUp) { return self; } UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); - [self drawInRect:(CGRect){{0, 0}, self.size}]; + [self drawInRect:(CGRect){ { 0, 0 }, self.size }]; UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return normalizedImage; } -- (UIImage *)resizedWithQuality:(CGInterpolationQuality)quality rate:(CGFloat)rate { +- (UIImage *)resizedWithQuality:(CGInterpolationQuality)quality rate:(CGFloat)rate +{ UIImage *resized = nil; - CGFloat width = self.size.width * rate; - CGFloat height = self.size.height * rate; + CGFloat width = self.size.width * rate; + CGFloat height = self.size.height * rate; UIGraphicsBeginImageContext(CGSizeMake(width, height)); CGContextRef context = UIGraphicsGetCurrentContext(); @@ -35,11 +37,11 @@ // Source: https://github.com/AliSoftware/UIImage-Resize -- (UIImage *)resizedImageToSize:(CGSize)dstSize { +- (UIImage *)resizedImageToSize:(CGSize)dstSize +{ CGImageRef imgRef = self.CGImage; // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) - CGSize srcSize = CGSizeMake( - CGImageGetWidth(imgRef), + CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! /* Don't resize if we already meet the required destination size. */ @@ -47,8 +49,8 @@ return self; } - CGFloat scaleRatio = dstSize.width / srcSize.width; - UIImageOrientation orient = self.imageOrientation; + CGFloat scaleRatio = dstSize.width / srcSize.width; + UIImageOrientation orient = self.imageOrientation; CGAffineTransform transform = CGAffineTransformIdentity; switch (orient) { case UIImageOrientationUp: // EXIF = 1 @@ -71,26 +73,26 @@ break; case UIImageOrientationLeftMirrored: // EXIF = 5 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); transform = CGAffineTransformScale(transform, -1.0, 1.0); transform = CGAffineTransformRotate(transform, (CGFloat)(3.0f * M_PI_2)); break; case UIImageOrientationLeft: // EXIF = 6 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(0.0, srcSize.width); transform = CGAffineTransformRotate(transform, (CGFloat)(3.0 * M_PI_2)); break; case UIImageOrientationRightMirrored: // EXIF = 7 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeScale(-1.0, 1.0); transform = CGAffineTransformRotate(transform, (CGFloat)M_PI_2); break; case UIImageOrientationRight: // EXIF = 8 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0); transform = CGAffineTransformRotate(transform, (CGFloat)M_PI_2); break; @@ -166,4 +168,28 @@ return dstImage; } ++ (UIImage *)imageWithColor:(UIColor *)color +{ + OWSAssert(color); + + return [self imageWithColor:color size:CGSizeMake(1.f, 1.f)]; +} + ++ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size +{ + OWSAssert(color); + + CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.f); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextClearRect(context, rect); + CGContextSetFillColorWithColor(context, [color CGColor]); + CGContextFillRect(context, rect); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + @end diff --git a/Signal/src/util/UIUtil.h b/Signal/src/util/UIUtil.h index d2aea1262..315805eee 100644 --- a/Signal/src/util/UIUtil.h +++ b/Signal/src/util/UIUtil.h @@ -7,7 +7,7 @@ #import "MIMETypeUtil.h" #import "UIColor+OWS.h" #import "UIFont+OWS.h" -#import "UIImage+normalizeImage.h" +#import "UIImage+OWS.h" typedef void (^completionBlock)(void); diff --git a/Signal/src/views/OWSFlatButton.swift b/Signal/src/views/OWSFlatButton.swift new file mode 100644 index 000000000..e65252811 --- /dev/null +++ b/Signal/src/views/OWSFlatButton.swift @@ -0,0 +1,174 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import Foundation + +@objc class OWSFlatButton: UIView { + let TAG = "[OWSFlatButton]" + + private var button: UIButton? + + private var pressedBlock : (() -> Void)? + + private var upColor: UIColor? + private var downColor: UIColor? + + init() { + AssertIsOnMainThread() + + super.init(frame:CGRect.zero) + + createContent() + } + + @available(*, unavailable, message:"use default constructor instead.") + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + owsFail("\(self.TAG) invalid constructor") + } + + private func createContent() { + let button = UIButton(type:.custom) + self.button = button + self.addSubview(button) + button.addTarget(self, action:#selector(buttonPressed), for:.touchUpInside) + button.autoPinWidthToSuperview() + button.autoPinHeightToSuperview() + } + + public class func button(title: String, + font: UIFont, + titleColor: UIColor, + backgroundColor: UIColor, + width: CGFloat, + height: CGFloat, + target:Any, + selector: Selector) -> OWSFlatButton { + let button = OWSFlatButton() + button.setTitle(title:title, + font: font, + titleColor: titleColor ) + button.setBackgroundColors(backgroundColor) + button.useDefaultCornerRadius() + button.setSize(width:width, height:height) + button.addTarget(target:target, selector:selector) + return button + } + + public class func button(title: String, + titleColor: UIColor, + backgroundColor: UIColor, + width: CGFloat, + height: CGFloat, + target:Any, + selector: Selector) -> OWSFlatButton { + return OWSFlatButton.button(title:title, + font:fontForHeight(height), + titleColor:titleColor, + backgroundColor:backgroundColor, + width:width, + height:height, + target:target, + selector:selector) + } + + public class func button(title: String, + font: UIFont, + titleColor: UIColor, + backgroundColor: UIColor, + target:Any, + selector: Selector) -> OWSFlatButton { + let button = OWSFlatButton() + button.setTitle(title:title, + font: font, + titleColor: titleColor ) + button.setBackgroundColors(backgroundColor) + button.useDefaultCornerRadius() + button.addTarget(target:target, selector:selector) + return button + } + + public class func fontForHeight(_ height: CGFloat) -> UIFont { + let fontPointSize = round(height * 0.45) + return UIFont.ows_mediumFont(withSize:fontPointSize)! + } + + // MARK: Methods + + public func setTitle(title: String, font: UIFont, + titleColor: UIColor ) { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.setTitle(title, for: .normal) + button.setTitleColor(titleColor, for: .normal) + button.titleLabel!.font = font + } + + public func setBackgroundColors(upColor: UIColor, + downColor: UIColor ) { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.setBackgroundImage(UIImage(color:upColor), for: .normal) + button.setBackgroundImage(UIImage(color:downColor), for: .highlighted) + } + + public func setBackgroundColors(_ backgroundColor: UIColor ) { + setBackgroundColors(upColor: backgroundColor, + downColor: backgroundColor.withAlphaComponent(0.7) ) + } + + public func setSize(width: CGFloat, height: CGFloat) { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.autoSetDimension(.width, toSize:width) + button.autoSetDimension(.height, toSize:height) + } + + public func useDefaultCornerRadius() { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.layer.cornerRadius = ScaleFromIPhone5To7Plus(4, 5) + button.clipsToBounds = true + } + + public func setEnabled(_ isEnabled: Bool) { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.isEnabled = isEnabled + } + + public func addTarget(target:Any, + selector: Selector) { + guard let button = self.button else { + owsFail("Missing button") + return + } + button.addTarget(target, action:selector, for:.touchUpInside) + } + + public func setPressedBlock(_ pressedBlock: @escaping () -> Void) { + guard self.pressedBlock == nil else { + owsFail("Button already has pressed block.") + return + } + self.pressedBlock = pressedBlock + } + + internal func buttonPressed() { + guard let pressedBlock = pressedBlock else { + return + } + pressedBlock() + } +}