diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 7ca8b9cd..0ce6e881 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -1,6 +1,6 @@ name: Swift -on: [push] +on: [push, pull_request] jobs: test: diff --git a/Examples/CategoriesHits/AppDelegate.swift b/Examples/CategoriesHits/AppDelegate.swift index d4a0c1d3..1e5c37ed 100644 --- a/Examples/CategoriesHits/AppDelegate.swift +++ b/Examples/CategoriesHits/AppDelegate.swift @@ -29,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/CategoriesHits/CategoriesHits.SearchResultsController.swift b/Examples/CategoriesHits/CategoriesHits.SearchResultsController.swift index 94cc3d8b..8888fefd 100644 --- a/Examples/CategoriesHits/CategoriesHits.SearchResultsController.swift +++ b/Examples/CategoriesHits/CategoriesHits.SearchResultsController.swift @@ -10,15 +10,15 @@ import InstantSearch import UIKit extension CategoriesHits { - + class SearchResultsController: UITableViewController { - + var didSelectSuggestion: ((String) -> Void)? - + enum Section: Int, CaseIterable { case categories case hits - + var title: String { switch self { case .categories: @@ -27,7 +27,7 @@ extension CategoriesHits { return "Products" } } - + var cellReuseIdentifier: String { switch self { case .categories: @@ -36,15 +36,15 @@ extension CategoriesHits { return "hits" } } - + init?(section: Int) { self.init(rawValue: section) } - + init?(indexPath: IndexPath) { self.init(section: indexPath.section) } - + } weak var categoriesInteractor: FacetListInteractor? { @@ -56,7 +56,7 @@ extension CategoriesHits { }.onQueue(.main) } } - + weak var hitsInteractor: HitsInteractor>? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -66,17 +66,17 @@ extension CategoriesHits { }.onQueue(.main) } } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(CategoryTableViewCell.self, forCellReuseIdentifier: Section.categories.cellReuseIdentifier) tableView.register(ProductTableViewCell.self, forCellReuseIdentifier: Section.hits.cellReuseIdentifier) } - + override func numberOfSections(in tableView: UITableView) -> Int { return Section.allCases.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let section = Section(rawValue: section) else { return 0 } switch section { @@ -86,12 +86,12 @@ extension CategoriesHits { return hitsInteractor?.numberOfHits() ?? 0 } } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let section = Section(rawValue: indexPath.section) else { return UITableViewCell() } let cell: UITableViewCell - + switch section { case .categories: cell = tableView.dequeueReusableCell(withIdentifier: Section.categories.cellReuseIdentifier, for: indexPath) @@ -108,10 +108,10 @@ extension CategoriesHits { productTableViewCell.setup(with: hit) } } - + return cell } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { guard let section = Section(rawValue: section) else { return nil } switch section { @@ -123,7 +123,7 @@ extension CategoriesHits { return section.title } } - + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { guard let section = Section(indexPath: indexPath) else { return 0 } switch section { @@ -133,7 +133,7 @@ extension CategoriesHits { return 100 } } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let section = Section(rawValue: indexPath.section) else { return } switch section { @@ -148,5 +148,5 @@ extension CategoriesHits { } } - + } diff --git a/Examples/CategoriesHits/CategoriesHits.SearchViewController.swift b/Examples/CategoriesHits/CategoriesHits.SearchViewController.swift index 7f3996d6..e4c76a2d 100644 --- a/Examples/CategoriesHits/CategoriesHits.SearchViewController.swift +++ b/Examples/CategoriesHits/CategoriesHits.SearchViewController.swift @@ -10,20 +10,20 @@ import UIKit import InstantSearch enum CategoriesHits { - + class SearchViewController: UIViewController { - + let searchController: UISearchController - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController let searcher: MultiSearcher let categoriesInteractor: FacetListInteractor let hitsInteractor: HitsInteractor> - + let searchResultsController: SearchResultsController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { searcher = .init(client: .instantSearch) searchResultsController = .init(style: .plain) @@ -35,33 +35,33 @@ enum CategoriesHits { controller: textFieldController) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + configureUI() - + let facetsSearcher = searcher.addFacetsSearcher(indexName: .instantSearch, attribute: "categories") categoriesInteractor.connectFacetSearcher(facetsSearcher) searchResultsController.categoriesInteractor = categoriesInteractor - + let hitsSearchers = searcher.addHitsSearcher(indexName: .instantSearch) hitsInteractor.connectSearcher(hitsSearchers) searchResultsController.hitsInteractor = hitsInteractor - + searcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func configureUI() { title = "Categories & Hits" view.backgroundColor = .white @@ -71,7 +71,7 @@ enum CategoriesHits { searchController.automaticallyShowsCancelButton = false navigationItem.searchController = searchController } - + } - + } diff --git a/Examples/CategoriesHits/SceneDelegate.swift b/Examples/CategoriesHits/SceneDelegate.swift index bc4b3a4c..908c400f 100644 --- a/Examples/CategoriesHits/SceneDelegate.swift +++ b/Examples/CategoriesHits/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(CategoriesHits.SearchViewController(), for: scene) } } - diff --git a/Examples/Examples/AppDelegate.swift b/Examples/Examples/AppDelegate.swift index f07d92ec..d0b7706d 100644 --- a/Examples/Examples/AppDelegate.swift +++ b/Examples/Examples/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Examples/Demo.swift b/Examples/Examples/Demo.swift index 857d0a6d..26524b15 100644 --- a/Examples/Examples/Demo.swift +++ b/Examples/Examples/Demo.swift @@ -10,20 +10,20 @@ import UIKit import AlgoliaSearchClient protocol DemoProtocol { - + var objectID: ObjectID { get } var name: String { get } var type: String { get } - -} +} struct Demo: Codable, DemoProtocol { - + let objectID: ObjectID let name: String let type: String - + + // swiftlint:disable type_name enum ID: String { case showcaseImperative = "showcase_imperative_ui" case showCaseDeclarative = "showcase_declarative_ui" @@ -38,5 +38,5 @@ struct Demo: Codable, DemoProtocol { case codexMultipleIndex = "codex_multiple_index" case codexCategoriesHits = "codex_categories_hits" } - + } diff --git a/Examples/Examples/DemoListViewController.swift b/Examples/Examples/DemoListViewController.swift index 2cc46309..c973c643 100644 --- a/Examples/Examples/DemoListViewController.swift +++ b/Examples/Examples/DemoListViewController.swift @@ -11,15 +11,15 @@ import UIKit import InstantSearch final class DemoListViewController: UITableViewController { - + let searcher: HitsSearcher let filterState: FilterState let hitsInteractor: HitsInteractor let textFieldController: TextFieldController let searchBoxInteractor: SearchBoxInteractor - + var didSelect: ((Demo) -> Void)? - + let searchController: UISearchController private let cellIdentifier = "cellID" var groupedDemos: [(groupName: String, demos: [Demo])] @@ -29,7 +29,7 @@ final class DemoListViewController: UITableViewCon filterState = .init() hitsInteractor = HitsInteractor(infiniteScrolling: .on(withOffset: 10), showItemsOnEmptyQuery: true) groupedDemos = [] - + searcher.request.query.hitsPerPage = 40 searcher.connectFilterState(filterState) hitsInteractor.connectSearcher(searcher) @@ -49,50 +49,50 @@ final class DemoListViewController: UITableViewCon viewController.updateDemos(demos) } } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground searcher.search() } - + func updateDemos(_ demos: [Demo]) { let demosPerType = Dictionary(grouping: demos, by: { $0.type }) self.groupedDemos = demosPerType .sorted { $0.key < $1.key } - .map { ($0.key, $0.value.sorted { $0.name < $1.name } ) } + .map { ($0.key, $0.value.sorted { $0.name < $1.name }) } DispatchQueue.main.async { self.tableView.reloadData() } } - //MARK: UITableViewDataSource - + // MARK: UITableViewDataSource + override func numberOfSections(in tableView: UITableView) -> Int { return groupedDemos.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return groupedDemos[section].demos.count } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let demo = groupedDemos[indexPath.section].demos[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) cell.textLabel?.text = demo.name return cell } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return groupedDemos[section].groupName } - - //MARK: UITableViewDelegate - + + // MARK: UITableViewDelegate + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let demo = groupedDemos[indexPath.section].demos[indexPath.row] didSelect?(demo) diff --git a/Examples/Examples/DemoViewControllerFactory.swift b/Examples/Examples/DemoViewControllerFactory.swift index 13cd4553..650d1c5b 100644 --- a/Examples/Examples/DemoViewControllerFactory.swift +++ b/Examples/Examples/DemoViewControllerFactory.swift @@ -7,42 +7,42 @@ import Foundation import UIKit - +// swiftlint:disable cyclomatic_complexity function_body_length class DemoViewControllerFactory: ViewControllerFactory { - + func viewController(for demo: Demo) -> UIViewController? { guard let id = Demo.ID(rawValue: demo.objectID.rawValue) else { return .none } - + switch id { case .codexQuerySuggestions: return QuerySuggestionsDemoViewController() - + case .codexVoiceSearch: return VoiceSearchViewController() - + case .codexMultipleIndex: return MultiIndex.SearchViewController() - + case .codexQuerySuggestionsCategories: return QuerySuggestionsCategories.SearchViewController() - + case .codexQuerySuggestionsRecent: return QuerySuggestionsAndRecentSearches.SearchViewController() - + case .codexQuerySuggestionsHits: return QuerySuggestionsAndHits.SearchViewController() - + case .codexCategoriesHits: return CategoriesHits.SearchViewController() - + case .guideInsights: return InsightsViewController() - + case .guideGettingStarted: return GettingStartedGuide.StepSeven.ViewController() - + case .guideDeclarativeUI: let controller = AlgoliaController() let rootView = ContentView(searchBoxController: controller.searchBoxController, @@ -51,7 +51,7 @@ class DemoViewControllerFactory: ViewControllerFactory { facetListController: controller.facetListController) return CommonSwiftUIDemoViewController(controller: controller, rootView: rootView) - + case .showcaseImperative: let factory = ShowcaseDemoViewControllerFactory(framework: .uikit) let viewController = DemoListViewController(indexName: "mobile_demo_home") @@ -60,7 +60,7 @@ class DemoViewControllerFactory: ViewControllerFactory { viewController.didSelect = pusher.callAsFunction viewController.title = "Imperative UI" return viewController - + case .showCaseDeclarative: let factory = ShowcaseDemoViewControllerFactory(framework: .swiftui) let viewController = DemoListViewController(indexName: "mobile_demo_home") @@ -71,6 +71,5 @@ class DemoViewControllerFactory: ViewControllerFactory { return viewController } } - -} +} diff --git a/Examples/Examples/FacetListTableController.swift b/Examples/Examples/FacetListTableController.swift index c8e5fb2d..1e18ca7f 100644 --- a/Examples/Examples/FacetListTableController.swift +++ b/Examples/Examples/FacetListTableController.swift @@ -47,11 +47,11 @@ class FacetListTableController: NSObject, FacetListController { } extension FacetListTableController: UITableViewDataSource { - + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return selectableItems.count } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) let selectableRefinement = selectableItems[indexPath.row] @@ -60,28 +60,28 @@ extension FacetListTableController: UITableViewDataSource { .font: UIFont.systemFont(ofSize: 14)] let facetCountString = NSAttributedString(string: " (\(selectableRefinement.item.count))", attributes: facetCountStringColor) facetAttributedString.append(facetCountString) - + cell.textLabel?.attributedText = facetAttributedString - + cell.accessoryType = selectableRefinement.isSelected ? .checkmark : .none - + return cell } - + } extension FacetListTableController: UITableViewDelegate { - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let selectableItem = selectableItems[indexPath.row] - + self.onClick?(selectableItem.item) } - + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - + guard let titleDescriptor = titleDescriptor else { return nil } - + let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 3 * 16)) let label = UILabel(frame: CGRect(x: 5, y: 16, width: tableView.frame.width, height: 2 * 16)) label.font = .systemFont(ofSize: 12) @@ -90,16 +90,16 @@ extension FacetListTableController: UITableViewDelegate { view.addSubview(label) view.backgroundColor = UIColor(hexString: "#f7f8fa") label.textColor = .gray - + label.text = titleDescriptor.text label.textColor = titleDescriptor.color - + return view } - + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { guard titleDescriptor != nil else { return 0 } return 3 * 16 } - + } diff --git a/Examples/Examples/ShowcaseDemo.swift b/Examples/Examples/ShowcaseDemo.swift index 1b0e1b35..7296bf13 100644 --- a/Examples/Examples/ShowcaseDemo.swift +++ b/Examples/Examples/ShowcaseDemo.swift @@ -9,11 +9,12 @@ import Foundation import AlgoliaSearchClient struct ShowcaseDemo: Codable, DemoProtocol { - + let objectID: ObjectID let name: String let type: String - + + // swiftlint:disable type_name enum ID: String { case singleIndex = "paging_single_index" case multiIndex = "paging_multiple_index" @@ -42,5 +43,5 @@ struct ShowcaseDemo: Codable, DemoProtocol { case queryRuleCustomData = "query_rule_custom_data" case relevantSort = "dynamic_sort" } - + } diff --git a/Examples/Examples/ShowcaseDemoViewControllerFactory.swift b/Examples/Examples/ShowcaseDemoViewControllerFactory.swift index 03383d8c..dd600fb7 100644 --- a/Examples/Examples/ShowcaseDemoViewControllerFactory.swift +++ b/Examples/Examples/ShowcaseDemoViewControllerFactory.swift @@ -9,208 +9,210 @@ import Foundation import UIKit class ShowcaseDemoViewControllerFactory: ViewControllerFactory { - + enum Framework { case uikit case swiftui } - + let framework: Framework - + init(framework: Framework) { self.framework = framework } - + func viewController(for demo: ShowcaseDemo) -> UIViewController? { - + guard let demoID = ShowcaseDemo.ID(rawValue: demo.objectID.rawValue) else { return nil } - + let viewController: UIViewController? - + switch framework { case .uikit: viewController = uikitShowcaseViewController(for: demoID) case .swiftui: viewController = swiftuiShowcaseViewController(for: demoID) } - + viewController?.title = demo.name - + return viewController } - + + // swiftlint:disable function_body_length cyclomatic_complexity func uikitShowcaseViewController(for demoID: ShowcaseDemo.ID) -> UIViewController? { let viewController: UIViewController - + switch demoID { case .singleIndex: viewController = SearchDemoViewController() - + case .sffv: viewController = FacetSearchDemoViewController() - + case .toggle: viewController = ToggleFilterDemoViewController() - + case .dynamicFacetList: viewController = DynamicFacetListDemoViewController() - + case .facetList: viewController = FacetListDemoViewController() - + case .facetListPersistentSelection: viewController = FacetListPersistentDemoViewController() - + case .segmented: viewController = SegmentedFilterDemoViewController() - + case .filterNumericComparison: viewController = FilterNumericComparisonDemoViewController() - + case .filterNumericRange: viewController = FilterNumericRangeDemoViewController() - + case .filterRating: viewController = RatingFilterDemoViewController() - + case .sortBy: viewController = SortByDemoViewController() - + case .currentFilters: viewController = CurrentFiltersDemoViewController() - + case .clearFilters: viewController = ClearFiltersDemoViewController() - + case .relevantSort: viewController = RelevantSortDemoViewController() - + case .multiIndex: viewController = MultiIndexDemoViewController() - + case .facetFilterList: viewController = FilterListDemo.facet() - + case .numericFilterList: viewController = FilterListDemo.numeric() - + case .tagFilterList: viewController = FilterListDemo.tag() - + case .searchOnSubmit: viewController = SearchDemoViewController(searchTriggeringMode: .searchOnSubmit) - + case .searchAsYouType: viewController = SearchDemoViewController() - + case .stats: viewController = StatsDemoViewController() - + case .highlighting: viewController = SearchDemoViewController() - + case .loading: viewController = SearchDemoViewController() - + case .hierarchical: viewController = HierarchicalDemoViewController() - + case .relatedItems: viewController = RelatedItemsDemoViewController() - + case .queryRuleCustomData: viewController = QueryRuleCustomDataDemoViewController() } - + return viewController } - + + // swiftlint:disable function_body_length cyclomatic_complexity func swiftuiShowcaseViewController(for demoID: ShowcaseDemo.ID) -> UIViewController? { let viewController: UIViewController - + switch demoID { case .singleIndex: viewController = SearchDemoSwiftUI.viewController() - + case .sffv: viewController = FacetSearchDemoSwiftUI.viewController() - + case .toggle: viewController = ToggleFilterDemoSwiftUI.viewController() - + case .dynamicFacetList: viewController = DynamicFacetDemoSwiftUI.viewController() - + case .facetList: viewController = FacetListDemoSwiftUI.viewController() - + case .facetListPersistentSelection: viewController = FacetListPersistentDemoSwiftUI.viewController() - + case .segmented: viewController = SegmentedDemoSwiftUI.viewController() - + case .filterNumericComparison: viewController = FilterNumericComparisonDemoSwiftUI.viewController() - + case .filterNumericRange: viewController = FilterNumericRangeDemoSwiftUI.viewController() - + case .filterRating: viewController = RatingFilterDemoSwiftUI.viewController() - + case .sortBy: viewController = SortByDemoSwiftUI.viewController() - + case .currentFilters: viewController = CurrentFiltersDemoSwiftUI.viewController() - + case .clearFilters: viewController = ClearFiltersDemoSwiftUI.viewController() - + case .relevantSort: viewController = RelevantSortDemoSwiftUI.viewController() - + case .multiIndex: viewController = MultiIndexDemoSwiftUI.viewController() - + case .facetFilterList: viewController = FilterListDemoSwiftUI.facetViewController() - + case .numericFilterList: viewController = FilterListDemoSwiftUI.numericViewController() - + case .tagFilterList: viewController = FilterListDemoSwiftUI.tagViewController() - + case .searchOnSubmit: viewController = SearchDemoSwiftUI.viewController(searchTriggeringMode: .searchOnSubmit) - + case .searchAsYouType: viewController = SearchDemoSwiftUI.viewController() - + case .stats: viewController = StatsDemoSwiftUI.viewController() - + case .highlighting: viewController = SearchDemoSwiftUI.viewController() - + case .loading: viewController = SearchDemoSwiftUI.viewController() - + case .hierarchical: viewController = HierarchicalDemoSwiftUI.viewController() - + case .relatedItems: viewController = RelatedItemsDemoViewController() - + case .queryRuleCustomData: viewController = QueryRuleCustomDataSwiftUI.viewController() } - + return viewController } - + } diff --git a/Examples/Examples/StoreItemTableViewCell+StoreItem.swift b/Examples/Examples/StoreItemTableViewCell+StoreItem.swift index bface73e..514186bd 100644 --- a/Examples/Examples/StoreItemTableViewCell+StoreItem.swift +++ b/Examples/Examples/StoreItemTableViewCell+StoreItem.swift @@ -11,11 +11,11 @@ import AlgoliaSearchClient import InstantSearchCore extension StoreItemView { - + func setup(with productHit: Hit) { let product = productHit.object itemImageView.sd_setImage(with: product.images.first) - + if let highlightedName = productHit.hightlightedString(forKey: "name") { titleLabel.attributedText = NSAttributedString(highlightedString: highlightedName, attributes: [ @@ -23,7 +23,7 @@ extension StoreItemView { } else { titleLabel.text = product.name } - + if let highlightedDescription = productHit.hightlightedString(forKey: "brand") { subtitleLabel.attributedText = NSAttributedString(highlightedString: highlightedDescription, attributes: [ @@ -32,27 +32,27 @@ extension StoreItemView { } else { subtitleLabel.text = product.brand } - + if let price = product.price { priceLabel.text = "\(price.value) €" } - + } - + } extension StoreItemCollectionViewCell { - + func setup(with productHit: Hit) { storeItemView.setup(with: productHit) } - + } extension StoreItemTableViewCell { - + func setup(with productHit: Hit) { storeItemView.setup(with: productHit) } - + } diff --git a/Examples/Examples/StoreItemTableViewCell.swift b/Examples/Examples/StoreItemTableViewCell.swift index 24bc4977..e3d563ae 100644 --- a/Examples/Examples/StoreItemTableViewCell.swift +++ b/Examples/Examples/StoreItemTableViewCell.swift @@ -10,7 +10,7 @@ import AlgoliaSearchClient import UIKit class StoreItemTableViewCell: UITableViewCell { - + let storeItemView: StoreItemView override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -20,9 +20,9 @@ class StoreItemTableViewCell: UITableViewCell { contentView.addSubview(storeItemView) storeItemView.pin(to: contentView) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/Examples/Examples/TemplateViewController.swift b/Examples/Examples/TemplateViewController.swift index 468da062..f8b5c5e5 100644 --- a/Examples/Examples/TemplateViewController.swift +++ b/Examples/Examples/TemplateViewController.swift @@ -10,7 +10,7 @@ import Foundation import UIKit class TemplateViewController: UIViewController { - + let label = UILabel() override func viewDidLoad() { @@ -20,5 +20,5 @@ class TemplateViewController: UIViewController { view.addSubview(label) label.pin(to: view.safeAreaLayoutGuide) } - + } diff --git a/Examples/Examples/ViewControllerFactory.swift b/Examples/Examples/ViewControllerFactory.swift index 7328ba30..31723524 100644 --- a/Examples/Examples/ViewControllerFactory.swift +++ b/Examples/Examples/ViewControllerFactory.swift @@ -9,9 +9,9 @@ import Foundation import UIKit protocol ViewControllerFactory { - + associatedtype Model - + func viewController(for model: Model) -> UIViewController? - + } diff --git a/Examples/Examples/ViewControllerPusher.swift b/Examples/Examples/ViewControllerPusher.swift index cb3250cb..70c90798 100644 --- a/Examples/Examples/ViewControllerPusher.swift +++ b/Examples/Examples/ViewControllerPusher.swift @@ -9,19 +9,19 @@ import Foundation import UIKit final class ViewControllerPusher { - + let factory: Factory let sourceViewController: UIViewController var isTransitionAnimated: Bool var missingNavigationControllerMessage: String? var missingModelMessage: ((Factory.Model) -> String)? - + init(factory: Factory, sourceViewController: UIViewController) { self.factory = factory self.sourceViewController = sourceViewController self.isTransitionAnimated = true } - + func callAsFunction(_ model: Factory.Model) { func presentErrorAlert(withMessage message: String?) { let alertController = UIAlertController(title: "Error", message: message, preferredStyle: .alert) @@ -38,5 +38,5 @@ final class ViewControllerPusher { } navigationController.pushViewController(destinationViewController, animated: isTransitionAnimated) } - + } diff --git a/Examples/Guide/GettingStartedSwiftUIGuide/AlgoliaController.swift b/Examples/Guide/GettingStartedSwiftUIGuide/AlgoliaController.swift index 0c4fdd64..bd21ddc8 100644 --- a/Examples/Guide/GettingStartedSwiftUIGuide/AlgoliaController.swift +++ b/Examples/Guide/GettingStartedSwiftUIGuide/AlgoliaController.swift @@ -11,7 +11,7 @@ import InstantSearchCore import InstantSearchSwiftUI class AlgoliaController { - + let searcher: HitsSearcher let searchBoxInteractor: SearchBoxInteractor @@ -24,7 +24,7 @@ class AlgoliaController { let statsController: StatsTextObservableController let filterState: FilterState - + let facetListInteractor: FacetListInteractor let facetListController: FacetListObservableController @@ -44,7 +44,7 @@ class AlgoliaController { setupConnections() searcher.search() } - + func setupConnections() { searchBoxInteractor.connectSearcher(searcher) searchBoxInteractor.connectController(searchBoxController) @@ -57,5 +57,5 @@ class AlgoliaController { facetListInteractor.connectFilterState(filterState, with: "manufacturer", operator: .or) facetListInteractor.connectController(facetListController, with: FacetListPresenter(sortBy: [.isRefined, .count(order: .descending)])) } - + } diff --git a/Examples/Guide/GettingStartedSwiftUIGuide/AppDelegate.swift b/Examples/Guide/GettingStartedSwiftUIGuide/AppDelegate.swift index 5bb7e1a0..671740b7 100644 --- a/Examples/Guide/GettingStartedSwiftUIGuide/AppDelegate.swift +++ b/Examples/Guide/GettingStartedSwiftUIGuide/AppDelegate.swift @@ -29,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Guide/GettingStartedSwiftUIGuide/ContentView.swift b/Examples/Guide/GettingStartedSwiftUIGuide/ContentView.swift index 02605b88..c67d0b0e 100644 --- a/Examples/Guide/GettingStartedSwiftUIGuide/ContentView.swift +++ b/Examples/Guide/GettingStartedSwiftUIGuide/ContentView.swift @@ -12,7 +12,7 @@ import InstantSearchSwiftUI import SwiftUI struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController @ObservedObject var statsController: StatsTextObservableController @@ -20,7 +20,7 @@ struct ContentView: View { @State private var isEditing = false @State private var isPresentingFacets = false - + var body: some View { VStack(spacing: 7) { SearchBar(text: $searchBoxController.query, @@ -45,7 +45,7 @@ struct ContentView: View { .navigationBarItems(trailing: facetsButton()) .sheet(isPresented: $isPresentingFacets, content: facets) } - + @ViewBuilder private func facets() -> some View { NavigationView { @@ -64,7 +64,7 @@ struct ContentView: View { .navigationBarTitle("Brand") } } - + private func facetsButton() -> some View { Button(action: { isPresentingFacets.toggle() @@ -74,5 +74,5 @@ struct ContentView: View { .font(.title) }) } - + } diff --git a/Examples/Guide/GettingStartedSwiftUIGuide/SceneDelegate.swift b/Examples/Guide/GettingStartedSwiftUIGuide/SceneDelegate.swift index 6fc3d2d7..61b1bbe6 100644 --- a/Examples/Guide/GettingStartedSwiftUIGuide/SceneDelegate.swift +++ b/Examples/Guide/GettingStartedSwiftUIGuide/SceneDelegate.swift @@ -23,4 +23,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Guide/GettingStartedUIKitGuide/AppDelegate.swift b/Examples/Guide/GettingStartedUIKitGuide/AppDelegate.swift index 877f9c69..323d8a76 100644 --- a/Examples/Guide/GettingStartedUIKitGuide/AppDelegate.swift +++ b/Examples/Guide/GettingStartedUIKitGuide/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Guide/GettingStartedUIKitGuide/GettingStartedSearchViewController.swift b/Examples/Guide/GettingStartedUIKitGuide/GettingStartedSearchViewController.swift index cdf92621..5fecec84 100644 --- a/Examples/Guide/GettingStartedUIKitGuide/GettingStartedSearchViewController.swift +++ b/Examples/Guide/GettingStartedUIKitGuide/GettingStartedSearchViewController.swift @@ -5,6 +5,7 @@ // Created by Vladislav Fitc on 29/07/2020. // Copyright © 2020 Algolia. All rights reserved. // +// swiftlint:disable file_length line_length unused_optional_binding import Foundation import UIKit @@ -75,7 +76,7 @@ struct Item: Codable { let name: String } */ - + /** ## Hits view controller @@ -85,30 +86,30 @@ struct Item: Codable { */ class SearchResultsViewController: UITableViewController, HitsController { - + var hitsSource: HitsInteractor? - + override func viewDidLoad() { super.viewDidLoad() tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { hitsSource?.numberOfHits() ?? 0 } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = hitsSource?.hit(atIndex: indexPath.row)?.name return cell } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let _ = hitsSource?.hit(atIndex: indexPath.row) { // Handle hit selection } } - + } /** @@ -118,12 +119,12 @@ class SearchResultsViewController: UITableViewController, HitsController { */ extension GettingStartedGuide.StepOne { - + class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() - + } } @@ -140,10 +141,10 @@ extension GettingStartedGuide.StepOne { extension GettingStartedGuide.StepTwo { class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() - + let searcher = HitsSearcher(appID: "latency", apiKey: "1f6fd3a6fb973cb08419fe7d288fa4db", indexName: "bestbuy") @@ -151,15 +152,15 @@ extension GettingStartedGuide.StepTwo { searchController: searchController, hitsInteractor: .init(), hitsController: hitsViewController) - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() searcher.search() } - + } - + } /** @@ -167,10 +168,9 @@ extension GettingStartedGuide.StepTwo { */ extension GettingStartedGuide.StepThree { - + class ViewController: UIViewController { - - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() @@ -181,19 +181,19 @@ extension GettingStartedGuide.StepThree { searchController: searchController, hitsInteractor: .init(), hitsController: hitsViewController) - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() searcher.search() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func setupUI() { view.backgroundColor = .white navigationItem.searchController = searchController @@ -201,9 +201,9 @@ extension GettingStartedGuide.StepThree { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } - + } /** @@ -215,9 +215,9 @@ extension GettingStartedGuide.StepThree { */ extension GettingStartedGuide.StepFour { - + class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() @@ -229,7 +229,7 @@ extension GettingStartedGuide.StepFour { hitsInteractor: .init(), hitsController: hitsViewController) let statsInteractor = StatsInteractor() - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() @@ -237,12 +237,12 @@ extension GettingStartedGuide.StepFour { searcher.search() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func setupUI() { view.backgroundColor = .white navigationItem.searchController = searchController @@ -250,9 +250,9 @@ extension GettingStartedGuide.StepFour { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } - + } /** @@ -263,9 +263,9 @@ extension GettingStartedGuide.StepFour { */ extension GettingStartedGuide.StepFive { - + class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsTableViewController) let hitsTableViewController = SearchResultsViewController() @@ -277,7 +277,7 @@ extension GettingStartedGuide.StepFive { hitsInteractor: .init(), hitsController: hitsTableViewController) let statsInteractor = StatsInteractor() - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() @@ -286,12 +286,12 @@ extension GettingStartedGuide.StepFive { searcher.search() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func setupUI() { view.backgroundColor = .white navigationItem.searchController = searchController @@ -299,13 +299,13 @@ extension GettingStartedGuide.StepFive { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } } extension GettingStartedGuide.StepFive.ViewController: StatsTextController { - + func setItem(_ item: String?) { title = item } @@ -325,9 +325,9 @@ extension GettingStartedGuide.StepFive.ViewController: StatsTextController { */ extension GettingStartedGuide.StepSix { - + class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() @@ -346,10 +346,10 @@ extension GettingStartedGuide.StepSix { attribute: "category", operator: .and, controller: categoryListController) - + lazy var categoryListController = FacetListTableController(tableView: categoryTableViewController.tableView) let categoryTableViewController = UITableViewController() - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() @@ -359,12 +359,12 @@ extension GettingStartedGuide.StepSix { searcher.search() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func setupUI() { view.backgroundColor = .white navigationItem.searchController = searchController @@ -372,17 +372,17 @@ extension GettingStartedGuide.StepSix { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } } extension GettingStartedGuide.StepSix.ViewController: StatsTextController { - + func setItem(_ item: String?) { title = item } - + } /** @@ -391,9 +391,9 @@ extension GettingStartedGuide.StepSix.ViewController: StatsTextController { */ extension GettingStartedGuide.StepSeven { - + class ViewController: UIViewController { - + lazy var searchController = UISearchController(searchResultsController: hitsViewController) let hitsViewController = SearchResultsViewController() @@ -412,10 +412,10 @@ extension GettingStartedGuide.StepSeven { attribute: "category", operator: .and, controller: categoryListController) - + lazy var categoryListController = FacetListTableController(tableView: categoryTableViewController.tableView) let categoryTableViewController = UITableViewController() - + override func viewDidLoad() { super.viewDidLoad() searchConnector.connect() @@ -425,12 +425,12 @@ extension GettingStartedGuide.StepSeven { searcher.search() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func setupUI() { view.backgroundColor = .white navigationItem.searchController = searchController @@ -440,27 +440,27 @@ extension GettingStartedGuide.StepSeven { searchController.automaticallyShowsCancelButton = false categoryTableViewController.title = "Category" } - + @objc func showFilters() { let navigationController = UINavigationController(rootViewController: categoryTableViewController) categoryTableViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFilters)) present(navigationController, animated: true, completion: .none) } - + @objc func dismissFilters() { categoryTableViewController.navigationController?.dismiss(animated: true, completion: .none) } - + } } extension GettingStartedGuide.StepSeven.ViewController: StatsTextController { - + func setItem(_ item: String?) { title = item } - + } /** diff --git a/Examples/Guide/GettingStartedUIKitGuide/SceneDelegate.swift b/Examples/Guide/GettingStartedUIKitGuide/SceneDelegate.swift index 2e9e6f16..aa9efdd8 100644 --- a/Examples/Guide/GettingStartedUIKitGuide/SceneDelegate.swift +++ b/Examples/Guide/GettingStartedUIKitGuide/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Insights/AppDelegate.swift b/Examples/Insights/AppDelegate.swift index 414f922a..0282d447 100644 --- a/Examples/Insights/AppDelegate.swift +++ b/Examples/Insights/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Insights/InsightsViewController.swift b/Examples/Insights/InsightsViewController.swift index f9e13fcc..f2704719 100644 --- a/Examples/Insights/InsightsViewController.swift +++ b/Examples/Insights/InsightsViewController.swift @@ -10,16 +10,16 @@ import InstantSearchInsights import InstantSearch class InsightsViewController: UIViewController { - + let searchController: UISearchController let searcher: HitsSearcher - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController - + let hitsConnector: HitsConnector> let searchResultsController: StoreItemsTableViewController - + let hitsTracker: HitsTracker override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { @@ -38,17 +38,16 @@ class InsightsViewController: UIViewController { insights: insights) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - override func viewDidLoad() { super.viewDidLoad() setup() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true @@ -62,12 +61,11 @@ class InsightsViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false searcher.search() - + searchResultsController.didSelect = { [weak self] index, hit in self?.hitsTracker.trackClick(for: hit, position: index) } - + } } - diff --git a/Examples/Insights/SceneDelegate.swift b/Examples/Insights/SceneDelegate.swift index 7f01e426..b1578263 100644 --- a/Examples/Insights/SceneDelegate.swift +++ b/Examples/Insights/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(InsightsViewController(), for: scene) } } - diff --git a/Examples/MediaDemo/ContentView.swift b/Examples/MediaDemo/ContentView.swift index fe033435..7b65388a 100644 --- a/Examples/MediaDemo/ContentView.swift +++ b/Examples/MediaDemo/ContentView.swift @@ -10,10 +10,10 @@ import InstantSearchCore import InstantSearchSwiftUI struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController> - + var body: some View { HitsList(hitsController) { hit, _ in MovieRow(movieHit: hit!) @@ -26,13 +26,13 @@ struct ContentView: View { .searchable(text: $searchBoxController.query) .navigationBarTitle("Movies") } - + } struct ContentView_Previews: PreviewProvider { - + static let controller = Controller() - + static var previews: some View { NavigationView { ContentView(searchBoxController: controller.searchBoxController, @@ -40,5 +40,5 @@ struct ContentView_Previews: PreviewProvider { } .navigationBarTitle("Movies") } - + } diff --git a/Examples/MediaDemo/Controller.swift b/Examples/MediaDemo/Controller.swift index 9c634e4d..d21ced0e 100644 --- a/Examples/MediaDemo/Controller.swift +++ b/Examples/MediaDemo/Controller.swift @@ -10,13 +10,13 @@ import InstantSearchCore import InstantSearchSwiftUI class Controller { - + let demoController: MovieDemoController let hitsController: HitsObservableController> let searchBoxController: SearchBoxObservableController let statsController: StatsTextObservableController let loadingController: LoadingObservableController - + init(searchTriggeringMode: SearchTriggeringMode = .searchAsYouType) { demoController = MovieDemoController() hitsController = HitsObservableController() @@ -27,5 +27,5 @@ class Controller { demoController.hitsInteractor.connectController(hitsController) demoController.searcher.search() } - + } diff --git a/Examples/MediaDemo/MediaDemoApp.swift b/Examples/MediaDemo/MediaDemoApp.swift index d1e2cc2c..9c4b9b62 100644 --- a/Examples/MediaDemo/MediaDemoApp.swift +++ b/Examples/MediaDemo/MediaDemoApp.swift @@ -9,9 +9,9 @@ import SwiftUI @main struct MediaDemoApp: App { - + let controller = Controller() - + var body: some Scene { WindowGroup { NavigationView { diff --git a/Examples/MediaDemo/MovieRow.swift b/Examples/MediaDemo/MovieRow.swift index 9e357cb9..00a97985 100644 --- a/Examples/MediaDemo/MovieRow.swift +++ b/Examples/MediaDemo/MovieRow.swift @@ -10,9 +10,9 @@ import InstantSearchCore import SwiftUI struct MovieRow: View { - + let movieHit: Hit - + var body: some View { VStack { HStack { @@ -46,8 +46,7 @@ struct MovieRow: View { Spacer() } } - + } - -} +} diff --git a/Examples/MultiIndex/AppDelegate.swift b/Examples/MultiIndex/AppDelegate.swift index f5460923..9874635f 100644 --- a/Examples/MultiIndex/AppDelegate.swift +++ b/Examples/MultiIndex/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/MultiIndex/MultiIndex.SearchResultsController.swift b/Examples/MultiIndex/MultiIndex.SearchResultsController.swift index e72b91c0..c70508a5 100644 --- a/Examples/MultiIndex/MultiIndex.SearchResultsController.swift +++ b/Examples/MultiIndex/MultiIndex.SearchResultsController.swift @@ -12,12 +12,12 @@ import UIKit extension MultiIndex { class SearchResultsController: UITableViewController { - + enum Section: Int, CaseIterable { - + case actors case movies - + var title: String { switch self { case .actors: @@ -26,7 +26,7 @@ extension MultiIndex { return "Movies" } } - + var image: UIImage? { switch self { case .movies: @@ -35,19 +35,19 @@ extension MultiIndex { return UIImage(systemName: "person.circle") } } - + init?(section: Int) { self.init(rawValue: section) } - + init?(indexPath: IndexPath) { self.init(section: indexPath.section) } - + } - + let cellReuseIdentifier = "cellID" - + func numberOfHits(in section: Section) -> Int { switch section { case .actors: @@ -56,7 +56,7 @@ extension MultiIndex { return moviesHitsInteractor?.numberOfHits() ?? 0 } } - + func cellLabel(forRowIndex rowIndex: Int, at section: Section) -> NSAttributedString? { switch section { case .actors: @@ -69,7 +69,7 @@ extension MultiIndex { } } } - + weak var actorsHitsInteractor: HitsInteractor>? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -79,7 +79,7 @@ extension MultiIndex { }.onQueue(.main) } } - + weak var moviesHitsInteractor: HitsInteractor>? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -89,21 +89,21 @@ extension MultiIndex { }.onQueue(.main) } } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier) } - + override func numberOfSections(in tableView: UITableView) -> Int { return Section.allCases.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let section = Section(section: section) else { return 0 } return numberOfHits(in: section) } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) guard let section = Section(indexPath: indexPath) else { return cell } @@ -112,12 +112,13 @@ extension MultiIndex { cell.textLabel?.attributedText = cellLabel(forRowIndex: indexPath.row, at: section) return cell } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { guard let section = Section(section: section), numberOfHits(in: section) != 0 else { return nil } return section.title } - + + // swiftlint:disable unused_optional_binding override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let section = Section(indexPath: indexPath) else { return } switch section { @@ -131,7 +132,7 @@ extension MultiIndex { } } } - + } - + } diff --git a/Examples/MultiIndex/MultiIndex.SearchViewController.swift b/Examples/MultiIndex/MultiIndex.SearchViewController.swift index 4de1fafb..56235f4b 100644 --- a/Examples/MultiIndex/MultiIndex.SearchViewController.swift +++ b/Examples/MultiIndex/MultiIndex.SearchViewController.swift @@ -11,7 +11,7 @@ import InstantSearch import UIKit enum MultiIndex { - + struct Movie: Codable { let title: String } @@ -19,20 +19,20 @@ enum MultiIndex { struct Actor: Codable { let name: String } - + class SearchViewController: UIViewController { - + let searchController: UISearchController - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController let searcher: MultiSearcher let actorHitsInteractor: HitsInteractor> let movieHitsInteractor: HitsInteractor> - + let searchResultsController: SearchResultsController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { searcher = .init(client: .instantSearch) searchResultsController = .init() @@ -44,32 +44,32 @@ enum MultiIndex { controller: textFieldController) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + configureUI() - + let actorsSearcher = searcher.addHitsSearcher(indexName: .actors) actorHitsInteractor.connectSearcher(actorsSearcher) searchResultsController.actorsHitsInteractor = actorHitsInteractor - + let moviesSearcher = searcher.addHitsSearcher(indexName: .movies) movieHitsInteractor.connectSearcher(moviesSearcher) searchResultsController.moviesHitsInteractor = movieHitsInteractor - + searcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func configureUI() { title = "Multi-Index Search" view.backgroundColor = .systemBackground @@ -79,7 +79,7 @@ enum MultiIndex { searchController.automaticallyShowsCancelButton = false navigationItem.searchController = searchController } - + } - + } diff --git a/Examples/MultiIndex/SceneDelegate.swift b/Examples/MultiIndex/SceneDelegate.swift index 55006d50..5ab4aee0 100644 --- a/Examples/MultiIndex/SceneDelegate.swift +++ b/Examples/MultiIndex/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/QuerySuggestions/AppDelegate.swift b/Examples/QuerySuggestions/AppDelegate.swift index 82468ff9..8a5a0ce7 100644 --- a/Examples/QuerySuggestions/AppDelegate.swift +++ b/Examples/QuerySuggestions/AppDelegate.swift @@ -29,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/QuerySuggestions/QuerySuggestionsDemoViewController.swift b/Examples/QuerySuggestions/QuerySuggestionsDemoViewController.swift index 87f08056..cd0f0996 100644 --- a/Examples/QuerySuggestions/QuerySuggestionsDemoViewController.swift +++ b/Examples/QuerySuggestions/QuerySuggestionsDemoViewController.swift @@ -10,73 +10,72 @@ import UIKit import InstantSearch public class QuerySuggestionsDemoViewController: UIViewController { - + let searchController: UISearchController let searcher: MultiSearcher - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController - + let suggestionsHitsConnector: HitsConnector let suggestionsViewController: SuggestionsTableViewController - + let resultsHitsConnector: HitsConnector> let resultsViewController: StoreItemsTableViewController - - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { - + searcher = .init(client: .ecommerce) - + let suggestionsSearcher = searcher.addHitsSearcher(indexName: .ecommerceSuggestions) suggestionsViewController = .init(style: .plain) suggestionsHitsConnector = HitsConnector(searcher: suggestionsSearcher, interactor: .init(infiniteScrolling: .off), controller: suggestionsViewController) - + let resultsSearcher = searcher.addHitsSearcher(indexName: .ecommerceProducts) resultsViewController = .init(style: .plain) resultsHitsConnector = HitsConnector(searcher: resultsSearcher, interactor: .init(), controller: resultsViewController) - + searchController = .init(searchResultsController: suggestionsViewController) - + textFieldController = .init(searchBar: searchController.searchBar) searchBoxConnector = .init(searcher: searcher, controller: textFieldController) - + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - + setup() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override public func viewDidLoad() { super.viewDidLoad() configureUI() } - + private func setup() { navigationItem.searchController = searchController navigationItem.hidesSearchBarWhenScrolling = false - + searchController.showsSearchResultsController = true - + addChild(resultsViewController) resultsViewController.didMove(toParent: self) - + searchBoxConnector.connectController(suggestionsViewController) searchBoxConnector.interactor.onQuerySubmitted.subscribe(with: searchController) { (searchController, _) in searchController.dismiss(animated: true, completion: .none) } - + searcher.search() } - + private func configureUI() { title = "Query Suggestions" view.backgroundColor = .systemBackground @@ -87,8 +86,8 @@ public class QuerySuggestionsDemoViewController: UIViewController { resultsView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), resultsView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), resultsView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - resultsView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + resultsView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } - + } diff --git a/Examples/QuerySuggestions/SceneDelegate.swift b/Examples/QuerySuggestions/SceneDelegate.swift index 6803e227..dee4f70a 100644 --- a/Examples/QuerySuggestions/SceneDelegate.swift +++ b/Examples/QuerySuggestions/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(QuerySuggestionsDemoViewController(), for: scene) } - -} +} diff --git a/Examples/QuerySuggestions/SuggestionsTableViewController.swift b/Examples/QuerySuggestions/SuggestionsTableViewController.swift index 77db3c81..03f2d319 100644 --- a/Examples/QuerySuggestions/SuggestionsTableViewController.swift +++ b/Examples/QuerySuggestions/SuggestionsTableViewController.swift @@ -10,10 +10,10 @@ import UIKit import InstantSearch class SuggestionsTableViewController: UITableViewController, HitsController, SearchBoxController { - + var onQueryChanged: ((String?) -> Void)? var onQuerySubmitted: ((String?) -> Void)? - + public var hitsSource: HitsInteractor? let cellID = "сellID" @@ -22,29 +22,29 @@ class SuggestionsTableViewController: UITableViewController, HitsController, Sea super.init(style: style) tableView.register(SearchSuggestionTableViewCell.self, forCellReuseIdentifier: cellID) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func setQuery(_ query: String?) { // not applicable } - + public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return hitsSource?.numberOfHits() ?? 0 } public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SearchSuggestionTableViewCell else { return .init() } - + if let suggestion = hitsSource?.hit(atIndex: indexPath.row) { cell.setup(with: suggestion) cell.didTapTypeAheadButton = { self.onQueryChanged?(suggestion.query) } } - + return cell } diff --git a/Examples/QuerySuggestionsCategories/AppDelegate.swift b/Examples/QuerySuggestionsCategories/AppDelegate.swift index 0a3bf7d6..87f38baf 100644 --- a/Examples/QuerySuggestionsCategories/AppDelegate.swift +++ b/Examples/QuerySuggestionsCategories/AppDelegate.swift @@ -29,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchResultsController.swift b/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchResultsController.swift index b4ba5b0a..31363aef 100644 --- a/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchResultsController.swift +++ b/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchResultsController.swift @@ -10,15 +10,15 @@ import InstantSearch import UIKit extension QuerySuggestionsCategories { - + class SearchResultsController: UITableViewController { - + var didSelectSuggestion: ((String) -> Void)? - + enum Section: Int, CaseIterable { case categories case suggestions - + var title: String { switch self { case .categories: @@ -27,7 +27,7 @@ extension QuerySuggestionsCategories { return "Suggestions" } } - + var cellReuseIdentifier: String { switch self { case .categories: @@ -36,7 +36,7 @@ extension QuerySuggestionsCategories { return "suggestions" } } - + } weak var categoriesInteractor: FacetListInteractor? { @@ -48,7 +48,7 @@ extension QuerySuggestionsCategories { }.onQueue(.main) } } - + weak var suggestionsInteractor: HitsInteractor? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -58,17 +58,17 @@ extension QuerySuggestionsCategories { }.onQueue(.main) } } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(SearchSuggestionTableViewCell.self, forCellReuseIdentifier: Section.suggestions.cellReuseIdentifier) tableView.register(CategoryTableViewCell.self, forCellReuseIdentifier: Section.categories.cellReuseIdentifier) } - + override func numberOfSections(in tableView: UITableView) -> Int { return Section.allCases.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let section = Section(rawValue: section) else { return 0 } switch section { @@ -78,12 +78,12 @@ extension QuerySuggestionsCategories { return suggestionsInteractor?.numberOfHits() ?? 0 } } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let section = Section(rawValue: indexPath.section) else { return UITableViewCell() } let cell: UITableViewCell - + switch section { case .categories: cell = tableView.dequeueReusableCell(withIdentifier: Section.categories.cellReuseIdentifier, for: indexPath) @@ -100,10 +100,10 @@ extension QuerySuggestionsCategories { suggestionCell.setup(with: suggestion) } } - + return cell } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { guard let section = Section(rawValue: section) else { return nil } switch section { @@ -115,7 +115,7 @@ extension QuerySuggestionsCategories { return section.title } } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let section = Section(rawValue: indexPath.section) else { return } switch section { @@ -129,5 +129,5 @@ extension QuerySuggestionsCategories { } } - + } diff --git a/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchViewController.swift b/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchViewController.swift index 1a985565..89260975 100644 --- a/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchViewController.swift +++ b/Examples/QuerySuggestionsCategories/QuerySuggestionsCategories.SearchViewController.swift @@ -11,20 +11,20 @@ import InstantSearch import UIKit enum QuerySuggestionsCategories { - + class SearchViewController: UIViewController { - + let searchController: UISearchController - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController let searcher: MultiSearcher let categoriesInteractor: FacetListInteractor let suggestionsInteractor: HitsInteractor - + let searchResultsController: SearchResultsController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { searcher = .init(client: .instantSearch) searchResultsController = .init() @@ -36,16 +36,16 @@ enum QuerySuggestionsCategories { controller: textFieldController) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + configureUI() - + let facetsSearcher = searcher.addFacetsSearcher(indexName: .instantSearch, attribute: "categories") categoriesInteractor.connectFacetSearcher(facetsSearcher) @@ -54,19 +54,19 @@ enum QuerySuggestionsCategories { let suggestionsSearcher = searcher.addHitsSearcher(indexName: .instantSearchSuggestions) suggestionsInteractor.connectSearcher(suggestionsSearcher) searchResultsController.suggestionsInteractor = suggestionsInteractor - + searchResultsController.didSelectSuggestion = { [weak self] suggestion in self?.searchBoxConnector.interactor.query = suggestion } - + searcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func configureUI() { title = "Suggestions & Categories" view.backgroundColor = .systemBackground @@ -76,7 +76,7 @@ enum QuerySuggestionsCategories { searchController.automaticallyShowsCancelButton = false navigationItem.searchController = searchController } - + } } diff --git a/Examples/QuerySuggestionsCategories/SceneDelegate.swift b/Examples/QuerySuggestionsCategories/SceneDelegate.swift index b0a7cd46..1389d5ea 100644 --- a/Examples/QuerySuggestionsCategories/SceneDelegate.swift +++ b/Examples/QuerySuggestionsCategories/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/QuerySuggestionsHits/AppDelegate.swift b/Examples/QuerySuggestionsHits/AppDelegate.swift index 08923c61..3455a8a7 100644 --- a/Examples/QuerySuggestionsHits/AppDelegate.swift +++ b/Examples/QuerySuggestionsHits/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchResultsController.swift b/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchResultsController.swift index 716e838c..4da072b6 100644 --- a/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchResultsController.swift +++ b/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchResultsController.swift @@ -10,13 +10,13 @@ import UIKit import InstantSearch extension QuerySuggestionsAndHits { - + class SearchResultsController: UITableViewController { - + enum Section: Int, CaseIterable { case suggestions case hits - + var title: String { switch self { case .suggestions: @@ -25,7 +25,7 @@ extension QuerySuggestionsAndHits { return "Products" } } - + var cellReuseIdentifier: String { switch self { case .suggestions: @@ -34,17 +34,17 @@ extension QuerySuggestionsAndHits { return "productCellID" } } - + init?(section: Int) { self.init(rawValue: section) } - + init?(indexPath: IndexPath) { self.init(section: indexPath.section) } - + } - + weak var suggestionsHitsInteractor: HitsInteractor? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -54,7 +54,7 @@ extension QuerySuggestionsAndHits { }.onQueue(.main) } } - + weak var hitsInteractor: HitsInteractor>? { didSet { oldValue?.onResultsUpdated.cancelSubscription(for: tableView) @@ -64,17 +64,17 @@ extension QuerySuggestionsAndHits { }.onQueue(.main) } } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(SearchSuggestionTableViewCell.self, forCellReuseIdentifier: Section.suggestions.cellReuseIdentifier) tableView.register(ProductTableViewCell.self, forCellReuseIdentifier: Section.hits.cellReuseIdentifier) } - + override func numberOfSections(in tableView: UITableView) -> Int { return Section.allCases.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let section = Section(section: section) else { return 0 } switch section { @@ -84,13 +84,13 @@ extension QuerySuggestionsAndHits { return hitsInteractor?.numberOfHits() ?? 0 } } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - + guard let section = Section(indexPath: indexPath) else { return UITableViewCell() } - + let cell: UITableViewCell - + switch section { case .suggestions: cell = tableView.dequeueReusableCell(withIdentifier: Section.suggestions.cellReuseIdentifier, for: indexPath) @@ -108,10 +108,10 @@ extension QuerySuggestionsAndHits { productTableViewCell.setup(with: product) } } - + return cell } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { guard let section = Section(section: section) else { return nil } switch section { @@ -123,7 +123,7 @@ extension QuerySuggestionsAndHits { return section.title } } - + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { guard let section = Section(indexPath: indexPath) else { return 0 } switch section { @@ -133,7 +133,7 @@ extension QuerySuggestionsAndHits { return 100 } } - + } - + } diff --git a/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchViewController.swift b/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchViewController.swift index 9174998d..eb9d8e19 100644 --- a/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchViewController.swift +++ b/Examples/QuerySuggestionsHits/QuerySuggestionsAndHits.SearchViewController.swift @@ -10,20 +10,20 @@ import UIKit import InstantSearch enum QuerySuggestionsAndHits { - + class SearchViewController: UIViewController { - + let searchController: UISearchController - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController let searcher: MultiSearcher let suggestionsInteractor: HitsInteractor let hitsInteractor: HitsInteractor> - + let searchResultsController: SearchResultsController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { searcher = .init(client: .instantSearch) searchResultsController = .init(style: .plain) @@ -35,33 +35,33 @@ enum QuerySuggestionsAndHits { controller: textFieldController) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + configureUI() - + let suggestionsSearcher = searcher.addHitsSearcher(indexName: .instantSearchSuggestions) suggestionsSearcher.request.query.hitsPerPage = 5 suggestionsInteractor.connectSearcher(suggestionsSearcher) searchResultsController.suggestionsHitsInteractor = suggestionsInteractor - + let hitsSearchers = searcher.addHitsSearcher(indexName: .instantSearch) hitsInteractor.connectSearcher(hitsSearchers) searchResultsController.hitsInteractor = hitsInteractor - + searcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func configureUI() { title = "Suggestions & Hits" view.backgroundColor = .systemBackground @@ -71,7 +71,7 @@ enum QuerySuggestionsAndHits { searchController.automaticallyShowsCancelButton = false navigationItem.searchController = searchController } - + } - + } diff --git a/Examples/QuerySuggestionsHits/SceneDelegate.swift b/Examples/QuerySuggestionsHits/SceneDelegate.swift index 41f41c4c..614e2bad 100644 --- a/Examples/QuerySuggestionsHits/SceneDelegate.swift +++ b/Examples/QuerySuggestionsHits/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/QuerySuggestionsRecentSearches/AppDelegate.swift b/Examples/QuerySuggestionsRecentSearches/AppDelegate.swift index 46cbb1ab..21906a22 100644 --- a/Examples/QuerySuggestionsRecentSearches/AppDelegate.swift +++ b/Examples/QuerySuggestionsRecentSearches/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchResultController.swift b/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchResultController.swift index c7198950..5b9a7dc8 100644 --- a/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchResultController.swift +++ b/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchResultController.swift @@ -10,22 +10,22 @@ import InstantSearch import UIKit extension QuerySuggestionsAndRecentSearches { - + class SearchResultsController: UITableViewController, HitsController { - + var hitsSource: HitsInteractor? - + var recentSearches: [String] = ["last search"] - + var onSelection: ((String) -> Void)? - + private let headerTitleFontSize: CGFloat = 15 private let headerTitleHeight: CGFloat = 28 - + enum Section: Int, CaseIterable { case recentSearches case querySuggestions - + var header: String { switch self { case .querySuggestions: @@ -34,7 +34,7 @@ extension QuerySuggestionsAndRecentSearches { return "Recent searches" } } - + var cellReuseIdentifier: String { switch self { case .querySuggestions: @@ -43,20 +43,20 @@ extension QuerySuggestionsAndRecentSearches { return "recentSearch" } } - + } - + override func viewDidLoad() { super.viewDidLoad() tableView.register(SearchSuggestionTableViewCell.self, forCellReuseIdentifier: Section.querySuggestions.cellReuseIdentifier) tableView.register(UITableViewCell.self, forCellReuseIdentifier: Section.recentSearches.cellReuseIdentifier) tableView.sectionHeaderTopPadding = 0 } - + override func numberOfSections(in tableView: UITableView) -> Int { return Section.allCases.count } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let section = Section(rawValue: section) else { return 0 } switch section { @@ -66,7 +66,7 @@ extension QuerySuggestionsAndRecentSearches { return hitsSource?.numberOfHits() ?? 0 } } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let section = Section(rawValue: indexPath.section) else { return UITableViewCell() } let cell: UITableViewCell @@ -75,7 +75,7 @@ extension QuerySuggestionsAndRecentSearches { cell = tableView.dequeueReusableCell(withIdentifier: Section.recentSearches.cellReuseIdentifier, for: indexPath) cell.imageView?.image = UIImage(systemName: "clock.arrow.circlepath") cell.textLabel?.text = recentSearches[indexPath.row] - + case .querySuggestions: cell = tableView.dequeueReusableCell(withIdentifier: Section.querySuggestions.cellReuseIdentifier, for: indexPath) if @@ -86,65 +86,65 @@ extension QuerySuggestionsAndRecentSearches { } return cell } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let section = Section(rawValue: indexPath.section) else { return } switch section { case .recentSearches: onSelection?(recentSearches[indexPath.row]) - + case .querySuggestions: hitsSource?.hit(atIndex: indexPath.row).flatMap { onSelection?($0.query) } } } - + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { guard let section = Section(rawValue: section) else { return nil } switch section { case .recentSearches: return recentSearches.isEmpty ? nil : section.header - + case .querySuggestions: let isEmpty = hitsSource.flatMap { $0.numberOfHits() == 0 } ?? true return isEmpty ? nil : section.header } } - + override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { guard let section = Section(rawValue: indexPath.section) else { return .none } switch section { case .recentSearches: return .delete - + case .querySuggestions: return .none } } - + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { guard let section = Section(rawValue: indexPath.section) else { return } switch section { case .recentSearches: deleteRecentSearch(atIndex: indexPath.row) - + case .querySuggestions: break } } - + override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { guard let section = Section(rawValue: section) else { return 0 } switch section { case .recentSearches: return recentSearches.isEmpty ? 0 : headerTitleHeight - + case .querySuggestions: return headerTitleHeight } } - + override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { guard let section = Section(rawValue: section) else { return nil } if case(.recentSearches) = section, !recentSearches.isEmpty { @@ -157,42 +157,42 @@ extension QuerySuggestionsAndRecentSearches { return nil } } - + private func deleteRecentSearch(atIndex index: Int) { recentSearches.remove(at: index) tableView.beginUpdates() tableView.reloadSections([Section.recentSearches.rawValue], with: .automatic) tableView.endUpdates() } - + @objc private func clearRecentSearches() { recentSearches.removeAll() tableView.beginUpdates() tableView.reloadSections([Section.recentSearches.rawValue], with: .automatic) tableView.endUpdates() } - + } - + } private class SectionHeader: UIView { - + let label = UILabel() let button = UIButton() - + override init(frame: CGRect) { super.init(frame: frame) - + label.textColor = UIColor.secondaryLabel label.translatesAutoresizingMaskIntoConstraints = false - + button.translatesAutoresizingMaskIntoConstraints = false button.setImage(UIImage(systemName: "trash"), for: .normal) - + let separator = UIView() separator.translatesAutoresizingMaskIntoConstraints = false - + let stackView = UIStackView() stackView.distribution = .fill stackView.isLayoutMarginsRelativeArrangement = true @@ -204,9 +204,9 @@ private class SectionHeader: UIView { addSubview(stackView) stackView.pin(to: self) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchViewController.swift b/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchViewController.swift index 63a61eaa..62d1f752 100644 --- a/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchViewController.swift +++ b/Examples/QuerySuggestionsRecentSearches/QuerySuggestionsRecentSearches.SearchViewController.swift @@ -10,19 +10,19 @@ import InstantSearch import UIKit enum QuerySuggestionsAndRecentSearches { - + class SearchViewController: UIViewController { - + let searchController: UISearchController - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController let hitsSearcher: HitsSearcher let hitsInteractor: HitsInteractor - + let searchResultsController: SearchResultsController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { hitsSearcher = .init(client: .instantSearch, indexName: .instantSearchSuggestions) @@ -40,22 +40,22 @@ enum QuerySuggestionsAndRecentSearches { } searchController.searchBar.searchTextField.addTarget(self, action: #selector(textFieldSubmitted), for: .editingDidEndOnExit) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() configureUI() hitsSearcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + func configureUI() { title = "Recent Searches & Suggestions" view.backgroundColor = .systemBackground @@ -64,7 +64,7 @@ enum QuerySuggestionsAndRecentSearches { searchController.automaticallyShowsCancelButton = false navigationItem.searchController = searchController } - + @objc func textFieldSubmitted() { guard let text = searchController.searchBar.text else { return } if let alreadyPresentIndex = searchResultsController.recentSearches.firstIndex(where: { $0 == text }) { @@ -73,7 +73,7 @@ enum QuerySuggestionsAndRecentSearches { searchResultsController.recentSearches.insert(text, at: searchResultsController.recentSearches.startIndex) searchResultsController.tableView.reloadData() } - + } } diff --git a/Examples/QuerySuggestionsRecentSearches/SceneDelegate.swift b/Examples/QuerySuggestionsRecentSearches/SceneDelegate.swift index 6671fd34..b4d0ae27 100644 --- a/Examples/QuerySuggestionsRecentSearches/SceneDelegate.swift +++ b/Examples/QuerySuggestionsRecentSearches/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Shared/CommonSwiftUIDemoViewController.swift b/Examples/Shared/CommonSwiftUIDemoViewController.swift index 054db71f..b7faa9ad 100644 --- a/Examples/Shared/CommonSwiftUIDemoViewController.swift +++ b/Examples/Shared/CommonSwiftUIDemoViewController.swift @@ -9,16 +9,16 @@ import Foundation import SwiftUI class CommonSwiftUIDemoViewController: UIHostingController { - + let controller: Controller - + init(controller: Controller, rootView: ContentView) { self.controller = controller super.init(rootView: rootView) } - + @MainActor required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/Examples/Shared/Credentials/Ecommerce.swift b/Examples/Shared/Credentials/Ecommerce.swift index ff013b1b..35fb7007 100644 --- a/Examples/Shared/Credentials/Ecommerce.swift +++ b/Examples/Shared/Credentials/Ecommerce.swift @@ -20,7 +20,6 @@ extension IndexName { static let ecommerceSuggestions: IndexName = "STAGING_native_ecom_demo_products_query_suggestions" } - extension RecommendClient { static let ecommerceRecommend = Self(appID: "XX85YRZZMV", apiKey: "d17ff64e913b3293cfba3d3665480217") } diff --git a/Examples/Shared/Credentials/InstantSearch.swift b/Examples/Shared/Credentials/InstantSearch.swift index 588c9d4c..a594901d 100644 --- a/Examples/Shared/Credentials/InstantSearch.swift +++ b/Examples/Shared/Credentials/InstantSearch.swift @@ -16,7 +16,7 @@ extension IndexName { static let instantSearchSuggestions: IndexName = "instant_search_demo_query_suggestions" static let movies: IndexName = "mobile_demo_movies" static let actors: IndexName = "mobile_demo_actors" - + static let facetList: IndexName = "mobile_demo_facet_list" static let facetSearch: IndexName = "mobile_demo_facet_list_search" static let hierarchicalFacets: IndexName = "mobile_demo_hierarchical" diff --git a/Examples/Shared/Double+Range.swift b/Examples/Shared/Double+Range.swift index e1385133..9adabaeb 100644 --- a/Examples/Shared/Double+Range.swift +++ b/Examples/Shared/Double+Range.swift @@ -7,12 +7,10 @@ import Foundation - extension Double { /// Rounds the double to decimal places value - func rounded(toPlaces places:Int) -> Double { + func rounded(toPlaces places: Int) -> Double { let divisor = pow(10.0, Double(places)) return (self * divisor).rounded() / divisor } } - diff --git a/Examples/Shared/EcommerceDemoController.swift b/Examples/Shared/EcommerceDemoController.swift index 9822fd2b..3a19a121 100644 --- a/Examples/Shared/EcommerceDemoController.swift +++ b/Examples/Shared/EcommerceDemoController.swift @@ -9,7 +9,7 @@ import Foundation import InstantSearchCore class EcommerceDemoController { - + let searcher: HitsSearcher let hitsInteractor: HitsInteractor> let searchBoxConnector: SearchBoxConnector @@ -25,5 +25,5 @@ class EcommerceDemoController { loadingConnector = .init(searcher: searcher) hitsInteractor.connectSearcher(searcher) } - + } diff --git a/Examples/Shared/FilterDebugController.swift b/Examples/Shared/FilterDebugController.swift index 6026e3fa..a34dc7fb 100644 --- a/Examples/Shared/FilterDebugController.swift +++ b/Examples/Shared/FilterDebugController.swift @@ -11,11 +11,11 @@ import UIKit import InstantSearchCore class FilterDebugController { - + let stateLabel: UILabel - let emptyMessage = NSAttributedString(string:"No filters applied") + let emptyMessage = NSAttributedString(string: "No filters applied") var colorMap: [String: UIColor] - + init() { stateLabel = UILabel(frame: .zero) colorMap = [:] @@ -23,59 +23,59 @@ class FilterDebugController { stateLabel.font = .systemFont(ofSize: 16) stateLabel.numberOfLines = 0 } - + func connectTo(_ filterState: FilterState) { filterState.onChange.subscribePast(with: self) { viewController, filterState in let filtersText = filterState.toFilterGroups().sqlFormWithSyntaxHighlighting(colorMap: viewController.colorMap) viewController.stateLabel.attributedText = filtersText.string.isEmpty ? viewController.emptyMessage : filtersText }.onQueue(.main) } - + } extension Collection where Element == FilterGroupType { - + public func sqlFormWithSyntaxHighlighting(colorMap: [String: UIColor]) -> NSAttributedString { let converter = FilterGroupConverter() let groupsSeparator = " AND " return compactMap { element -> NSAttributedString? in - + let color: UIColor - + if let groupName = element.name, let specifiedColor = colorMap[groupName] { color = specifiedColor } else { color = .darkText } - + return converter.sql(element) .flatMap { $0.replacingOccurrences(of: "\"", with: "") } .flatMap { sqlString in return NSMutableAttributedString() .appendWith(color: color, weight: .regular, ofSize: 18.0, sqlString) } - + } .joined(separator: NSMutableAttributedString() .appendWith(weight: .semibold, ofSize: 18.0, groupsSeparator)) } - + } extension NSMutableAttributedString { - - @discardableResult func appendWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString{ - let attrText = NSAttributedString.makeWith(color: color, weight: weight, ofSize:ofSize, text) + + @discardableResult func appendWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString { + let attrText = NSAttributedString.makeWith(color: color, weight: weight, ofSize: ofSize, text) self.append(attrText) return self } - + } extension NSAttributedString { - + public static func makeWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString { let attrs = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: ofSize, weight: weight), NSAttributedString.Key.foregroundColor: color] - return NSMutableAttributedString(string: text, attributes:attrs) + return NSMutableAttributedString(string: text, attributes: attrs) } } @@ -85,23 +85,22 @@ extension Sequence where Iterator.Element: NSAttributedString { /// - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string. func joined(separator: NSAttributedString = NSAttributedString(string: "")) -> NSAttributedString { var isFirst = true - return self.reduce(NSMutableAttributedString()) { - (r, e) in + return self.reduce(NSMutableAttributedString()) { (source, string) in if isFirst { isFirst = false } else { - r.append(separator) + source.append(separator) } - r.append(e) - return r + source.append(string) + return source } } - + /// Returns a new attributed string by concatenating the elements of the sequence, adding the given separator between each element. /// - parameters: /// - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string. func joined(separator: String = "") -> NSAttributedString { return joined(separator: NSAttributedString(string: separator)) } - + } diff --git a/Examples/Shared/FilterDebugViewController.swift b/Examples/Shared/FilterDebugViewController.swift index b56d9c60..8a4acbac 100644 --- a/Examples/Shared/FilterDebugViewController.swift +++ b/Examples/Shared/FilterDebugViewController.swift @@ -12,11 +12,11 @@ import InstantSearch import InstantSearchCore class FilterDebugViewController: UIViewController { - + let titleLabel: UILabel let filterStateViewController: FilterDebugController let clearFilterController: FilterClearButtonController - + init(filterState: FilterState) { self.titleLabel = UILabel() self.filterStateViewController = FilterDebugController() @@ -25,33 +25,33 @@ class FilterDebugViewController: UIViewController { configureFilterStateViewController() filterStateViewController.connectTo(filterState) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + private func setupUI() { configureTitleLabel() configureClearButton() configureLayout() } - + func configureTitleLabel() { titleLabel.font = .boldSystemFont(ofSize: 25) titleLabel.text = "Filters" titleLabel.translatesAutoresizingMaskIntoConstraints = false } - + func configureClearButton() { clearFilterController.button.setImage(UIImage(systemName: "trash.fill"), for: .normal) clearFilterController.button.translatesAutoresizingMaskIntoConstraints = false } - + func configureFilterStateViewController() { filterStateViewController.colorMap = [ "_tags": .systemIndigo, @@ -61,7 +61,7 @@ class FilterDebugViewController: UIViewController { "category": .systemGreen ] } - + func configureLayout() { let headerStackView = UIStackView() headerStackView.translatesAutoresizingMaskIntoConstraints = false @@ -77,7 +77,7 @@ class FilterDebugViewController: UIViewController { mainStackView.addArrangedSubview(headerStackView) mainStackView.addArrangedSubview(filterStateViewController.stateLabel) mainStackView.addArrangedSubview(.spacer) - + let containerView = UIView() containerView.translatesAutoresizingMaskIntoConstraints = false containerView.layer.borderWidth = 0.5 @@ -86,9 +86,9 @@ class FilterDebugViewController: UIViewController { containerView.layer.cornerRadius = 10 containerView.addSubview(mainStackView) view.addSubview(containerView) - + mainStackView.pin(to: containerView, insets: .init(top: 10, left: 10, bottom: -10, right: -10)) containerView.pin(to: view) } - + } diff --git a/Examples/Shared/FilterStateObservableController.swift b/Examples/Shared/FilterStateObservableController.swift index 1bfa35c6..951879e7 100644 --- a/Examples/Shared/FilterStateObservableController.swift +++ b/Examples/Shared/FilterStateObservableController.swift @@ -10,16 +10,16 @@ import UIKit import InstantSearch class FilterStateObservableController: ObservableObject { - + @Published public var filtersString: String private let emptyMessage = "No filters applied" - + public init(filterState: FilterState) { filtersString = emptyMessage - filterState.onChange.subscribePast(with: self) { vc, _ in + filterState.onChange.subscribePast(with: self) { viewController, _ in let sqlString = filterState.toFilterGroups().sqlFormWithSyntaxHighlighting(colorMap: [:]).string - vc.filtersString = sqlString.isEmpty ? vc.emptyMessage : sqlString + viewController.filtersString = sqlString.isEmpty ? viewController.emptyMessage : sqlString } } - + } diff --git a/Examples/Shared/Model/Movie.swift b/Examples/Shared/Model/Movie.swift index f75a0e16..e4ed5e00 100644 --- a/Examples/Shared/Model/Movie.swift +++ b/Examples/Shared/Model/Movie.swift @@ -8,21 +8,21 @@ import Foundation struct Movie: Codable { - + let title: String let genres: [String] let posterPath: String let note: Float - + var imageURL: URL { return URL(string: "https://image.tmdb.org/t/p/w185\(posterPath)")! } - + enum CodingKeys: String, CodingKey { case title case genres case posterPath = "poster_path" case note = "vote_average" } - + } diff --git a/Examples/Shared/Model/Product.swift b/Examples/Shared/Model/Product.swift index ca749f7e..742ed658 100644 --- a/Examples/Shared/Model/Product.swift +++ b/Examples/Shared/Model/Product.swift @@ -8,11 +8,11 @@ import Foundation struct Product: Codable { - + let name: String let description: String let brand: String? let image: URL let price: Double? - + } diff --git a/Examples/Shared/Model/StoreItem.swift b/Examples/Shared/Model/StoreItem.swift index 4cc03de3..e3b9de86 100644 --- a/Examples/Shared/Model/StoreItem.swift +++ b/Examples/Shared/Model/StoreItem.swift @@ -8,13 +8,13 @@ import Foundation struct StoreItem: Codable { - + let name: String let brand: String? let description: String? let images: [URL] let price: Double? - + enum CodingKeys: String, CodingKey { case name case brand @@ -22,11 +22,11 @@ struct StoreItem: Codable { case images = "image_urls" case price } - + enum PriceCodingKeys: String, CodingKey { case value } - + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.name = try container.decode(String.self, forKey: .name) @@ -45,7 +45,7 @@ struct StoreItem: Codable { self.price = .none } } - + func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(name, forKey: .name) @@ -54,5 +54,5 @@ struct StoreItem: Codable { try container.encode(images, forKey: .images) try container.encode(price, forKey: .price) } - + } diff --git a/Examples/Shared/MovieDemoController.swift b/Examples/Shared/MovieDemoController.swift index 3b1c5fd5..25b6006f 100644 --- a/Examples/Shared/MovieDemoController.swift +++ b/Examples/Shared/MovieDemoController.swift @@ -9,7 +9,7 @@ import Foundation import InstantSearchCore class MovieDemoController { - + let searcher: HitsSearcher let hitsInteractor: HitsInteractor> let searchBoxConnector: SearchBoxConnector @@ -22,5 +22,5 @@ class MovieDemoController { searchTriggeringMode: searchTriggeringMode) hitsInteractor.connectSearcher(searcher) } - + } diff --git a/Examples/Shared/ProductsTableViewController.swift b/Examples/Shared/ProductsTableViewController.swift index 4301685b..30ff306b 100644 --- a/Examples/Shared/ProductsTableViewController.swift +++ b/Examples/Shared/ProductsTableViewController.swift @@ -10,18 +10,18 @@ import UIKit import InstantSearchCore class ProductsTableViewController: UITableViewController, HitsController { - + let cellIdentifier = "cellID" - + var hitsSource: HitsInteractor>? - + var didSelect: ((Hit) -> Void)? - + override func viewDidLoad() { super.viewDidLoad() tableView.register(ProductTableViewCell.self, forCellReuseIdentifier: cellIdentifier) } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let hitsCount = hitsSource?.numberOfHits() ?? 0 if hitsCount == 0 { @@ -31,7 +31,7 @@ class ProductsTableViewController: UITableViewController, HitsController { } return hitsCount } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ProductTableViewCell else { return UITableViewCell() @@ -42,15 +42,15 @@ class ProductsTableViewController: UITableViewController, HitsController { cell.setup(with: hit) return cell } - + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 80 } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let hit = hitsSource?.hit(atIndex: indexPath.row) { didSelect?(hit) } } - + } diff --git a/Examples/Shared/ResultsViewController.swift b/Examples/Shared/ResultsViewController.swift index 8ee0977c..a72255f8 100644 --- a/Examples/Shared/ResultsViewController.swift +++ b/Examples/Shared/ResultsViewController.swift @@ -11,16 +11,16 @@ import InstantSearch import SDWebImage class ResultsViewController: UIViewController { - + let stackView: UIStackView let hitsViewController: StoreItemsTableViewController - + let statsConnector: StatsConnector let statsController: LabelStatsController - + let loadingConnector: LoadingConnector let loadingController: ActivityIndicatorController - + init(searcher: HitsSearcher) { stackView = .init(frame: .zero) hitsViewController = .init(style: .plain) @@ -32,11 +32,11 @@ class ResultsViewController: UIViewController { addChild(hitsViewController) hitsViewController.didMove(toParent: self) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() stackView.translatesAutoresizingMaskIntoConstraints = false @@ -46,7 +46,7 @@ class ResultsViewController: UIViewController { stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor), stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) statsController.label.heightAnchor.constraint(equalToConstant: 25).isActive = true statsController.label.translatesAutoresizingMaskIntoConstraints = false @@ -63,5 +63,5 @@ class ResultsViewController: UIViewController { stackView.addArrangedSubview(detailsStackView) stackView.addArrangedSubview(hitsViewController.view) } - + } diff --git a/Examples/Shared/StoreItemsTableViewController+SearchResponse.swift b/Examples/Shared/StoreItemsTableViewController+SearchResponse.swift index c17d20e3..f278322e 100644 --- a/Examples/Shared/StoreItemsTableViewController+SearchResponse.swift +++ b/Examples/Shared/StoreItemsTableViewController+SearchResponse.swift @@ -10,7 +10,7 @@ import UIKit import InstantSearch extension StoreItemsTableViewController { - + static func with(_ response: SearchResponse) -> Self { let hitsInteractor = HitsInteractor>(infiniteScrolling: .off) hitsInteractor.update(response) @@ -18,5 +18,5 @@ extension StoreItemsTableViewController { hitsInteractor.connectController(viewController) return viewController } - + } diff --git a/Examples/Shared/StoreItemsTableViewController.swift b/Examples/Shared/StoreItemsTableViewController.swift index 18121ae0..cfc8720a 100644 --- a/Examples/Shared/StoreItemsTableViewController.swift +++ b/Examples/Shared/StoreItemsTableViewController.swift @@ -10,23 +10,23 @@ import UIKit import InstantSearch class StoreItemsTableViewController: UITableViewController, HitsController { - + var hitsSource: HitsInteractor>? - + var didSelect: ((Int, Hit) -> Void)? - + let cellIdentifier = "cellID" - + override func viewDidLoad() { super.viewDidLoad() tableView.register(ProductTableViewCell.self, forCellReuseIdentifier: cellIdentifier) } - + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { setEmptyStateIfNeeded() return hitsSource?.numberOfHits() ?? 0 } - + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ProductTableViewCell else { return UITableViewCell() @@ -37,17 +37,17 @@ class StoreItemsTableViewController: UITableViewController, HitsController { cell.setup(with: hit) return cell } - + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 80 } - + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let hit = hitsSource?.hit(atIndex: indexPath.row) { didSelect?(indexPath.row, hit) } } - + private func setEmptyStateIfNeeded() { if hitsSource?.numberOfHits() ?? 0 == 0 { tableView.setEmptyMessage("No results") @@ -55,6 +55,5 @@ class StoreItemsTableViewController: UITableViewController, HitsController { tableView.restore() } } - -} +} diff --git a/Examples/Shared/SwiftUIDemo.swift b/Examples/Shared/SwiftUIDemo.swift index e6cde8ee..3073fcdd 100644 --- a/Examples/Shared/SwiftUIDemo.swift +++ b/Examples/Shared/SwiftUIDemo.swift @@ -10,22 +10,22 @@ import SwiftUI import UIKit protocol SwiftUIDemo { - + associatedtype Controller associatedtype ContentView: View - + static var controller: Controller { get } static func contentView(with controller: Controller) -> ContentView static func viewController() -> UIViewController - + } extension SwiftUIDemo { - + static func viewController() -> UIViewController { let rootView = contentView(with: controller) return CommonSwiftUIDemoViewController(controller: controller, rootView: rootView) } - + } diff --git a/Examples/Shared/UIColor+Convenience.swift b/Examples/Shared/UIColor+Convenience.swift index bebf3e30..b29b9f1c 100644 --- a/Examples/Shared/UIColor+Convenience.swift +++ b/Examples/Shared/UIColor+Convenience.swift @@ -10,6 +10,8 @@ import Foundation import UIKit extension UIColor { + + // swiftlint:disable identifier_name convenience init(hexString: String) { var hexFormatted = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) if hexFormatted.hasPrefix("#") { @@ -39,7 +41,7 @@ extension UIColor { } extension CGColor { - + static let algoliaCyan = CGColor(red: 84/255, green: 104/255, blue: 255/255, alpha: 1) - + } diff --git a/Examples/Shared/UITableView+EmptyResult.swift b/Examples/Shared/UITableView+EmptyResult.swift index 6c083df6..71babef2 100644 --- a/Examples/Shared/UITableView+EmptyResult.swift +++ b/Examples/Shared/UITableView+EmptyResult.swift @@ -26,5 +26,5 @@ extension UITableView { self.backgroundView = nil self.separatorStyle = .singleLine } - + } diff --git a/Examples/Shared/UIView+Layout.swift b/Examples/Shared/UIView+Layout.swift index 45d185ad..26e3e571 100644 --- a/Examples/Shared/UIView+Layout.swift +++ b/Examples/Shared/UIView+Layout.swift @@ -9,29 +9,29 @@ import Foundation import UIKit extension UIView { - + func pin(to view: UIView, insets: UIEdgeInsets = .init()) { NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: view.topAnchor, constant: insets.top), bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: insets.bottom), leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: insets.left), - trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: insets.right), + trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: insets.right) ]) } - + func pin(to layoutGuide: UILayoutGuide, insets: UIEdgeInsets = .init()) { NSLayoutConstraint.activate([ topAnchor.constraint(equalTo: layoutGuide.topAnchor, constant: insets.top), bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor, constant: insets.bottom), leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor, constant: insets.left), - trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor, constant: insets.right), + trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor, constant: insets.right) ]) } - + static var spacer: UIView { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false return view } - + } diff --git a/Examples/Shared/View/CategoryTableViewCell+Facet.swift b/Examples/Shared/View/CategoryTableViewCell+Facet.swift index ddce083c..1a1db08b 100644 --- a/Examples/Shared/View/CategoryTableViewCell+Facet.swift +++ b/Examples/Shared/View/CategoryTableViewCell+Facet.swift @@ -10,7 +10,7 @@ import UIKit import AlgoliaSearchClient extension CategoryTableViewCell { - + func setup(with facet: Facet) { guard let textLabel = textLabel else { return } if let rawHighlighted = facet.highlighted { @@ -23,5 +23,5 @@ extension CategoryTableViewCell { textLabel.text = facet.value } } - + } diff --git a/Examples/Shared/View/CategoryTableViewCell.swift b/Examples/Shared/View/CategoryTableViewCell.swift index f2877aea..a45b2caa 100644 --- a/Examples/Shared/View/CategoryTableViewCell.swift +++ b/Examples/Shared/View/CategoryTableViewCell.swift @@ -10,15 +10,15 @@ import UIKit import InstantSearch class CategoryTableViewCell: UITableViewCell { - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) imageView?.image = UIImage(systemName: "square.grid.2x2") tintColor = .lightGray } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/Examples/Shared/View/DynamicFacetList.swift b/Examples/Shared/View/DynamicFacetList.swift index a7e829f2..5c08f6f3 100644 --- a/Examples/Shared/View/DynamicFacetList.swift +++ b/Examples/Shared/View/DynamicFacetList.swift @@ -10,15 +10,15 @@ import InstantSearchSwiftUI import SwiftUI struct DynamicFacetList: View { - + @ObservedObject var dynamicFacetListController: DynamicFacetListObservableController - + var body: some View { ScrollView { ForEach(dynamicFacetListController.orderedFacets, id: \.attribute) { orderedFacet in Section(header: header(withTitle: "\(orderedFacet.attribute.rawValue)")) { ForEach(orderedFacet.facets, id: \.value) { facet in - VStack() { + VStack { FacetRow(facet: facet, isSelected: dynamicFacetListController.isSelected(facet, for: orderedFacet.attribute)) .onTapGesture { @@ -33,7 +33,7 @@ struct DynamicFacetList: View { } } } - + @ViewBuilder func header(withTitle title: String) -> some View { VStack(spacing: 0) { Text(title) @@ -44,5 +44,5 @@ struct DynamicFacetList: View { } .padding(.horizontal, 20) } - + } diff --git a/Examples/Shared/View/FilterStateDebugView.swift b/Examples/Shared/View/FilterStateDebugView.swift index 0c2bad0e..17a917bf 100644 --- a/Examples/Shared/View/FilterStateDebugView.swift +++ b/Examples/Shared/View/FilterStateDebugView.swift @@ -10,16 +10,16 @@ import SwiftUI import InstantSearchSwiftUI struct FilterStateDebugView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + init(filterStateController: FilterStateObservableController, clearFilterController: FilterClearObservableController) { self.filterStateController = filterStateController self.clearFilterController = clearFilterController } - + var body: some View { VStack(alignment: .leading, spacing: 0) { HStack { @@ -27,7 +27,7 @@ struct FilterStateDebugView: View { .fontWeight(.heavy) .font(.title3) Spacer() - Button(action: { clearFilterController.clear() }) { + Button(action: clearFilterController.clear) { Image(systemName: "trash.fill") } }.padding() @@ -42,5 +42,5 @@ struct FilterStateDebugView: View { .stroke(Color.black, lineWidth: 1) ) } - + } diff --git a/Examples/Shared/View/MovieHit+Text.swift b/Examples/Shared/View/MovieHit+Text.swift index 30fd5f04..6f155ec6 100644 --- a/Examples/Shared/View/MovieHit+Text.swift +++ b/Examples/Shared/View/MovieHit+Text.swift @@ -11,7 +11,7 @@ import SwiftUI import InstantSearchSwiftUI extension Hit where T == Movie { - + var titleText: Text { if let highlightedTitle = hightlightedString(forKey: "title") { return Text(highlightedString: highlightedTitle, @@ -20,10 +20,10 @@ extension Hit where T == Movie { return Text(object.title) } } - + var genresText: Text { - if let highlightedGenres = highlightResult?.value(forKey: "genres"), case .array(let hg) = highlightedGenres { - let highlightedTexts = hg.compactMap({ $0.value }).map(\.value).map { Text(highlightedString: $0, highlighted: { Text($0).foregroundColor(Color(.algoliaCyan)) }) } + if let highlightedGenres = highlightResult?.value(forKey: "genres"), case .array(let higligtedGenres) = highlightedGenres { + let highlightedTexts = higligtedGenres.compactMap({ $0.value }).map(\.value).map { Text(highlightedString: $0, highlighted: { Text($0).foregroundColor(Color(.algoliaCyan)) }) } if highlightedTexts.count > 1 { return highlightedTexts.suffix(from: 1).reduce(highlightedTexts.first!, { $0 + Text(", ") + $1 }) } else { @@ -33,5 +33,5 @@ extension Hit where T == Movie { return Text(object.genres.joined(separator: ", ")) } } - + } diff --git a/Examples/Shared/View/Product/ProductCollectionViewCell+StoreItem.swift b/Examples/Shared/View/Product/ProductCollectionViewCell+StoreItem.swift index 3184f300..89ec36c3 100644 --- a/Examples/Shared/View/Product/ProductCollectionViewCell+StoreItem.swift +++ b/Examples/Shared/View/Product/ProductCollectionViewCell+StoreItem.swift @@ -10,11 +10,11 @@ import UIKit import InstantSearchCore extension ProductCollectionViewCell { - + func setup(with productHit: Hit) { let product = productHit.object itemImageView.sd_setImage(with: product.images.first) - + if let highlightedName = productHit.hightlightedString(forKey: "name") { titleLabel.attributedText = NSAttributedString(highlightedString: highlightedName, attributes: [ @@ -22,7 +22,7 @@ extension ProductCollectionViewCell { } else { titleLabel.text = product.name } - + if let highlightedDescription = productHit.hightlightedString(forKey: "brand") { subtitleLabel.attributedText = NSAttributedString(highlightedString: highlightedDescription, attributes: [ @@ -31,11 +31,10 @@ extension ProductCollectionViewCell { } else { subtitleLabel.text = product.brand } - + if let price = product.price { priceLabel.text = "\(price) €" } } - -} +} diff --git a/Examples/Shared/View/Product/ProductCollectionViewCell.swift b/Examples/Shared/View/Product/ProductCollectionViewCell.swift index cbfe31c1..2ab06ecb 100644 --- a/Examples/Shared/View/Product/ProductCollectionViewCell.swift +++ b/Examples/Shared/View/Product/ProductCollectionViewCell.swift @@ -11,15 +11,15 @@ import UIKit import SDWebImage class ProductCollectionViewCell: UICollectionViewCell { - + let itemImageView: UIImageView let titleLabel: UILabel let subtitleLabel: UILabel let priceLabel: UILabel - + let mainStackView: UIStackView let labelsStackView: UIStackView - + override init(frame: CGRect) { itemImageView = .init(frame: .zero) titleLabel = .init(frame: .zero) @@ -30,15 +30,15 @@ class ProductCollectionViewCell: UICollectionViewCell { super.init(frame: frame) layout() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private func layout() { contentView.backgroundColor = .systemBackground contentView.layer.cornerRadius = 12 - + itemImageView.sd_imageIndicator = SDWebImageActivityIndicator.gray itemImageView.translatesAutoresizingMaskIntoConstraints = false itemImageView.clipsToBounds = true @@ -48,15 +48,15 @@ class ProductCollectionViewCell: UICollectionViewCell { titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.font = .systemFont(ofSize: 15, weight: .bold) titleLabel.numberOfLines = 1 - + subtitleLabel.translatesAutoresizingMaskIntoConstraints = false subtitleLabel.font = .systemFont(ofSize: 13, weight: .regular) subtitleLabel.textColor = .gray subtitleLabel.numberOfLines = 0 - + priceLabel.translatesAutoresizingMaskIntoConstraints = false priceLabel.font = .systemFont(ofSize: 14) - + labelsStackView.axis = .vertical labelsStackView.translatesAutoresizingMaskIntoConstraints = false labelsStackView.spacing = 3 @@ -64,19 +64,18 @@ class ProductCollectionViewCell: UICollectionViewCell { labelsStackView.addArrangedSubview(subtitleLabel) labelsStackView.addArrangedSubview(priceLabel) labelsStackView.addArrangedSubview(UIView()) - + mainStackView.axis = .vertical mainStackView.translatesAutoresizingMaskIntoConstraints = false mainStackView.spacing = 20 mainStackView.addArrangedSubview(itemImageView) mainStackView.addArrangedSubview(labelsStackView) - + contentView.addSubview(mainStackView) layoutMargins = .init(top: 5, left: 3, bottom: 5, right: 3) - + itemImageView.widthAnchor.constraint(equalTo: itemImageView.heightAnchor).isActive = true mainStackView.pin(to: layoutMarginsGuide) } - -} +} diff --git a/Examples/Shared/View/Product/ProductRow+ProductHit.swift b/Examples/Shared/View/Product/ProductRow+ProductHit.swift index b471cd82..8e827b9b 100644 --- a/Examples/Shared/View/Product/ProductRow+ProductHit.swift +++ b/Examples/Shared/View/Product/ProductRow+ProductHit.swift @@ -9,7 +9,7 @@ import Foundation import InstantSearchCore extension ProductRow { - + init(productHit: Hit, configuration: Configuration = .phone) { let product = productHit.object self.title = productHit.hightlightedString(forKey: "name") ?? HighlightedString(string: product.name) @@ -19,5 +19,5 @@ extension ProductRow { self.price = product.price self.configuration = configuration } - + } diff --git a/Examples/Shared/View/Product/ProductRow+StoreItem.swift b/Examples/Shared/View/Product/ProductRow+StoreItem.swift index a51757b2..6a7f511d 100644 --- a/Examples/Shared/View/Product/ProductRow+StoreItem.swift +++ b/Examples/Shared/View/Product/ProductRow+StoreItem.swift @@ -11,7 +11,7 @@ import InstantSearchCore import InstantSearchSwiftUI extension ProductRow { - + init(storeItemHit: Hit, configuration: Configuration = .phone) { let item = storeItemHit.object self.title = storeItemHit.hightlightedString(forKey: "name") ?? HighlightedString(string: item.name) @@ -21,5 +21,5 @@ extension ProductRow { self.price = item.price self.configuration = configuration } - + } diff --git a/Examples/Shared/View/Product/ProductRow.swift b/Examples/Shared/View/Product/ProductRow.swift index 66cbd9d5..4841cf1b 100644 --- a/Examples/Shared/View/Product/ProductRow.swift +++ b/Examples/Shared/View/Product/ProductRow.swift @@ -12,29 +12,30 @@ import InstantSearchCore import InstantSearchSwiftUI struct ProductRow: View { - + let title: HighlightedString let subtitle: HighlightedString let details: HighlightedString let imageURL: URL? let price: Double? let configuration: Configuration - + struct Configuration { - + let showDescription: Bool let imageWidth: CGFloat let horizontalSpacing: CGFloat let verticalSpacing: CGFloat - + static let phone = Self(showDescription: true, imageWidth: 60, horizontalSpacing: 20, verticalSpacing: 5) static let watch = Self(showDescription: false, imageWidth: 60, horizontalSpacing: 7, verticalSpacing: 5) + // swiftlint:disable identifier_name static let tv = Self(showDescription: true, imageWidth: 200, horizontalSpacing: 30, verticalSpacing: 10) } - + var body: some View { - VStack() { + VStack { HStack(alignment: .top, spacing: configuration.horizontalSpacing) { AsyncImage(url: imageURL, content: { image in @@ -78,7 +79,7 @@ struct ProductRow: View { Spacer() } } - + init(title: HighlightedString = .init(string: ""), subtitle: HighlightedString = .init(string: ""), details: HighlightedString = .init(string: ""), @@ -92,11 +93,12 @@ struct ProductRow: View { self.price = price self.configuration = configuration } - + } -struct ProductRow_Previews : PreviewProvider { - +// swiftlint:disable line_length +struct ProductRow_Previews: PreviewProvider { + static var previews: some View { ProductRow( title: HighlightedString(string: "Samsung - Galaxy S7 32GB - Black Onyx (AT&T)"), @@ -112,7 +114,7 @@ struct ProductRow_Previews : PreviewProvider { imageURL: .none, price: 694.99 ) - + } - + } diff --git a/Examples/Shared/View/Product/ProductTableViewCell+ProductHit.swift b/Examples/Shared/View/Product/ProductTableViewCell+ProductHit.swift index 6c0db368..c100c730 100644 --- a/Examples/Shared/View/Product/ProductTableViewCell+ProductHit.swift +++ b/Examples/Shared/View/Product/ProductTableViewCell+ProductHit.swift @@ -10,11 +10,11 @@ import UIKit import AlgoliaSearchClient extension ProductTableViewCell { - + func setup(with productHit: Hit) { let product = productHit.object itemImageView.sd_setImage(with: product.image) - + if let highlightedName = productHit.hightlightedString(forKey: "name") { titleLabel.attributedText = NSAttributedString(highlightedString: highlightedName, attributes: [ @@ -22,7 +22,7 @@ extension ProductTableViewCell { } else { titleLabel.text = product.name } - + if let highlightedDescription = productHit.hightlightedString(forKey: "description") { subtitleLabel.attributedText = NSAttributedString(highlightedString: highlightedDescription, attributes: [ @@ -31,11 +31,11 @@ extension ProductTableViewCell { } else { subtitleLabel.text = product.brand } - + if let price = product.price { priceLabel.text = "\(price) €" } - + } - + } diff --git a/Examples/Shared/View/Product/ProductTableViewCell+StoreItem.swift b/Examples/Shared/View/Product/ProductTableViewCell+StoreItem.swift index bf1ce933..716a28b2 100644 --- a/Examples/Shared/View/Product/ProductTableViewCell+StoreItem.swift +++ b/Examples/Shared/View/Product/ProductTableViewCell+StoreItem.swift @@ -10,11 +10,11 @@ import UIKit import AlgoliaSearchClient extension ProductTableViewCell { - + func setup(with productHit: Hit) { let product = productHit.object itemImageView.sd_setImage(with: product.images.first) - + if let highlightedName = productHit.hightlightedString(forKey: "name") { titleLabel.attributedText = NSAttributedString(highlightedString: highlightedName, attributes: [ @@ -22,7 +22,7 @@ extension ProductTableViewCell { } else { titleLabel.text = product.name } - + if let highlightedDescription = productHit.hightlightedString(forKey: "brand") { subtitleLabel.attributedText = NSAttributedString(highlightedString: highlightedDescription, attributes: [ @@ -31,11 +31,11 @@ extension ProductTableViewCell { } else { subtitleLabel.text = product.brand } - + if let price = product.price { priceLabel.text = "\(price) €" } - + } } diff --git a/Examples/Shared/View/Product/ProductTableViewCell.swift b/Examples/Shared/View/Product/ProductTableViewCell.swift index a867bcbb..fe13d09a 100644 --- a/Examples/Shared/View/Product/ProductTableViewCell.swift +++ b/Examples/Shared/View/Product/ProductTableViewCell.swift @@ -10,7 +10,7 @@ import UIKit import SDWebImage class ProductTableViewCell: UITableViewCell { - + let itemImageView: UIImageView let titleLabel: UILabel let subtitleLabel: UILabel @@ -18,7 +18,7 @@ class ProductTableViewCell: UITableViewCell { let mainStackView: UIStackView let labelsStackView: UIStackView - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { itemImageView = .init() titleLabel = .init() @@ -30,11 +30,11 @@ class ProductTableViewCell: UITableViewCell { layout() backgroundColor = .systemBackground } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private func layout() { itemImageView.sd_imageIndicator = SDWebImageActivityIndicator.gray itemImageView.translatesAutoresizingMaskIntoConstraints = false @@ -45,15 +45,15 @@ class ProductTableViewCell: UITableViewCell { titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.font = .systemFont(ofSize: 15, weight: .bold) titleLabel.numberOfLines = 1 - + subtitleLabel.translatesAutoresizingMaskIntoConstraints = false subtitleLabel.font = .systemFont(ofSize: 13, weight: .regular) subtitleLabel.textColor = .systemGray subtitleLabel.numberOfLines = 1 - + priceLabel.translatesAutoresizingMaskIntoConstraints = false priceLabel.font = .systemFont(ofSize: 14) - + labelsStackView.axis = .vertical labelsStackView.translatesAutoresizingMaskIntoConstraints = false labelsStackView.spacing = 3 @@ -61,18 +61,18 @@ class ProductTableViewCell: UITableViewCell { labelsStackView.addArrangedSubview(subtitleLabel) labelsStackView.addArrangedSubview(priceLabel) labelsStackView.addArrangedSubview(UIView()) - + mainStackView.axis = .horizontal mainStackView.translatesAutoresizingMaskIntoConstraints = false mainStackView.spacing = 20 mainStackView.addArrangedSubview(itemImageView) mainStackView.addArrangedSubview(labelsStackView) - + contentView.addSubview(mainStackView) contentView.layoutMargins = .init(top: 5, left: 3, bottom: 5, right: 3) mainStackView.pin(to: contentView.layoutMarginsGuide) itemImageView.widthAnchor.constraint(equalTo: itemImageView.heightAnchor).isActive = true } - + } diff --git a/Examples/Shared/View/SearchSuggestionTableViewCell+QuerySuggestion.swift b/Examples/Shared/View/SearchSuggestionTableViewCell+QuerySuggestion.swift index 49b04013..4a56caa3 100644 --- a/Examples/Shared/View/SearchSuggestionTableViewCell+QuerySuggestion.swift +++ b/Examples/Shared/View/SearchSuggestionTableViewCell+QuerySuggestion.swift @@ -10,7 +10,7 @@ import UIKit import InstantSearchCore extension SearchSuggestionTableViewCell { - + func setup(with querySuggestion: QuerySuggestion) { guard let textLabel = textLabel else { return } textLabel.attributedText = querySuggestion @@ -21,5 +21,5 @@ extension SearchSuggestionTableViewCell { attributes: [.font: UIFont.boldSystemFont(ofSize: textLabel.font.pointSize)]) } } - + } diff --git a/Examples/Shared/View/SearchSuggestionTableViewCell.swift b/Examples/Shared/View/SearchSuggestionTableViewCell.swift index 8ba16d39..a143474f 100644 --- a/Examples/Shared/View/SearchSuggestionTableViewCell.swift +++ b/Examples/Shared/View/SearchSuggestionTableViewCell.swift @@ -9,9 +9,9 @@ import Foundation import UIKit class SearchSuggestionTableViewCell: UITableViewCell { - + var didTapTypeAheadButton: (() -> Void)? - + private func typeAheadButton() -> UIButton { let typeAheadButton = UIButton() typeAheadButton.setImage(UIImage(systemName: "arrow.up.left"), for: .normal) @@ -19,20 +19,20 @@ class SearchSuggestionTableViewCell: UITableViewCell { typeAheadButton.addTarget(self, action: #selector(typeAheadButtonTap), for: .touchUpInside) return typeAheadButton } - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) accessoryView = typeAheadButton() imageView?.image = UIImage(systemName: "magnifyingglass") tintColor = .lightGray } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func typeAheadButtonTap(_ sender: UIButton) { didTapTypeAheadButton?() } - + } diff --git a/Examples/Showcase/Facet/DynamicFacets/AppDelegate.swift b/Examples/Showcase/Facet/DynamicFacets/AppDelegate.swift index e51aa919..8f197896 100644 --- a/Examples/Showcase/Facet/DynamicFacets/AppDelegate.swift +++ b/Examples/Showcase/Facet/DynamicFacets/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetDemoSwiftUI.swift b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetDemoSwiftUI.swift index 04cdd695..ace04e14 100644 --- a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetDemoSwiftUI.swift +++ b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearchSwiftUI import SwiftUI struct DynamicFacetDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let searchBoxController: SearchBoxObservableController let filterStateController: FilterStateObservableController let facetsController: DynamicFacetListObservableController let demoController: DynamicFacetListDemoController - + init() { searchBoxController = SearchBoxObservableController() facetsController = DynamicFacetListObservableController() @@ -27,21 +27,21 @@ struct DynamicFacetDemoSwiftUI: SwiftUIDemo, PreviewProvider { dynamicFacetListController: facetsController) filterStateController = FilterStateObservableController(filterState: demoController.filterState) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, facetsController: controller.facetsController) } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController let facetsController: DynamicFacetListObservableController - + @State private var isHelpPresented: Bool = false - + var body: some View { DynamicFacetList(dynamicFacetListController: facetsController) .alert(isPresented: $isHelpPresented) { @@ -51,16 +51,15 @@ struct DynamicFacetDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { - Button(action: { isHelpPresented = true }) { - Image(systemName: "info.circle.fill") - } + Button(action: { isHelpPresented = true }, + label: { Image(systemName: "info.circle.fill") }) } } .searchable(text: $searchBoxController.query) } - + } - + static let controller = Controller() static var previews: some View { return NavigationView { @@ -71,5 +70,5 @@ struct DynamicFacetDemoSwiftUI: SwiftUIDemo, PreviewProvider { } } } - + } diff --git a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoController.swift b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoController.swift index 82539da5..5120567c 100644 --- a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoController.swift +++ b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoController.swift @@ -11,14 +11,14 @@ import Foundation import InstantSearch class DynamicFacetListDemoController { - + let searcher: HitsSearcher let searchBoxConnector: SearchBoxConnector let dynamicFacetListConnector: DynamicFacetListConnector let filterState: FilterState - + static let helpMessage = "Type \"6\", \"61\" or \"616\" to trigger a rule" - + init(searchBoxController: SBC, dynamicFacetListController: DFC) { searcher = .init(client: .init(appID: "RVURKQXRHU", @@ -34,7 +34,7 @@ class DynamicFacetListDemoController { ], filterGroupForAttribute: [ "brand": ("brand", .or), - "color" : ("color", .or), + "color": ("color", .or), "size": ("size", .or), "country": ("country", .or) ], @@ -43,5 +43,5 @@ class DynamicFacetListDemoController { searcher.connectFilterState(filterState) searcher.search() } - + } diff --git a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoViewController.swift b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoViewController.swift index 25b92e4c..11c22dce 100644 --- a/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoViewController.swift +++ b/Examples/Showcase/Facet/DynamicFacets/DynamicFacetsDemoViewController.swift @@ -11,13 +11,13 @@ import InstantSearch import UIKit class DynamicFacetListDemoViewController: UIViewController { - + let searchController: UISearchController let demoController: DynamicFacetListDemoController - + let textFieldController: TextFieldController let facetsTableViewController: DynamicFacetListTableViewController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { facetsTableViewController = .init() searchController = .init(searchResultsController: facetsTableViewController) @@ -26,21 +26,21 @@ class DynamicFacetListDemoViewController: UIViewController { dynamicFacetListController: facetsTableViewController) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + private func setupUI() { title = "Dynamic Facets" view.backgroundColor = .systemBackground @@ -53,11 +53,11 @@ class DynamicFacetListDemoViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + @objc private func presentHint() { let hintController = UIAlertController(title: "Help", message: DynamicFacetListDemoController.helpMessage, preferredStyle: .alert) hintController.addAction(UIAlertAction(title: "OK", style: .cancel)) present(hintController, animated: true) } - + } diff --git a/Examples/Showcase/Facet/DynamicFacets/SceneDelegate.swift b/Examples/Showcase/Facet/DynamicFacets/SceneDelegate.swift index 75c64b2b..d1bd0ee3 100644 --- a/Examples/Showcase/Facet/DynamicFacets/SceneDelegate.swift +++ b/Examples/Showcase/Facet/DynamicFacets/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Facet/FacetList/AppDelegate.swift b/Examples/Showcase/Facet/FacetList/AppDelegate.swift index e119500e..62c017bb 100644 --- a/Examples/Showcase/Facet/FacetList/AppDelegate.swift +++ b/Examples/Showcase/Facet/FacetList/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Facet/FacetList/FacetListDemoController.swift b/Examples/Showcase/Facet/FacetList/FacetListDemoController.swift index 755d6a48..0b6545bc 100644 --- a/Examples/Showcase/Facet/FacetList/FacetListDemoController.swift +++ b/Examples/Showcase/Facet/FacetList/FacetListDemoController.swift @@ -10,15 +10,15 @@ import Foundation import InstantSearch class FacetListDemoController { - + let searcher: HitsSearcher let filterState: FilterState - + let clearConnector: FilterClearConnector let colorConnector: FacetListConnector let categoryConnector: FacetListConnector let promotionConnector: FacetListConnector - + init(colorController: CC, promotionController: PC, categoryController: CTC) { @@ -26,7 +26,7 @@ class FacetListDemoController { indexName: .facetList) filterState = .init() clearConnector = .init(filterState: filterState) - + // Color let colorPresenter = FacetListPresenter(sortBy: [.isRefined, .alphabetical(order: .ascending)], limit: 3) @@ -38,7 +38,7 @@ class FacetListDemoController { operator: .and, controller: colorController, presenter: colorPresenter) - + // Promotion let promotionPresenter = FacetListPresenter(sortBy: [.count(order: .descending)], limit: 5) @@ -50,10 +50,10 @@ class FacetListDemoController { operator: .and, controller: promotionController, presenter: promotionPresenter) - + // Category let categoryRefinementListPresenter = FacetListPresenter(sortBy: [.count(order: .descending), .alphabetical(order: .ascending)], showEmptyFacets: false) - + categoryConnector = .init(searcher: searcher, filterState: filterState, attribute: "category", @@ -63,15 +63,13 @@ class FacetListDemoController { controller: categoryController, presenter: categoryRefinementListPresenter) - - // Predefined filter let greenColor = Filter.Facet(attribute: "color", stringValue: "green") let groupID = FilterGroup.ID.and(name: "color") filterState.notify(.add(filter: greenColor, toGroupWithID: groupID)) - + searcher.connectFilterState(filterState) searcher.search() } - + } diff --git a/Examples/Showcase/Facet/FacetList/FacetListDemoSwiftUI.swift b/Examples/Showcase/Facet/FacetList/FacetListDemoSwiftUI.swift index 53cd841a..cba43162 100644 --- a/Examples/Showcase/Facet/FacetList/FacetListDemoSwiftUI.swift +++ b/Examples/Showcase/Facet/FacetList/FacetListDemoSwiftUI.swift @@ -12,16 +12,16 @@ import InstantSearchSwiftUI import SwiftUI class FacetListDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: FacetListDemoController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController let colorController: FacetListObservableController let promotionController: FacetListObservableController let categoryController: FacetListObservableController - + init() { colorController = FacetListObservableController() promotionController = FacetListObservableController() @@ -33,18 +33,18 @@ class FacetListDemoSwiftUI: SwiftUIDemo, PreviewProvider { filterStateController = FilterStateObservableController(filterState: demoController.filterState) demoController.clearConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @ObservedObject var colorController: FacetListObservableController @ObservedObject var promotionController: FacetListObservableController @ObservedObject var categoryController: FacetListObservableController - + var body: some View { VStack { FilterStateDebugView(filterStateController: filterStateController, @@ -55,7 +55,7 @@ class FacetListDemoSwiftUI: SwiftUIDemo, PreviewProvider { ForEach([ (title: "Color", controller: colorController), (title: "Promotion", controller: promotionController), - (title: "Category", controller: categoryController), + (title: "Category", controller: categoryController) ], id: \.title) { facetElement in VStack { HStack { @@ -78,9 +78,9 @@ class FacetListDemoSwiftUI: SwiftUIDemo, PreviewProvider { .padding() } } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, @@ -88,14 +88,14 @@ class FacetListDemoSwiftUI: SwiftUIDemo, PreviewProvider { promotionController: controller.promotionController, categoryController: controller.categoryController) } - + static let controller = Controller() static var previews: some View { NavigationView { contentView(with: controller) .navigationBarTitle("Refinement List") } - + } - + } diff --git a/Examples/Showcase/Facet/FacetList/FacetListDemoViewController.swift b/Examples/Showcase/Facet/FacetList/FacetListDemoViewController.swift index aaa7e372..a3aaf787 100644 --- a/Examples/Showcase/Facet/FacetList/FacetListDemoViewController.swift +++ b/Examples/Showcase/Facet/FacetList/FacetListDemoViewController.swift @@ -19,27 +19,27 @@ extension CGFloat { } class FacetListDemoViewController: UIViewController { - + let demoController: FacetListDemoController - + let colorController: FacetListTableController let categoryController: FacetListTableController let promotionController: FacetListTableController let filterDebugViewController: FilterDebugViewController - + init() { // Color let colorTitleDescriptor = TitleDescriptor(text: "And, IsRefined-AlphaAsc, I=3", color: .systemRed) colorController = FacetListTableController(tableView: .init(), titleDescriptor: colorTitleDescriptor) - + // Promotion let promotionTitleDescriptor = TitleDescriptor(text: "And, CountDesc, I=5", color: .systemBlue) promotionController = FacetListTableController(tableView: .init(), titleDescriptor: promotionTitleDescriptor) - + // Category let categoryTitleDescriptor = TitleDescriptor(text: "Or, CountDesc-AlphaAsc, I=5", color: .systemGreen) categoryController = .init(tableView: .init(), titleDescriptor: categoryTitleDescriptor) - + demoController = .init(colorController: colorController, promotionController: promotionController, categoryController: categoryController) @@ -47,61 +47,61 @@ class FacetListDemoViewController: UIViewController { super.init(nibName: nil, bundle: nil) demoController.clearConnector.connectController(filterDebugViewController.clearFilterController) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + } extension FacetListDemoViewController { - + func setupUI() { - + title = "Facet List" view.backgroundColor = .swBackground - + let mainStackView = UIStackView() mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) mainStackView.axis = .vertical mainStackView.distribution = .fill mainStackView.translatesAutoresizingMaskIntoConstraints = false - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true mainStackView.addArrangedSubview(filterDebugViewController.view) - + let gridStackView = UIStackView() gridStackView.axis = .horizontal gridStackView.spacing = 10 gridStackView.distribution = .fillEqually - + gridStackView.translatesAutoresizingMaskIntoConstraints = false - + let firstColumn = UIStackView() firstColumn.axis = .vertical firstColumn.spacing = 10 firstColumn.distribution = .fillEqually - + firstColumn.addArrangedSubview(colorController.tableView) firstColumn.addArrangedSubview(promotionController.tableView) - + gridStackView.addArrangedSubview(firstColumn) gridStackView.addArrangedSubview(categoryController.tableView) - + mainStackView.addArrangedSubview(gridStackView) - + view.addSubview(mainStackView) - + mainStackView.pin(to: view.safeAreaLayoutGuide) - + [ colorController, promotionController, @@ -115,5 +115,5 @@ extension FacetListDemoViewController { $0.backgroundColor = .swBackground } } - + } diff --git a/Examples/Showcase/Facet/FacetList/SceneDelegate.swift b/Examples/Showcase/Facet/FacetList/SceneDelegate.swift index 2c51522a..41c9bc52 100644 --- a/Examples/Showcase/Facet/FacetList/SceneDelegate.swift +++ b/Examples/Showcase/Facet/FacetList/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Facet/FacetListPersistentSelection/AppDelegate.swift b/Examples/Showcase/Facet/FacetListPersistentSelection/AppDelegate.swift index acbb12eb..d7f858d3 100644 --- a/Examples/Showcase/Facet/FacetListPersistentSelection/AppDelegate.swift +++ b/Examples/Showcase/Facet/FacetListPersistentSelection/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoSwiftUI.swift b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoSwiftUI.swift index ab471e3a..f07683ea 100644 --- a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoSwiftUI.swift +++ b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoSwiftUI.swift @@ -10,15 +10,15 @@ import SwiftUI import InstantSearchSwiftUI struct FacetListPersistentDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: FacetListPersistentSelectionDemoController let clearFilterController: FilterClearObservableController let filterStateController: FilterStateObservableController let colorController: FacetListObservableController let categoryController: FacetListObservableController - + init() { demoController = .init() clearFilterController = .init() @@ -29,17 +29,17 @@ struct FacetListPersistentDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.categoryConnector.connectController(categoryController) demoController.colorConnector.connectController(colorController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @ObservedObject var colorController: FacetListObservableController @ObservedObject var categoryController: FacetListObservableController - + var body: some View { VStack(spacing: 20) { FilterStateDebugView(filterStateController: filterStateController, @@ -74,7 +74,7 @@ struct FacetListPersistentDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .padding() } - + @ViewBuilder func header(withTitle title: String) -> some View { Text(title) .font(.footnote) @@ -82,16 +82,16 @@ struct FacetListPersistentDemoSwiftUI: SwiftUIDemo, PreviewProvider { .frame(maxWidth: .infinity) .background(Color(UIColor.systemGray5)) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, colorController: controller.colorController, categoryController: controller.categoryController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -99,5 +99,5 @@ struct FacetListPersistentDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Facet List Persistent Selection") } } - + } diff --git a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoViewController.swift b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoViewController.swift index ba308f19..6e1d3258 100644 --- a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoViewController.swift +++ b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentDemoViewController.swift @@ -11,7 +11,7 @@ import UIKit import InstantSearch class FacetListPersistentDemoViewController: UIViewController { - + let demoController: FacetListPersistentSelectionDemoController let colorListController: FacetListTableController let categoryListController: FacetListTableController @@ -27,16 +27,16 @@ class FacetListPersistentDemoViewController: UIViewController { super.init(nibName: nil, bundle: nil) setup() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupLayout() } - + } private extension FacetListPersistentDemoViewController { @@ -46,17 +46,17 @@ private extension FacetListPersistentDemoViewController { demoController.categoryConnector.interactor.connectController(categoryListController) demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + func setupLayout() { view.backgroundColor = .systemBackground - + let mainStackView = UIStackView(frame: .zero) mainStackView.axis = .vertical mainStackView.translatesAutoresizingMaskIntoConstraints = false mainStackView.distribution = .fill mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) - + let listsStackView = UIStackView(frame: .zero) listsStackView.translatesAutoresizingMaskIntoConstraints = false listsStackView.axis = .horizontal @@ -64,16 +64,16 @@ private extension FacetListPersistentDemoViewController { listsStackView.spacing = 10 listsStackView.addArrangedSubview(colorListController.tableView) listsStackView.addArrangedSubview(categoryListController.tableView) - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true mainStackView.addArrangedSubview(filterDebugViewController.view) mainStackView.addArrangedSubview(listsStackView) mainStackView.addArrangedSubview(.spacer) - + view.addSubview(mainStackView) - + mainStackView.pin(to: view.safeAreaLayoutGuide) [ @@ -87,7 +87,7 @@ private extension FacetListPersistentDemoViewController { $0.alwaysBounceVertical = false $0.tableFooterView = UIView(frame: .zero) } - + } - + } diff --git a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentSelectionDemoController.swift b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentSelectionDemoController.swift index ccfb5e82..57cecbc7 100644 --- a/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentSelectionDemoController.swift +++ b/Examples/Showcase/Facet/FacetListPersistentSelection/FacetListPersistentSelectionDemoController.swift @@ -7,16 +7,16 @@ import Foundation import InstantSearchCore - +// swiftlint:disable type_name class FacetListPersistentSelectionDemoController { - + let searcher: HitsSearcher let filterState: FilterState - + let clearFilterConnector: FilterClearConnector let colorConnector: FacetListConnector let categoryConnector: FacetListConnector - + init() { searcher = .init(client: .instantSearch, indexName: .facetList) @@ -34,10 +34,10 @@ class FacetListPersistentSelectionDemoController { operator: .or) setup() } - + private func setup() { searcher.connectFilterState(filterState) searcher.search() } - + } diff --git a/Examples/Showcase/Facet/FacetListPersistentSelection/SceneDelegate.swift b/Examples/Showcase/Facet/FacetListPersistentSelection/SceneDelegate.swift index f909c65b..0ac9eb71 100644 --- a/Examples/Showcase/Facet/FacetListPersistentSelection/SceneDelegate.swift +++ b/Examples/Showcase/Facet/FacetListPersistentSelection/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Facet/FacetSearch/AppDelegate.swift b/Examples/Showcase/Facet/FacetSearch/AppDelegate.swift index 300d88bc..4915b934 100644 --- a/Examples/Showcase/Facet/FacetSearch/AppDelegate.swift +++ b/Examples/Showcase/Facet/FacetSearch/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoController.swift b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoController.swift index 9978f85b..def87fbb 100644 --- a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoController.swift +++ b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoController.swift @@ -9,13 +9,13 @@ import Foundation import InstantSearch class FacetSearchDemoController { - + let facetSearcher: FacetSearcher let filterState: FilterState let clearFilterConnector: FilterClearConnector let facetListConnector: FacetListConnector let searchBoxConnector: SearchBoxConnector - + init() { filterState = .init() clearFilterConnector = .init(filterState: filterState) @@ -29,5 +29,5 @@ class FacetSearchDemoController { searchBoxConnector = SearchBoxConnector(searcher: facetSearcher) facetSearcher.search() } - + } diff --git a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoSwiftUI.swift b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoSwiftUI.swift index 26e25608..16f30a46 100644 --- a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoSwiftUI.swift +++ b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoSwiftUI.swift @@ -11,16 +11,16 @@ import InstantSearchSwiftUI import SwiftUI class FacetSearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: FacetSearchDemoController let facetListController: FacetListObservableController let clearFilterController: FilterClearObservableController let searchBoxController: SearchBoxObservableController let filterStateController: FilterStateObservableController - + init() { facetListController = FacetListObservableController() searchBoxController = SearchBoxObservableController() @@ -31,14 +31,14 @@ class FacetSearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.searchBoxConnector.connectController(searchBoxController) demoController.clearFilterConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var facetListController: FacetListObservableController @@ -60,16 +60,16 @@ class FacetSearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .searchable(text: $searchBoxController.query) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, searchBoxController: controller.searchBoxController, facetListController: controller.facetListController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -77,5 +77,5 @@ class FacetSearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Facet Search") } } - + } diff --git a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoViewController.swift b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoViewController.swift index 6e237aea..54830dd0 100644 --- a/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoViewController.swift +++ b/Examples/Showcase/Facet/FacetSearch/FacetSearchDemoViewController.swift @@ -26,11 +26,11 @@ class FacetSearchDemoViewController: UIViewController { filterDebugViewController = FilterDebugViewController(filterState: demoController.filterState) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setup() @@ -40,7 +40,7 @@ class FacetSearchDemoViewController: UIViewController { } private extension FacetSearchDemoViewController { - + func setup() { addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) @@ -48,7 +48,7 @@ private extension FacetSearchDemoViewController { demoController.searchBoxConnector.connectController(textFieldController) demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + func setupUI() { view.backgroundColor = .systemBackground let tableView = facetListController.tableView @@ -75,4 +75,3 @@ private extension FacetSearchDemoViewController { } } - diff --git a/Examples/Showcase/Facet/FacetSearch/SceneDelegate.swift b/Examples/Showcase/Facet/FacetSearch/SceneDelegate.swift index b696276d..5be648ba 100644 --- a/Examples/Showcase/Facet/FacetSearch/SceneDelegate.swift +++ b/Examples/Showcase/Facet/FacetSearch/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Facet/HierarchicalFacets/AppDelegate.swift b/Examples/Showcase/Facet/HierarchicalFacets/AppDelegate.swift index 4dfde085..ba8eb1ad 100644 --- a/Examples/Showcase/Facet/HierarchicalFacets/AppDelegate.swift +++ b/Examples/Showcase/Facet/HierarchicalFacets/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoController.swift b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoController.swift index 725ebaed..053d5457 100644 --- a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoController.swift +++ b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoController.swift @@ -10,25 +10,25 @@ import Foundation import InstantSearch class HierarchicalDemoController { - + let searcher: HitsSearcher let filterState: FilterState let clearFilterConnector: FilterClearConnector let hierarchicalConnector: HierarchicalConnector - + struct HierarchicalCategory { static var base: Attribute = "hierarchicalCategories" static var lvl0: Attribute { "\(base).lvl0" } static var lvl1: Attribute { "\(base).lvl1" } static var lvl2: Attribute { "\(base).lvl2" } } - + let order = [ HierarchicalCategory.lvl0, HierarchicalCategory.lvl1, - HierarchicalCategory.lvl2, + HierarchicalCategory.lvl2 ] - + init(controller: Controller) where Controller.Item == [HierarchicalFacet] { searcher = HitsSearcher(client: .instantSearch, indexName: .hierarchicalFacets) @@ -43,5 +43,5 @@ class HierarchicalDemoController { searcher.connectFilterState(filterState) searcher.search() } - + } diff --git a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoSwiftUI.swift b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoSwiftUI.swift index 0ead2617..83e7689b 100644 --- a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoSwiftUI.swift +++ b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearchSwiftUI import SwiftUI class HierarchicalDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: HierarchicalDemoController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController let observableController: HierarchicalObservableController - + init() { observableController = HierarchicalObservableController() demoController = HierarchicalDemoController(controller: observableController) @@ -27,11 +27,11 @@ class HierarchicalDemoSwiftUI: SwiftUIDemo, PreviewProvider { clearFilterController = .init() demoController.clearFilterConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + let hierarchicalController: HierarchicalObservableController let filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @@ -51,15 +51,15 @@ class HierarchicalDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .padding() } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(hierarchicalController: controller.observableController, filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -67,6 +67,5 @@ class HierarchicalDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Hierarchical Facets") } } - -} +} diff --git a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoViewController.swift b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoViewController.swift index f03a9a4c..f5d6a1a0 100644 --- a/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoViewController.swift +++ b/Examples/Showcase/Facet/HierarchicalFacets/HierarchicalDemoViewController.swift @@ -11,7 +11,7 @@ import InstantSearch import UIKit class HierarchicalDemoViewController: UIViewController { - + let demoController: HierarchicalDemoController let hierarchicalTableViewController: HierarchicalTableViewController @@ -36,17 +36,17 @@ class HierarchicalDemoViewController: UIViewController { setupUI() setup() } - + private func setup() { addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) addChild(tableViewController) tableViewController.didMove(toParent: self) - + demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + private func setupUI() { title = "Hierarchical Facets" view.backgroundColor = . white @@ -57,7 +57,7 @@ class HierarchicalDemoViewController: UIViewController { mainStackView.spacing = 10 mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) - + let searchDebugView = filterDebugViewController.view! searchDebugView.translatesAutoresizingMaskIntoConstraints = false searchDebugView.heightAnchor.constraint(equalToConstant: 150).isActive = true @@ -72,4 +72,3 @@ class HierarchicalDemoViewController: UIViewController { } } - diff --git a/Examples/Showcase/Facet/HierarchicalFacets/SceneDelegate.swift b/Examples/Showcase/Facet/HierarchicalFacets/SceneDelegate.swift index 52c9aa74..f7a17ff9 100644 --- a/Examples/Showcase/Facet/HierarchicalFacets/SceneDelegate.swift +++ b/Examples/Showcase/Facet/HierarchicalFacets/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(HierarchicalDemoViewController(), for: scene) } } - diff --git a/Examples/Showcase/Filter/FilterClear/AppDelegate.swift b/Examples/Showcase/Filter/FilterClear/AppDelegate.swift index f95233d5..47c1eeb1 100644 --- a/Examples/Showcase/Filter/FilterClear/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterClear/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoController.swift b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoController.swift index dcea5c76..707d5f6b 100644 --- a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoController.swift +++ b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoController.swift @@ -10,13 +10,13 @@ import Foundation import InstantSearch class ClearFiltersDemoController { - + let filterState: FilterState - + let clearConnector: FilterClearConnector let clearGroupConnector: FilterClearConnector let clearExceptGroupConnector: FilterClearConnector - + init() { filterState = .init() clearConnector = .init(filterState: filterState) @@ -27,14 +27,14 @@ class ClearFiltersDemoController { clearExceptGroupConnector = .init(filterState: filterState, clearMode: .except, filterGroupIDs: [groupColor]) - + let categoryFacet = Filter.Facet(attribute: "category", value: "shoe") let redFacet = Filter.Facet(attribute: "color", value: "red") let greenFacet = Filter.Facet(attribute: "color", value: "green") - + filterState[and: "category"].add(categoryFacet) filterState[or: "color"].add(redFacet, greenFacet) filterState.notifyChange() } - + } diff --git a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoSwiftUI.swift index c70b4719..553ded8f 100644 --- a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoSwiftUI.swift @@ -12,15 +12,15 @@ import InstantSearchSwiftUI import SwiftUI struct ClearFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: ClearFiltersDemoController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController let clearFilterGroupController: FilterClearObservableController let clearExceptFilterGroupController: FilterClearObservableController - + init() { clearFilterController = .init() clearFilterGroupController = .init() @@ -31,17 +31,17 @@ struct ClearFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.clearGroupConnector.connectController(clearFilterGroupController) demoController.clearExceptGroupConnector.connectController(clearExceptFilterGroupController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + @ObservedObject var clearFilterGroupController: FilterClearObservableController @ObservedObject var clearExceptFilterGroupController: FilterClearObservableController - + var body: some View { VStack { FilterStateDebugView(filterStateController: filterStateController, @@ -59,18 +59,18 @@ struct ClearFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { } Spacer() }.padding() - + } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, clearFilterGroupController: controller.clearFilterGroupController, clearExceptFilterGroupController: controller.clearExceptFilterGroupController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -78,5 +78,5 @@ struct ClearFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Filter Clear") } } - + } diff --git a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoViewController.swift b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoViewController.swift index ec0c5126..e9a9ebdf 100644 --- a/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterClear/ClearFiltersDemoViewController.swift @@ -13,7 +13,7 @@ import UIKit class ClearFiltersDemoViewController: UIViewController { let demoController: ClearFiltersDemoController - + let filterDebugViewController: FilterDebugViewController let clearGroupController: FilterClearButtonController @@ -70,7 +70,7 @@ class ClearFiltersDemoViewController: UIViewController { mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) mainStackView.spacing = 10 mainStackView.translatesAutoresizingMaskIntoConstraints = false - + mainStackView.addArrangedSubview(filterDebugViewController.view) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true @@ -81,10 +81,10 @@ class ClearFiltersDemoViewController: UIViewController { buttonsStackView.addArrangedSubview(clearGroupController.button) buttonsStackView.addArrangedSubview(clearExceptGroupController.button) - + mainStackView.addArrangedSubview(buttonsStackView) mainStackView.addArrangedSubview(.init()) - + view.addSubview(mainStackView) mainStackView.pin(to: view.safeAreaLayoutGuide) diff --git a/Examples/Showcase/Filter/FilterClear/SceneDelegate.swift b/Examples/Showcase/Filter/FilterClear/SceneDelegate.swift index 737a0873..3c281535 100644 --- a/Examples/Showcase/Filter/FilterClear/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterClear/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Filter/FilterCurrent/AppDelegate.swift b/Examples/Showcase/Filter/FilterCurrent/AppDelegate.swift index 9c74ed06..1aa8217c 100644 --- a/Examples/Showcase/Filter/FilterCurrent/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterCurrent/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoController.swift b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoController.swift index aef51700..c0150712 100644 --- a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoController.swift +++ b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoController.swift @@ -9,18 +9,18 @@ import Foundation import InstantSearchCore class CurrentFiltersDemoController { - + let filterState: FilterState let clearFiltersConnector: FilterClearConnector let currentFiltersListConnector: CurrentFiltersConnector - + init() { filterState = .init() currentFiltersListConnector = .init(filterState: filterState) clearFiltersConnector = .init(filterState: filterState) setup() } - + func setup() { let filterFacet1 = Filter.Facet(attribute: "category", value: "table") @@ -32,7 +32,7 @@ class CurrentFiltersDemoController { filterFacet2, filterFacet3, filterFacet4) - + let filterNumeric1 = Filter.Numeric(attribute: "price", operator: .greaterThan, value: 10) let filterNumeric2 = Filter.Numeric(attribute: "price", operator: .lessThan, value: 20) @@ -41,5 +41,5 @@ class CurrentFiltersDemoController { filterState.notifyChange() } - + } diff --git a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoSwiftUI.swift index ae0550c9..70628104 100644 --- a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearchSwiftUI import SwiftUI struct CurrentFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: CurrentFiltersDemoController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController let currentFiltersController: CurrentFiltersObservableController - + init() { demoController = .init() currentFiltersController = .init() @@ -28,11 +28,11 @@ struct CurrentFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.currentFiltersListConnector.connectController(currentFiltersController) demoController.clearFiltersConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @@ -70,15 +70,15 @@ struct CurrentFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .padding() } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, currentFiltersController: controller.currentFiltersController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -86,5 +86,5 @@ struct CurrentFiltersDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Current Filter") } } - + } diff --git a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoViewController.swift b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoViewController.swift index 5f4770cf..827cd398 100644 --- a/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterCurrent/CurrentFiltersDemoViewController.swift @@ -39,7 +39,7 @@ class CurrentFiltersDemoViewController: UIViewController { setup() setupUI() } - + } private extension CurrentFiltersDemoViewController { @@ -49,7 +49,7 @@ private extension CurrentFiltersDemoViewController { demoController.currentFiltersListConnector.connectController(currentFiltersController2) demoController.clearFiltersConnector.connectController(filterDebugViewController.clearFilterController) } - + func setupUI() { view.backgroundColor = .systemBackground @@ -63,7 +63,7 @@ private extension CurrentFiltersDemoViewController { view.addSubview(mainStackView) mainStackView.pin(to: view) - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true @@ -77,8 +77,7 @@ private extension CurrentFiltersDemoViewController { mainStackView.addArrangedSubview(filterDebugViewController.view) mainStackView.addArrangedSubview(searchTextFieldContainer) mainStackView.addArrangedSubview(tableView) - + } } - diff --git a/Examples/Showcase/Filter/FilterCurrent/SceneDelegate.swift b/Examples/Showcase/Filter/FilterCurrent/SceneDelegate.swift index 6d9bed53..93df15ae 100644 --- a/Examples/Showcase/Filter/FilterCurrent/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterCurrent/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Filter/FilterList/AppDelegate.swift b/Examples/Showcase/Filter/FilterList/AppDelegate.swift index d3c02caa..6a9809c2 100644 --- a/Examples/Showcase/Filter/FilterList/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterList/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterList/FilterListDemo.swift b/Examples/Showcase/Filter/FilterList/FilterListDemo.swift index 4e5b4051..1426a6ee 100644 --- a/Examples/Showcase/Filter/FilterList/FilterListDemo.swift +++ b/Examples/Showcase/Filter/FilterList/FilterListDemo.swift @@ -10,19 +10,19 @@ import Foundation import InstantSearch struct FilterListDemo { - + static func facet() -> FilterListDemoViewController { - + let facetFilters: [Filter.Facet] = ["red", "blue", "green", "yellow", "black"].map { .init(attribute: "color", stringValue: $0) } - + return FilterListDemoViewController(items: facetFilters, selectionMode: .multiple) - + } - + static func numeric() -> FilterListDemoViewController { - + let numericFilters: [Filter.Numeric] = [ .init(attribute: "price", operator: .lessThan, value: 5), .init(attribute: "price", range: 5...10), @@ -30,18 +30,18 @@ struct FilterListDemo { .init(attribute: "price", range: 25...100), .init(attribute: "price", operator: .greaterThan, value: 100) ] - + return FilterListDemoViewController(items: numericFilters, selectionMode: .single) - + } - + static func tag() -> FilterListDemoViewController { - + let tagFilters: [Filter.Tag] = [ "coupon", "free shipping", "free return", "on sale", "no exchange"] - + return FilterListDemoViewController(items: tagFilters, selectionMode: .multiple) - + } - + } diff --git a/Examples/Showcase/Filter/FilterList/FilterListDemoController.swift b/Examples/Showcase/Filter/FilterList/FilterListDemoController.swift index 09ef5998..bd3cdbab 100644 --- a/Examples/Showcase/Filter/FilterList/FilterListDemoController.swift +++ b/Examples/Showcase/Filter/FilterList/FilterListDemoController.swift @@ -10,12 +10,12 @@ import Foundation import InstantSearch class FilterListDemoController { - + let searcher: HitsSearcher let filterState: FilterState let clearFilterConnector: FilterClearConnector let filterListConnector: FilterListConnector - + init(filters: [Filter], controller: Controller, selectionMode: SelectionMode) where Controller.Item == Filter { @@ -33,5 +33,5 @@ class FilterListDemoController { searcher.search() searcher.connectFilterState(filterState) } - + } diff --git a/Examples/Showcase/Filter/FilterList/FilterListDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterList/FilterListDemoSwiftUI.swift index f27780c4..2d6c26e7 100644 --- a/Examples/Showcase/Filter/FilterList/FilterListDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterList/FilterListDemoSwiftUI.swift @@ -12,16 +12,16 @@ import InstantSearchSwiftUI import SwiftUI struct FilterListDemoSwiftUI: PreviewProvider { - + class Controller { - + let title: String let observableController: FilterListObservableController let demoController: FilterListDemoController let clearFilterController: FilterClearObservableController let filters: [F] let description: (F) -> String - + init(title: String, filters: [F], selectionMode: SelectionMode, @@ -36,17 +36,17 @@ struct FilterListDemoSwiftUI: PreviewProvider { self.description = description demoController.clearFilterConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + let title: String let description: (Filter) -> String let controller: FilterListObservableController let filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + init(filterStateController: FilterStateObservableController, clearFilterController: FilterClearObservableController, controller: FilterListObservableController, @@ -58,7 +58,7 @@ struct FilterListDemoSwiftUI: PreviewProvider { self.description = description self.title = title } - + public var body: some View { VStack { FilterStateDebugView(filterStateController: filterStateController, @@ -73,7 +73,7 @@ struct FilterListDemoSwiftUI: PreviewProvider { .navigationBarTitle(title) .padding() } - + func selectableText(text: String, isSelected: Bool) -> some View { HStack { Text(text) @@ -85,14 +85,14 @@ struct FilterListDemoSwiftUI: PreviewProvider { } .contentShape(Rectangle()) } - + } - + class ViewController: UIHostingController> { - + let controller: Controller let filterStateObservableController: FilterStateObservableController - + init(controller: Controller) { self.controller = controller filterStateObservableController = .init(filterState: controller.demoController.filterState) @@ -103,27 +103,27 @@ struct FilterListDemoSwiftUI: PreviewProvider { title: controller.title) super.init(rootView: contentView) UIScrollView.appearance().keyboardDismissMode = .interactive - + } - + @objc required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } - + static func facetViewController() -> ViewController { return ViewController(controller: facetController) } - + static func numericViewController() -> ViewController { return ViewController(controller: numericController) } - + static func tagViewController() -> ViewController { return ViewController(controller: tagController) } - + static let facetController = Controller(title: "Color", filters: ["red", "blue", @@ -134,8 +134,7 @@ struct FilterListDemoSwiftUI: PreviewProvider { }, selectionMode: .multiple, description: \.value.description) - - + static let numericController = Controller(title: "Price", filters: [ NumericFilter(attribute: "price", operator: .lessThan, value: 5), NumericFilter(attribute: "price", range: 5...10), @@ -144,8 +143,7 @@ struct FilterListDemoSwiftUI: PreviewProvider { NumericFilter(attribute: "price", operator: .greaterThan, value: 100) ], selectionMode: .single, description: \.value.description) - - + static let tagController = Controller(title: "Promotion", filters: [Filter.Tag]([ "coupon", @@ -156,7 +154,7 @@ struct FilterListDemoSwiftUI: PreviewProvider { ]), selectionMode: .multiple, description: \.value.description) - + static var previews: some View { NavigationView { ContentView(filterStateController: FilterStateObservableController(filterState: facetController.demoController.filterState), @@ -180,5 +178,5 @@ struct FilterListDemoSwiftUI: PreviewProvider { title: tagController.title) } } - + } diff --git a/Examples/Showcase/Filter/FilterList/FilterListDemoViewController.swift b/Examples/Showcase/Filter/FilterList/FilterListDemoViewController.swift index 5ee07396..464373de 100644 --- a/Examples/Showcase/Filter/FilterList/FilterListDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterList/FilterListDemoViewController.swift @@ -11,12 +11,12 @@ import InstantSearch import UIKit class FilterListDemoViewController: UIViewController { - + let demoController: FilterListDemoController - + let filterListController: FilterListTableController let filterDebugViewController: FilterDebugViewController - + init(items: [F], selectionMode: SelectionMode) { filterListController = FilterListTableController(tableView: .init()) demoController = .init(filters: items, @@ -26,41 +26,41 @@ class FilterListDemoViewController: UIViewController { super.init(nibName: nil, bundle: nil) demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + } private extension FilterListDemoViewController { - + func setupUI() { - + view.backgroundColor = .systemBackground - + let mainStackView = UIStackView() mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) mainStackView.translatesAutoresizingMaskIntoConstraints = false mainStackView.axis = .vertical mainStackView.spacing = 10 - + view.addSubview(mainStackView) - + mainStackView.pin(to: view) - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true - + mainStackView.addArrangedSubview(filterDebugViewController.view) mainStackView.addArrangedSubview(filterListController.tableView) } - + } diff --git a/Examples/Showcase/Filter/FilterList/MainViewController.swift b/Examples/Showcase/Filter/FilterList/MainViewController.swift index 6378873e..9148d483 100644 --- a/Examples/Showcase/Filter/FilterList/MainViewController.swift +++ b/Examples/Showcase/Filter/FilterList/MainViewController.swift @@ -8,7 +8,7 @@ import UIKit class MainViewController: UIViewController { - + let segmentedControl: UISegmentedControl let viewStack: UIStackView @@ -17,17 +17,17 @@ class MainViewController: UIViewController { viewStack = .init() super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() layout() configureSegmentedControl() } - + private func configureSegmentedControl() { [ "Facet", @@ -42,28 +42,28 @@ class MainViewController: UIViewController { segmentedControl.selectedSegmentIndex = 0 segmentedControl.sendActions(for: .valueChanged) } - + @objc private func didSelectSegment() { for (index, view) in viewStack.arrangedSubviews.enumerated() { view.isHidden = segmentedControl.selectedSegmentIndex != index } } - + private func layout() { title = "Filter List" view.backgroundColor = .systemBackground - + segmentedControl.translatesAutoresizingMaskIntoConstraints = false let segmentedControlContainer = UIView() segmentedControlContainer.translatesAutoresizingMaskIntoConstraints = false segmentedControlContainer.addSubview(segmentedControl) segmentedControl.pin(to: segmentedControlContainer, insets: .init(top: 0, left: 10, bottom: 0, right: -10)) - + let mainStackView = UIStackView() mainStackView.axis = .vertical mainStackView.spacing = 10 mainStackView.translatesAutoresizingMaskIntoConstraints = false - + viewStack.axis = .horizontal viewStack.translatesAutoresizingMaskIntoConstraints = false let viewControllers = [ @@ -71,20 +71,18 @@ class MainViewController: UIViewController { FilterListDemo.numeric(), FilterListDemo.tag() ] - + for viewController in viewControllers { addChild(viewController) viewController.didMove(toParent: self) viewController.view.translatesAutoresizingMaskIntoConstraints = false viewStack.addArrangedSubview(viewController.view) } - + mainStackView.addArrangedSubview(segmentedControlContainer) mainStackView.addArrangedSubview(viewStack) view.addSubview(mainStackView) mainStackView.pin(to: view.safeAreaLayoutGuide) } - } - diff --git a/Examples/Showcase/Filter/FilterList/SceneDelegate.swift b/Examples/Showcase/Filter/FilterList/SceneDelegate.swift index 9d9236a3..a7cac25d 100644 --- a/Examples/Showcase/Filter/FilterList/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterList/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(MainViewController(), for: scene) } } - diff --git a/Examples/Showcase/Filter/FilterNumericComparison/AppDelegate.swift b/Examples/Showcase/Filter/FilterNumericComparison/AppDelegate.swift index da75469e..e84ac3c4 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoController.swift b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoController.swift index 21bfdd8c..53c88a4b 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoController.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoController.swift @@ -9,14 +9,14 @@ import Foundation import InstantSearchCore class FilterNumericComparisonDemoController { - + let searcher: HitsSearcher let filterState: FilterState let clearFilterConnector: FilterClearConnector - + let yearConnector: FilterComparisonConnector let priceConnector: FilterComparisonConnector - + init() { searcher = HitsSearcher(client: .instantSearch, indexName: .filterNumericComparison) @@ -29,7 +29,7 @@ class FilterNumericComparisonDemoController { number: 2014, bounds: nil, operator: .and) - + priceConnector = .init(searcher: searcher, filterState: filterState, attribute: "price", @@ -39,11 +39,10 @@ class FilterNumericComparisonDemoController { operator: .and) setup() } - + private func setup() { searcher.connectFilterState(filterState) searcher.search() } - - + } diff --git a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoSwiftUI.swift index e91d28f5..b2c4b307 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoSwiftUI.swift @@ -11,15 +11,15 @@ import InstantSearchCore import InstantSearchSwiftUI struct FilterNumericComparisonDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: FilterNumericComparisonDemoController let clearFilterController: FilterClearObservableController let yearController: NumberObservableController let priceController: NumberObservableController let filterStateController: FilterStateObservableController - + init() { demoController = .init() yearController = .init() @@ -30,24 +30,24 @@ struct FilterNumericComparisonDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.clearFilterConnector.connectController(clearFilterController) filterStateController = .init(filterState: demoController.filterState) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @ObservedObject var priceController: NumberObservableController @ObservedObject var yearController: NumberObservableController - + @State private var yearValue: String = "" - + var body: some View { - return VStack(spacing: 40){ + return VStack(spacing: 40) { FilterStateDebugView(filterStateController: filterStateController, clearFilterController: clearFilterController) - HStack() { + HStack { Text("Year") Spacer() TextField("Year", text: $yearValue) @@ -64,7 +64,7 @@ struct FilterNumericComparisonDemoSwiftUI: SwiftUIDemo, PreviewProvider { Stepper(value: $priceController.value, in: priceController.bounds, step: 0.1) { - HStack{ + HStack { Text("Price:") Spacer() Text(String(format: "%.2f", priceController.value)) @@ -78,16 +78,16 @@ struct FilterNumericComparisonDemoSwiftUI: SwiftUIDemo, PreviewProvider { yearValue = "\(yearController.value)" } } - + } - + static func contentView(with controller: Controller) -> ContentView { return ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, priceController: controller.priceController, yearController: controller.yearController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -95,7 +95,5 @@ struct FilterNumericComparisonDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Filter Numeric Comparison") } } - -} - +} diff --git a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoViewController.swift b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoViewController.swift index 417cfced..8f4b53f3 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/FilterNumericComparisonDemoViewController.swift @@ -5,13 +5,14 @@ // Created by Guy Daher on 05/06/2019. // Copyright © 2019 Algolia. All rights reserved. // +// swiftlint:disable type_name import Foundation import UIKit import InstantSearch class FilterNumericComparisonDemoViewController: UIViewController { - + let demoController: FilterNumericComparisonDemoController let yearTextFieldController: NumericTextFieldController let numericStepperController: NumericStepperController @@ -26,47 +27,64 @@ class FilterNumericComparisonDemoViewController: UIViewController { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) setup() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + } private extension FilterNumericComparisonDemoViewController { - + func setup() { demoController.priceConnector.connectNumberController(numericStepperController) demoController.yearConnector.connectNumberController(yearTextFieldController) priceStepperValueLabel.text = demoController.priceConnector.interactor.item.flatMap { "\($0)" } demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + func setupUI() { - + view.backgroundColor = .systemBackground - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) - + let searchDebugView = filterDebugViewController.view! searchDebugView.heightAnchor.constraint(equalToConstant: 150).isActive = true searchDebugView.translatesAutoresizingMaskIntoConstraints = false - + + let mainStackView = UIStackView() + mainStackView.isLayoutMarginsRelativeArrangement = true + mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) + mainStackView.axis = .vertical + mainStackView.spacing = 10 + mainStackView.distribution = .fill + mainStackView.translatesAutoresizingMaskIntoConstraints = false + mainStackView.addArrangedSubview(searchDebugView) + mainStackView.addArrangedSubview(makeYearInputStackView()) + mainStackView.addArrangedSubview(makePriceStackView()) + mainStackView.addArrangedSubview(.spacer) + + view.addSubview(mainStackView) + mainStackView.pin(to: view) + } + + private func makeYearInputStackView() -> UIStackView { let yearInputLabel = UILabel() yearInputLabel.translatesAutoresizingMaskIntoConstraints = false yearInputLabel.text = "Year:" - + yearTextFieldController.textField.borderStyle = .roundedRect yearTextFieldController.textField.textAlignment = .right yearTextFieldController.textField.translatesAutoresizingMaskIntoConstraints = false yearTextFieldController.textField.keyboardType = .numberPad - + let yearInputStackView = UIStackView() yearInputStackView.spacing = 10 yearInputStackView.translatesAutoresizingMaskIntoConstraints = false @@ -74,17 +92,20 @@ private extension FilterNumericComparisonDemoViewController { yearInputStackView.addArrangedSubview(yearInputLabel) yearInputStackView.addArrangedSubview(.spacer) yearInputStackView.addArrangedSubview(yearTextFieldController.textField) - + return yearInputStackView + } + + private func makePriceStackView() -> UIStackView { let priceStepperTitleLabel = UILabel() priceStepperTitleLabel.translatesAutoresizingMaskIntoConstraints = false priceStepperTitleLabel.text = "Price:" - + numericStepperController.stepper.translatesAutoresizingMaskIntoConstraints = false numericStepperController.stepper.addTarget(self, action: #selector(onStepperValueChanged), for: .valueChanged) - + priceStepperValueLabel.translatesAutoresizingMaskIntoConstraints = false priceStepperValueLabel.widthAnchor.constraint(equalToConstant: 40).isActive = true - + let priceStepperStackView = UIStackView() priceStepperStackView.translatesAutoresizingMaskIntoConstraints = false priceStepperStackView.axis = .horizontal @@ -93,25 +114,11 @@ private extension FilterNumericComparisonDemoViewController { priceStepperStackView.addArrangedSubview(.spacer) priceStepperStackView.addArrangedSubview(priceStepperValueLabel) priceStepperStackView.addArrangedSubview(numericStepperController.stepper) - - let mainStackView = UIStackView() - mainStackView.isLayoutMarginsRelativeArrangement = true - mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) - mainStackView.axis = .vertical - mainStackView.spacing = 10 - mainStackView.distribution = .fill - mainStackView.translatesAutoresizingMaskIntoConstraints = false - mainStackView.addArrangedSubview(searchDebugView) - mainStackView.addArrangedSubview(yearInputStackView) - mainStackView.addArrangedSubview(priceStepperStackView) - mainStackView.addArrangedSubview(.spacer) - - view.addSubview(mainStackView) - mainStackView.pin(to: view) + return priceStepperStackView } - + @objc func onStepperValueChanged(sender: UIStepper) { priceStepperValueLabel.text = demoController.priceConnector.interactor.item.flatMap { "\($0)" } } - + } diff --git a/Examples/Showcase/Filter/FilterNumericComparison/NumberObservableController.swift b/Examples/Showcase/Filter/FilterNumericComparison/NumberObservableController.swift index d71c3a8e..1260179a 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/NumberObservableController.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/NumberObservableController.swift @@ -9,35 +9,35 @@ import Foundation import InstantSearchCore public class NumberObservableController: ObservableObject, NumberController { - + @Published public var value: Number { didSet { guard value != oldValue else { return } computation.just(value: value) } } - + @Published public var bounds: ClosedRange - + private var computation: Computation! - + public init(value: Number = 0, bounds: ClosedRange = 0...1000000) { self.value = value self.bounds = bounds } - + public func setItem(_ value: Number) { self.value = value } - + public func setBounds(bounds: ClosedRange?) { if let bounds = bounds { self.bounds = bounds } } - + public func setComputation(computation: Computation) { self.computation = computation } - + } diff --git a/Examples/Showcase/Filter/FilterNumericComparison/SceneDelegate.swift b/Examples/Showcase/Filter/FilterNumericComparison/SceneDelegate.swift index 5226664d..8becc83f 100644 --- a/Examples/Showcase/Filter/FilterNumericComparison/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterNumericComparison/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(FilterNumericComparisonDemoViewController(), for: scene) } } - diff --git a/Examples/Showcase/Filter/FilterNumericRange/AppDelegate.swift b/Examples/Showcase/Filter/FilterNumericRange/AppDelegate.swift index cc4503d1..6d31d94b 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoController.swift b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoController.swift index 858885c3..fd0d41d0 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoController.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoController.swift @@ -10,13 +10,13 @@ import Foundation import InstantSearchCore class FilterNumericRangeDemoController { - + let searcher: HitsSearcher let filterState: FilterState let filterClearConnector: FilterClearConnector - + let rangeConnector: NumberRangeConnector - + init() { self.searcher = HitsSearcher(client: .instantSearch, indexName: .filterNumericComparison) @@ -27,7 +27,7 @@ class FilterNumericRangeDemoController { attribute: "price") searcher.connectFilterState(filterState) searcher.search() - + } - + } diff --git a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoSwiftUI.swift index 441e9a69..44c2c0c3 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearchSwiftUI import SwiftUI struct FilterNumericRangeDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { let demoController = FilterNumericRangeDemoController() let numberRangeController = NumberRangeObservableController(range: 0...5, bounds: 0...5) let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController - + init() { filterStateController = .init(filterState: demoController.filterState) clearFilterController = .init() @@ -27,17 +27,17 @@ struct FilterNumericRangeDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.filterClearConnector.connectController(clearFilterController) } } - + struct ContentView: View { - + @ObservedObject var slider = CustomSlider(bounds: 0.0...5, values: 0...5) @ObservedObject var numberRangeController: NumberRangeObservableController @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + var body: some View { let range = numberRangeController.range - VStack(spacing: 40){ + VStack(spacing: 40) { FilterStateDebugView(filterStateController: filterStateController, clearFilterController: clearFilterController) HStack(spacing: 20) { @@ -59,7 +59,7 @@ struct FilterNumericRangeDemoSwiftUI: SwiftUIDemo, PreviewProvider { slider.highHandle.currentValue = newValue.upperBound }.padding() } - + func makeRange(_ lowerBound: Double, _ upperBound: Double) -> ClosedRange? { if lowerBound < upperBound && numberRangeController.bounds.contains(lowerBound) && @@ -69,15 +69,15 @@ struct FilterNumericRangeDemoSwiftUI: SwiftUIDemo, PreviewProvider { return nil } } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(numberRangeController: controller.numberRangeController, filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -85,5 +85,5 @@ struct FilterNumericRangeDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Number Range Filter") } } - + } diff --git a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoViewController.swift b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoViewController.swift index fdc1c511..85cdcf27 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/FilterNumericRangeDemoViewController.swift @@ -36,7 +36,7 @@ class FilterNumericRangeDemoViewController: UIViewController { } private extension FilterNumericRangeDemoViewController { - + func setup() { addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) @@ -52,7 +52,7 @@ private extension FilterNumericRangeDemoViewController { mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) mainStackView.translatesAutoresizingMaskIntoConstraints = false - + let searchDebugView = filterDebugViewController.view! searchDebugView.translatesAutoresizingMaskIntoConstraints = false searchDebugView.heightAnchor.constraint(equalToConstant: 150).isActive = true diff --git a/Examples/Showcase/Filter/FilterNumericRange/NumericRangeController.swift b/Examples/Showcase/Filter/FilterNumericRange/NumericRangeController.swift index dedad83b..6de8b70b 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/NumericRangeController.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/NumericRangeController.swift @@ -13,11 +13,11 @@ import UIKit public class NumericRangeController: UIViewController, NumberRangeController { public typealias Number = Double - + public let lowerBoundLabel: UILabel public let upperBoundLabel: UILabel public let rangeSlider: RangeSlider - + public var onRangeChanged: ((ClosedRange) -> Void)? public func setItem(_ item: ClosedRange) { @@ -36,7 +36,7 @@ public class NumericRangeController: UIViewController, NumberRangeController { lowerBoundLabel.text = "\(bounds.lowerBound.rounded(toPlaces: 2))" upperBoundLabel.text = "\(bounds.upperBound.rounded(toPlaces: 2))" } - + public init(rangeSlider: RangeSlider) { self.rangeSlider = rangeSlider self.lowerBoundLabel = .init() @@ -44,21 +44,21 @@ public class NumericRangeController: UIViewController, NumberRangeController { super.init(nibName: nil, bundle: nil) rangeSlider.addTarget(self, action: #selector(onValueChanged(sender:)), for: [.touchUpInside, .touchUpOutside]) } - + public override func viewDidLoad() { super.viewDidLoad() - + lowerBoundLabel.translatesAutoresizingMaskIntoConstraints = false lowerBoundLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true lowerBoundLabel.textAlignment = .center - + upperBoundLabel.translatesAutoresizingMaskIntoConstraints = false upperBoundLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true upperBoundLabel.textAlignment = .center rangeSlider.translatesAutoresizingMaskIntoConstraints = false rangeSlider.heightAnchor.constraint(equalToConstant: 30).isActive = true - + let stackView = UIStackView() stackView.axis = .horizontal stackView.spacing = 0 @@ -70,9 +70,9 @@ public class NumericRangeController: UIViewController, NumberRangeController { view.addSubview(stackView) stackView.pin(to: view) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/Examples/Showcase/Filter/FilterNumericRange/RangeSlider.swift b/Examples/Showcase/Filter/FilterNumericRange/RangeSlider.swift index ccaa0f2a..b569f0c7 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/RangeSlider.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/RangeSlider.swift @@ -11,22 +11,22 @@ import QuartzCore class RangeSliderTrackLayer: CALayer { weak var rangeSlider: RangeSlider? - + override func draw(in ctx: CGContext) { guard let slider = rangeSlider else { return } - + // Clip let cornerRadius = bounds.height * slider.curvaceousness / 2.0 let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius) ctx.addPath(path.cgPath) - + // Fill the track ctx.setFillColor(slider.trackTintColor.cgColor) ctx.addPath(path.cgPath) ctx.fillPath() - + // Fill the highlighted range ctx.setFillColor(slider.trackHighlightTintColor.cgColor) let lowerValuePosition = CGFloat(slider.positionForValue(slider.lowerValue)) @@ -37,14 +37,14 @@ class RangeSliderTrackLayer: CALayer { } class RangeSliderThumbLayer: CALayer { - + var highlighted: Bool = false { didSet { setNeedsDisplay() } } weak var rangeSlider: RangeSlider? - + var strokeColor: UIColor = UIColor.gray { didSet { setNeedsDisplay() @@ -55,27 +55,27 @@ class RangeSliderThumbLayer: CALayer { setNeedsDisplay() } } - + override func draw(in ctx: CGContext) { guard let slider = rangeSlider else { return } - + let thumbFrame = bounds.insetBy(dx: 2.0, dy: 2.0) let cornerRadius = thumbFrame.height * slider.curvaceousness / 2.0 let thumbPath = UIBezierPath(roundedRect: thumbFrame, cornerRadius: cornerRadius) - + // Fill ctx.setFillColor(slider.thumbTintColor.cgColor) ctx.addPath(thumbPath.cgPath) ctx.fillPath() - + // Outline ctx.setStrokeColor(strokeColor.cgColor) ctx.setLineWidth(lineWidth) ctx.addPath(thumbPath.cgPath) ctx.strokePath() - + if highlighted { ctx.setFillColor(UIColor(white: 0.0, alpha: 0.1).cgColor) ctx.addPath(thumbPath.cgPath) @@ -94,7 +94,7 @@ public class RangeSlider: UIControl { updateLayerFrames() } } - + @IBInspectable public var maximumValue: Double = 1.0 { willSet(newValue) { assert(newValue > minimumValue, "RangeSlider: maximumValue should be greater than minimumValue") @@ -103,7 +103,7 @@ public class RangeSlider: UIControl { updateLayerFrames() } } - + @IBInspectable public var lowerValue: Double = 0.2 { didSet { if lowerValue < minimumValue { @@ -112,7 +112,7 @@ public class RangeSlider: UIControl { updateLayerFrames() } } - + @IBInspectable public var upperValue: Double = 0.8 { didSet { if upperValue > maximumValue { @@ -121,171 +121,171 @@ public class RangeSlider: UIControl { updateLayerFrames() } } - + var gapBetweenThumbs: Double { return 0.5 * Double(thumbWidth) * (maximumValue - minimumValue) / Double(bounds.width) } - + @IBInspectable public var trackTintColor: UIColor = UIColor(white: 0.9, alpha: 1.0) { didSet { trackLayer.setNeedsDisplay() } } - + @IBInspectable public var trackHighlightTintColor: UIColor = UIColor(red: 0.0, green: 0.45, blue: 0.94, alpha: 1.0) { didSet { trackLayer.setNeedsDisplay() } } - + @IBInspectable public var thumbTintColor: UIColor = UIColor.white { didSet { lowerThumbLayer.setNeedsDisplay() upperThumbLayer.setNeedsDisplay() } } - + @IBInspectable public var thumbBorderColor: UIColor = UIColor.gray { didSet { lowerThumbLayer.strokeColor = thumbBorderColor upperThumbLayer.strokeColor = thumbBorderColor } } - + @IBInspectable public var thumbBorderWidth: CGFloat = 0.5 { didSet { lowerThumbLayer.lineWidth = thumbBorderWidth upperThumbLayer.lineWidth = thumbBorderWidth } } - + @IBInspectable public var curvaceousness: CGFloat = 1.0 { didSet { if curvaceousness < 0.0 { curvaceousness = 0.0 } - + if curvaceousness > 1.0 { curvaceousness = 1.0 } - + trackLayer.setNeedsDisplay() lowerThumbLayer.setNeedsDisplay() upperThumbLayer.setNeedsDisplay() } } - + fileprivate var previouslocation = CGPoint() - + fileprivate let trackLayer = RangeSliderTrackLayer() fileprivate let lowerThumbLayer = RangeSliderThumbLayer() fileprivate let upperThumbLayer = RangeSliderThumbLayer() - + fileprivate var thumbWidth: CGFloat { return CGFloat(bounds.height) } - + override public var frame: CGRect { didSet { updateLayerFrames() } } - + override public init(frame: CGRect) { super.init(frame: frame) initializeLayers() } - + required public init?(coder: NSCoder) { super.init(coder: coder) initializeLayers() } - + + // swiftlint:disable identifier_name override public func layoutSublayers(of: CALayer) { - super.layoutSublayers(of:layer) + super.layoutSublayers(of: layer) updateLayerFrames() } - + fileprivate func initializeLayers() { layer.backgroundColor = UIColor.clear.cgColor - + trackLayer.rangeSlider = self trackLayer.contentsScale = UIScreen.main.scale layer.addSublayer(trackLayer) - + lowerThumbLayer.rangeSlider = self lowerThumbLayer.contentsScale = UIScreen.main.scale layer.addSublayer(lowerThumbLayer) - + upperThumbLayer.rangeSlider = self upperThumbLayer.contentsScale = UIScreen.main.scale layer.addSublayer(upperThumbLayer) } - + func updateLayerFrames() { CATransaction.begin() CATransaction.setDisableActions(true) - + trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height/3) trackLayer.setNeedsDisplay() - + let lowerThumbCenter = CGFloat(positionForValue(lowerValue)) lowerThumbLayer.frame = CGRect(x: lowerThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth) lowerThumbLayer.setNeedsDisplay() - + let upperThumbCenter = CGFloat(positionForValue(upperValue)) upperThumbLayer.frame = CGRect(x: upperThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth) upperThumbLayer.setNeedsDisplay() - + CATransaction.commit() } - + func positionForValue(_ value: Double) -> Double { return Double(bounds.width - thumbWidth) * (value - minimumValue) / (maximumValue - minimumValue) + Double(thumbWidth/2.0) } - + func boundValue(_ value: Double, toLowerValue lowerValue: Double, upperValue: Double) -> Double { return min(max(value, lowerValue), upperValue) } - - + // MARK: - Touches - + override public func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { previouslocation = touch.location(in: self) - + // Hit test the thumb layers if lowerThumbLayer.frame.contains(previouslocation) { lowerThumbLayer.highlighted = true } else if upperThumbLayer.frame.contains(previouslocation) { upperThumbLayer.highlighted = true } - + return lowerThumbLayer.highlighted || upperThumbLayer.highlighted } - + override public func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { let location = touch.location(in: self) - + // Determine by how much the user has dragged let deltaLocation = Double(location.x - previouslocation.x) let deltaValue = (maximumValue - minimumValue) * deltaLocation / Double(bounds.width - bounds.height) - + previouslocation = location - + // Update the values if lowerThumbLayer.highlighted { lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs) } else if upperThumbLayer.highlighted { upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue) } - + sendActions(for: .valueChanged) - + return true } - + override public func endTracking(_ touch: UITouch?, with event: UIEvent?) { lowerThumbLayer.highlighted = false upperThumbLayer.highlighted = false diff --git a/Examples/Showcase/Filter/FilterNumericRange/SceneDelegate.swift b/Examples/Showcase/Filter/FilterNumericRange/SceneDelegate.swift index b138ee79..c1cd12bb 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(FilterNumericRangeDemoViewController(), for: scene) } } - diff --git a/Examples/Showcase/Filter/FilterNumericRange/SliderView.swift b/Examples/Showcase/Filter/FilterNumericRange/SliderView.swift index d32f6f82..dbc6e3a5 100644 --- a/Examples/Showcase/Filter/FilterNumericRange/SliderView.swift +++ b/Examples/Showcase/Filter/FilterNumericRange/SliderView.swift @@ -8,15 +8,15 @@ import SwiftUI import Combine -//SliderValue to restrict double range: 0.0 to 1.0 +// SliderValue to restrict double range: 0.0 to 1.0 @propertyWrapper struct SliderValue: Equatable { var value: Double - + init(wrappedValue: Double) { self.value = wrappedValue } - + var wrappedValue: Double { get { value } set { value = min(max(0.0, newValue), 1.0) } @@ -24,7 +24,7 @@ struct SliderValue: Equatable { } extension SliderValue: ExpressibleByFloatLiteral { - + init(floatLiteral value: Double) { self.value = value } @@ -32,66 +32,66 @@ extension SliderValue: ExpressibleByFloatLiteral { } class SliderHandle: ObservableObject { - - //Slider Size + + // Slider Size let sliderWidth: CGFloat let sliderHeight: CGFloat - - //Slider Range + + // Slider Range let sliderValueStart: Double let sliderValueRange: Double - - //Slider Handle + + // Slider Handle var diameter: CGFloat = 30 var startLocation: CGPoint - + var lowerBoundPercentage: Double = 0 var upperBoundPercentage: Double = 100 - - //Current Value + + // Current Value @Published var currentPercentage: SliderValue - - //Slider Button Location + + // Slider Button Location @Published var onDrag: Bool @Published var currentLocation: CGPoint - + init(sliderWidth: CGFloat, sliderHeight: CGFloat, sliderValueStart: Double, sliderValueEnd: Double, startPercentage: SliderValue) { self.sliderWidth = sliderWidth self.sliderHeight = sliderHeight - + self.sliderValueStart = sliderValueStart self.sliderValueRange = sliderValueEnd - sliderValueStart - + let startLocation = CGPoint(x: (CGFloat(startPercentage.wrappedValue)/1.0)*sliderWidth, y: sliderHeight/2) - + self.startLocation = startLocation self.currentLocation = startLocation self.currentPercentage = startPercentage self.onDrag = false } - + lazy var sliderDragGesture: _EndedGesture<_ChangedGesture> = DragGesture() .onChanged { value in self.onDrag = true - + let dragLocation = value.location - - //Restrict possible drag area + + // Restrict possible drag area self.restrictSliderBtnLocation(dragLocation) - - //Get current value + + // Get current value self.currentPercentage.wrappedValue = Double(self.currentLocation.x / self.sliderWidth) - + }.onEnded { _ in self.onDrag = false } - + private func restrictSliderBtnLocation(_ dragLocation: CGPoint) { let expectedPercentage = dragLocation.x > 0 ? dragLocation.x / sliderWidth : 0 guard expectedPercentage >= lowerBoundPercentage && expectedPercentage <= upperBoundPercentage else { return } - //On Slider Width + // On Slider Width if dragLocation.x < .zero { calcSliderBtnLocation(CGPoint(x: 0, y: dragLocation.y)) } else if dragLocation.x > sliderWidth { @@ -100,7 +100,7 @@ class SliderHandle: ObservableObject { calcSliderBtnLocation(dragLocation) } } - + private func calcSliderBtnLocation(_ dragLocation: CGPoint) { if dragLocation.y != sliderHeight/2 { currentLocation = CGPoint(x: dragLocation.x, y: sliderHeight/2) @@ -108,13 +108,13 @@ class SliderHandle: ObservableObject { currentLocation = dragLocation } } - - //Current Value + + // Current Value var currentValue: Double { get { return (sliderValueStart + currentPercentage.wrappedValue * sliderValueRange).rounded(toPlaces: 2) } - + set { guard newValue <= sliderValueStart + sliderValueRange else { return } let newPercentage = (newValue - sliderValueStart) / sliderValueRange @@ -125,43 +125,43 @@ class SliderHandle: ObservableObject { } class CustomSlider: ObservableObject { - - //Slider Size + + // Slider Size final let width: CGFloat = 300 final let lineWidth: CGFloat = 8 - - //Slider value range from valueStart to valueEnd + + // Slider value range from valueStart to valueEnd final let valueStart: Double final let valueEnd: Double - - //Slider Handle + + // Slider Handle @Published var highHandle: SliderHandle @Published var lowHandle: SliderHandle - + final var anyCancellableHigh: AnyCancellable? final var anyCancellableLow: AnyCancellable? - + init(start: Double, end: Double, highStartPercentage: SliderValue = 1.0, lowStartPercentage: SliderValue = 0.0) { valueStart = start valueEnd = end - + highHandle = SliderHandle(sliderWidth: width, sliderHeight: lineWidth, sliderValueStart: valueStart, sliderValueEnd: valueEnd, startPercentage: highStartPercentage ) - + lowHandle = SliderHandle(sliderWidth: width, sliderHeight: lineWidth, sliderValueStart: valueStart, sliderValueEnd: valueEnd, startPercentage: lowStartPercentage ) - + anyCancellableHigh = highHandle.objectWillChange.sink { _ in self.lowHandle.upperBoundPercentage = self.highHandle.currentPercentage.value self.objectWillChange.send() @@ -171,7 +171,7 @@ class CustomSlider: ObservableObject { self.objectWillChange.send() } } - + convenience init(bounds: ClosedRange, values: ClosedRange) { let highStartPercentage = values.upperBound / bounds.upperBound let lowStartPercentage = values.lowerBound / (bounds.upperBound - bounds.lowerBound) @@ -180,21 +180,21 @@ class CustomSlider: ObservableObject { highStartPercentage: SliderValue(wrappedValue: highStartPercentage), lowStartPercentage: SliderValue(wrappedValue: lowStartPercentage)) } - + var bounds: ClosedRange { return valueStart...valueEnd } - + var range: ClosedRange { return lowHandle.currentValue...highHandle.currentValue } - - //Percentages between high and low handle + + // Percentages between high and low handle var percentagesBetween: String { return String(format: "%.2f", highHandle.currentPercentage.wrappedValue - lowHandle.currentPercentage.wrappedValue) } - - //Value between high and low handle + + // Value between high and low handle var valueBetween: String { return String(format: "%.2f", highHandle.currentValue - lowHandle.currentValue) } @@ -202,32 +202,32 @@ class CustomSlider: ObservableObject { struct SliderView: View { @ObservedObject var slider: CustomSlider - + var body: some View { RoundedRectangle(cornerRadius: slider.lineWidth) .fill(Color.gray.opacity(0.2)) .frame(width: slider.width, height: slider.lineWidth) .overlay( ZStack { - //Path between both handles + // Path between both handles SliderPathBetweenView(slider: slider) - - //Low Handle + + // Low Handle SliderHandleView(handle: slider.lowHandle) .highPriorityGesture(slider.lowHandle.sliderDragGesture) - - //High Handle + + // High Handle SliderHandleView(handle: slider.highHandle) .highPriorityGesture(slider.highHandle.sliderDragGesture) } ) } - + } struct SliderHandleView: View { @ObservedObject var handle: SliderHandle - + var body: some View { Circle() .frame(width: handle.diameter, height: handle.diameter) @@ -241,7 +241,7 @@ struct SliderHandleView: View { struct SliderPathBetweenView: View { @ObservedObject var slider: CustomSlider - + var body: some View { Path { path in path.move(to: slider.lowHandle.currentLocation) diff --git a/Examples/Showcase/Filter/FilterRating/AppDelegate.swift b/Examples/Showcase/Filter/FilterRating/AppDelegate.swift index 0a91557e..1e8bb91b 100644 --- a/Examples/Showcase/Filter/FilterRating/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterRating/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoController.swift b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoController.swift index f8b27a9e..7acc8f27 100644 --- a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoController.swift +++ b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoController.swift @@ -9,11 +9,11 @@ import Foundation import InstantSearchCore class RatingFilterDemoController { - + let filterState: FilterState let numberInteractor: NumberInteractor let clearFilterConnector: FilterClearConnector - + init() { numberInteractor = NumberInteractor() filterState = FilterState() @@ -23,5 +23,5 @@ class RatingFilterDemoController { numericOperator: .greaterThanOrEqual) filterState.notify(.add(filter: Filter.Numeric(attribute: "rating", operator: .greaterThanOrEqual, value: 3.5), toGroupWithID: .and(name: "rating"))) } - + } diff --git a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoSwiftUI.swift index f6a3055e..5b24c4bd 100644 --- a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoSwiftUI.swift @@ -10,14 +10,14 @@ import SwiftUI import InstantSearchSwiftUI struct RatingFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: RatingFilterDemoController let ratingController: NumberObservableController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController - + init() { demoController = .init() ratingController = .init(value: 3.5) @@ -26,16 +26,16 @@ struct RatingFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.clearFilterConnector.connectController(clearFilterController) demoController.numberInteractor.connectNumberController(ratingController) } - + } - + struct ContentView: View { - + @State var value: Double = 3.5 @ObservedObject var ratingController: NumberObservableController @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + var body: some View { VStack { FilterStateDebugView(filterStateController: filterStateController, @@ -52,15 +52,15 @@ struct RatingFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .padding() } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(ratingController: controller.ratingController, filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -68,5 +68,5 @@ struct RatingFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Filter Rating") } } - + } diff --git a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoViewController.swift b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoViewController.swift index c9ac9b34..674ce476 100644 --- a/Examples/Showcase/Filter/FilterRating/RatingFilterDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterRating/RatingFilterDemoViewController.swift @@ -11,7 +11,7 @@ import UIKit import InstantSearch class RatingFilterDemoViewController: UIViewController { - + let demoController: RatingFilterDemoController let valueLabel: UILabel let stepper: UIStepper @@ -30,27 +30,27 @@ class RatingFilterDemoViewController: UIViewController { filterDebugViewController = FilterDebugViewController(filterState: demoController.filterState) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupLayout() setup() } - + private func setup() { addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) demoController.numberInteractor.connectNumberController(ratingController) demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) } - + func setupLayout() { view.backgroundColor = .systemBackground - + let mainStackView = UIStackView() mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) @@ -59,12 +59,12 @@ class RatingFilterDemoViewController: UIViewController { mainStackView.spacing = 10 view.addSubview(mainStackView) mainStackView.pin(to: view) - + let searchDebugView = filterDebugViewController.view! searchDebugView.translatesAutoresizingMaskIntoConstraints = false searchDebugView.heightAnchor.constraint(equalToConstant: 150).isActive = true mainStackView.addArrangedSubview(searchDebugView) - + ratingControl.translatesAutoresizingMaskIntoConstraints = false ratingControl.value = 3.5 ratingControl.maximumValue = 5 @@ -105,11 +105,11 @@ class RatingFilterDemoViewController: UIViewController { } refreshLabel() } - + private func refreshLabel() { valueLabel.text = fractionalString(for: ratingControl.value, fractionDigits: 1) } - + private func fractionalString(for value: Double, fractionDigits: Int) -> String { let formatter = NumberFormatter() formatter.minimumFractionDigits = fractionDigits diff --git a/Examples/Showcase/Filter/FilterRating/RatingView.swift b/Examples/Showcase/Filter/FilterRating/RatingView.swift index 625abbed..43e6e756 100644 --- a/Examples/Showcase/Filter/FilterRating/RatingView.swift +++ b/Examples/Showcase/Filter/FilterRating/RatingView.swift @@ -10,38 +10,38 @@ import SwiftUI import InstantSearch struct RatingView: UIViewRepresentable { - + @Binding var value: Double - + func makeUIView(context: Context) -> RatingControl { let ratingControl = RatingControl() ratingControl.addTarget(context.coordinator, action: #selector(context.coordinator.valueChanged), for: .valueChanged) return ratingControl } - + func updateUIView(_ uiView: RatingControl, context: Context) { guard uiView.value != value else { return } uiView.value = value } - + class Coordinator: NSObject { - + var onValueChange: (Double) -> Void - + init(onValueChange: @escaping (Double) -> Void) { self.onValueChange = onValueChange } - + @objc func valueChanged(_ sender: RatingControl) { onValueChange(sender.value) } - + } - + func makeCoordinator() -> Coordinator { Coordinator { value in self.value = value } } - + } diff --git a/Examples/Showcase/Filter/FilterRating/SceneDelegate.swift b/Examples/Showcase/Filter/FilterRating/SceneDelegate.swift index 4d6d375e..78c76b81 100644 --- a/Examples/Showcase/Filter/FilterRating/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterRating/SceneDelegate.swift @@ -15,6 +15,4 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { setMain(RatingFilterDemoViewController(), for: scene) } - } - diff --git a/Examples/Showcase/Filter/FilterSegment/AppDelegate.swift b/Examples/Showcase/Filter/FilterSegment/AppDelegate.swift index be500fd7..9b6d3929 100644 --- a/Examples/Showcase/Filter/FilterSegment/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterSegment/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterSegment/SceneDelegate.swift b/Examples/Showcase/Filter/FilterSegment/SceneDelegate.swift index f67d76fe..36f32017 100644 --- a/Examples/Showcase/Filter/FilterSegment/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterSegment/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Filter/FilterSegment/SegmentedDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterSegment/SegmentedDemoSwiftUI.swift index 63a6c3e1..fd126df6 100644 --- a/Examples/Showcase/Filter/FilterSegment/SegmentedDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterSegment/SegmentedDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearch import InstantSearchSwiftUI class SegmentedDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: SegmentedFilterDemoController let selectableSegmentController: SelectableSegmentObservableController let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController - + init() { selectableSegmentController = SelectableSegmentObservableController() demoController = SegmentedFilterDemoController() @@ -28,18 +28,18 @@ class SegmentedDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.filterMapConnector.connectController(selectableSegmentController) demoController.clearFilterConnector.connectController(clearFilterController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController - + @ObservedObject var selectableSegmentController: SelectableSegmentObservableController @State private var selected = 0 - + var body: some View { let selectedBinding = Binding( get: { self.selectableSegmentController.selectedSegmentIndex ?? 0 }, @@ -62,15 +62,15 @@ class SegmentedDemoSwiftUI: SwiftUIDemo, PreviewProvider { Spacer() } } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, selectableSegmentController: controller.selectableSegmentController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -78,5 +78,5 @@ class SegmentedDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Filter Segment") } } - + } diff --git a/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoController.swift b/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoController.swift index 1ee182d7..bb4a087a 100644 --- a/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoController.swift +++ b/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoController.swift @@ -9,24 +9,24 @@ import Foundation import InstantSearch class SegmentedFilterDemoController { - + let searcher: HitsSearcher let filterState: FilterState let filterMapConnector: FilterMapConnector let clearFilterConnector: FilterClearConnector - + init() { let gender: Attribute = "gender" let male = Filter.Facet(attribute: "gender", stringValue: "male") let female = Filter.Facet(attribute: "gender", stringValue: "female") let notSpecified = Filter.Facet(attribute: "gender", stringValue: "not specified") - + self.searcher = HitsSearcher(client: .instantSearch, indexName: .filterSegment) let items: [Int: Filter.Facet] = [ 0: male, 1: female, - 2: notSpecified, + 2: notSpecified ] self.filterState = FilterState() self.clearFilterConnector = .init(filterState: filterState) @@ -36,10 +36,10 @@ class SegmentedFilterDemoController { selected: 0, attribute: gender, operator: .or) - + searcher.search() searcher.connectFilterState(filterState) filterState.notify(.add(filter: male, toGroupWithID: .or(name: gender.rawValue, filterType: .facet))) } - + } diff --git a/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoViewController.swift b/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoViewController.swift index 4d9ea727..ff0156e5 100644 --- a/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterSegment/SegmentedFilterDemoViewController.swift @@ -11,48 +11,48 @@ import UIKit import InstantSearch class SegmentedFilterDemoViewController: UIViewController { - + let demoController: SegmentedFilterDemoController let segmentedController: SegmentedController let filterDebugViewController: FilterDebugViewController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { segmentedController = SegmentedController(segmentedControl: .init()) demoController = .init() filterDebugViewController = FilterDebugViewController(filterState: demoController.filterState) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setup() setupUI() } - + } private extension SegmentedFilterDemoViewController { - + func setup() { demoController.filterMapConnector.connectController(segmentedController) demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) segmentedController.segmentedControl.selectedSegmentIndex = 0 } - + func setupUI() { view.backgroundColor = .systemBackground - + let mainStackView = UIStackView() mainStackView.axis = .vertical mainStackView.spacing = 10 mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) mainStackView.translatesAutoresizingMaskIntoConstraints = false - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true @@ -60,9 +60,9 @@ private extension SegmentedFilterDemoViewController { mainStackView.addArrangedSubview(filterDebugViewController.view) mainStackView.addArrangedSubview(segmentedController.segmentedControl) mainStackView.addArrangedSubview(.spacer) - + view.addSubview(mainStackView) mainStackView.pin(to: view) } - + } diff --git a/Examples/Showcase/Filter/FilterToggle/AppDelegate.swift b/Examples/Showcase/Filter/FilterToggle/AppDelegate.swift index 45e30a6d..fea46103 100644 --- a/Examples/Showcase/Filter/FilterToggle/AppDelegate.swift +++ b/Examples/Showcase/Filter/FilterToggle/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Filter/FilterToggle/SceneDelegate.swift b/Examples/Showcase/Filter/FilterToggle/SceneDelegate.swift index 7d5bcca7..bc97686b 100644 --- a/Examples/Showcase/Filter/FilterToggle/SceneDelegate.swift +++ b/Examples/Showcase/Filter/FilterToggle/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoController.swift b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoController.swift index f6e3d629..d3cc8c08 100644 --- a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoController.swift +++ b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoController.swift @@ -10,21 +10,21 @@ import Foundation import InstantSearch class ToggleFilterDemoController { - + let searcher: HitsSearcher let filterState: FilterState let clearFilterConnector: FilterClearConnector - + let sizeConstraintConnector: FilterToggleConnector let vintageConnector: FilterToggleConnector let couponConnector: FilterToggleConnector - + init() { searcher = HitsSearcher(client: .instantSearch, indexName: .filterToggle) filterState = .init() clearFilterConnector = .init(filterState: filterState) - + // Size constraint button let sizeConstraintFilter = Filter.Numeric(attribute: "size", operator: .greaterThan, value: 40) sizeConstraintConnector = .init(filterState: filterState, @@ -40,10 +40,8 @@ class ToggleFilterDemoController { couponConnector = .init(filterState: filterState, filter: couponFacet) - searcher.connectFilterState(filterState) searcher.search() } - - + } diff --git a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoSwiftUI.swift b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoSwiftUI.swift index 75821862..94c9ecdf 100644 --- a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoSwiftUI.swift +++ b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoSwiftUI.swift @@ -12,18 +12,18 @@ import InstantSearchSwiftUI import SwiftUI struct ToggleFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: ToggleFilterDemoController - + let filterStateController: FilterStateObservableController let clearFilterController: FilterClearObservableController - + let tagFilterFilterObservableController: FilterToggleObservableController let facetFilterFilterObservableController: FilterToggleObservableController let numericFilterFilterObservableController: FilterToggleObservableController - + init() { self.tagFilterFilterObservableController = .init() self.facetFilterFilterObservableController = .init() @@ -36,23 +36,23 @@ struct ToggleFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.couponConnector.connectController(facetFilterFilterObservableController) demoController.vintageConnector.connectController(tagFilterFilterObservableController) } - + } - + struct ContentView: View { - + @ObservedObject var filterStateController: FilterStateObservableController @ObservedObject var clearFilterController: FilterClearObservableController @ObservedObject var tagFilterFilterObservableController: FilterToggleObservableController @ObservedObject var facetFilterFilterObservableController: FilterToggleObservableController @ObservedObject var numericFilterFilterObservableController: FilterToggleObservableController - + var body: some View { VStack(spacing: 20) { FilterStateDebugView(filterStateController: filterStateController, clearFilterController: clearFilterController) - HStack() { + HStack { if let numericFilter = numericFilterFilterObservableController.filter { Toggle(numericFilter.description, isOn: $numericFilterFilterObservableController.isSelected) .toggleStyle(.button) @@ -61,16 +61,16 @@ struct ToggleFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { Toggle(tagFilter.description, isOn: $tagFilterFilterObservableController.isSelected) .toggleStyle(CheckboxToggleStyle()) } - if let _ = facetFilterFilterObservableController.filter { + if facetFilterFilterObservableController.filter != nil { Toggle("Coupon", isOn: $facetFilterFilterObservableController.isSelected) } } Spacer() }.padding() } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(filterStateController: controller.filterStateController, clearFilterController: controller.clearFilterController, @@ -78,7 +78,7 @@ struct ToggleFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { facetFilterFilterObservableController: controller.facetFilterFilterObservableController, numericFilterFilterObservableController: controller.numericFilterFilterObservableController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -86,7 +86,7 @@ struct ToggleFilterDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Filter Toggle") } } - + } struct CheckboxToggleStyle: ToggleStyle { diff --git a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoViewController.swift b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoViewController.swift index 3464e2ec..e2ecace1 100644 --- a/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoViewController.swift +++ b/Examples/Showcase/Filter/FilterToggle/ToggleFilterDemoViewController.swift @@ -17,15 +17,15 @@ class ToggleFilterDemoViewController: UIViewController { let mainStackView = UIStackView() let controlsStackView = UIStackView() let couponStackView = UIStackView() - + let vintageButtonController: SelectableFilterButtonController let sizeConstraintButtonController: SelectableFilterButtonController let couponSwitchController: FilterSwitchController - + let filterDebugViewController: FilterDebugViewController - + let couponLabel = UILabel() - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { sizeConstraintButtonController = SelectableFilterButtonController(button: .init()) vintageButtonController = SelectableFilterButtonController(button: .init()) @@ -35,28 +35,27 @@ class ToggleFilterDemoViewController: UIViewController { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) setup() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - -} +} private extension ToggleFilterDemoViewController { - + func setup() { demoController.clearFilterConnector.connectController(filterDebugViewController.clearFilterController) demoController.sizeConstraintConnector.connectController(sizeConstraintButtonController) demoController.vintageConnector.connectController(vintageButtonController) demoController.couponConnector.connectController(couponSwitchController) } - + func setupUI() { view.backgroundColor = .systemBackground configureSizeButton() @@ -68,22 +67,22 @@ private extension ToggleFilterDemoViewController { configureControlsStackView() configureLayout() } - + func configureLayout() { - + view.addSubview(mainStackView) - + mainStackView.pin(to: view) - + addChild(filterDebugViewController) filterDebugViewController.didMove(toParent: self) filterDebugViewController.view.heightAnchor.constraint(equalToConstant: 150).isActive = true mainStackView.addArrangedSubview(filterDebugViewController.view) - + couponStackView.addArrangedSubview(couponLabel) couponStackView.addArrangedSubview(couponSwitchController.switch) - + controlsStackView.addArrangedSubview(spacer()) controlsStackView.addArrangedSubview(sizeConstraintButtonController.button) controlsStackView.addArrangedSubview(spacer()) @@ -94,13 +93,13 @@ private extension ToggleFilterDemoViewController { mainStackView.addArrangedSubview(controlsStackView) mainStackView.addArrangedSubview(spacer()) } - + private func spacer() -> UIView { let view = UIView() view.setContentHuggingPriority(.defaultLow, for: .horizontal) return view } - + func configureMainStackView() { mainStackView.isLayoutMarginsRelativeArrangement = true mainStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) @@ -108,13 +107,13 @@ private extension ToggleFilterDemoViewController { mainStackView.spacing = 10 mainStackView.translatesAutoresizingMaskIntoConstraints = false } - + func configureControlsStackView() { controlsStackView.axis = .horizontal controlsStackView.distribution = .equalSpacing controlsStackView.translatesAutoresizingMaskIntoConstraints = false } - + func configureCouponStackView() { couponStackView.translatesAutoresizingMaskIntoConstraints = false couponStackView.axis = .horizontal @@ -122,7 +121,7 @@ private extension ToggleFilterDemoViewController { couponStackView.alignment = .center couponStackView.distribution = .fill } - + func configureSizeButton() { let button = sizeConstraintButtonController.button button.translatesAutoresizingMaskIntoConstraints = false @@ -134,12 +133,12 @@ private extension ToggleFilterDemoViewController { button.contentEdgeInsets = .init(top: 5, left: 5, bottom: 5, right: 5) button.addTarget(self, action: #selector(didTapSizeButton), for: .touchUpInside) } - + @objc func didTapSizeButton(_ button: UIButton) { let borderColor: UIColor = button.isSelected ? .systemGray : UIColor.tintColor button.layer.borderColor = borderColor.cgColor } - + func configureVintageButton() { let button = vintageButtonController.button button.translatesAutoresizingMaskIntoConstraints = false @@ -149,14 +148,14 @@ private extension ToggleFilterDemoViewController { button.setImage(UIImage(systemName: "square"), for: .normal) button.setImage(UIImage(systemName: "checkmark.square"), for: .selected) } - + func configureCouponSwitch() { couponSwitchController.switch.translatesAutoresizingMaskIntoConstraints = false } - + func configureCouponLabel() { couponLabel.text = "Coupon" couponLabel.translatesAutoresizingMaskIntoConstraints = false } - + } diff --git a/Examples/Showcase/QueryRuleCustomData/AppDelegate.swift b/Examples/Showcase/QueryRuleCustomData/AppDelegate.swift index 56d2e017..0a04d55b 100644 --- a/Examples/Showcase/QueryRuleCustomData/AppDelegate.swift +++ b/Examples/Showcase/QueryRuleCustomData/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/QueryRuleCustomData/BannerViewController.swift b/Examples/Showcase/QueryRuleCustomData/BannerViewController.swift index 3985c352..58421544 100644 --- a/Examples/Showcase/QueryRuleCustomData/BannerViewController.swift +++ b/Examples/Showcase/QueryRuleCustomData/BannerViewController.swift @@ -11,7 +11,7 @@ import UIKit import InstantSearchCore class BannerViewController: UIViewController, ItemController { - + var banner: Banner? { didSet { guard let banner = banner else { return } @@ -23,11 +23,11 @@ class BannerViewController: UIViewController, ItemController { } } } - + let imageView: UIImageView let label: UILabel var didTapBanner: (() -> Void)? - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { imageView = .init() label = .init() @@ -38,11 +38,11 @@ class BannerViewController: UIViewController, ItemController { view.isUserInteractionEnabled = true view.addGestureRecognizer(tapGestureRecognizer) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() imageView.translatesAutoresizingMaskIntoConstraints = false @@ -53,11 +53,11 @@ class BannerViewController: UIViewController, ItemController { view.addSubview(label) label.pin(to: view, insets: .init(top: 10, left: 10, bottom: -10, right: -10)) } - + @objc func didTapBanner(_ tapGestureRecognizer: UITapGestureRecognizer) { didTapBanner?() } - + func setItem(_ item: Banner?) { banner = item if banner == nil { @@ -69,5 +69,5 @@ class BannerViewController: UIViewController, ItemController { view.isHidden = false } } - + } diff --git a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoController.swift b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoController.swift index 89c191c4..4fc06de4 100644 --- a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoController.swift +++ b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoController.swift @@ -9,18 +9,18 @@ import Foundation import InstantSearchCore class QueryRuleCustomDataDemoController { - + let searcher: HitsSearcher let searchBoxConnector: SearchBoxConnector let hitsConnector: HitsConnector> let queryRuleCustomDataConnector: QueryRuleCustomDataConnector - + static let helpMessage = """ - Type "iphone" to show image banner. Click banner to redirect.\n - Type "discount" to show textual banner. Click banner to redirect.\n - Type "help" to activate redirect on submit. Submit by clicking "search" button on the keyboard to redirect. """ - + init() { searcher = .init(client: .instantSearch, indexName: .instantSearch) @@ -29,5 +29,5 @@ class QueryRuleCustomDataDemoController { queryRuleCustomDataConnector = .init(searcher: searcher) searcher.search() } - + } diff --git a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoSwiftUI.swift b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoSwiftUI.swift index 09a36728..13f6fa97 100644 --- a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoSwiftUI.swift +++ b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoSwiftUI.swift @@ -12,14 +12,14 @@ import InstantSearchCore import InstantSearchSwiftUI struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: QueryRuleCustomDataDemoController let searchBoxController: SearchBoxObservableController let bannerController: BannerObservableController let hitsController: HitsObservableController> - + init() { self.demoController = .init() self.searchBoxController = .init() @@ -31,20 +31,20 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { demoController.searcher.search() } } - + struct ContentView: View { - + struct Redirect: Identifiable { var id: String { url } let url: String } - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController> @ObservedObject var bannerController: BannerObservableController - + @State private var selectedRedirect: Redirect? - + var body: some View { VStack { if let imageURL = bannerController.banner?.banner { @@ -89,7 +89,7 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { Alert(title: Text("Redirect"), message: Text(redirect.id), dismissButton: .cancel()) - + } .safeAreaInset(edge: .top, alignment: .center, spacing: 0) { Color.clear @@ -101,7 +101,7 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { handleSubmit() } } - + func handleSubmit() { guard let link = bannerController.banner?.link else { return @@ -110,7 +110,7 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { selectedRedirect = .init(url: link.absoluteString) } } - + func handleBannerTap() { guard let link = bannerController.banner?.link else { return @@ -122,15 +122,15 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { UIApplication.shared.open(link) } } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, hitsController: controller.hitsController, bannerController: controller.bannerController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -138,15 +138,15 @@ struct QueryRuleCustomDataSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Query Rule Custom Data") } } - + } class BannerObservableController: ObservableObject, ItemController { - + @Published var banner: Banner? - + func setItem(_ item: Banner?) { self.banner = item } - + } diff --git a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoViewController.swift b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoViewController.swift index c393ee29..1188ca27 100644 --- a/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoViewController.swift +++ b/Examples/Showcase/QueryRuleCustomData/QueryRuleCustomDataDemoViewController.swift @@ -11,14 +11,14 @@ import InstantSearch import SDWebImage class QueryRuleCustomDataDemoViewController: UIViewController { - + let searchBar = UISearchBar() - + let demoController: QueryRuleCustomDataDemoController let textFieldController: TextFieldController let hitsTableViewController: ProductsTableViewController let bannerViewController: BannerViewController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { demoController = .init() textFieldController = .init(searchBar: searchBar) @@ -27,29 +27,29 @@ class QueryRuleCustomDataDemoViewController: UIViewController { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) setup() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() configureUI() } - + private func setup() { - + demoController.searchBoxConnector.connectController(textFieldController) demoController.hitsConnector.connectController(hitsTableViewController) demoController.queryRuleCustomDataConnector.connectController(bannerViewController) - + addChild(bannerViewController) bannerViewController.didMove(toParent: self) - + addChild(hitsTableViewController) hitsTableViewController.didMove(toParent: self) hitsTableViewController.tableView.keyboardDismissMode = .onDrag - + bannerViewController.didTapBanner = { [weak self] in if let link = self?.bannerViewController.banner?.link { switch link.absoluteString { @@ -63,7 +63,7 @@ class QueryRuleCustomDataDemoViewController: UIViewController { } } } - + demoController.searchBoxConnector.interactor.onQuerySubmitted.subscribe(with: self) { (viewController, _) in guard let link = viewController.demoController.queryRuleCustomDataConnector.interactor.item?.link else { return } if link.absoluteString == "algoliademo://help" { @@ -74,13 +74,13 @@ class QueryRuleCustomDataDemoViewController: UIViewController { viewController.present(UINavigationController(rootViewController: submitViewController), animated: true, completion: nil) } }.onQueue(.main) - + navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "info.circle.fill"), style: .plain, target: self, action: #selector(presentInfo)) } - + @objc func presentInfo() { let alertController = UIAlertController(title: "Help", message: QueryRuleCustomDataDemoController.helpMessage, preferredStyle: .alert) alertController.addAction(.init(title: "OK", style: .cancel, handler: nil)) @@ -90,20 +90,20 @@ class QueryRuleCustomDataDemoViewController: UIViewController { } private extension QueryRuleCustomDataDemoViewController { - + func configureUI() { title = "Query Rule Custom Data" view.backgroundColor = .systemBackground configureLayout() } - + func configureLayout() { searchBar.translatesAutoresizingMaskIntoConstraints = false searchBar.searchBarStyle = .minimal bannerViewController.view.isHidden = true bannerViewController.view.heightAnchor.constraint(lessThanOrEqualToConstant: 66.7).isActive = true - + let stackView = UIStackView() stackView.spacing = 16 stackView.axis = .vertical @@ -116,8 +116,8 @@ private extension QueryRuleCustomDataDemoViewController { stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } - + } diff --git a/Examples/Showcase/QueryRuleCustomData/SceneDelegate.swift b/Examples/Showcase/QueryRuleCustomData/SceneDelegate.swift index 6befd264..7964034a 100644 --- a/Examples/Showcase/QueryRuleCustomData/SceneDelegate.swift +++ b/Examples/Showcase/QueryRuleCustomData/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/RelatedItems/AppDelegate.swift b/Examples/Showcase/RelatedItems/AppDelegate.swift index d6736ce2..dc107213 100644 --- a/Examples/Showcase/RelatedItems/AppDelegate.swift +++ b/Examples/Showcase/RelatedItems/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/RelatedItems/RecommendController.swift b/Examples/Showcase/RelatedItems/RecommendController.swift index d5454b71..b8480089 100644 --- a/Examples/Showcase/RelatedItems/RecommendController.swift +++ b/Examples/Showcase/RelatedItems/RecommendController.swift @@ -11,13 +11,13 @@ import UIKit import AlgoliaSearchClient class RecommendController { - + let recommendClient: RecommendClient init(recommendClient: RecommendClient) { self.recommendClient = recommendClient } - + func presentRelatedItems(for objectID: ObjectID, from sourceViewController: UIViewController, animated: Bool = true) { recommendClient.getRelatedProducts(options: [.init(indexName: .ecommerceRecommend, objectID: objectID)]) { result in DispatchQueue.main.async { @@ -36,5 +36,5 @@ class RecommendController { } } - + } diff --git a/Examples/Showcase/RelatedItems/RelatedItemsDemoViewController.swift b/Examples/Showcase/RelatedItems/RelatedItemsDemoViewController.swift index 50c34742..1b3955b5 100644 --- a/Examples/Showcase/RelatedItems/RelatedItemsDemoViewController.swift +++ b/Examples/Showcase/RelatedItems/RelatedItemsDemoViewController.swift @@ -11,16 +11,16 @@ import InstantSearch import SDWebImage class RelatedItemsDemoViewController: UIViewController { - + let searcher: HitsSearcher let hitsInteractor: HitsInteractor> - + let searchBoxConnector: SearchBoxConnector let searchController: UISearchController let textFieldController: TextFieldController let resultsViewController: ResultsViewController let recommendController: RecommendController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { self.searcher = .init(client: .ecommerceRecommend, indexName: .ecommerceRecommend) @@ -34,11 +34,11 @@ class RelatedItemsDemoViewController: UIViewController { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) setup() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() @@ -47,12 +47,12 @@ class RelatedItemsDemoViewController: UIViewController { viewController.recommendController.presentRelatedItems(for: hit.objectID, from: viewController) } } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + fileprivate func setupUI() { title = "Related Items" view.backgroundColor = .systemBackground @@ -62,11 +62,11 @@ class RelatedItemsDemoViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + private func setup() { hitsInteractor.connectSearcher(searcher) hitsInteractor.connectController(resultsViewController.hitsViewController) searcher.search() } - + } diff --git a/Examples/Showcase/RelatedItems/SceneDelegate.swift b/Examples/Showcase/RelatedItems/SceneDelegate.swift index 679612ff..071befbc 100644 --- a/Examples/Showcase/RelatedItems/SceneDelegate.swift +++ b/Examples/Showcase/RelatedItems/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Search/PaginationMultiIndex/AppDelegate.swift b/Examples/Showcase/Search/PaginationMultiIndex/AppDelegate.swift index e703fed8..cb3d8bdd 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/AppDelegate.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoController.swift b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoController.swift index 46d03cff..610b4854 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoController.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoController.swift @@ -9,12 +9,12 @@ import Foundation import InstantSearchCore class MultiIndexDemoController { - + let multiSearcher: MultiSearcher let suggestionsHitsConnector: HitsConnector let productsHitsConnector: HitsConnector> let searchBoxConnector: SearchBoxConnector - + init() { multiSearcher = .init(client: .ecommerce) let suggestionsSearcher = multiSearcher.addHitsSearcher(indexName: .ecommerceSuggestions) @@ -24,5 +24,5 @@ class MultiIndexDemoController { suggestionsHitsConnector = .init(searcher: suggestionsSearcher) multiSearcher.search() } - + } diff --git a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoSwiftUI.swift b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoSwiftUI.swift index e18681a9..643141a7 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoSwiftUI.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoSwiftUI.swift @@ -11,14 +11,14 @@ import InstantSearchCore import InstantSearchSwiftUI struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: MultiIndexDemoController let searchBoxController: SearchBoxObservableController let suggestionsHitsController: HitsObservableController let productsHitsController: HitsObservableController> - + init() { demoController = .init() searchBoxController = .init() @@ -28,15 +28,15 @@ struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.suggestionsHitsConnector.connectController(suggestionsHitsController) demoController.productsHitsConnector.connectController(productsHitsController) } - + } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var suggestionsHitsController: HitsObservableController @ObservedObject var productsHitsController: HitsObservableController> - + var body: some View { VStack { HStack { @@ -73,10 +73,10 @@ struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { .searchable(text: $searchBoxController.query) .background(Color(.systemGray6)) } - + func cellForSuggestion(atIndex index: Int) -> some View { let suggestion = suggestionsHitsController.hits[index]! - + return Text(highlightedString: HighlightedString(string: suggestion.highlighted!)) { string in Text(string) .foregroundColor(Color(.tintColor)) @@ -90,7 +90,7 @@ struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { suggestionsHitsController.notifyAppearanceOfHit(atIndex: index) } } - + func cellForProduct(atIndex index: Int) -> some View { let product = productsHitsController.hits[index]! return VStack { @@ -135,15 +135,15 @@ struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { productsHitsController.notifyAppearanceOfHit(atIndex: index) } } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, suggestionsHitsController: controller.suggestionsHitsController, productsHitsController: controller.productsHitsController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -151,5 +151,5 @@ struct MultiIndexDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Paging Multiple Index") } } - + } diff --git a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoViewController.swift b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoViewController.swift index 968cf75e..7155cf00 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoViewController.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/MultiIndexDemoViewController.swift @@ -11,14 +11,14 @@ import InstantSearch import UIKit enum MultiIndexDemoSection: CaseIterable { - + case suggestions case products - + var index: Int { return MultiIndexDemoSection.allCases.firstIndex(of: self)! } - + var title: String { switch self { case .suggestions: @@ -27,17 +27,17 @@ enum MultiIndexDemoSection: CaseIterable { return "Products" } } - + var indexName: IndexName { switch self { case .suggestions: return .ecommerceSuggestions - + case .products: return .ecommerceProducts } } - + var cellIdentifier: String { switch self { case .suggestions: @@ -46,16 +46,16 @@ enum MultiIndexDemoSection: CaseIterable { return "productCell" } } - + } class MultiIndexDemoViewController: UIViewController { - + let searchController: UISearchController let demoController: MultiIndexDemoController let textFieldController: TextFieldController let hitsViewController: MultiIndexHitsViewController - + init() { demoController = .init() hitsViewController = .init() @@ -66,25 +66,25 @@ class MultiIndexDemoViewController: UIViewController { demoController.suggestionsHitsConnector.connectController(hitsViewController.suggestionsCollectionViewController) super.init(nibName: nil, bundle: nil) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + } private extension MultiIndexDemoViewController { - + func setupUI() { view.backgroundColor = .systemBackground definesPresentationContext = true @@ -94,39 +94,39 @@ private extension MultiIndexDemoViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } class ProductsCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, HitsController { - + var hitsSource: HitsInteractor>? - + override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .clear collectionView.register(ProductCollectionViewCell.self, forCellWithReuseIdentifier: MultiIndexDemoSection.products.cellIdentifier) } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 10 } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 10 } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { CGSize(width: collectionView.bounds.width / 2 - 10, height: collectionView.bounds.height - 10) } - + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { hitsSource?.numberOfHits() ?? 0 } - + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MultiIndexDemoSection.products.cellIdentifier, for: indexPath) if let item = hitsSource?.hit(atIndex: indexPath.row) { @@ -134,39 +134,39 @@ class ProductsCollectionViewController: UICollectionViewController, UICollection } return cell } - + } class SuggestionsCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, HitsController { - + var hitsSource: HitsInteractor? - + override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .clear collectionView.register(SuggestionCollectionViewCell.self, forCellWithReuseIdentifier: MultiIndexDemoSection.suggestions.cellIdentifier) } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 10 } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 10 } - + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { CGSize(width: collectionView.bounds.width / 3, height: 40) } - + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { hitsSource?.numberOfHits() ?? 0 } - + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MultiIndexDemoSection.suggestions.cellIdentifier, for: indexPath) if let suggestion = hitsSource?.hit(atIndex: indexPath.row) { @@ -174,73 +174,73 @@ class SuggestionsCollectionViewController: UICollectionViewController, UICollect } return cell } - + } class MultiIndexHitsViewController: UIViewController { - + let suggestionsCollectionViewController: SuggestionsCollectionViewController let productsCollectionViewController: ProductsCollectionViewController - + init() { let productsFlowLayout = UICollectionViewFlowLayout() productsFlowLayout.scrollDirection = .horizontal productsCollectionViewController = .init(collectionViewLayout: productsFlowLayout) - + let suggestionsFlowLayout = UICollectionViewFlowLayout() suggestionsFlowLayout.scrollDirection = .horizontal suggestionsCollectionViewController = .init(collectionViewLayout: suggestionsFlowLayout) - + super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + func setupUI() { view.backgroundColor = UIColor.systemGray6 configureCollectionView() - + addChild(productsCollectionViewController) productsCollectionViewController.didMove(toParent: self) - + addChild(suggestionsCollectionViewController) suggestionsCollectionViewController.didMove(toParent: self) - + suggestionsCollectionViewController.collectionView.heightAnchor.constraint(equalToConstant: 50).isActive = true productsCollectionViewController.collectionView.heightAnchor.constraint(equalToConstant: 300).isActive = true - + let stackView = UIStackView() stackView.translatesAutoresizingMaskIntoConstraints = false stackView.axis = .vertical stackView.spacing = 16 - + let suggestionsTitleLabel = UILabel() suggestionsTitleLabel.text = MultiIndexDemoSection.suggestions.title suggestionsTitleLabel.font = .systemFont(ofSize: 15, weight: .semibold) stackView.addArrangedSubview(suggestionsTitleLabel) stackView.addArrangedSubview(suggestionsCollectionViewController.collectionView) - + let productsTitleLabel = UILabel() productsTitleLabel.text = MultiIndexDemoSection.products.title productsTitleLabel.font = .systemFont(ofSize: 15, weight: .semibold) stackView.addArrangedSubview(productsTitleLabel) stackView.addArrangedSubview(productsCollectionViewController.collectionView) - + stackView.addArrangedSubview(.spacer) - + view.addSubview(stackView) stackView.layoutMargins = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12) stackView.isLayoutMarginsRelativeArrangement = true stackView.pin(to: view.safeAreaLayoutGuide, insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)) } - + func configureCollectionView() { [ productsCollectionViewController, @@ -250,5 +250,5 @@ class MultiIndexHitsViewController: UIViewController { controller.view?.backgroundColor = .clear } } - + } diff --git a/Examples/Showcase/Search/PaginationMultiIndex/SceneDelegate.swift b/Examples/Showcase/Search/PaginationMultiIndex/SceneDelegate.swift index 9e9627f8..2dad9669 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/SceneDelegate.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(MultiIndexDemoViewController(), for: scene) } } - diff --git a/Examples/Showcase/Search/PaginationMultiIndex/SuggestionCollectionViewCell.swift b/Examples/Showcase/Search/PaginationMultiIndex/SuggestionCollectionViewCell.swift index bf65f34d..e2e3cc89 100644 --- a/Examples/Showcase/Search/PaginationMultiIndex/SuggestionCollectionViewCell.swift +++ b/Examples/Showcase/Search/PaginationMultiIndex/SuggestionCollectionViewCell.swift @@ -11,19 +11,19 @@ import UIKit import InstantSearchCore class SuggestionCollectionViewCell: UICollectionViewCell { - + let label: UILabel - + override init(frame: CGRect) { self.label = UILabel(frame: .zero) super.init(frame: frame) layout() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private func layout() { contentView.backgroundColor = .systemBackground contentView.layer.cornerRadius = 12 @@ -33,11 +33,11 @@ class SuggestionCollectionViewCell: UICollectionViewCell { contentView.addSubview(label) label.pin(to: contentView.layoutMarginsGuide) } - + } extension SuggestionCollectionViewCell { - + func setup(with querySuggestion: QuerySuggestion) { label.attributedText = querySuggestion .highlighted @@ -47,5 +47,5 @@ extension SuggestionCollectionViewCell { attributes: [.foregroundColor: UIColor.tintColor]) } } - + } diff --git a/Examples/Showcase/Search/PaginationSingleIndex/AppDelegate.swift b/Examples/Showcase/Search/PaginationSingleIndex/AppDelegate.swift index 7e9c9e12..a923cf90 100644 --- a/Examples/Showcase/Search/PaginationSingleIndex/AppDelegate.swift +++ b/Examples/Showcase/Search/PaginationSingleIndex/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Search/PaginationSingleIndex/SceneDelegate.swift b/Examples/Showcase/Search/PaginationSingleIndex/SceneDelegate.swift index 6ea4bd2c..df4fccd0 100644 --- a/Examples/Showcase/Search/PaginationSingleIndex/SceneDelegate.swift +++ b/Examples/Showcase/Search/PaginationSingleIndex/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoSwiftUI.swift b/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoSwiftUI.swift index 686d37df..4002299d 100644 --- a/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoSwiftUI.swift +++ b/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoSwiftUI.swift @@ -11,15 +11,15 @@ import InstantSearchCore import InstantSearchSwiftUI struct SearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: EcommerceDemoController let hitsController: HitsObservableController> let searchBoxController: SearchBoxObservableController let statsController: StatsTextObservableController let loadingController: LoadingObservableController - + init(searchTriggeringMode: SearchTriggeringMode) { demoController = EcommerceDemoController(searchTriggeringMode: searchTriggeringMode) hitsController = HitsObservableController() @@ -32,16 +32,16 @@ struct SearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.loadingConnector.connectController(loadingController) demoController.searcher.search() } - + } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController> @ObservedObject var statsController: StatsTextObservableController @ObservedObject var loadingController: LoadingObservableController - + var body: some View { VStack { HStack { @@ -52,7 +52,7 @@ struct SearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { } } .padding(.horizontal, 20) - HitsList(hitsController) { (hit, index) in + HitsList(hitsController) { (hit, _) in ProductRow(storeItemHit: hit!) .padding() .frame(height: 100) @@ -68,28 +68,28 @@ struct SearchDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .padding(.horizontal, 15) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, hitsController: controller.hitsController, statsController: controller.statsController, loadingController: controller.loadingController) } - + static func viewController(searchTriggeringMode: SearchTriggeringMode) -> UIViewController { let controller = Controller(searchTriggeringMode: searchTriggeringMode) let contentView = contentView(with: controller) return CommonSwiftUIDemoViewController(controller: controller, rootView: contentView) } - + static let controller = Controller(searchTriggeringMode: .searchAsYouType) static var previews: some View { NavigationView { contentView(with: controller) } } - + } diff --git a/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoViewController.swift b/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoViewController.swift index 79b7159b..953c2391 100644 --- a/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoViewController.swift +++ b/Examples/Showcase/Search/PaginationSingleIndex/SearchDemoViewController.swift @@ -11,12 +11,12 @@ import UIKit import InstantSearch class SearchDemoViewController: UIViewController { - + let demoController: EcommerceDemoController let searchController: UISearchController let textFieldController: TextFieldController let resultsViewController: ResultsViewController - + init(searchTriggeringMode: SearchTriggeringMode = .searchAsYouType) { demoController = EcommerceDemoController(searchTriggeringMode: searchTriggeringMode) resultsViewController = .init(searcher: demoController.searcher) @@ -24,11 +24,11 @@ class SearchDemoViewController: UIViewController { textFieldController = .init(searchBar: searchController.searchBar) super.init(nibName: .none, bundle: .none) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() @@ -36,12 +36,12 @@ class SearchDemoViewController: UIViewController { demoController.hitsInteractor.connectController(resultsViewController.hitsViewController) demoController.searcher.search() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + private func setupUI() { title = "Search" view.backgroundColor = .systemBackground @@ -51,5 +51,5 @@ class SearchDemoViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } diff --git a/Examples/Showcase/Sort/RelevantSort/AppDelegate.swift b/Examples/Showcase/Sort/RelevantSort/AppDelegate.swift index 724aa3b8..aca60850 100644 --- a/Examples/Showcase/Sort/RelevantSort/AppDelegate.swift +++ b/Examples/Showcase/Sort/RelevantSort/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoController.swift b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoController.swift index e56cb749..578d84fa 100644 --- a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoController.swift +++ b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoController.swift @@ -10,14 +10,14 @@ import Foundation import InstantSearch class RelevantSortDemoController { - + let searcher: HitsSearcher let searchBoxConnector: SearchBoxConnector let hitsConnector: HitsConnector> let sortByConnector: SortByConnector let relevantSortConnector: RelevantSortConnector let statsConnector: StatsConnector - + init() { let indices: [IndexName] = [ "test_Bestbuy", @@ -36,7 +36,7 @@ class RelevantSortDemoController { self.statsConnector = .init(searcher: searcher) searcher.search() } - + func title(for indexName: IndexName) -> String { switch indexName { case "test_Bestbuy": @@ -49,5 +49,5 @@ class RelevantSortDemoController { return indexName.rawValue } } - + } diff --git a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoSwiftUI.swift b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoSwiftUI.swift index ed725952..5bee1814 100644 --- a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoSwiftUI.swift +++ b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoSwiftUI.swift @@ -12,16 +12,16 @@ import InstantSearchSwiftUI import SwiftUI struct RelevantSortDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let relevantSortController: RelevantSortObservableController let sortByController: SelectableSegmentObservableController let hitsController: HitsObservableController> let searchBoxController: SearchBoxObservableController let statsController: StatsTextObservableController let demoController: RelevantSortDemoController - + init() { relevantSortController = RelevantSortObservableController() sortByController = SelectableSegmentObservableController() @@ -36,19 +36,19 @@ struct RelevantSortDemoSwiftUI: SwiftUIDemo, PreviewProvider { demoController.searchBoxConnector.connectController(searchBoxController) demoController.statsConnector.connectController(statsController) } - + } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var sortByController: SelectableSegmentObservableController @ObservedObject var relevantSortController: RelevantSortObservableController @ObservedObject var hitsController: HitsObservableController> @ObservedObject var statsController: StatsTextObservableController - + @State var isEditing: Bool = false - + var body: some View { VStack { HStack { @@ -89,18 +89,18 @@ struct RelevantSortDemoSwiftUI: SwiftUIDemo, PreviewProvider { .padding() .searchable(text: $searchBoxController.query) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, sortByController: controller.sortByController, relevantSortController: controller.relevantSortController, hitsController: controller.hitsController, statsController: controller.statsController) - + } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -108,6 +108,5 @@ struct RelevantSortDemoSwiftUI: SwiftUIDemo, PreviewProvider { .navigationBarTitle("Relevant Sort") } } - - + } diff --git a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoViewController.swift b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoViewController.swift index 3096fe02..1194f0ae 100644 --- a/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoViewController.swift +++ b/Examples/Showcase/Sort/RelevantSort/RelevantSortDemoViewController.swift @@ -11,15 +11,15 @@ import InstantSearch import UIKit class RelevantSortDemoViewController: UIViewController { - + let demoController: RelevantSortDemoController let searchController: UISearchController let textFieldController: TextFieldController let resultsViewController: RelevantSortResultsViewController - + var onClick: ((Int) -> Void)? - + init() { resultsViewController = .init() self.searchController = .init(searchResultsController: resultsViewController) @@ -29,21 +29,21 @@ class RelevantSortDemoViewController: UIViewController { demoController.sortByConnector.connectController(self, presenter: demoController.title(for:)) setup() } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + private func setup() { searchController.searchBar.delegate = self demoController.searchBoxConnector.connectController(textFieldController) @@ -51,7 +51,7 @@ class RelevantSortDemoViewController: UIViewController { demoController.hitsConnector.connectController(resultsViewController.hitsController) demoController.statsConnector.connectController(resultsViewController.statsController) } - + private func setupUI() { view.backgroundColor = .systemBackground definesPresentationContext = true @@ -60,27 +60,27 @@ class RelevantSortDemoViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + } extension RelevantSortDemoViewController: UISearchBarDelegate { - + func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { onClick?(selectedScope) } - + } extension RelevantSortDemoViewController: SelectableSegmentController { - + func setSelected(_ selected: Int?) { if let index = selected { searchController.searchBar.selectedScopeButtonIndex = index } } - - func setItems(items: [Int : String]) { + + func setItems(items: [Int: String]) { searchController.searchBar.scopeButtonTitles = items.sorted(by: \.key).map(\.value) } - + } diff --git a/Examples/Showcase/Sort/RelevantSort/RelevantSortResultsViewController.swift b/Examples/Showcase/Sort/RelevantSort/RelevantSortResultsViewController.swift index d47ccb49..55bdbe0f 100644 --- a/Examples/Showcase/Sort/RelevantSort/RelevantSortResultsViewController.swift +++ b/Examples/Showcase/Sort/RelevantSort/RelevantSortResultsViewController.swift @@ -10,7 +10,7 @@ import UIKit import InstantSearch class RelevantSortResultsViewController: UIViewController { - + let hitsController: ProductsTableViewController let relevantSortController: RelevantSortToggleController let statsController: LabelStatsController @@ -21,16 +21,16 @@ class RelevantSortResultsViewController: UIViewController { statsController = .init(label: .init()) super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setupUI() } - + private func setupUI() { let infoStackView = UIStackView() infoStackView.spacing = 5 @@ -38,13 +38,13 @@ class RelevantSortResultsViewController: UIViewController { infoStackView.isLayoutMarginsRelativeArrangement = true infoStackView.axis = .vertical infoStackView.translatesAutoresizingMaskIntoConstraints = false - + statsController.label.translatesAutoresizingMaskIntoConstraints = false infoStackView.addArrangedSubview(statsController.label) relevantSortController.view.translatesAutoresizingMaskIntoConstraints = false infoStackView.addArrangedSubview(relevantSortController.view) - + let stackView = UIStackView() stackView.translatesAutoresizingMaskIntoConstraints = false stackView.axis = .vertical @@ -53,11 +53,11 @@ class RelevantSortResultsViewController: UIViewController { stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) stackView.addArrangedSubview(infoStackView) stackView.addArrangedSubview(hitsController.view) } - + } diff --git a/Examples/Showcase/Sort/RelevantSort/RelevantSortToggleController.swift b/Examples/Showcase/Sort/RelevantSort/RelevantSortToggleController.swift index a7e936dc..b290399e 100644 --- a/Examples/Showcase/Sort/RelevantSort/RelevantSortToggleController.swift +++ b/Examples/Showcase/Sort/RelevantSort/RelevantSortToggleController.swift @@ -11,27 +11,27 @@ import UIKit import InstantSearch class RelevantSortToggleController: UIViewController, RelevantSortController { - + var didToggle: (() -> Void)? - + let label: UILabel let button: UIButton - + init() { self.label = .init() self.button = .init() super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() layout() } - + func layout() { label.numberOfLines = 2 label.translatesAutoresizingMaskIntoConstraints = false @@ -63,9 +63,9 @@ class RelevantSortToggleController: UIViewController, RelevantSortController { label.text = item.hintText button.setTitle(item.toggleTitle, for: .normal) } - + @objc func didTapButton() { didToggle?() } - + } diff --git a/Examples/Showcase/Sort/RelevantSort/SceneDelegate.swift b/Examples/Showcase/Sort/RelevantSort/SceneDelegate.swift index 7a23f1d9..50d768ee 100644 --- a/Examples/Showcase/Sort/RelevantSort/SceneDelegate.swift +++ b/Examples/Showcase/Sort/RelevantSort/SceneDelegate.swift @@ -18,4 +18,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Sort/RelevantSort/SortByController.swift b/Examples/Showcase/Sort/RelevantSort/SortByController.swift index 5871660f..66c56af6 100644 --- a/Examples/Showcase/Sort/RelevantSort/SortByController.swift +++ b/Examples/Showcase/Sort/RelevantSort/SortByController.swift @@ -11,21 +11,21 @@ import UIKit import InstantSearch class SortByController: NSObject, SelectableSegmentController { - + let searchBar: UISearchBar - + var onClick: ((Int) -> Void)? - + init(searchBar: UISearchBar) { self.searchBar = searchBar super.init() self.searchBar.delegate = self } - + func setSelected(_ selected: Int?) { searchBar.selectedScopeButtonIndex = selected ?? 0 } - + func setItems(items: [Int: String]) { searchBar.scopeButtonTitles = items.sorted(by: \.key).map(\.value) } @@ -33,9 +33,9 @@ class SortByController: NSObject, SelectableSegmentController { } extension SortByController: UISearchBarDelegate { - + func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { onClick?(selectedScope) } - + } diff --git a/Examples/Showcase/Sort/SortBy/AppDelegate.swift b/Examples/Showcase/Sort/SortBy/AppDelegate.swift index 21b89f72..1bf38ad8 100644 --- a/Examples/Showcase/Sort/SortBy/AppDelegate.swift +++ b/Examples/Showcase/Sort/SortBy/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Sort/SortBy/SceneDelegate.swift b/Examples/Showcase/Sort/SortBy/SceneDelegate.swift index 72fb4301..7799e60f 100644 --- a/Examples/Showcase/Sort/SortBy/SceneDelegate.swift +++ b/Examples/Showcase/Sort/SortBy/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Sort/SortBy/SortByDemoController.swift b/Examples/Showcase/Sort/SortBy/SortByDemoController.swift index b2b82a4c..f2947eab 100644 --- a/Examples/Showcase/Sort/SortBy/SortByDemoController.swift +++ b/Examples/Showcase/Sort/SortBy/SortByDemoController.swift @@ -10,13 +10,13 @@ import Foundation import InstantSearch class SortByDemoController { - + let searcher: HitsSearcher let searchBoxConnector: SearchBoxConnector let statsConnector: StatsConnector let hitsConnector: HitsConnector> let sortByConnector: SortByConnector - + init() { self.searcher = HitsSearcher(client: .ecommerce, indexName: .ecommerceProducts) @@ -31,7 +31,7 @@ class SortByDemoController { searcher.search() searcher.isDisjunctiveFacetingEnabled = false } - + func title(for indexName: IndexName) -> String { switch indexName { case .ecommerceProducts: @@ -44,5 +44,5 @@ class SortByDemoController { return indexName.rawValue } } - + } diff --git a/Examples/Showcase/Sort/SortBy/SortByDemoSwiftUI.swift b/Examples/Showcase/Sort/SortBy/SortByDemoSwiftUI.swift index f08cb89b..0097d6d8 100644 --- a/Examples/Showcase/Sort/SortBy/SortByDemoSwiftUI.swift +++ b/Examples/Showcase/Sort/SortBy/SortByDemoSwiftUI.swift @@ -12,34 +12,34 @@ import InstantSearchSwiftUI import SwiftUI struct SortByDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: SortByDemoController let searchBoxController: SearchBoxObservableController let selectableSegmentObservableController: SelectableSegmentObservableController let hitsController: HitsObservableController> - + init() { demoController = SortByDemoController() searchBoxController = SearchBoxObservableController() selectableSegmentObservableController = SelectableSegmentObservableController() hitsController = HitsObservableController>() - + demoController.searchBoxConnector.connectController(searchBoxController) demoController.hitsConnector.connectController(hitsController) demoController.sortByConnector.connectController(selectableSegmentObservableController, presenter: demoController.title(for:)) } - + } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var selectableSegmentObservableController: SelectableSegmentObservableController @ObservedObject var hitsController: HitsObservableController> - + var body: some View { let selectedBinding = Binding( get: { self.selectableSegmentObservableController.selectedSegmentIndex ?? 0 }, @@ -55,7 +55,7 @@ struct SortByDemoSwiftUI: SwiftUIDemo, PreviewProvider { } } .pickerStyle(.segmented) - HitsList(hitsController) { hit, index in + HitsList(hitsController) { hit, _ in ProductRow(storeItemHit: hit!) .padding() .frame(height: 100) @@ -65,22 +65,22 @@ struct SortByDemoSwiftUI: SwiftUIDemo, PreviewProvider { .padding(.horizontal, 16) .searchable(text: $searchBoxController.query) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, selectableSegmentObservableController: controller.selectableSegmentObservableController, hitsController: controller.hitsController) } - + static let controller = Controller() static var previews: some View { NavigationView { contentView(with: controller) .navigationBarTitle("Sort By") } - + } - + } diff --git a/Examples/Showcase/Sort/SortBy/SortByDemoViewController.swift b/Examples/Showcase/Sort/SortBy/SortByDemoViewController.swift index a9f64e36..ee5a8bef 100644 --- a/Examples/Showcase/Sort/SortBy/SortByDemoViewController.swift +++ b/Examples/Showcase/Sort/SortBy/SortByDemoViewController.swift @@ -10,15 +10,15 @@ import UIKit import InstantSearch class SortByDemoViewController: UIViewController { - + let demoController: SortByDemoController let searchController: UISearchController let textFieldController: TextFieldController let resultsViewController: ResultsViewController - - var onClick: ((Int) -> Void)? = nil - + + var onClick: ((Int) -> Void)? + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { self.demoController = .init() self.resultsViewController = .init(searcher: demoController.searcher) @@ -36,7 +36,7 @@ class SortByDemoViewController: UIViewController { super.viewDidLoad() setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true @@ -49,7 +49,7 @@ class SortByDemoViewController: UIViewController { demoController.searchBoxConnector.connectController(textFieldController) demoController.sortByConnector.connectController(self, presenter: demoController.title(for:)) } - + private func setupUI() { title = "Sort By" view.backgroundColor = .systemBackground @@ -63,24 +63,23 @@ class SortByDemoViewController: UIViewController { } extension SortByDemoViewController: UISearchBarDelegate { - + func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { onClick?(selectedScope) } - + } extension SortByDemoViewController: SelectableSegmentController { - + func setItems(items: [Int: String]) { searchController.searchBar.scopeButtonTitles = items.sorted(by: \.key).map(\.value) } - func setSelected(_ selected: Int?) { if let index = selected { searchController.searchBar.selectedScopeButtonIndex = index } } - + } diff --git a/Examples/Showcase/Stats/AppDelegate.swift b/Examples/Showcase/Stats/AppDelegate.swift index b5e89517..f9404c65 100644 --- a/Examples/Showcase/Stats/AppDelegate.swift +++ b/Examples/Showcase/Stats/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/Showcase/Stats/SceneDelegate.swift b/Examples/Showcase/Stats/SceneDelegate.swift index 9b9aefa7..bcfaef90 100644 --- a/Examples/Showcase/Stats/SceneDelegate.swift +++ b/Examples/Showcase/Stats/SceneDelegate.swift @@ -16,4 +16,3 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - diff --git a/Examples/Showcase/Stats/StatsDemoController.swift b/Examples/Showcase/Stats/StatsDemoController.swift index f0cce42e..2e8b0433 100644 --- a/Examples/Showcase/Stats/StatsDemoController.swift +++ b/Examples/Showcase/Stats/StatsDemoController.swift @@ -11,7 +11,7 @@ import InstantSearch import UIKit class StatsDemoController { - + let searcher: HitsSearcher let statsConnector: StatsConnector let searchBoxConnector: SearchBoxConnector @@ -23,6 +23,5 @@ class StatsDemoController { self.statsConnector = .init(searcher: searcher) searcher.search() } - - + } diff --git a/Examples/Showcase/Stats/StatsDemoSwiftUI.swift b/Examples/Showcase/Stats/StatsDemoSwiftUI.swift index 71a97bcb..ec9be347 100644 --- a/Examples/Showcase/Stats/StatsDemoSwiftUI.swift +++ b/Examples/Showcase/Stats/StatsDemoSwiftUI.swift @@ -12,13 +12,13 @@ import InstantSearchSwiftUI import SwiftUI struct StatsDemoSwiftUI: SwiftUIDemo, PreviewProvider { - + class Controller { - + let demoController: StatsDemoController let searchBoxController: SearchBoxObservableController let statsController: StatsTextObservableController - + init() { searchBoxController = .init() demoController = .init() @@ -31,16 +31,16 @@ struct StatsDemoSwiftUI: SwiftUIDemo, PreviewProvider { return "\(stats.totalHitsCount) hits in \(stats.processingTimeMS) ms" } } - + } - + struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var statsController: StatsTextObservableController - + var body: some View { - VStack() { + VStack { Text(statsController.stats) .padding() Text(statsController.stats) @@ -50,14 +50,14 @@ struct StatsDemoSwiftUI: SwiftUIDemo, PreviewProvider { } .searchable(text: $searchBoxController.query) } - + } - + static func contentView(with controller: Controller) -> ContentView { ContentView(searchBoxController: controller.searchBoxController, statsController: controller.statsController) } - + static let controller = Controller() static var previews: some View { NavigationView { @@ -66,4 +66,3 @@ struct StatsDemoSwiftUI: SwiftUIDemo, PreviewProvider { } } } - diff --git a/Examples/Showcase/Stats/StatsDemoViewController.swift b/Examples/Showcase/Stats/StatsDemoViewController.swift index 88657257..b9de49e1 100644 --- a/Examples/Showcase/Stats/StatsDemoViewController.swift +++ b/Examples/Showcase/Stats/StatsDemoViewController.swift @@ -11,13 +11,13 @@ import UIKit import InstantSearch class StatsDemoViewController: UIViewController { - + let searchController: UISearchController let controller: StatsDemoController - + let textFieldController: TextFieldController let resultsViewController: ResultsViewController - + init() { self.resultsViewController = ResultsViewController() self.searchController = .init(searchResultsController: resultsViewController) @@ -25,11 +25,11 @@ class StatsDemoViewController: UIViewController { self.controller = .init() super.init(nibName: .none, bundle: .none) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() controller.searchBoxConnector.connectController(textFieldController) @@ -50,12 +50,12 @@ class StatsDemoViewController: UIViewController { } setupUI() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + private func setupUI() { view.backgroundColor = .systemBackground definesPresentationContext = true @@ -65,9 +65,9 @@ class StatsDemoViewController: UIViewController { searchController.showsSearchResultsController = true searchController.automaticallyShowsCancelButton = false } - + class ResultsViewController: UIViewController { - + let stackView: UIStackView let labelStatsController: LabelStatsController let attributedLabelStatsController: AttributedLabelStatsController @@ -78,16 +78,16 @@ class StatsDemoViewController: UIViewController { labelStatsController = LabelStatsController(label: .init()) super.init(nibName: nil, bundle: nil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() configureUI() } - + private func configureUI() { title = "Stats" view.backgroundColor = .systemBackground @@ -107,5 +107,5 @@ class StatsDemoViewController: UIViewController { } } - + } diff --git a/Examples/TVSearch/TVSearch/ContentView.swift b/Examples/TVSearch/TVSearch/ContentView.swift index 9562802a..24402366 100644 --- a/Examples/TVSearch/TVSearch/ContentView.swift +++ b/Examples/TVSearch/TVSearch/ContentView.swift @@ -10,10 +10,10 @@ import InstantSearchCore import InstantSearchSwiftUI struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController> - + var body: some View { HitsList(hitsController) { hit, _ in MovieRow(movieHit: hit!) @@ -25,12 +25,11 @@ struct ContentView: View { } .searchable(text: $searchBoxController.query) } - -} +} struct ContentView_Previews: PreviewProvider { - + static let controller = Controller() static var previews: some View { ContentView(searchBoxController: controller.searchBoxController, diff --git a/Examples/TVSearch/TVSearch/Controller.swift b/Examples/TVSearch/TVSearch/Controller.swift index 90125000..959aa798 100644 --- a/Examples/TVSearch/TVSearch/Controller.swift +++ b/Examples/TVSearch/TVSearch/Controller.swift @@ -10,13 +10,13 @@ import InstantSearchCore import InstantSearchSwiftUI class Controller { - + let demoController: MovieDemoController let hitsController: HitsObservableController> let searchBoxController: SearchBoxObservableController let statsController: StatsTextObservableController let loadingController: LoadingObservableController - + init(searchTriggeringMode: SearchTriggeringMode = .searchAsYouType) { demoController = MovieDemoController() hitsController = HitsObservableController() @@ -27,5 +27,5 @@ class Controller { demoController.hitsInteractor.connectController(hitsController) demoController.searcher.search() } - + } diff --git a/Examples/TVSearch/TVSearch/MovieRow.swift b/Examples/TVSearch/TVSearch/MovieRow.swift index 799f2b0e..6887c549 100644 --- a/Examples/TVSearch/TVSearch/MovieRow.swift +++ b/Examples/TVSearch/TVSearch/MovieRow.swift @@ -10,9 +10,9 @@ import InstantSearchCore import SwiftUI struct MovieRow: View { - + let movieHit: Hit - + var body: some View { VStack { HStack { @@ -47,7 +47,7 @@ struct MovieRow: View { Spacer() } } - + } - + } diff --git a/Examples/TVSearch/TVSearch/TVSearchApp.swift b/Examples/TVSearch/TVSearch/TVSearchApp.swift index 324d4461..91be50fb 100644 --- a/Examples/TVSearch/TVSearch/TVSearchApp.swift +++ b/Examples/TVSearch/TVSearch/TVSearchApp.swift @@ -9,7 +9,7 @@ import SwiftUI @main struct TVSearchApp: App { - + let controller = Controller() var body: some Scene { WindowGroup { @@ -17,5 +17,5 @@ struct TVSearchApp: App { hitsController: controller.hitsController) } } - + } diff --git a/Examples/VoiceSearch/AppDelegate.swift b/Examples/VoiceSearch/AppDelegate.swift index 5c308469..a680fbae 100644 --- a/Examples/VoiceSearch/AppDelegate.swift +++ b/Examples/VoiceSearch/AppDelegate.swift @@ -10,8 +10,6 @@ import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -31,6 +29,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - } - diff --git a/Examples/VoiceSearch/SceneDelegate.swift b/Examples/VoiceSearch/SceneDelegate.swift index f1adf9f1..29bc18a3 100644 --- a/Examples/VoiceSearch/SceneDelegate.swift +++ b/Examples/VoiceSearch/SceneDelegate.swift @@ -11,10 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { setMain(VoiceSearchViewController(), for: scene) } } - diff --git a/Examples/VoiceSearch/VoiceSearchViewController.swift b/Examples/VoiceSearch/VoiceSearchViewController.swift index a0286846..0dcd0d02 100644 --- a/Examples/VoiceSearch/VoiceSearchViewController.swift +++ b/Examples/VoiceSearch/VoiceSearchViewController.swift @@ -11,18 +11,18 @@ import InstantSearch import InstantSearchVoiceOverlay class VoiceSearchViewController: UIViewController { - + let searchController: UISearchController let searcher: HitsSearcher - + let searchBoxConnector: SearchBoxConnector let textFieldController: TextFieldController - + let hitsConnector: HitsConnector> let searchResultsController: StoreItemsTableViewController - + let voiceOverlayController: VoiceOverlayController - + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { searcher = .init(client: .ecommerce, indexName: .ecommerceProducts) @@ -36,21 +36,21 @@ class VoiceSearchViewController: UIViewController { voiceOverlayController = .init() super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } - + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() setup() } - + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) searchController.isActive = true } - + private func setup() { title = "Voice Search" view.backgroundColor = .systemBackground @@ -63,7 +63,7 @@ class VoiceSearchViewController: UIViewController { searchController.searchBar.delegate = self searcher.search() } - + private func present(_ error: Error) { let alertController = UIAlertController(title: "Error", message: error.localizedDescription, @@ -75,13 +75,13 @@ class VoiceSearchViewController: UIViewController { animated: true, completion: nil) } - + } extension VoiceSearchViewController: UISearchBarDelegate { - + func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) { - voiceOverlayController.start(on: self.navigationController!) { [weak self] (text, isFinal, _) in + voiceOverlayController.start(on: self.navigationController!) { [weak self] (text, _, _) in self?.searchBoxConnector.interactor.query = text } errorHandler: { error in guard let error = error else { return } @@ -90,5 +90,5 @@ extension VoiceSearchViewController: UISearchBarDelegate { } } } - + } diff --git a/Examples/WatchSearch/WatchSearch WatchKit Extension/ComplicationController.swift b/Examples/WatchSearch/WatchSearch WatchKit Extension/ComplicationController.swift index bfe160a2..9700ffb4 100644 --- a/Examples/WatchSearch/WatchSearch WatchKit Extension/ComplicationController.swift +++ b/Examples/WatchSearch/WatchSearch WatchKit Extension/ComplicationController.swift @@ -7,9 +7,8 @@ import ClockKit - class ComplicationController: NSObject, CLKComplicationDataSource { - + // MARK: - Complication Configuration func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) { @@ -17,41 +16,41 @@ class ComplicationController: NSObject, CLKComplicationDataSource { CLKComplicationDescriptor(identifier: "complication", displayName: "WatchSearch", supportedFamilies: CLKComplicationFamily.allCases) // Multiple complication support can be added here with more descriptors ] - + // Call the handler with the currently supported complication descriptors handler(descriptors) } - + func handleSharedComplicationDescriptors(_ complicationDescriptors: [CLKComplicationDescriptor]) { // Do any necessary work to support these newly shared complication descriptors } // MARK: - Timeline Configuration - + func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { // Call the handler with the last entry date you can currently provide or nil if you can't support future timelines handler(nil) } - + func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) { // Call the handler with your desired behavior when the device is locked handler(.showOnLockScreen) } // MARK: - Timeline Population - + func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) { // Call the handler with the current timeline entry handler(nil) } - + func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { // Call the handler with the timeline entries after the given date handler(nil) } // MARK: - Sample Templates - + func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { // This method will be called once per supported complication, and the results will be cached handler(nil) diff --git a/Examples/WatchSearch/WatchSearch WatchKit Extension/ContentView.swift b/Examples/WatchSearch/WatchSearch WatchKit Extension/ContentView.swift index 314a1f0d..878b52bf 100644 --- a/Examples/WatchSearch/WatchSearch WatchKit Extension/ContentView.swift +++ b/Examples/WatchSearch/WatchSearch WatchKit Extension/ContentView.swift @@ -10,10 +10,10 @@ import InstantSearchSwiftUI import SwiftUI struct ContentView: View { - + @ObservedObject var searchBoxController: SearchBoxObservableController @ObservedObject var hitsController: HitsObservableController> - + var body: some View { NavigationView { HitsList(hitsController) { hit, _ in @@ -27,18 +27,18 @@ struct ContentView: View { } .searchable(text: $searchBoxController.query) } - + } struct ContentView_Previews: PreviewProvider { - + static let controller = Controller() - + static var previews: some View { ContentView(searchBoxController: controller.searchBoxController, hitsController: controller.hitsController) .navigationBarTitle("Algolia") - + } - + } diff --git a/Examples/WatchSearch/WatchSearch WatchKit Extension/Controller.swift b/Examples/WatchSearch/WatchSearch WatchKit Extension/Controller.swift index c3039aea..4a31efeb 100644 --- a/Examples/WatchSearch/WatchSearch WatchKit Extension/Controller.swift +++ b/Examples/WatchSearch/WatchSearch WatchKit Extension/Controller.swift @@ -10,11 +10,11 @@ import InstantSearchCore import InstantSearchSwiftUI class Controller { - + let demoController: MovieDemoController let hitsController: HitsObservableController> let searchBoxController: SearchBoxObservableController - + init(searchTriggeringMode: SearchTriggeringMode = .searchAsYouType) { demoController = MovieDemoController() hitsController = HitsObservableController() @@ -23,5 +23,5 @@ class Controller { demoController.hitsInteractor.connectController(hitsController) demoController.searcher.search() } - + } diff --git a/Examples/WatchSearch/WatchSearch WatchKit Extension/MovieRow.swift b/Examples/WatchSearch/WatchSearch WatchKit Extension/MovieRow.swift index c6394b42..ee9753d9 100644 --- a/Examples/WatchSearch/WatchSearch WatchKit Extension/MovieRow.swift +++ b/Examples/WatchSearch/WatchSearch WatchKit Extension/MovieRow.swift @@ -10,9 +10,9 @@ import InstantSearchCore import SwiftUI struct MovieRow: View { - + let movieHit: Hit - + var body: some View { HStack(alignment: .top, spacing: 8) { AsyncImage(url: movieHit.object.imageURL, @@ -45,5 +45,5 @@ struct MovieRow: View { Spacer() } } - + } diff --git a/Examples/WatchSearch/WatchSearch WatchKit Extension/WatchSearchApp.swift b/Examples/WatchSearch/WatchSearch WatchKit Extension/WatchSearchApp.swift index b024ac3f..593487b3 100644 --- a/Examples/WatchSearch/WatchSearch WatchKit Extension/WatchSearchApp.swift +++ b/Examples/WatchSearch/WatchSearch WatchKit Extension/WatchSearchApp.swift @@ -9,9 +9,9 @@ import SwiftUI @main struct WatchSearchApp: App { - + let controller = Controller() - + @SceneBuilder var body: some Scene { WindowGroup { NavigationView { @@ -19,7 +19,7 @@ struct WatchSearchApp: App { hitsController: controller.hitsController) } } - + WKNotificationScene(controller: NotificationController.self, category: "myCategory") } } diff --git a/Package.swift b/Package.swift index 93d10522..d1a2ef8b 100644 --- a/Package.swift +++ b/Package.swift @@ -55,7 +55,7 @@ let package = Package( .copy("Misc/disjunctiveHierarchical.json"), .copy("Misc/hierarchical.json"), .copy("Misc/SearchResultFacets.json"), - .copy("Misc/SearchResultFacets2.json"), + .copy("Misc/SearchResultFacets2.json") ]), .target( name: "InstantSearch", @@ -69,6 +69,6 @@ let package = Package( .testTarget( name: "InstantSearchSwiftUITests", dependencies: ["InstantSearchSwiftUI"]) - + ] ) diff --git a/Sources/InstantSearchCore/AdvancedConnectors/SearchConnector.swift b/Sources/InstantSearchCore/AdvancedConnectors/SearchConnector.swift index d477143b..2da71b69 100644 --- a/Sources/InstantSearchCore/AdvancedConnectors/SearchConnector.swift +++ b/Sources/InstantSearchCore/AdvancedConnectors/SearchConnector.swift @@ -22,25 +22,25 @@ import Foundation Most of the components associated by this connector are created and connected automatically, it's only required to provide a proper `Controller` implementations. */ public struct SearchConnector: Connection { - + /// Connector establishing the linkage between searcher, hits interactor and optionally filter state public let hitsConnector: HitsConnector - + /// Connection between hits interactor of hits connector and provided hits controller public let hitsControllerConnection: Connection - + /// Connector establishing the linkage between searcher and search box interactor public let searchBoxConnector: SearchBoxConnector - + /// Connection between query input interactor of search box connector and provided search box controller public let searchBoxControllerConnection: Connection - + /// Connection between filter state and hits interactor of hits connector public let filterStateHitsInteractorConnection: Connection? - + /// Connection between filter state and searcher public let filterStateSearcherConnection: Connection? - + /** - Parameters: - searcher: External single index sercher @@ -58,10 +58,10 @@ public struct SearchConnector: Connection { filterState: FilterState? = nil) where HC.DataSource == HitsInteractor { hitsConnector = .init(searcher: searcher, interactor: hitsInteractor, filterState: filterState) searchBoxConnector = .init(searcher: searcher, interactor: searchBoxInteractor) - + searchBoxControllerConnection = searchBoxInteractor.connectController(searchBoxController) hitsControllerConnection = hitsInteractor.connectController(hitsController) - + if let filterState = filterState { filterStateHitsInteractorConnection = hitsInteractor.connectFilterState(filterState) filterStateSearcherConnection = searcher.connectFilterState(filterState) @@ -69,13 +69,13 @@ public struct SearchConnector: Connection { filterStateHitsInteractorConnection = nil filterStateSearcherConnection = nil } - + Telemetry.shared.traceConnector(type: .hitsSearcher, parameters: [ filterState == nil ? .none : .filterState ]) } - + /** - Parameters: - appID: Application ID @@ -104,7 +104,7 @@ public struct SearchConnector: Connection { hitsInteractor: hitsInteractor, hitsController: hitsController, filterState: filterState) - + Telemetry.shared.traceConnector(type: .hitsSearcher, parameters: [ .appID, @@ -113,7 +113,7 @@ public struct SearchConnector: Connection { filterState == nil ? .none : .filterStateParameter ]) } - + public func connect() { disconnect() searchBoxConnector.connect() @@ -123,7 +123,7 @@ public struct SearchConnector: Connection { filterStateSearcherConnection?.connect() filterStateHitsInteractorConnection?.connect() } - + public func disconnect() { searchBoxConnector.disconnect() searchBoxControllerConnection.disconnect() @@ -132,26 +132,26 @@ public struct SearchConnector: Connection { filterStateSearcherConnection?.disconnect() filterStateHitsInteractorConnection?.disconnect() } - + } @available(*, deprecated, renamed: "SearchConnector") public typealias SingleIndexSearchConnector = SearchConnector public extension SearchConnector { - + /// Connector establishing the linkage between searcher and query input interactor @available(*, deprecated, renamed: "searchBoxConnector") var queryInputConnector: QueryInputConnector { searchBoxConnector } - + /// Connection between query input interactor of query input connector and provided query input controller @available(*, deprecated, renamed: "searchBoxControllerConnection") var queryInputControllerConnection: Connection { searchBoxControllerConnection } - + /** - Parameters: - searcher: External single index sercher @@ -175,7 +175,7 @@ public extension SearchConnector { hitsController: hitsController, filterState: filterState) } - + /** - Parameters: - appID: Application ID @@ -205,5 +205,5 @@ public extension SearchConnector { hitsController: hitsController, filterState: filterState) } - + } diff --git a/Sources/InstantSearchCore/Common/Number/Boundable.swift b/Sources/InstantSearchCore/Common/Number/Boundable.swift index 359c9e16..9a1837c1 100644 --- a/Sources/InstantSearchCore/Common/Number/Boundable.swift +++ b/Sources/InstantSearchCore/Common/Number/Boundable.swift @@ -9,7 +9,7 @@ import Foundation public protocol Boundable: AnyObject { - associatedtype Number: Comparable & DoubleRepresentable + associatedtype Number: Comparable, DoubleRepresentable func applyBounds(bounds: ClosedRange?) } diff --git a/Sources/InstantSearchCore/SearchBox/Connector/SearchBoxConnector+Controller.swift b/Sources/InstantSearchCore/SearchBox/Connector/SearchBoxConnector+Controller.swift index 1fa9b1ea..0daf2f87 100644 --- a/Sources/InstantSearchCore/SearchBox/Connector/SearchBoxConnector+Controller.swift +++ b/Sources/InstantSearchCore/SearchBox/Connector/SearchBoxConnector+Controller.swift @@ -8,7 +8,7 @@ import Foundation public extension SearchBoxConnector { - + /** - Parameters: - searcher: Searcher that handles your searches @@ -25,7 +25,7 @@ public extension SearchBoxConnector { searchTriggeringMode: searchTriggeringMode) connectController(controller) } - + /** Establishes a connection with the controller - Parameters: @@ -37,5 +37,5 @@ public extension SearchBoxConnector { controllerConnections.append(connection) return connection } - + } diff --git a/Sources/InstantSearchCore/Searcher/Multi/MultiSearcher.swift b/Sources/InstantSearchCore/Searcher/Multi/MultiSearcher.swift index 9c0824ae..13f90ae2 100644 --- a/Sources/InstantSearchCore/Searcher/Multi/MultiSearcher.swift +++ b/Sources/InstantSearchCore/Searcher/Multi/MultiSearcher.swift @@ -24,7 +24,7 @@ public class MultiSearcher: AbstractMultiSearcher { initialRequest: initialRequest) Telemetry.shared.trace(type: .multiSearcher) } - + /** - Parameters: - appID: Application ID diff --git a/Sources/InstantSearchSwiftUI/DataModel/CurrentFiltersObservableController.swift b/Sources/InstantSearchSwiftUI/DataModel/CurrentFiltersObservableController.swift index a840cbce..32471650 100644 --- a/Sources/InstantSearchSwiftUI/DataModel/CurrentFiltersObservableController.swift +++ b/Sources/InstantSearchSwiftUI/DataModel/CurrentFiltersObservableController.swift @@ -32,7 +32,7 @@ public class CurrentFiltersObservableController: ObservableObject, CurrentFilter public init(filters: [FilterAndID] = []) { self.filters = filters } - + public func remove(_ filter: FilterAndID) { onRemoveItem?(filter) }