diff --git a/Signal/Images.xcassets/searchbar_clear.imageset/Contents.json b/Signal/Images.xcassets/searchbar_clear.imageset/Contents.json new file mode 100644 index 000000000..0b4042676 --- /dev/null +++ b/Signal/Images.xcassets/searchbar_clear.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Search-clear_17x17_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Search-clear_17x17_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Search-clear_17x17_@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@1x.png b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@1x.png new file mode 100644 index 000000000..3310dbc42 Binary files /dev/null and b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@1x.png differ diff --git a/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@2x.png b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@2x.png new file mode 100644 index 000000000..f750f3eea Binary files /dev/null and b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@2x.png differ diff --git a/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@3x.png b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@3x.png new file mode 100644 index 000000000..c367e8eb7 Binary files /dev/null and b/Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@3x.png differ diff --git a/Signal/Images.xcassets/searchbar_search.imageset/Contents.json b/Signal/Images.xcassets/searchbar_search.imageset/Contents.json new file mode 100644 index 000000000..b3a1189bc --- /dev/null +++ b/Signal/Images.xcassets/searchbar_search.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "UIButtonBarSearch_18x18_@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "UIButtonBarSearch_18x18_@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "UIButtonBarSearch_18x18_@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@1x.png b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@1x.png new file mode 100644 index 000000000..0d99c7a9c Binary files /dev/null and b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@1x.png differ diff --git a/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@2x.png b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@2x.png new file mode 100644 index 000000000..a2052f53c Binary files /dev/null and b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@2x.png differ diff --git a/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@3x.png b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@3x.png new file mode 100644 index 000000000..b017f2397 Binary files /dev/null and b/Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@3x.png differ diff --git a/Signal/src/ViewControllers/ContactsPicker.swift b/Signal/src/ViewControllers/ContactsPicker.swift index f629c749a..62286243a 100644 --- a/Signal/src/ViewControllers/ContactsPicker.swift +++ b/Signal/src/ViewControllers/ContactsPicker.swift @@ -26,10 +26,10 @@ public enum SubtitleCellValue: Int { } @objc -public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate { +public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableViewDataSource, OWSSearchBarDelegate { var tableView: UITableView! - var searchBar: UISearchBar! + var searchBar: OWSSearchBar! // MARK: - Properties @@ -336,7 +336,11 @@ public class ContactsPicker: OWSViewController, UITableViewDelegate, UITableView } // MARK: - Search Actions - open func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + open func searchBar(_ searchBar: OWSSearchBar, textDidChange searchText: String) { + updateSearchResults(searchText: searchText) + } + + open func searchBar(_ searchBar: OWSSearchBar, returnWasPressed searchText: String) { updateSearchResults(searchText: searchText) } diff --git a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift index 39be0c880..4c628a922 100644 --- a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift +++ b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift @@ -12,7 +12,7 @@ protocol GifPickerViewControllerDelegate: class { func gifPickerDidSelect(attachment: SignalAttachment) } -class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegate, GifPickerLayoutDelegate { +class GifPickerViewController: OWSViewController, OWSSearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegate, GifPickerLayoutDelegate { // MARK: Properties @@ -36,7 +36,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect let thread: TSThread let messageSender: MessageSender - let searchBar: UISearchBar + let searchBar: OWSSearchBar let layout: GifPickerLayout let collectionView: UICollectionView var noResultsView: UILabel? @@ -423,9 +423,9 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect dismiss(animated: true, completion: nil) } - // MARK: - UISearchBarDelegate + // MARK: - OWSSearchBarDelegate - public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + public func searchBar(_ searchBar: OWSSearchBar, textDidChange searchText: String) { // Clear error messages immediately. if viewMode == .error || viewMode == .noResults { viewMode = .idle @@ -444,7 +444,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect } } - public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { + public func searchBar(_ searchBar: OWSSearchBar, returnWasPressed searchText: String) { self.searchBar.resignFirstResponder() tryToSearch() diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index b78a7fdb0..79a92efff 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -63,7 +63,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations @interface HomeViewController () @property (nonatomic) UITableView *tableView; @@ -82,7 +82,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations // Mark: Search -@property (nonatomic, readonly) UISearchBar *searchBar; +@property (nonatomic, readonly) OWSSearchBar *searchBar; @property (nonatomic) ConversationSearchViewController *searchResultsController; // Dependencies @@ -398,7 +398,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations // Search - UISearchBar *searchBar = [OWSSearchBar new]; + OWSSearchBar *searchBar = [OWSSearchBar new]; _searchBar = searchBar; searchBar.placeholder = NSLocalizedString(@"HOME_VIEW_CONVERSATION_SEARCHBAR_PLACEHOLDER", @"Placeholder text for search bar which filters conversations."); @@ -978,51 +978,23 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations } } -#pragma mark - UISearchBarDelegate +#pragma mark - OWSSearchBarDelegate -- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar +- (void)searchBar:(OWSSearchBar *)searchBar textDidChange:(NSString *)text { - [self scrollSearchBarToTopAnimated:NO]; - [self updateSearchResultsVisibility]; - - [self ensureSearchBarCancelButton]; } -- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar +- (void)searchBar:(OWSSearchBar *)searchBar returnWasPressed:(NSString *)text { [self updateSearchResultsVisibility]; - - [self ensureSearchBarCancelButton]; } -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText +- (void)searchBarDidBeginEditing:(OWSSearchBar *)searchBar { - [self updateSearchResultsVisibility]; - - [self ensureSearchBarCancelButton]; -} - -- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar -{ - [self updateSearchResultsVisibility]; -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar -{ - self.searchBar.text = nil; - - [self.searchBar resignFirstResponder]; - OWSAssert(!self.searchBar.isFirstResponder); + [self scrollSearchBarToTopAnimated:NO]; [self updateSearchResultsVisibility]; - - [self ensureSearchBarCancelButton]; -} - -- (void)ensureSearchBarCancelButton -{ - self.searchBar.showsCancelButton = (self.searchBar.isFirstResponder || self.searchBar.text.length > 0); } - (void)updateSearchResultsVisibility diff --git a/Signal/src/ViewControllers/NewContactThreadViewController.m b/Signal/src/ViewControllers/NewContactThreadViewController.m index 30b192bb3..c3d40859b 100644 --- a/Signal/src/ViewControllers/NewContactThreadViewController.m +++ b/Signal/src/ViewControllers/NewContactThreadViewController.m @@ -38,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface NewContactThreadViewController () -@interface CountryCodeViewController () +@interface CountryCodeViewController () -@property (nonatomic, readonly) UISearchBar *searchBar; +@property (nonatomic, readonly) OWSSearchBar *searchBar; @property (nonatomic) NSArray *countryCodes; @@ -46,7 +46,7 @@ - (void)createViews { // Search - UISearchBar *searchBar = [OWSSearchBar new]; + OWSSearchBar *searchBar = [OWSSearchBar new]; _searchBar = searchBar; searchBar.delegate = self; searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @""); @@ -117,29 +117,14 @@ [self dismissViewControllerAnimated:YES completion:nil]; } -#pragma mark - UISearchBarDelegate +#pragma mark - OWSSearchBarDelegate -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText +- (void)searchBar:(OWSSearchBar *)searchBar textDidChange:(NSString *)text { [self searchTextDidChange]; } -- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar -{ - [self searchTextDidChange]; -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar -{ - [self searchTextDidChange]; -} - -- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar -{ - [self searchTextDidChange]; -} - -- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope +- (void)searchBar:(OWSSearchBar *)searchBar returnWasPressed:(NSString *)text { [self searchTextDidChange]; } diff --git a/SignalMessaging/ViewControllers/SelectThreadViewController.h b/SignalMessaging/ViewControllers/SelectThreadViewController.h index cfa3da58d..969a8dbaa 100644 --- a/SignalMessaging/ViewControllers/SelectThreadViewController.h +++ b/SignalMessaging/ViewControllers/SelectThreadViewController.h @@ -4,6 +4,7 @@ #import +@class OWSSearchBar; @class TSThread; NS_ASSUME_NONNULL_BEGIN @@ -14,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)canSelectBlockedContact; -- (nullable UIView *)createHeaderWithSearchBar:(UISearchBar *)searchBar; +- (nullable UIView *)createHeaderWithSearchBar:(OWSSearchBar *)searchBar; @end diff --git a/SignalMessaging/ViewControllers/SelectThreadViewController.m b/SignalMessaging/ViewControllers/SelectThreadViewController.m index 5107c670c..07ccefab4 100644 --- a/SignalMessaging/ViewControllers/SelectThreadViewController.m +++ b/SignalMessaging/ViewControllers/SelectThreadViewController.m @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @interface SelectThreadViewController () @property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper; @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) OWSTableViewController *tableViewController; -@property (nonatomic, readonly) UISearchBar *searchBar; +@property (nonatomic, readonly) OWSSearchBar *searchBar; @end @@ -87,7 +87,7 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert(self.selectThreadViewDelegate); // Search - UISearchBar *searchBar = [OWSSearchBar new]; + OWSSearchBar *searchBar = [OWSSearchBar new]; _searchBar = searchBar; searchBar.delegate = self; searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @""); @@ -132,29 +132,14 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } -#pragma mark - UISearchBarDelegate +#pragma mark - OWSSearchBarDelegate -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText +- (void)searchBar:(OWSSearchBar *)searchBar textDidChange:(NSString *)text { [self updateTableContents]; } -- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar -{ - [self updateTableContents]; -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar -{ - [self updateTableContents]; -} - -- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar -{ - [self updateTableContents]; -} - -- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope +- (void)searchBar:(OWSSearchBar *)searchBar returnWasPressed:(NSString *)text { [self updateTableContents]; } diff --git a/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m b/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m index 4de16e05a..ce60f463c 100644 --- a/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m +++ b/SignalMessaging/ViewControllers/SharingThreadPickerViewController.m @@ -80,7 +80,7 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); return NO; } -- (nullable UIView *)createHeaderWithSearchBar:(UISearchBar *)searchBar +- (nullable UIView *)createHeaderWithSearchBar:(OWSSearchBar *)searchBar { OWSAssert(searchBar); diff --git a/SignalMessaging/Views/OWSSearchBar.h b/SignalMessaging/Views/OWSSearchBar.h index 4e6586f96..dc44f649c 100644 --- a/SignalMessaging/Views/OWSSearchBar.h +++ b/SignalMessaging/Views/OWSSearchBar.h @@ -4,7 +4,27 @@ NS_ASSUME_NONNULL_BEGIN -@interface OWSSearchBar : UISearchBar +@class OWSSearchBar; + +@protocol OWSSearchBarDelegate + +- (void)searchBar:(OWSSearchBar *)searchBar textDidChange:(NSString *)text; +- (void)searchBar:(OWSSearchBar *)searchBar returnWasPressed:(NSString *)text; + +@optional +- (void)searchBarDidBeginEditing:(OWSSearchBar *)searchBar; + +@end + +#pragma mark - + +@interface OWSSearchBar : UIView + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, nullable) NSString *text; + +@property (nonatomic, nullable) NSString *placeholder; @end diff --git a/SignalMessaging/Views/OWSSearchBar.m b/SignalMessaging/Views/OWSSearchBar.m index e081b0273..e2c19ed87 100644 --- a/SignalMessaging/Views/OWSSearchBar.m +++ b/SignalMessaging/Views/OWSSearchBar.m @@ -3,21 +3,34 @@ // #import "OWSSearchBar.h" +#import "OWSTextField.h" #import "Theme.h" +#import "UIFont+OWS.h" #import "UIView+OWS.h" +#import +#import NS_ASSUME_NONNULL_BEGIN -@implementation OWSSearchBar +@interface OWSSearchBar () -- (instancetype)init -{ - if (self = [super init]) { - [self ows_configure]; - } +@property (nonatomic) OWSTextField *textField; - return self; -} +@property (nonatomic) UIButton *cancelButton; + +@property (nonatomic) CAShapeLayer *pillboxLayer; +@property (nonatomic) OWSLayerView *pillboxView; + +@property (nonatomic) UIButton *clearButton; +@property (nonatomic) UIImageView *searchIconView; + +@property (nonatomic) UIStackView *contentStackView; + +@end + +#pragma mark - + +@implementation OWSSearchBar - (instancetype)initWithFrame:(CGRect)frame { @@ -37,10 +50,147 @@ NS_ASSUME_NONNULL_BEGIN return self; } +- (CGFloat)contentHMargin +{ + return 8.f; +} + +- (CGFloat)contentVMargin +{ + return 10.f; +} + +- (CGFloat)pillboxHMargin +{ + return 8.f; +} + +- (CGFloat)pillboxVMargin +{ + return 7.f; +} + +- (CGFloat)contentSpacing +{ + return 12.f; +} + +- (CGFloat)pillboxSpacing +{ + return 8.f; +} + ++ (CGFloat)pillboxRadius +{ + return 10.f; +} + +- (CGSize)sizeThatFits:(CGSize)size +{ + // All that matters is the height. + CGSize result = [self.textField sizeThatFits:CGSizeZero]; + result.width += self.pillboxHMargin * 2; + result.height += self.pillboxVMargin * 2; + result.width += self.contentHMargin * 2; + result.height += self.contentVMargin * 2; + return result; +} + - (void)ows_configure { + OWSAssert(!self.searchIconView); + + self.opaque = NO; + self.backgroundColor = [UIColor clearColor]; + + UIImage *_Nullable searchIcon = [UIImage imageNamed:@"searchbar_search"]; + searchIcon = [searchIcon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + OWSAssert(searchIcon); + self.searchIconView = [[UIImageView alloc] initWithImage:searchIcon]; + [self.searchIconView setContentHuggingHigh]; + [self.searchIconView setCompressionResistanceHigh]; + + UIImage *_Nullable clearIcon = [UIImage imageNamed:@"searchbar_clear"]; + clearIcon = [clearIcon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + OWSAssert(clearIcon); + self.clearButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.clearButton setImage:clearIcon forState:UIControlStateNormal]; + [self.clearButton addTarget:self action:@selector(clearButtonPressed) forControlEvents:UIControlEventTouchUpInside]; + [self.clearButton setContentHuggingHigh]; + [self.clearButton setCompressionResistanceHigh]; + + self.textField = [OWSTextField new]; + self.textField.font = [UIFont ows_dynamicTypeBodyFont]; + self.textField.delegate = self; + self.textField.ows_delegate = self; + self.textField.returnKeyType = UIReturnKeySearch; + self.textField.enablesReturnKeyAutomatically = YES; + [self.textField addTarget:self action:@selector(textDidChange:) forControlEvents:UIControlEventEditingChanged]; + [self.textField addTarget:self + action:@selector(textFieldReturnWasPressed:) + forControlEvents:UIControlEventEditingDidEndOnExit]; + [self.textField setContentHuggingVerticalLow]; + [self.textField setContentHuggingVerticalHigh]; + [self.textField setCompressionResistanceHorizontalLow]; + [self.textField setCompressionResistanceVerticalHigh]; + + UIStackView *pillboxStackView = [[UIStackView alloc] initWithArrangedSubviews:@[ + self.searchIconView, + self.textField, + self.clearButton, + ]]; + pillboxStackView.spacing = self.pillboxSpacing; + pillboxStackView.axis = UILayoutConstraintAxisHorizontal; + pillboxStackView.alignment = UIStackViewAlignmentCenter; + pillboxStackView.layoutMargins + = UIEdgeInsetsMake(self.pillboxVMargin, self.pillboxHMargin, self.pillboxVMargin, self.pillboxHMargin); + pillboxStackView.layoutMarginsRelativeArrangement = YES; + + self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.cancelButton setTitle:CommonStrings.cancelButton forState:UIControlStateNormal]; + self.cancelButton.titleLabel.font = UIFont.ows_dynamicTypeBodyFont; + [self.cancelButton setContentHuggingHigh]; + [self.cancelButton setCompressionResistanceHigh]; + [self.cancelButton addTarget:self + action:@selector(cancelButtonPressed) + forControlEvents:UIControlEventTouchUpInside]; + + self.contentStackView = [[UIStackView alloc] initWithArrangedSubviews:@[ + pillboxStackView, + self.cancelButton, + ]]; + self.contentStackView.spacing = self.contentSpacing; + self.contentStackView.axis = UILayoutConstraintAxisHorizontal; + self.contentStackView.alignment = UIStackViewAlignmentCenter; + [self addSubview:self.contentStackView]; + [self.contentStackView autoPinWidthToSuperviewWithMargin:self.contentHMargin]; + [self.contentStackView autoPinHeightToSuperviewWithMargin:self.contentVMargin]; + + + CAShapeLayer *pillboxLayer = [CAShapeLayer new]; + self.pillboxLayer = pillboxLayer; + self.pillboxView = [[OWSLayerView alloc] + initWithFrame:CGRectZero + layoutCallback:^(UIView *layerView) { + pillboxLayer.path = + [UIBezierPath bezierPathWithRoundedRect:layerView.bounds cornerRadius:OWSSearchBar.pillboxRadius] + .CGPath; + }]; + self.pillboxView.userInteractionEnabled = NO; + [self.pillboxView.layer addSublayer:pillboxLayer]; + [pillboxStackView addSubview:self.pillboxView]; + [self.pillboxView autoPinEdgesToSuperviewEdges]; + [self.pillboxView setContentHuggingLow]; + [self.pillboxView setCompressionResistanceLow]; + self.pillboxView.layer.zPosition = -1; + + self.userInteractionEnabled = YES; + [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapSearchBar:)]]; + [self ows_applyTheme]; + [self updateState]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(themeDidChange:) name:ThemeDidChangeNotification @@ -56,21 +206,83 @@ NS_ASSUME_NONNULL_BEGIN { OWSAssertIsOnMainThread(); - self.searchBarStyle = UISearchBarStyleMinimal; - self.backgroundColor = Theme.searchBarBackgroundColor; - self.barTintColor = Theme.backgroundColor; - self.barStyle = Theme.barStyle; - self.searchBarStyle = Theme.searchBarStyle; + self.searchIconView.tintColor = Theme.placeholderColor; + self.clearButton.tintColor = Theme.placeholderColor; + + self.pillboxLayer.fillColor = Theme.offBackgroundColor.CGColor; + + self.textField.textColor = Theme.primaryColor; + if (self.placeholder.length > 0) { + self.textField.attributedPlaceholder = + [[NSAttributedString alloc] initWithString:self.placeholder + attributes:@{ + NSForegroundColorAttributeName : Theme.placeholderColor, + }]; + } + + [self.cancelButton setTitleColor:Theme.primaryColor forState:UIControlStateNormal]; +} + +- (void)updateState +{ + self.cancelButton.hidden = (!self.textField.isFirstResponder && self.textField.text.length < 1); + self.clearButton.hidden = self.textField.text.length < 1; +} + +- (void)setPlaceholder:(nullable NSString *)placeholder +{ + self.textField.attributedPlaceholder = + [[NSAttributedString alloc] initWithString:placeholder + attributes:@{ + NSForegroundColorAttributeName : Theme.placeholderColor, + }]; +} + +- (nullable NSString *)placeholder +{ + return self.textField.placeholder; +} + +- (void)setText:(nullable NSString *)text +{ + self.textField.text = text; + + [self updateState]; +} + +- (nullable NSString *)text +{ + return self.textField.text; +} + +- (BOOL)becomeFirstResponder +{ + return [self.textField becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder +{ + return [self.textField resignFirstResponder]; +} + +#pragma mark - OWSTextFieldDelegate - [self traverseViewHierarchyWithVisitor:^(UIView *view) { - if ([view isKindOfClass:[UITextField class]]) { - UITextField *textField = (UITextField *)view; - textField.keyboardAppearance - = (Theme.isDarkThemeEnabled ? UIKeyboardAppearanceDark : UIKeyboardAppearanceDefault); - } - }]; +- (void)textFieldDidBecomeFirstResponder:(OWSTextField *)textField +{ + [self updateState]; + + if ([self.delegate respondsToSelector:@selector(searchBarDidBeginEditing:)]) { + [self.delegate searchBarDidBeginEditing:self]; + } } +- (void)textFieldDidResignFirstResponder:(OWSTextField *)textField +{ + [self updateState]; +} + +#pragma mark - Events + - (void)themeDidChange:(NSNotification *)notification { OWSAssertIsOnMainThread(); @@ -78,6 +290,42 @@ NS_ASSUME_NONNULL_BEGIN [self ows_applyTheme]; } +- (void)textDidChange:(id)sender +{ + [self updateState]; + [self.delegate searchBar:self textDidChange:self.text]; +} + +- (void)textFieldReturnWasPressed:(id)sender +{ + [self.textField resignFirstResponder]; + [self updateState]; + [self.delegate searchBar:self returnWasPressed:self.text]; +} + +- (void)cancelButtonPressed +{ + self.text = nil; + + [self updateState]; + + [self.delegate searchBar:self textDidChange:self.text]; +} + +- (void)clearButtonPressed +{ + self.text = nil; + + [self updateState]; + + [self.delegate searchBar:self textDidChange:self.text]; +} + +- (void)didTapSearchBar:(UIGestureRecognizer *)sender +{ + [self becomeFirstResponder]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/Views/OWSTextField.h b/SignalMessaging/Views/OWSTextField.h index de4749817..5c5e018bf 100644 --- a/SignalMessaging/Views/OWSTextField.h +++ b/SignalMessaging/Views/OWSTextField.h @@ -4,8 +4,21 @@ NS_ASSUME_NONNULL_BEGIN +@class OWSTextField; + +@protocol OWSTextFieldDelegate + +- (void)textFieldDidBecomeFirstResponder:(OWSTextField *)textField; +- (void)textFieldDidResignFirstResponder:(OWSTextField *)textField; + +@end + +#pragma mark - + @interface OWSTextField : UITextField +@property (nonatomic, weak) id ows_delegate; + @end NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/Views/OWSTextField.m b/SignalMessaging/Views/OWSTextField.m index e029458da..4d6168184 100644 --- a/SignalMessaging/Views/OWSTextField.m +++ b/SignalMessaging/Views/OWSTextField.m @@ -32,6 +32,24 @@ NS_ASSUME_NONNULL_BEGIN self.keyboardAppearance = (Theme.isDarkThemeEnabled ? UIKeyboardAppearanceDark : UIKeyboardAppearanceDefault); } +- (BOOL)becomeFirstResponder +{ + BOOL result = [super becomeFirstResponder]; + + [self.ows_delegate textFieldDidBecomeFirstResponder:self]; + + return result; +} + +- (BOOL)resignFirstResponder +{ + BOOL result = [super resignFirstResponder]; + + [self.ows_delegate textFieldDidResignFirstResponder:self]; + + return result; +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/categories/Theme.h b/SignalMessaging/categories/Theme.h index 103fc17a2..109e96b4b 100644 --- a/SignalMessaging/categories/Theme.h +++ b/SignalMessaging/categories/Theme.h @@ -46,9 +46,6 @@ extern NSString *const ThemeDidChangeNotification; #pragma mark - -@property (class, readonly, nonatomic) UIBarStyle barStyle; -@property (class, readonly, nonatomic) UISearchBarStyle searchBarStyle; -@property (class, readonly, nonatomic) UIColor *searchBarBackgroundColor; @property (class, readonly, nonatomic) UIBlurEffect *barBlurEffect; #pragma mark - diff --git a/SignalMessaging/categories/Theme.m b/SignalMessaging/categories/Theme.m index a6fd5c993..b46c20795 100644 --- a/SignalMessaging/categories/Theme.m +++ b/SignalMessaging/categories/Theme.m @@ -140,31 +140,6 @@ NSString *const ThemeKeyThemeEnabled = @"ThemeKeyThemeEnabled"; #pragma mark - -+ (UIBarStyle)barStyle -{ - if (Theme.isDarkThemeEnabled) { - return UIBarStyleDefault; - } else { - return UIBarStyleDefault; - } -} - -+ (UISearchBarStyle)searchBarStyle -{ - if (Theme.isDarkThemeEnabled) { - return UISearchBarStyleProminent; - } else { - return UISearchBarStyleMinimal; - } -} - -+ (UIColor *)searchBarBackgroundColor -{ - return Theme.backgroundColor; -} - -#pragma mark - - + (UIColor *)toastForegroundColor { return (Theme.isDarkThemeEnabled ? UIColor.ows_whiteColor : UIColor.ows_whiteColor); diff --git a/SignalMessaging/utils/UIUtil.m b/SignalMessaging/utils/UIUtil.m index de67335fb..c925d9625 100644 --- a/SignalMessaging/utils/UIUtil.m +++ b/SignalMessaging/utils/UIUtil.m @@ -41,9 +41,6 @@ // ? UIKeyboardAppearanceDark // : UIKeyboardAppearanceDefault); - // [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:[UIColor - // ows_materialBlueColor]]; - [[UISwitch appearance] setOnTintColor:[UIColor ows_materialBlueColor]]; [[UIToolbar appearance] setTintColor:[UIColor ows_materialBlueColor]];