diff --git a/Cineaste.xcodeproj/project.pbxproj b/Cineaste.xcodeproj/project.pbxproj index cb02e767..1a999197 100644 --- a/Cineaste.xcodeproj/project.pbxproj +++ b/Cineaste.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ 3F4701C6238C8312006C1577 /* PagedMovieResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F4701C5238C8312006C1577 /* PagedMovieResultTests.swift */; }; 3F4701C8238C850A006C1577 /* PagedMovieResult+Testing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F4701C7238C850A006C1577 /* PagedMovieResult+Testing.swift */; }; 3F4701C9238C8541006C1577 /* PagedMovieResult+Testing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F4701C7238C850A006C1577 /* PagedMovieResult+Testing.swift */; }; + 3F48A7DF257CE76B00956F2E /* SearchSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E903D95249E5DE600EAA4E6 /* SearchSection.swift */; }; 3F492E6F24F250C900016B2A /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F492E6E24F250C900016B2A /* WidgetKit.framework */; }; 3F492E7124F250C900016B2A /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F492E7024F250C900016B2A /* SwiftUI.framework */; }; 3F492E7424F250C900016B2A /* CountdownWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F492E7324F250C900016B2A /* CountdownWidget.swift */; }; @@ -106,6 +107,7 @@ 3F7ABD5620F5C71E004B069E /* String+Locale.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F941B6C20F527E5008A4407 /* String+Locale.swift */; }; 3F7B66C62353B81600464BCC /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F7B66C52353B81600464BCC /* ContextMenu.swift */; }; 3F7D1D4F23D4A84900BA530F /* SearchMovieDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F7D1D4E23D4A84900BA530F /* SearchMovieDataSource.swift */; }; + 3F7D1D5123D4AEB400BA530F /* SearchTokenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F7D1D5023D4AEB400BA530F /* SearchTokenCell.swift */; }; 3F8065BC238AE3220087D6EA /* DateFormatter+Cineaste.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F8065BB238AE3220087D6EA /* DateFormatter+Cineaste.swift */; }; 3F80F27222359E5C007E03C5 /* UIView+SlideIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F80F27122359E5C007E03C5 /* UIView+SlideIn.swift */; }; 3F8CEBEE2250A229001916BD /* Screenshots+ScrollToElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F8CEBED2250A229001916BD /* Screenshots+ScrollToElement.swift */; }; @@ -388,6 +390,7 @@ 3F75665B2381737E007E2DE8 /* UIViewController+ShareMovie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+ShareMovie.swift"; sourceTree = ""; }; 3F7B66C52353B81600464BCC /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = ""; }; 3F7D1D4E23D4A84900BA530F /* SearchMovieDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchMovieDataSource.swift; sourceTree = ""; }; + 3F7D1D5023D4AEB400BA530F /* SearchTokenCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTokenCell.swift; sourceTree = ""; }; 3F8065BB238AE3220087D6EA /* DateFormatter+Cineaste.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Cineaste.swift"; sourceTree = ""; }; 3F80F27122359E5C007E03C5 /* UIView+SlideIn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+SlideIn.swift"; sourceTree = ""; }; 3F83BE771FF39DFC00E584E9 /* Instantiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instantiable.swift; sourceTree = ""; }; @@ -458,6 +461,7 @@ 3FFEC6CC236DCF91005E7EED /* Storyboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storyboard.swift; sourceTree = ""; }; 4E20FD24226851D3006EB4B8 /* PersistenceSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceSubscriber.swift; sourceTree = ""; }; 4E779FC022690151007B278D /* SelectionReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionReducerTests.swift; sourceTree = ""; }; + 4E903D95249E5DE600EAA4E6 /* SearchSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSection.swift; sourceTree = ""; }; 4EABD57D2129C622007F20D9 /* SeparatorViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorViewTests.swift; sourceTree = ""; }; 4EB512012268B07600CBDC7E /* AppReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppReducer.swift; sourceTree = ""; }; 4EB512032268B1FD00CBDC7E /* SelectionReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionReducer.swift; sourceTree = ""; }; @@ -863,6 +867,8 @@ 3FEEE8E6222BBC6A00EB1649 /* SearchMoviesViewController+SwipeAction.swift */, 6409298F22DBAB0C0011AB96 /* SearchMoviesViewController+SwipeHint.swift */, 3FD722CB20264B720046DEAC /* SearchMoviesViewController+UITableView.swift */, + 3F7D1D5023D4AEB400BA530F /* SearchTokenCell.swift */, + 4E903D95249E5DE600EAA4E6 /* SearchSection.swift */, ); path = SearchMovies; sourceTree = ""; @@ -1489,6 +1495,7 @@ 1A31111D2518003000F05C16 /* AppGroup+Kingfisher.swift in Sources */, 3F187F952263491500B7A9CF /* SortDescriptor.swift in Sources */, 3F36F5D2238A8CCE00267280 /* UserDefaults+Cineaste.swift in Sources */, + 3F48A7DF257CE76B00956F2E /* SearchSection.swift in Sources */, 3FF790F620DE274A007B7D37 /* NavigationController.swift in Sources */, 3FF790F720DE274A007B7D37 /* Button.swift in Sources */, 3F229212225A40BC001D4358 /* Store.swift in Sources */, @@ -1518,6 +1525,7 @@ 3FF095D5210325D100ADFB86 /* SettingsViewController+UIDocumentPicker.swift in Sources */, 3FF7910220DE274A007B7D37 /* SettingsCell.swift in Sources */, 3FF7910420DE274A007B7D37 /* SettingsDetailViewController.swift in Sources */, + 3F7D1D5123D4AEB400BA530F /* SearchTokenCell.swift in Sources */, 4ED2FC7D22666D89007BDE06 /* CoreDataMigrator.swift in Sources */, 3F0C1D1322A4395E00F0F52A /* ShortcutIdentifier.swift in Sources */, 3FF7910620DE274A007B7D37 /* Model.xcdatamodeld in Sources */, diff --git a/Cineaste/Storyboards/Base.lproj/Search.storyboard b/Cineaste/Storyboards/Base.lproj/Search.storyboard index 97e858e4..b78bb764 100644 --- a/Cineaste/Storyboards/Base.lproj/Search.storyboard +++ b/Cineaste/Storyboards/Base.lproj/Search.storyboard @@ -133,6 +133,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -171,7 +206,7 @@ - + diff --git a/Cineaste/ViewController/SearchMovies/SearchMovieDataSource.swift b/Cineaste/ViewController/SearchMovies/SearchMovieDataSource.swift index 496aae4b..4fafe460 100644 --- a/Cineaste/ViewController/SearchMovies/SearchMovieDataSource.swift +++ b/Cineaste/ViewController/SearchMovies/SearchMovieDataSource.swift @@ -9,18 +9,70 @@ import UIKit class SearchMovieDataSource: NSObject, UITableViewDataSource { + enum Mode { + case discover + @available (iOS 13, *) + case manualSearch + } + + var mode: Mode = .discover var movies: [Movie] = [] + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + guard #available(iOS 13, *), + mode == .manualSearch + else { return nil } + + switch SearchSection(rawValue: section) { + case .tokens?: + return "Genres" + case .movies?: + return "Movies" + default: + return nil + } + } + + func numberOfSections(in tableView: UITableView) -> Int { + switch mode { + case .discover: + return 1 + case .manualSearch: + return 2 + } + } + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - movies.count + switch (mode, SearchSection(rawValue: section)) { + case (.discover, _), + (.manualSearch, .movies?): + return movies.count + case (.manualSearch, .tokens?): + return 1 + default: + return 0 + } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: SearchMoviesCell = tableView.dequeueCell(identifier: SearchMoviesCell.identifier) - let movie = movies[indexPath.row] - cell.configure(with: movie) + switch (mode, SearchSection(rawValue: indexPath.section)) { + case (.discover, _), + (.manualSearch, .movies?): + let cell: SearchMoviesCell = tableView.dequeueCell(identifier: SearchMoviesCell.identifier) + + let movie = movies[indexPath.row] + + cell.configure(with: movie) + + return cell + case (.manualSearch, .tokens?): + let cell: SearchTokenCell = tableView.dequeueCell(identifier: SearchTokenCell.identifier) + cell.configure() + return cell + default: + fatalError("The impossible has happened") + } - return cell } } diff --git a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+SearchController.swift b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+SearchController.swift index e1a06159..c8f6081a 100644 --- a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+SearchController.swift +++ b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+SearchController.swift @@ -15,6 +15,22 @@ extension SearchMoviesViewController: UISearchControllerDelegate { } } +extension SearchMoviesViewController: UITextFieldDelegate { + func textFieldDidBeginEditing(_ textField: UITextField) { + if #available(iOS 13, *) { + dataSource.mode = .manualSearch + } else { + dataSource.mode = .discover + } + tableView.reloadData() + } + + func textFieldDidEndEditing(_ textField: UITextField) { + dataSource.mode = .discover + tableView.reloadData() + } +} + extension SearchMoviesViewController: UISearchResultsUpdating { internal func updateSearchResults(for searchController: UISearchController) { searchDelayTimer?.invalidate() diff --git a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+UITableView.swift b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+UITableView.swift index ffd6c8b9..32e43e76 100644 --- a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+UITableView.swift +++ b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController+UITableView.swift @@ -18,8 +18,25 @@ extension SearchMoviesViewController: UITableViewDataSourcePrefetching { extension SearchMoviesViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let selectedMovie = movies[indexPath.row] - store.dispatch(SelectionAction.select(movie: selectedMovie)) - perform(segue: .showMovieDetail, sender: self) + + switch (dataSource.mode, SearchSection(rawValue: indexPath.section)) { + case (.discover, _), + (.manualSearch, .movies?): + let selectedMovie = movies[indexPath.row] + store.dispatch(SelectionAction.select(movie: selectedMovie)) + perform(segue: .showMovieDetail, sender: self) + case (.manualSearch, .tokens?): + guard #available(iOS 13.0, *), + let cell = tableView.cellForRow(at: indexPath) as? SearchTokenCell, + let genre = cell.title.text + else { return } + + let searchField = resultSearchController.searchBar.searchTextField + let searchToken = UISearchToken(icon: UIImage.moreIcon, text: genre) + searchField.insertToken(searchToken, at: 0) + searchField.tokenBackgroundColor = .cineButton + default: + break + } } } diff --git a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController.swift b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController.swift index c72727c4..1365d2a9 100644 --- a/Cineaste/ViewController/SearchMovies/SearchMoviesViewController.swift +++ b/Cineaste/ViewController/SearchMovies/SearchMoviesViewController.swift @@ -114,6 +114,10 @@ class SearchMoviesViewController: UIViewController { navigationItem.hidesSearchBarWhenScrolling = false definesPresentationContext = true + + if #available(iOS 13.0, *) { + resultSearchController.searchBar.searchTextField.delegate = self + } } } diff --git a/Cineaste/ViewController/SearchMovies/SearchSection.swift b/Cineaste/ViewController/SearchMovies/SearchSection.swift new file mode 100644 index 00000000..7bb2c960 --- /dev/null +++ b/Cineaste/ViewController/SearchMovies/SearchSection.swift @@ -0,0 +1,12 @@ +// +// SearchSection.swift +// Cineaste App +// +// Created by Felizia Bernutz on 19.01.20. +// Copyright © 2020 spacepandas.de. All rights reserved. +// + +enum SearchSection: Int { + case tokens = 0 + case movies = 1 +} diff --git a/Cineaste/ViewController/SearchMovies/SearchTokenCell.swift b/Cineaste/ViewController/SearchMovies/SearchTokenCell.swift new file mode 100644 index 00000000..cb545d23 --- /dev/null +++ b/Cineaste/ViewController/SearchMovies/SearchTokenCell.swift @@ -0,0 +1,22 @@ +// +// SearchTokenCell.swift +// Cineaste App +// +// Created by Felizia Bernutz on 19.01.20. +// Copyright © 2020 spacepandas.de. All rights reserved. +// + +import UIKit + +class SearchTokenCell: UITableViewCell { + static let identifier = "SearchTokenCell" + + @IBOutlet weak var tokenIcon: UIImageView! + @IBOutlet weak var title: UILabel! + + func configure() { + tokenIcon.image = UIImage.searchIcon + title.text = "Horror" + } + +}