From 8daaef22da8ed68f8636464bfb24452491952d3f Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 17 Aug 2018 12:43:35 -0400 Subject: [PATCH] Add custom themed search bar. --- .../searchbar_clear.imageset/Contents.json | 23 ++ .../Search-clear_17x17_@1x.png | Bin 0 -> 3577 bytes .../Search-clear_17x17_@2x.png | Bin 0 -> 3806 bytes .../Search-clear_17x17_@3x.png | Bin 0 -> 4114 bytes .../searchbar_search.imageset/Contents.json | 23 ++ .../UIButtonBarSearch_18x18_@1x.png | Bin 0 -> 527 bytes .../UIButtonBarSearch_18x18_@2x.png | Bin 0 -> 1198 bytes .../UIButtonBarSearch_18x18_@3x.png | Bin 0 -> 1862 bytes .../src/ViewControllers/ContactsPicker.swift | 10 +- .../GifPicker/GifPickerViewController.swift | 10 +- .../HomeView/HomeViewController.m | 44 +-- .../NewContactThreadViewController.m | 27 +- .../CountryCodeViewController.m | 27 +- .../SelectThreadViewController.h | 3 +- .../SelectThreadViewController.m | 27 +- .../SharingThreadPickerViewController.m | 2 +- SignalMessaging/Views/OWSSearchBar.h | 22 +- SignalMessaging/Views/OWSSearchBar.m | 288 ++++++++++++++++-- SignalMessaging/Views/OWSTextField.h | 13 + SignalMessaging/Views/OWSTextField.m | 18 ++ SignalMessaging/categories/Theme.h | 3 - SignalMessaging/categories/Theme.m | 25 -- SignalMessaging/utils/UIUtil.m | 3 - 23 files changed, 407 insertions(+), 161 deletions(-) create mode 100644 Signal/Images.xcassets/searchbar_clear.imageset/Contents.json create mode 100644 Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@1x.png create mode 100644 Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@2x.png create mode 100644 Signal/Images.xcassets/searchbar_clear.imageset/Search-clear_17x17_@3x.png create mode 100644 Signal/Images.xcassets/searchbar_search.imageset/Contents.json create mode 100644 Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@1x.png create mode 100644 Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@2x.png create mode 100644 Signal/Images.xcassets/searchbar_search.imageset/UIButtonBarSearch_18x18_@3x.png 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 0000000000000000000000000000000000000000..3310dbc4223d5e488e9997a2c8859ca4a0ac58bf GIT binary patch literal 3577 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..f750f3eeaf2fa5fd46b2308898d75e498239a844 GIT binary patch literal 3806 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 Uq1K1T$N&HU07*qoM6N<$g5^6*UH||9 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c367e8eb70f7b6c26ad0a5d7ebad9b23b43cfb5d GIT binary patch literal 4114 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0d99c7a9c32b9b806f5594aa98747e65d875b004 GIT binary patch literal 527 zcmV+q0`UEbP)Px$$w@>(R5%fxRKH8ZKoss>M4E)Qpok=mNU>e4Lv?Z1T|oqKa8*PQUHv!I!O5i# z&KB4DFF3R=jhj}`#nvX)P;-8-8cEN_UkAs%_r34Fdw1_8EEXD>OlH*cy!Dt6D}ZxC zhz?`ShFwxM?ZCF}hY-ETeF+gG#@Ghqd?>D}7VIr>hF#aavMg&k;P+ik z(_BoO=FPZi&h#Y!OsCTY(=hHL#ppT^dcd5H5(#jK%tGuwo6U{{Sgdna^9oO`)zwoKwdFT>VY? zsh5Zw*R=gFLe%!C+9pG0--&fagg6K95zirHA>i+WIu>ak!8?WUNh+19Ql!yn*ex+*9E2LaztUhleux7E;$_71m_1@WLJ0mi z=rGrDsH^kXTv2s>o-+Hh5S`S`+;PfysHs5gUqZ4NdT5uhe-FwG|FInscmpWzsE}^7 RPWS)-002ovPDHLkV1h%9_muzu literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a2052f53c8c944019c12a554add3e92688f8b4e7 GIT binary patch literal 1198 zcmV;f1X25mP)Px(Xh}ptR9FeUS50UWK@{GZSgd~uibCCOBGi@~)QkAriWCu16wyOb+oFi##hV9z zz(c`H!Gj0ILl9K7wNeoj1@Ta*ASze{sfe@`ZQ3ZPXpO`|vO9in+|i`Xc6JlVLYd6G z?|bjfdv9i5nW6cF5Nw%cH93Z{8^6~H!-zA+7J|kw|7I{Y#0}$_!TG~vGWi5DKuZ6Z z7qz3KgC`P+LjatD;kXwre;v*Y1K)Y{*s-hNV-LZoOu;4V#JL``#>Wt!j3rAr0I zB%EufXib4ln>IH$&oWK(FgPjV;x7&E_Gv)PLP3Pc8N~TMb~+n^J9FmEJ2E^x{6nLo zKwMW>7nz)#yk-co2hqzi&UcTEjXf#=`I%6f@*;B;P8B%oM~A`?7rHL1NFj2*YLNIc z6{G+)a~)#@xxd%g)N~ZPEBUk#cWiw8ICgXwHs&K*U4GK8He^_qb9M(p_tsNBk)L6CuYrNnqsr)adBwH$Ox_n30i@2}JxXVG-^#e#(HyOtT626$tak znwpw!KZb%}8XFsLLU#(zERRN`n{`}n3$a6jgy`I&i6S z&iNPOqLvovbdW8G?z4i6t)mt4V=w1#Mv|O>SiJ zA5t3?O-+B#KWoK*$&@J(^}f^tWBwCP?LztnsVM!NJ~t|@aOMqhl}>jIp=-Q}EbO1M zK5beMAtjYPFce_E#$Ee>9roZ(=o6g3!BZgLJ-UJE(sS>b127sRJe2n1AIE!$_IXV6 zuM%yfiaJC}X~$O*iNiQ0r?KODTGM?<^J_%-JpP02qSGrQ@@HdHooYk+ZWq(%>5u}$ z874bD$JvQ~W+S4|0AmZ`Xb!(WL&1B@`;q&{qp8$W#ZzNYr?d_!#pR4}Y9E}Zu2CDQ zd_XxiXXK_)=nKMO`nP&7{?tLDaWActTq&rCLuAaaQx$W_uTvGNA(aj_&QMcpRX!EA zBBMO=jJ3ho-Ys)z$#MkrEv?{awSE_h)ozP`*fSLYl34L`liO}a!|r2qf` M07*qoM6N<$g7#rGZvX%Q literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b017f2397b0f1ac355f36f13c0a990f3f129807c GIT binary patch literal 1862 zcmV-M2f6r(P)Px+07*naRA>d&S=~<@RTQ6@1yNc)w2jIF3pJo=NhJk?fr=3|RZEOoMgIa~tZg6a zgSJmRn5v0Q8nscM^ufedENYb2HjU*&B~hwkq^1!gUDzc>Nr45*vb!_>&M;>>EbQ*w zS(aUH0_X0XbI&=yd(J)g&KX&9*jidzTz!3gjhd$IlvH(xCP~{M>NZ)H3qfW41@LTK zlI6>aBn?Q4a-pE0pl@(+aKWKUp=o4*Q1f^^RgqBWfF{d(Bu(2aG8v#JG3O-ae(3l6 ze-)W4%4-{#4k#Rc3trd_CAR0qG6(|Bz>9}`KHoqro@B-o8dzRle)Gb@LK_$l0#tUC zvSEy$lU=S}m#SXMktDC0n;Qs+!*GsV5SgDZi73i;%xeH&GpIXiegxz1Was1@9v&W^ zk9wBWPsokk?sB_5^P1KHj#>*BB1vvnT(09IBO^VQ@wi=pl1oZTnn3p>9G?QSsT=YJ zWJPHi9Uc8Et`LETrts)Fo}!{!toygteFWxiB`a$m0R0ioFY+4z>oiq829WhU58x&M zZa2XF#AC_O6@itx-8ErJIuFISl5i*uf$`vo&vzVsB*5ewd9b*+_!TVN8<3V|NSr|= zJhB?#mI2elPm(UOrvT)dOOl@S`u#s74`;cA($dlg)kx$^%OaBJ>XQvi95FXqMMXsp z_S7j0s0p~MDOI3IGwoA&X%`l7ihcv&CWL7_B`x~xv@HQPKR5R}1l>o%plAUK_oONv zTMY)dendqxbcSdg;HpEx;1Mg2Xdm(x8#eTIRaHO6FC8qx;Z=mg3FC3f$y6XPl9!iv z9g21t%Ifk93cd;i0#}_VH$A3BB5y)~4ip>j=Z1!cV@?DnGY8Re6uP?%87^GaD6u$d zdh$SaszzM@W=K%st(vt6!Ido5j~Og1p6Rw_%W~}%zyFt&c;k&NdQ4UKG85wbRJuTs z4c@V_i?HEywkNDRL5Klr-cXB_Sw5_d8h5mD<4XWB?_HA|) z+>dIQ7fIts?q>k)V;g|7n)`OC0#{csGx|wgZduMM(Hk$Kns&FSOa&RJ$TDff(obs_ zcKyo+pnnJV?NajCMrJN7EDUfz-4tLZEH>m>`nI~{G1{nl3kHMwp~%0}Nm2NTuzoDQ zc|+o{M3g3&UQ*`fgjXh!0;kU>Cnrr?u=q2gawrtXc~Vf4Jlsz=gG=$=_C}*1+m&ezNmX(!lg$*sN4|U9sxGzF= zVDy0iD|6bIs6@iyw7rvsLm|?w+l4LC?zA|o3m`zKzaIk8PkXFbliTgyOXF+VP@;GV zx*sN;02RX9#$l)W%_`OO^z_yIygYj0tTzNdnxCJ49#x`Ir@}?%p-Of?-YTgowpbOG z<+o9yF!#QQEaEjiMnCAQ2Ubcy*RXOqQ1s1O>^FU1scNULlMIohncUpmBa2;U|Ca!x zPdRY^bBKfgNE{Sx!hY+~SJRpNgtJIC_Ej(GvM_I)o1HyLm1)bEPJTo*j6pY6g{VXOhVg$HK`al2!tThLf(lD~lyP_W} z=te<@FXYiVWsMe!4)cYVbX%JfaB+c=aQf;&9|&-FqZ^5tMGeLOK)_i5?Zw;bpP*iT z3#a!f0Pw(iI&d3}yWbXL9+NQk^HE9^2)h&Dd4eBAQ&DgUfw2O3?_R3!$5YO{b|@C% zYlQV{9M-g#XivqHF9OasFg6xRWQR;;XIXv$o>(lj^1}oaU?#!xDKhT|NK(H?v#%yN zVPI?wm7P(ctw+JN31L``By$f8za7u%m7e6z0=OSzf5Qv?$h18${QE=~+SLN*7#IUg z1zinr83~LQD_L+E3oKc184WBMa2XHGDLCutPckyH(RGThRq(=@SO(JhhjXxl_9pSH z3y(1vn+fIgoo@Hj>%wCU%#P=9ak$do-ydFA9%F#9JcrA``=dVJ%b=N29A$$=Xf!x0 zD3Y@-J;n=Qfa{>}V^8t3bx&(+YqN1DUFM+w0iz-Sz$oNpWdHyG07*qoM6N<$g6|?+ A#{d8T literal 0 HcmV?d00001 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]];