From c6d17e96ab8201edaeb3d73ec9b8012bd5883dec Mon Sep 17 00:00:00 2001 From: Nikita Semenov Date: Wed, 3 Aug 2022 19:57:33 +0300 Subject: [PATCH] fix: remove excessive level of an abstraction --- ...UICollectionViewLayout+DefaultLayout.swift | 24 ++-- .../Models/DefaultFilterModel.swift | 0 .../Models/DefaultFilterPropertyValue.swift | 12 +- .../Models/FiltersLayoutConfiguration.swift} | 50 ++----- .../CollectionDirectorRepresenter.swift | 24 ++-- .../Protocols/FilterCollectionItem.swift | 56 ++++---- .../Protocols/FilterItemsDelegate.swift | 8 +- .../FilterPropertyValueRepresenter.swift | 8 +- .../Protocols/FilterRepresenter.swift | 0 .../Protocols/FiltersCollectionHolder.swift | 7 +- .../Protocols/FiltersViewModelProtocol.swift | 49 ++++--- .../Protocols/SelectableCell.swift | 0 .../ViewModels/DefaultCellViewModel.swift | 4 +- .../DefaultFiltersCollectionDirector.swift | 128 ++++++++++++++++++ .../ViewModels/DefaultFiltersViewModel.swift | 81 +++++++++++ .../Views}/BaseFilterCollectionCell.swift | 61 ++------- .../Views}/BaseFilterCollectionItem.swift | 58 ++++---- .../Views}/BaseFiltersCollectionView.swift | 88 ++++++------ .../CollectionViewLayoutProtocol.swift | 27 ---- .../DefaultFiltersCollectionDirector.swift | 128 ------------------ .../ViewModels/DefaultFiltersViewModel.swift | 39 ------ 21 files changed, 398 insertions(+), 454 deletions(-) rename TIUIElements/Sources/{Helpers/Extensions => Filters/Helpers}/UICollectionViewLayout+DefaultLayout.swift (71%) rename TIUIElements/Sources/{Helpers => Filters}/Models/DefaultFilterModel.swift (100%) rename TIUIElements/Sources/{Helpers => Filters}/Models/DefaultFilterPropertyValue.swift (83%) rename TIUIElements/Sources/{Helpers/Models/FiltersCollectionViewLayout.swift => Filters/Models/FiltersLayoutConfiguration.swift} (56%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/CollectionDirectorRepresenter.swift (71%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FilterCollectionItem.swift (58%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FilterItemsDelegate.swift (90%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FilterPropertyValueRepresenter.swift (83%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FilterRepresenter.swift (100%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FiltersCollectionHolder.swift (84%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/FiltersViewModelProtocol.swift (57%) rename TIUIElements/Sources/{Helpers => Filters}/Protocols/SelectableCell.swift (100%) rename TIUIElements/Sources/{Helpers => Filters}/ViewModels/DefaultCellViewModel.swift (88%) create mode 100644 TIUIElements/Sources/Filters/ViewModels/DefaultFiltersCollectionDirector.swift create mode 100644 TIUIElements/Sources/Filters/ViewModels/DefaultFiltersViewModel.swift rename TIUIElements/Sources/{Views/FiltersCollectionView => Filters/Views}/BaseFilterCollectionCell.swift (59%) rename TIUIElements/Sources/{Views/FiltersCollectionView => Filters/Views}/BaseFilterCollectionItem.swift (53%) rename TIUIElements/Sources/{Views/FiltersCollectionView => Filters/Views}/BaseFiltersCollectionView.swift (58%) delete mode 100644 TIUIElements/Sources/Helpers/Protocols/CollectionViewLayoutProtocol.swift delete mode 100644 TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersCollectionDirector.swift delete mode 100644 TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersViewModel.swift diff --git a/TIUIElements/Sources/Helpers/Extensions/UICollectionViewLayout+DefaultLayout.swift b/TIUIElements/Sources/Filters/Helpers/UICollectionViewLayout+DefaultLayout.swift similarity index 71% rename from TIUIElements/Sources/Helpers/Extensions/UICollectionViewLayout+DefaultLayout.swift rename to TIUIElements/Sources/Filters/Helpers/UICollectionViewLayout+DefaultLayout.swift index 966b88c3..6051f722 100644 --- a/TIUIElements/Sources/Helpers/Extensions/UICollectionViewLayout+DefaultLayout.swift +++ b/TIUIElements/Sources/Filters/Helpers/UICollectionViewLayout+DefaultLayout.swift @@ -24,27 +24,33 @@ import UIKit @available(iOS 13, *) public extension UICollectionViewLayout { - - static func makeHorizontalLayout(_ conf: FiltersLayoutConfiguration) -> UICollectionViewLayout { + + static func gridLayout(_ conf: FiltersLayoutConfiguration) -> UICollectionViewLayout { let item = NSCollectionLayoutItem(layoutSize: conf.itemSize) - let group = NSCollectionLayoutGroup.horizontal(layoutSize: conf.groupSize, subitems: [item]) - group.interItemSpacing = conf.itemSpacing + + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), + heightDimension: conf.itemSize.heightDimension) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) + group.interItemSpacing = .fixed(conf.horizontalItemSpacing) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(insets: conf.contentInsets) - section.interGroupSpacing = conf.groupSpacing + section.interGroupSpacing = conf.verticalItemSpacing return UICollectionViewCompositionalLayout(section: section) } - static func makeHorizontalScrollLayout(_ conf: FiltersLayoutConfiguration) -> UICollectionViewLayout { + static func horizontalScrollLayout(_ conf: FiltersLayoutConfiguration) -> UICollectionViewLayout { let item = NSCollectionLayoutItem(layoutSize: conf.itemSize) - let group = NSCollectionLayoutGroup.horizontal(layoutSize: conf.groupSize, subitems: [item]) - group.interItemSpacing = conf.itemSpacing + + let groupSize = NSCollectionLayoutSize(widthDimension: conf.itemSize.widthDimension, + heightDimension: .fractionalHeight(1)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) + group.interItemSpacing = .fixed(conf.horizontalItemSpacing) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(insets: conf.contentInsets) - section.interGroupSpacing = conf.groupSpacing + section.interGroupSpacing = conf.verticalItemSpacing section.orthogonalScrollingBehavior = .continuous return UICollectionViewCompositionalLayout(section: section) diff --git a/TIUIElements/Sources/Helpers/Models/DefaultFilterModel.swift b/TIUIElements/Sources/Filters/Models/DefaultFilterModel.swift similarity index 100% rename from TIUIElements/Sources/Helpers/Models/DefaultFilterModel.swift rename to TIUIElements/Sources/Filters/Models/DefaultFilterModel.swift diff --git a/TIUIElements/Sources/Helpers/Models/DefaultFilterPropertyValue.swift b/TIUIElements/Sources/Filters/Models/DefaultFilterPropertyValue.swift similarity index 83% rename from TIUIElements/Sources/Helpers/Models/DefaultFilterPropertyValue.swift rename to TIUIElements/Sources/Filters/Models/DefaultFilterPropertyValue.swift index e4949884..242ee30c 100644 --- a/TIUIElements/Sources/Helpers/Models/DefaultFilterPropertyValue.swift +++ b/TIUIElements/Sources/Filters/Models/DefaultFilterPropertyValue.swift @@ -32,12 +32,12 @@ public struct DefaultFilterPropertyValue: FilterPropertyValueRepresenter, public var isSelected: Bool - public func convertToViewModel() -> CellViewModelRepresentable { - DefaultCellViewModel(id: id, - title: title, - selectedColor: .green, - insets: .init(top: .zero, left: 8, bottom: .zero, right: 8), - isSelected: isSelected) + public func convertToViewModel() -> FilterCellViewModelRepresentable { + DefaultFilterCellViewModel(id: id, + title: title, + selectedColor: .green, + insets: .init(top: .zero, left: 8, bottom: .zero, right: 8), + isSelected: isSelected) } } diff --git a/TIUIElements/Sources/Helpers/Models/FiltersCollectionViewLayout.swift b/TIUIElements/Sources/Filters/Models/FiltersLayoutConfiguration.swift similarity index 56% rename from TIUIElements/Sources/Helpers/Models/FiltersCollectionViewLayout.swift rename to TIUIElements/Sources/Filters/Models/FiltersLayoutConfiguration.swift index 87ecf53b..1d2fbddc 100644 --- a/TIUIElements/Sources/Helpers/Models/FiltersCollectionViewLayout.swift +++ b/TIUIElements/Sources/Filters/Models/FiltersLayoutConfiguration.swift @@ -22,62 +22,38 @@ import UIKit -@available(iOS 13, *) -public enum FiltersCollectionViewLayout: CollectionViewLayoutProtocol { - case horizontalScroll(FiltersLayoutConfiguration?) - case horizontal(FiltersLayoutConfiguration?) - case custom(UICollectionViewLayout) - - public var collectionViewLayout: UICollectionViewLayout { - switch self { - case let .horizontalScroll(configuration): - return .makeHorizontalScrollLayout(configuration ?? FiltersLayoutConfiguration.horizontalScrollConfiguration) - case let .horizontal(configuration): - return .makeHorizontalLayout(configuration ?? FiltersLayoutConfiguration.horizontalConfiguration) - case let .custom(layout): - return layout - } - } -} - @available(iOS 13, *) public struct FiltersLayoutConfiguration { - + public var itemSize: NSCollectionLayoutSize - public var groupSize: NSCollectionLayoutSize - public var itemSpacing: NSCollectionLayoutSpacing - public var groupSpacing: CGFloat + public var horizontalItemSpacing: CGFloat + public var verticalItemSpacing: CGFloat public var contentInsets: UIEdgeInsets public init(itemSize: NSCollectionLayoutSize = .init(widthDimension: .estimated(32), heightDimension: .estimated(32)), - groupSize: NSCollectionLayoutSize = .init(widthDimension: .fractionalWidth(1), - heightDimension: .estimated(32)), - itemSpacing: NSCollectionLayoutSpacing = .fixed(.zero), - groupSpacing: CGFloat, + horizontalItemSpacing: CGFloat = .zero, + verticalItemSpacing: CGFloat = .zero, contentInsets: UIEdgeInsets) { self.itemSize = itemSize - self.groupSize = groupSize - self.itemSpacing = itemSpacing - self.groupSpacing = groupSpacing + self.horizontalItemSpacing = horizontalItemSpacing + self.verticalItemSpacing = verticalItemSpacing self.contentInsets = contentInsets } } @available(iOS 13, *) extension FiltersLayoutConfiguration { - static let horizontalScrollConfiguration = FiltersLayoutConfiguration(itemSpacing: .fixed(8), - groupSpacing: 16, + static let horizontalScrollConfiguration = FiltersLayoutConfiguration(horizontalItemSpacing: 16, contentInsets: .init(top: .zero, left: 8, bottom: .zero, right: 8)) - static let horizontalConfiguration = FiltersLayoutConfiguration(itemSpacing: .fixed(8), - groupSpacing: 16, - contentInsets: .init(top: .zero, - left: 8, - bottom: .zero, - right: 8)) + static let gridConfiguration = FiltersLayoutConfiguration(verticalItemSpacing: 16, + contentInsets: .init(top: .zero, + left: 8, + bottom: .zero, + right: 8)) } diff --git a/TIUIElements/Sources/Helpers/Protocols/CollectionDirectorRepresenter.swift b/TIUIElements/Sources/Filters/Protocols/CollectionDirectorRepresenter.swift similarity index 71% rename from TIUIElements/Sources/Helpers/Protocols/CollectionDirectorRepresenter.swift rename to TIUIElements/Sources/Filters/Protocols/CollectionDirectorRepresenter.swift index 7708cfcd..a651b3bc 100644 --- a/TIUIElements/Sources/Helpers/Protocols/CollectionDirectorRepresenter.swift +++ b/TIUIElements/Sources/Filters/Protocols/CollectionDirectorRepresenter.swift @@ -22,15 +22,15 @@ import UIKit -public protocol CollectionDirectorRepresenter: UICollectionViewDataSource, UICollectionViewDelegate { - - associatedtype Item - - var collectionView: UICollectionView? { get set } - var delegate: FilterItemsDelegate? { get set } - - func insertItem(_ item: Item, at index: Int) - func deleteItem(at index: Int) - func update(item: Item, at index: Int) - func scrollToItem(at indexPath: IndexPath, animated: Bool) -} +//public protocol CollectionDirectorRepresenter: UICollectionViewDataSource, UICollectionViewDelegate { +// +// associatedtype Item +// +// var collectionView: UICollectionView? { get set } +// var delegate: FilterItemsDelegate? { get set } +// +// func insertItem(_ item: Item, at index: Int) +// func deleteItem(at index: Int) +// func update(item: Item, at index: Int) +// func scrollToItem(at indexPath: IndexPath, animated: Bool) +//} diff --git a/TIUIElements/Sources/Helpers/Protocols/FilterCollectionItem.swift b/TIUIElements/Sources/Filters/Protocols/FilterCollectionItem.swift similarity index 58% rename from TIUIElements/Sources/Helpers/Protocols/FilterCollectionItem.swift rename to TIUIElements/Sources/Filters/Protocols/FilterCollectionItem.swift index 9aaf8f32..d287f9a6 100644 --- a/TIUIElements/Sources/Helpers/Protocols/FilterCollectionItem.swift +++ b/TIUIElements/Sources/Filters/Protocols/FilterCollectionItem.swift @@ -19,31 +19,31 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // - -import TIUIKitCore -import UIKit - -public protocol FilterCollectionItem { - - associatedtype Filter: FilterPropertyValueRepresenter - - var identifier: String { get } - var itemType: AnyClass { get } - var filter: Filter { get set } - - init(filter: Filter, viewModel: CellViewModelRepresentable) - - func register(for collectionView: UICollectionView) - func configure(item: UICollectionViewCell) - func didSelectItem(atIndexPath indexPath: IndexPath, cell: UICollectionViewCell?) -} - -public extension FilterCollectionItem { - var identifier: String { - filter.id - } - - func register(for collectionView: UICollectionView) { - collectionView.register(itemType, forCellWithReuseIdentifier: identifier) - } -} +// +//import TIUIKitCore +//import UIKit +// +//public protocol FilterCollectionItem { +// +// associatedtype Filter: FilterPropertyValueRepresenter +// +// var identifier: String { get } +// var itemType: AnyClass { get } +// var filter: Filter { get set } +// +// init(filter: Filter, viewModel: FilterCellViewModelRepresentable) +// +// func register(for collectionView: UICollectionView) +// func configure(item: UICollectionViewCell) +// func didSelectItem(atIndexPath indexPath: IndexPath, cell: UICollectionViewCell?) +//} +// +//public extension FilterCollectionItem { +// var identifier: String { +// filter.id +// } +// +// func register(for collectionView: UICollectionView) { +// collectionView.register(itemType, forCellWithReuseIdentifier: identifier) +// } +//} diff --git a/TIUIElements/Sources/Helpers/Protocols/FilterItemsDelegate.swift b/TIUIElements/Sources/Filters/Protocols/FilterItemsDelegate.swift similarity index 90% rename from TIUIElements/Sources/Helpers/Protocols/FilterItemsDelegate.swift rename to TIUIElements/Sources/Filters/Protocols/FilterItemsDelegate.swift index 612ca002..32e466d9 100644 --- a/TIUIElements/Sources/Helpers/Protocols/FilterItemsDelegate.swift +++ b/TIUIElements/Sources/Filters/Protocols/FilterItemsDelegate.swift @@ -21,7 +21,7 @@ // import UIKit - -public protocol FilterItemsDelegate: AnyObject { - func didSelectItem(atIndexPath indexPath: IndexPath) -} +// +//public protocol FilterItemsDelegate: AnyObject { +// func didSelectItem(atIndexPath indexPath: IndexPath) +//} diff --git a/TIUIElements/Sources/Helpers/Protocols/FilterPropertyValueRepresenter.swift b/TIUIElements/Sources/Filters/Protocols/FilterPropertyValueRepresenter.swift similarity index 83% rename from TIUIElements/Sources/Helpers/Protocols/FilterPropertyValueRepresenter.swift rename to TIUIElements/Sources/Filters/Protocols/FilterPropertyValueRepresenter.swift index 2641ecba..0e8fda13 100644 --- a/TIUIElements/Sources/Helpers/Protocols/FilterPropertyValueRepresenter.swift +++ b/TIUIElements/Sources/Filters/Protocols/FilterPropertyValueRepresenter.swift @@ -20,14 +20,14 @@ // THE SOFTWARE. // -public protocol FilterPropertyValueRepresenter: CellViewModelConvertable { +public protocol FilterPropertyValueRepresenter: FilterCellViewModelConvertable { var id: String { get } var excludingProperties: [String]? { get } var isSelected: Bool { get set } } -public protocol CellViewModelRepresentable { } +public protocol FilterCellViewModelRepresentable { } -public protocol CellViewModelConvertable { - func convertToViewModel() -> CellViewModelRepresentable +public protocol FilterCellViewModelConvertable { + func convertToViewModel() -> FilterCellViewModelRepresentable } diff --git a/TIUIElements/Sources/Helpers/Protocols/FilterRepresenter.swift b/TIUIElements/Sources/Filters/Protocols/FilterRepresenter.swift similarity index 100% rename from TIUIElements/Sources/Helpers/Protocols/FilterRepresenter.swift rename to TIUIElements/Sources/Filters/Protocols/FilterRepresenter.swift diff --git a/TIUIElements/Sources/Helpers/Protocols/FiltersCollectionHolder.swift b/TIUIElements/Sources/Filters/Protocols/FiltersCollectionHolder.swift similarity index 84% rename from TIUIElements/Sources/Helpers/Protocols/FiltersCollectionHolder.swift rename to TIUIElements/Sources/Filters/Protocols/FiltersCollectionHolder.swift index f9182dac..02aada7d 100644 --- a/TIUIElements/Sources/Helpers/Protocols/FiltersCollectionHolder.swift +++ b/TIUIElements/Sources/Filters/Protocols/FiltersCollectionHolder.swift @@ -24,10 +24,11 @@ import UIKit public protocol FiltersCollectionHolder: AnyObject { - var collectionView: UICollectionView { get set } + var collectionView: UICollectionView { get } var viewModel: DefaultFiltersViewModel? { get set } - func select(_ items: [FilterPropertyValueRepresenter]) - func deselect(_ items: [FilterPropertyValueRepresenter]) + func applyChange(_ changes: [DefaultFiltersViewModel.Change]) func updateView() + func configure(filterCell: UICollectionViewCell, cellViewModel: FilterCellViewModelProtocol) + func registerCells() } diff --git a/TIUIElements/Sources/Helpers/Protocols/FiltersViewModelProtocol.swift b/TIUIElements/Sources/Filters/Protocols/FiltersViewModelProtocol.swift similarity index 57% rename from TIUIElements/Sources/Helpers/Protocols/FiltersViewModelProtocol.swift rename to TIUIElements/Sources/Filters/Protocols/FiltersViewModelProtocol.swift index 759f7a33..7001885a 100644 --- a/TIUIElements/Sources/Helpers/Protocols/FiltersViewModelProtocol.swift +++ b/TIUIElements/Sources/Filters/Protocols/FiltersViewModelProtocol.swift @@ -31,54 +31,51 @@ public protocol FiltersViewModelProtocol: AnyObject { var filtersCollectionHolder: FiltersCollectionHolder? { get set } - func filterItem(atIndexPath indexPath: IndexPath) + func toggleFilter(atIndexPath indexPath: IndexPath) -> (selected: [Filter], deselected: [Filter]) } public extension FiltersViewModelProtocol { - func filterItem(atIndexPath indexPath: IndexPath) { - guard let item = getItemSafely(indexPath.item) else { return } + func toggleFilter(atIndexPath indexPath: IndexPath) -> (selected: [Filter], deselected: [Filter]) { + guard let item = getItemSafely(indexPath.item) else { return ([], []) } - let (s, d) = filterItem(item) - filtersCollectionHolder?.select(s) - filtersCollectionHolder?.deselect(d) - filtersCollectionHolder?.updateView() + return toggleFilter(item) } @discardableResult - private func filterItem(_ item: Filter) -> (selected: [Filter], deselected: [Filter]) { - var itemsToDeselect = [Filter]() - var itemsToSelect = [Filter]() - let selectedItem = selectedFilters.first { selectedItem in - selectedItem.id == item.id + private func toggleFilter(_ filter: Filter) -> (selected: [Filter], deselected: [Filter]) { + var filtersToDeselect = [Filter]() + var filtersToSelect = [Filter]() + let selectedFilter = selectedFilters.first { selectedFilter in + selectedFilter.id == filter.id } - if let selectedItem = selectedItem { - selectedFilters.remove(selectedItem) - itemsToDeselect.append(item) + if let selectedFilter = selectedFilter { + selectedFilters.remove(selectedFilter) + filtersToDeselect.append(filter) } else { - selectedFilters.insert(item) - itemsToSelect.append(item) + selectedFilters.insert(filter) + filtersToSelect.append(filter) - if let itemsToExclude = item.excludingProperties, !itemsToExclude.isEmpty { - for itemIdToExclude in itemsToExclude { - let itemToExclude = selectedFilters.first { item in - item.id == itemIdToExclude + if let filtersToExclude = filter.excludingProperties, !filtersToExclude.isEmpty { + for filtersIdToExclude in filtersToExclude { + let filterToExclude = selectedFilters.first { filter in + filter.id == filtersIdToExclude } - if let itemToExclude = itemToExclude { - let (_, deselected) = filterItem(itemToExclude) - itemsToDeselect.append(contentsOf: deselected) + if let itemToExclude = filterToExclude { + let (_, deselected) = toggleFilter(itemToExclude) + filtersToDeselect.append(contentsOf: deselected) } } } } - return (itemsToSelect, itemsToDeselect) + return (filtersToSelect, filtersToDeselect) } private func getItemSafely(_ index: Int) -> Filter? { - guard index >= 0 && index <= filters.count else { + guard index >= 0 && index < filters.count else { return nil } diff --git a/TIUIElements/Sources/Helpers/Protocols/SelectableCell.swift b/TIUIElements/Sources/Filters/Protocols/SelectableCell.swift similarity index 100% rename from TIUIElements/Sources/Helpers/Protocols/SelectableCell.swift rename to TIUIElements/Sources/Filters/Protocols/SelectableCell.swift diff --git a/TIUIElements/Sources/Helpers/ViewModels/DefaultCellViewModel.swift b/TIUIElements/Sources/Filters/ViewModels/DefaultCellViewModel.swift similarity index 88% rename from TIUIElements/Sources/Helpers/ViewModels/DefaultCellViewModel.swift rename to TIUIElements/Sources/Filters/ViewModels/DefaultCellViewModel.swift index bf7fa001..fa7644a9 100644 --- a/TIUIElements/Sources/Helpers/ViewModels/DefaultCellViewModel.swift +++ b/TIUIElements/Sources/Filters/ViewModels/DefaultCellViewModel.swift @@ -22,7 +22,7 @@ import UIKit -public protocol CellViewModelProtocol: CellViewModelRepresentable { +public protocol FilterCellViewModelProtocol: FilterCellViewModelRepresentable { var id: String { get set } var title: String { get set } var selectedColor: UIColor { get set } @@ -30,7 +30,7 @@ public protocol CellViewModelProtocol: CellViewModelRepresentable { var isSelected: Bool { get set } } -public struct DefaultCellViewModel: CellViewModelProtocol, CellViewModelRepresentable { +public struct DefaultFilterCellViewModel: FilterCellViewModelProtocol, FilterCellViewModelRepresentable { public var id: String public var title: String public var selectedColor: UIColor diff --git a/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersCollectionDirector.swift b/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersCollectionDirector.swift new file mode 100644 index 00000000..b0acfd5a --- /dev/null +++ b/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersCollectionDirector.swift @@ -0,0 +1,128 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +//open class DefaultFiltersCollectionDirector: NSObject, +// CollectionDirectorRepresenter, +// UICollectionViewDataSource, +// UICollectionViewDelegate { +// +// private var _collectionItems: [FilterItem] = [] +// +// public weak var collectionView: UICollectionView? +// public weak var delegate: FilterItemsDelegate? +// +// public var collectionItems: [FilterItem] { +// get { +// _collectionItems +// } +// set { +// _collectionItems = newValue +// collectionView?.reloadData() +// } +// } +// +// public init(collectionView: UICollectionView) { +// super.init() +// +// bind(to: collectionView) +// } +// +// public func insertItem(_ item: FilterItem, at index: Int) { +// collectionItems.insert(item, at: index) +// +// let indexPath = IndexPath(row: index, section: .zero) +// +// guard collectionItems.count != 1 else { +// return +// } +// +// scrollToItem(at: indexPath) +// } +// +// public func deleteItem(at index: Int) { +// collectionItems.remove(at: index) +// +// let indexPath = IndexPath(row: max(index - 1, .zero), section: .zero) +// scrollToItem(at: indexPath) +// } +// +// public func update(item: FilterItem, at index: Int) { +// _collectionItems[index] = item +// } +// +// public func scrollToItem(at indexPath: IndexPath, animated: Bool = true) { +// collectionView?.performBatchUpdates(nil, completion: { [weak self] isReady in +// if isReady { +// self?.collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: animated) +// } +// }) +// } +// +// // MARK: - UICollectionViewDataSource +// +// public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { +// collectionItems.forEach { $0.register(for: collectionView) } +// return collectionItems.count +// } +// +// public func collectionView(_ collectionView: UICollectionView, +// cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { +// +// let viewModel = collectionItems[indexPath.item] +// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.identifier, for: indexPath) +// viewModel.configure(item: cell) +// return cell +// } +// +// // MARK: - UICollectionViewDelegate +// +// public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { +// let cell = collectionView.cellForItem(at: indexPath) +// didSelectItem(atIndexPath: indexPath, cell: cell) +// } +// +// private func didSelectItem(atIndexPath indexPath: IndexPath, +// cell: UICollectionViewCell?) { +// +// guard let item = item(at: indexPath) else { return } +// +// delegate?.didSelectItem(atIndexPath: indexPath) +// +// item.didSelectItem(atIndexPath: indexPath, cell: cell) +// } +// +// private func bind(to collectionView: UICollectionView) { +// self.collectionView = collectionView +// +// collectionView.delegate = self +// collectionView.dataSource = self +// } +// +// private func item(at indexPath: IndexPath) -> FilterItem? { +// let index = indexPath.item +// let amount = collectionItems.count +// +// return (index < amount && index >= 0) ? collectionItems[index] : nil +// } +//} diff --git a/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersViewModel.swift b/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersViewModel.swift new file mode 100644 index 00000000..beb0938d --- /dev/null +++ b/TIUIElements/Sources/Filters/ViewModels/DefaultFiltersViewModel.swift @@ -0,0 +1,81 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +open class DefaultFiltersViewModel: NSObject, + FiltersViewModelProtocol, + UICollectionViewDelegate, + UICollectionViewDataSource { + + public typealias Change = (indexPath: IndexPath, viewModel: FilterCellViewModelProtocol) + + public var filters: [DefaultFilterPropertyValue] + public var selectedFilters: Set = [] + public var cellsViewModels: [FilterCellViewModelProtocol] + + public weak var filtersCollectionHolder: FiltersCollectionHolder? + + public init(filters: [DefaultFilterPropertyValue]) { + self.filters = filters + self.cellsViewModels = filters.compactMap { $0.convertToViewModel() as? FilterCellViewModelProtocol } + } + + // MARK: - UICollectionViewDataSource + + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + filtersCollectionHolder?.registerCells() + return cellsViewModels.count + } + + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + let viewModel = cellsViewModels[indexPath.item] + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.id, for: indexPath) + filtersCollectionHolder?.configure(filterCell: cell, cellViewModel: viewModel) + + return cell + } + + // MARK: - UICollectionViewDelegate + + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let (selected, deselected) = toggleFilter(atIndexPath: indexPath) + + let changedFilters = filters + .enumerated() + .filter { selected.contains($0.element) || deselected.contains($0.element) } + + for (offset, element) in changedFilters { + cellsViewModels[offset].isSelected = selectedFilters.contains(element) + filters[offset].isSelected = selectedFilters.contains(element) + } + + let changedItems = changedFilters + .map { + Change(indexPath: IndexPath(item: $0.offset, section: .zero), + viewModel: cellsViewModels[$0.offset]) + } + + filtersCollectionHolder?.applyChange(changedItems) + } +} diff --git a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionCell.swift b/TIUIElements/Sources/Filters/Views/BaseFilterCollectionCell.swift similarity index 59% rename from TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionCell.swift rename to TIUIElements/Sources/Filters/Views/BaseFilterCollectionCell.swift index 22ab5460..ee1cc6ce 100644 --- a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionCell.swift +++ b/TIUIElements/Sources/Filters/Views/BaseFilterCollectionCell.swift @@ -23,14 +23,15 @@ import UIKit import TIUIKitCore -open class BaseFilterCollectionCell: UICollectionViewCell, +open class BaseFilterCollectionCell: ContainerCollectionViewCell, SelectableCell, - InitializableViewProtocol, ConfigurableView { - public let titleLabel = UILabel() + public override var wrappedView: UILabel { + UILabel() + } - public var viewModel: DefaultCellViewModel? + public var viewModel: DefaultFilterCellViewModel? open var isFilterSelected: Bool = false { didSet { @@ -40,68 +41,28 @@ open class BaseFilterCollectionCell: UICollectionViewCell, open var isLabelHidden: Bool { get { - titleLabel.isHidden + wrappedView.isHidden } set { - titleLabel.isHidden = newValue + wrappedView.isHidden = newValue } } - open override var intrinsicContentSize: CGSize { - let contentSize = super.intrinsicContentSize - let insets = viewModel?.insets ?? .zero - let xInsets = insets.left + insets.right - let yInsets = insets.top + insets.bottom - return .init(width: contentSize.width + xInsets, height: contentSize.height + yInsets) - } - - public override init(frame: CGRect) { - super.init(frame: .zero) - - addViews() - configureLayout() - bindViews() - configureAppearance() - localize() - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - open func addViews() { - addSubview(titleLabel) - } - - open func configureLayout() { - titleLabel.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate(titleLabel.edgesEqualToSuperview()) - } - - open func bindViews() { - // override in subclass - } - - open func configureAppearance() { + open override func configureAppearance() { layer.round(corners: .allCorners, radius: 6) } - open func localize() { - // override in subclass - } - - open func configure(with viewModel: DefaultCellViewModel) { + open func configure(with viewModel: DefaultFilterCellViewModel) { self.viewModel = viewModel - titleLabel.text = viewModel.title + wrappedView.text = viewModel.title setSelected(isSelected: viewModel.isSelected) } open func setSelected(isSelected: Bool) { let selectedColor = viewModel?.selectedColor ?? .green - titleLabel.textColor = isSelected ? selectedColor : .black + wrappedView.textColor = isSelected ? selectedColor : .black if isSelected { backgroundColor = .white diff --git a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionItem.swift b/TIUIElements/Sources/Filters/Views/BaseFilterCollectionItem.swift similarity index 53% rename from TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionItem.swift rename to TIUIElements/Sources/Filters/Views/BaseFilterCollectionItem.swift index 70270900..1e1a7469 100644 --- a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFilterCollectionItem.swift +++ b/TIUIElements/Sources/Filters/Views/BaseFilterCollectionItem.swift @@ -23,33 +23,33 @@ import UIKit import TIUIKitCore -public typealias AnyCollectionCell = SelectableCell & ConfigurableView +//public typealias AnyCollectionCell = SelectableCell & ConfigurableView -open class BaseFilterCollectionItem: FilterCollectionItem where CellType.ViewModelType: CellViewModelRepresentable { - - public var itemType: AnyClass{ - CellType.self - } - - public var filter: Filter - - public var viewModel: CellViewModelRepresentable? - - required public init(filter: Filter, viewModel: CellViewModelRepresentable) { - self.filter = filter - self.viewModel = viewModel - } - - open func configure(item: UICollectionViewCell) { - guard let viewModel = viewModel as? CellType.ViewModelType else { - return - } - - (item as? CellType)?.configure(with: viewModel) - } - - open func didSelectItem(atIndexPath indexPath: IndexPath, cell: UICollectionViewCell?) { - // Override in subviews - } -} +//open class BaseFilterCollectionItem: FilterCollectionItem where CellType.ViewModelType: CellViewModelRepresentable { +// +// public var itemType: AnyClass{ +// CellType.self +// } +// +// public var filter: Filter +// +// public var viewModel: CellViewModelRepresentable? +// +// required public init(filter: Filter, viewModel: CellViewModelRepresentable) { +// self.filter = filter +// self.viewModel = viewModel +// } +// +// open func configure(item: UICollectionViewCell) { +// guard let viewModel = viewModel as? CellType.ViewModelType else { +// return +// } +// +// (item as? CellType)?.configure(with: viewModel) +// } +// +// open func didSelectItem(atIndexPath indexPath: IndexPath, cell: UICollectionViewCell?) { +// // Override in subviews +// } +//} diff --git a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFiltersCollectionView.swift b/TIUIElements/Sources/Filters/Views/BaseFiltersCollectionView.swift similarity index 58% rename from TIUIElements/Sources/Views/FiltersCollectionView/BaseFiltersCollectionView.swift rename to TIUIElements/Sources/Filters/Views/BaseFiltersCollectionView.swift index c8618aee..2c1c7da8 100644 --- a/TIUIElements/Sources/Views/FiltersCollectionView/BaseFiltersCollectionView.swift +++ b/TIUIElements/Sources/Filters/Views/BaseFiltersCollectionView.swift @@ -23,33 +23,25 @@ import TIUIKitCore import UIKit -public typealias DefaultBaseFiltersCollectionView = BaseFiltersCollectionView> +open class BaseFiltersCollectionView: UICollectionView, + InitializableViewProtocol, + ConfigurableView, + FiltersCollectionHolder where CellType.ViewModelType: FilterCellViewModelProtocol { -open class BaseFiltersCollectionView: BaseInitializableView, - ConfigurableView, - FiltersCollectionHolder { - - public typealias Director = DefaultFiltersCollectionDirector - - public var collectionDirector: Director - - public var collectionView: UICollectionView - - public var layout: CollectionViewLayoutProtocol + public var layout: UICollectionViewLayout public weak var viewModel: DefaultFiltersViewModel? - open weak var filtersDelegate: FilterItemsDelegate? + open var collectionView: UICollectionView { + self + } // MARK: - Init - public init(layout: CollectionViewLayoutProtocol) { + public init(layout: UICollectionViewLayout) { self.layout = layout - self.collectionView = .init(frame: .zero, collectionViewLayout: layout.collectionViewLayout) - self.collectionDirector = .init(collectionView: collectionView) - - super.init(frame: .zero) + + super.init(frame: .zero, collectionViewLayout: layout) } required public init?(coder aDecoder: NSCoder) { @@ -58,70 +50,66 @@ open class BaseFiltersCollectionView: BaseInitializa // MARK: - Life cycle - open override func addViews() { - super.addViews() - + open func addViews() { addSubview(collectionView) } - open override func configureLayout() { - super.configureLayout() - + open func configureLayout() { collectionView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate(collectionView.edgesEqualToSuperview()) } - open override func configureAppearance() { - super.configureAppearance() + open func bindViews() { + delegate = viewModel + dataSource = viewModel + } + open func configureAppearance() { backgroundColor = .white collectionView.backgroundColor = .white } + open func localize() { + // override in subclass + } + // MARK: - ConfigurableView open func configure(with viewModel: DefaultFiltersViewModel) { self.viewModel = viewModel viewModel.filtersCollectionHolder = self - collectionDirector.delegate = viewModel updateView() } // MARK: - FiltersCollectionHolder - open func select(_ items: [FilterPropertyValueRepresenter]) { - guard let viewModel = viewModel else { return } - - items.forEach { item in - if let index = viewModel.filters.firstIndex(where: { $0.id == item.id }) { - viewModel.filters[index].isSelected = true + open func applyChange(_ changes: [DefaultFiltersViewModel.Change]) { + for change in changes { + guard let cell = cellForItem(at: change.indexPath) else { + continue } - } - } - open func deselect(_ items: [FilterPropertyValueRepresenter]) { - guard let viewModel = viewModel else { return } - - items.forEach { item in - if let index = viewModel.filters.firstIndex(where: { $0.id == item.id }) { - viewModel.filters[index].isSelected = false - } + configure(filterCell: cell, cellViewModel: change.viewModel) } } open func updateView() { - guard let viewModel = viewModel else { return } + reloadData() + } - collectionDirector.collectionItems = viewModel.filters.compactMap { - guard let filter = $0 as? Cell.Filter else { - return nil - } + open func configure(filterCell: UICollectionViewCell, cellViewModel: FilterCellViewModelProtocol) { + guard let cellViewModel = cellViewModel as? CellType.ViewModelType else { return } - return Cell(filter: filter, viewModel: $0.convertToViewModel()) - } + guard let configurableCell = filterCell as? CellType else { return } + + configurableCell.configure(with: cellViewModel) + } + + open func registerCells() { + viewModel?.filters.forEach { self.register(CellType.self, forCellWithReuseIdentifier: $0.id) } } } diff --git a/TIUIElements/Sources/Helpers/Protocols/CollectionViewLayoutProtocol.swift b/TIUIElements/Sources/Helpers/Protocols/CollectionViewLayoutProtocol.swift deleted file mode 100644 index 805cf967..00000000 --- a/TIUIElements/Sources/Helpers/Protocols/CollectionViewLayoutProtocol.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) 2022 Touch Instinct -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the Software), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import UIKit - -public protocol CollectionViewLayoutProtocol { - var collectionViewLayout: UICollectionViewLayout { get } -} \ No newline at end of file diff --git a/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersCollectionDirector.swift b/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersCollectionDirector.swift deleted file mode 100644 index ef137b8f..00000000 --- a/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersCollectionDirector.swift +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright (c) 2022 Touch Instinct -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the Software), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import UIKit - -open class DefaultFiltersCollectionDirector: NSObject, - CollectionDirectorRepresenter, - UICollectionViewDataSource, - UICollectionViewDelegate { - - private var _collectionItems: [FilterItem] = [] - - public weak var collectionView: UICollectionView? - public weak var delegate: FilterItemsDelegate? - - public var collectionItems: [FilterItem] { - get { - _collectionItems - } - set { - _collectionItems = newValue - collectionView?.reloadData() - } - } - - public init(collectionView: UICollectionView) { - super.init() - - bind(to: collectionView) - } - - public func insertItem(_ item: FilterItem, at index: Int) { - collectionItems.insert(item, at: index) - - let indexPath = IndexPath(row: index, section: .zero) - - guard collectionItems.count != 1 else { - return - } - - scrollToItem(at: indexPath) - } - - public func deleteItem(at index: Int) { - collectionItems.remove(at: index) - - let indexPath = IndexPath(row: max(index - 1, .zero), section: .zero) - scrollToItem(at: indexPath) - } - - public func update(item: FilterItem, at index: Int) { - _collectionItems[index] = item - } - - public func scrollToItem(at indexPath: IndexPath, animated: Bool = true) { - collectionView?.performBatchUpdates(nil, completion: { [weak self] isReady in - if isReady { - self?.collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: animated) - } - }) - } - - // MARK: - UICollectionViewDataSource - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - collectionItems.forEach { $0.register(for: collectionView) } - return collectionItems.count - } - - public func collectionView(_ collectionView: UICollectionView, - cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - - let viewModel = collectionItems[indexPath.item] - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.identifier, for: indexPath) - viewModel.configure(item: cell) - return cell - } - - // MARK: - UICollectionViewDelegate - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let cell = collectionView.cellForItem(at: indexPath) - didSelectItem(atIndexPath: indexPath, cell: cell) - } - - private func didSelectItem(atIndexPath indexPath: IndexPath, - cell: UICollectionViewCell?) { - - guard let item = item(at: indexPath) else { return } - - delegate?.didSelectItem(atIndexPath: indexPath) - - item.didSelectItem(atIndexPath: indexPath, cell: cell) - } - - private func bind(to collectionView: UICollectionView) { - self.collectionView = collectionView - - collectionView.delegate = self - collectionView.dataSource = self - } - - private func item(at indexPath: IndexPath) -> FilterItem? { - let index = indexPath.item - let amount = collectionItems.count - - return (index < amount && index >= 0) ? collectionItems[index] : nil - } -} diff --git a/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersViewModel.swift b/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersViewModel.swift deleted file mode 100644 index 93bdf018..00000000 --- a/TIUIElements/Sources/Helpers/ViewModels/DefaultFiltersViewModel.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2022 Touch Instinct -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the Software), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -import UIKit - -open class DefaultFiltersViewModel: FiltersViewModelProtocol, FilterItemsDelegate { - - public var filters: [DefaultFilterPropertyValue] - public var selectedFilters: Set = [] - - public weak var filtersCollectionHolder: FiltersCollectionHolder? - - public init(filters: [DefaultFilterPropertyValue]) { - self.filters = filters - } - - open func didSelectItem(atIndexPath indexPath: IndexPath) { - filterItem(atIndexPath: indexPath) - } -}