fix: review notes
This commit is contained in:
parent
7bef631668
commit
95a0045582
|
|
@ -27,7 +27,6 @@ public struct DefaultFilterPropertyValue: FilterPropertyValueRepresenter, Identi
|
|||
public let id: String
|
||||
public let title: String
|
||||
public let excludingProperties: [String]?
|
||||
public let cellAppearance: FilterCellAppearanceProtocol
|
||||
|
||||
public var isSelected: Bool
|
||||
}
|
||||
|
|
@ -37,7 +36,6 @@ public extension DefaultFilterPropertyValue {
|
|||
self.id = id
|
||||
self.title = title
|
||||
self.excludingProperties = excludingProperties
|
||||
self.cellAppearance = BaseFilterCellAppearance.defaultFilterCellAppearance
|
||||
self.isSelected = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,6 @@
|
|||
public protocol FilterCellViewModelProtocol {
|
||||
var id: String { get set }
|
||||
var title: String { get set }
|
||||
var appearance: FilterCellAppearanceProtocol { get set }
|
||||
var isSelected: Bool { get set }
|
||||
|
||||
init(id: String,
|
||||
title: String,
|
||||
appearance: FilterCellAppearanceProtocol,
|
||||
isSelected: Bool)
|
||||
var appearance: FilterCellAppearanceProtocol { get }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,5 @@
|
|||
public protocol FilterPropertyValueRepresenter {
|
||||
var id: String { get }
|
||||
var excludingProperties: [String]? { get }
|
||||
var cellAppearance: FilterCellAppearanceProtocol { get }
|
||||
var isSelected: Bool { get set }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
//
|
||||
// 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 Foundation
|
||||
|
||||
public protocol FilterViewModelProtocol: AnyObject {
|
||||
|
||||
associatedtype Property: FilterPropertyValueRepresenter, Hashable
|
||||
associatedtype CellViewModel: FilterCellViewModelProtocol & Hashable
|
||||
|
||||
typealias Change = (indexPath: IndexPath, viewModel: CellViewModel)
|
||||
|
||||
|
||||
var properties: [Property] { get set }
|
||||
var selectedProperties: Set<Property> { get set }
|
||||
|
||||
func filterDidSelected(atIndexPath indexPath: IndexPath) -> [Change]
|
||||
func toggleProperty(atIndexPath indexPath: IndexPath) -> (selected: [Property], deselected: [Property])
|
||||
func getCellsViewModels() -> [CellViewModel]
|
||||
}
|
||||
|
||||
public extension FilterViewModelProtocol {
|
||||
|
||||
func toggleProperty(atIndexPath indexPath: IndexPath) -> (selected: [Property], deselected: [Property]) {
|
||||
guard let item = getPropertySafely(indexPath.item) else { return ([], []) }
|
||||
|
||||
return toggleProperty(item)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func toggleProperty(_ property: Property) -> (selected: [Property], deselected: [Property]) {
|
||||
var propertiesToDeselect = [Property]()
|
||||
var propertiesToSelect = [Property]()
|
||||
let selectedProperty = selectedProperties.first { selectedProperty in
|
||||
selectedProperty.id == property.id
|
||||
}
|
||||
|
||||
if let selectedProperty = selectedProperty {
|
||||
// Removes previously selected filter
|
||||
selectedProperties.remove(selectedProperty)
|
||||
propertiesToDeselect.append(property)
|
||||
} else {
|
||||
// Selectes unselected filter
|
||||
selectedProperties.insert(property)
|
||||
propertiesToSelect.append(property)
|
||||
|
||||
// If the filter has filters to exclude, these filters marks as deselected
|
||||
let excludedProperties = excludeProperties(property)
|
||||
propertiesToDeselect.append(contentsOf: excludedProperties)
|
||||
}
|
||||
|
||||
return (propertiesToSelect, propertiesToDeselect)
|
||||
}
|
||||
|
||||
private func excludeProperties(_ filter: Property) -> [Property] {
|
||||
guard let propertiesToExclude = filter.excludingProperties, !propertiesToExclude.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
||||
var excludedProperties = [Property]()
|
||||
|
||||
for propertiesIdToExclude in propertiesToExclude {
|
||||
let propertyToExclude = selectedProperties.first { property in
|
||||
property.id == propertiesIdToExclude
|
||||
}
|
||||
|
||||
if let propertyToExclude = propertyToExclude {
|
||||
let (_, deselected) = toggleProperty(propertyToExclude)
|
||||
excludedProperties.append(contentsOf: deselected)
|
||||
}
|
||||
}
|
||||
|
||||
return excludedProperties
|
||||
}
|
||||
|
||||
private func getPropertySafely(_ index: Int) -> Property? {
|
||||
guard index >= 0 && index < properties.count else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return properties[index]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +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 Foundation
|
||||
|
||||
public protocol FiltersViewModelProtocol: AnyObject {
|
||||
|
||||
associatedtype Filter: FilterPropertyValueRepresenter, Hashable
|
||||
associatedtype CellViewModel: FilterCellViewModelProtocol & Hashable
|
||||
|
||||
typealias Change = (indexPath: IndexPath, viewModel: CellViewModel)
|
||||
|
||||
var filters: [Filter] { get set }
|
||||
var selectedFilters: Set<Filter> { get set }
|
||||
|
||||
func filterDidSelected(atIndexPath indexPath: IndexPath) -> [Change]
|
||||
func toggleFilter(atIndexPath indexPath: IndexPath) -> (selected: [Filter], deselected: [Filter])
|
||||
}
|
||||
|
||||
public extension FiltersViewModelProtocol {
|
||||
|
||||
func toggleFilter(atIndexPath indexPath: IndexPath) -> (selected: [Filter], deselected: [Filter]) {
|
||||
guard let item = getFilterSafely(indexPath.item) else { return ([], []) }
|
||||
|
||||
return toggleFilter(item)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
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 selectedFilter = selectedFilter {
|
||||
// Removes previously selected filter
|
||||
selectedFilters.remove(selectedFilter)
|
||||
filtersToDeselect.append(filter)
|
||||
} else {
|
||||
// Selectes unselected filter
|
||||
selectedFilters.insert(filter)
|
||||
filtersToSelect.append(filter)
|
||||
|
||||
// If the filter has filters to exclude, these filters marks as deselected
|
||||
let excludedFilters = excludeFilters(filter)
|
||||
filtersToDeselect.append(contentsOf: excludedFilters)
|
||||
}
|
||||
|
||||
return (filtersToSelect, filtersToDeselect)
|
||||
}
|
||||
|
||||
private func excludeFilters(_ filter: Filter) -> [Filter] {
|
||||
guard let filtersToExclude = filter.excludingProperties, !filtersToExclude.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
||||
var excludedFilters = [Filter]()
|
||||
|
||||
for filtersIdToExclude in filtersToExclude {
|
||||
let filterToExclude = selectedFilters.first { filter in
|
||||
filter.id == filtersIdToExclude
|
||||
}
|
||||
|
||||
if let itemToExclude = filterToExclude {
|
||||
let (_, deselected) = toggleFilter(itemToExclude)
|
||||
excludedFilters.append(contentsOf: deselected)
|
||||
}
|
||||
}
|
||||
|
||||
return excludedFilters
|
||||
}
|
||||
|
||||
private func getFilterSafely(_ index: Int) -> Filter? {
|
||||
guard index >= 0 && index < filters.count else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return filters[index]
|
||||
}
|
||||
}
|
||||
|
|
@ -23,52 +23,43 @@
|
|||
import TIUIKitCore
|
||||
import UIKit
|
||||
|
||||
open class DefaultFiltersViewModel<CellViewModelType: FilterCellViewModelProtocol & Hashable>: NSObject,
|
||||
FiltersViewModelProtocol {
|
||||
open class BaseFilterViewModel<CellViewModelType: FilterCellViewModelProtocol & Hashable,
|
||||
PropertyValue: FilterPropertyValueRepresenter & Hashable>: FilterViewModelProtocol {
|
||||
|
||||
// MARK: - FilterViewModelProtocol
|
||||
|
||||
public typealias Property = PropertyValue
|
||||
public typealias CellViewModel = CellViewModelType
|
||||
|
||||
private var cellsViewModels: [CellViewModelType]
|
||||
private var cellsViewModels: [CellViewModelType] = []
|
||||
|
||||
public var filters: [DefaultFilterPropertyValue] {
|
||||
public var properties: [PropertyValue] = [] {
|
||||
didSet {
|
||||
rebuildCellsViewModels()
|
||||
filtersCollection?.updateView()
|
||||
}
|
||||
}
|
||||
|
||||
public var selectedFilters: Set<DefaultFilterPropertyValue> = [] {
|
||||
public var selectedProperties: Set<PropertyValue> = [] {
|
||||
didSet {
|
||||
reselectFilters()
|
||||
rebuildCellsViewModels()
|
||||
filtersCollection?.updateView()
|
||||
}
|
||||
}
|
||||
|
||||
public weak var filtersCollection: UpdatableView?
|
||||
|
||||
public init(filters: [DefaultFilterPropertyValue]) {
|
||||
self.filters = filters
|
||||
self.cellsViewModels = filters.compactMap {
|
||||
CellViewModelType(id: $0.id,
|
||||
title: $0.title,
|
||||
appearance: $0.cellAppearance,
|
||||
isSelected: $0.isSelected)
|
||||
}
|
||||
public init(filters: [PropertyValue]) {
|
||||
self.properties = filters
|
||||
}
|
||||
|
||||
// MARK: - Open methods
|
||||
|
||||
open func filterDidSelected(atIndexPath indexPath: IndexPath) -> [Change] {
|
||||
let (selected, deselected) = toggleFilter(atIndexPath: indexPath)
|
||||
let (selected, deselected) = toggleProperty(atIndexPath: indexPath)
|
||||
|
||||
let changedFilters = filters
|
||||
let changedFilters = properties
|
||||
.enumerated()
|
||||
.filter { isFilterInArray($0.element, filters: selected) || isFilterInArray($0.element, filters: deselected) }
|
||||
|
||||
for (offset, element) in changedFilters {
|
||||
cellsViewModels[offset].isSelected = selectedFilters.contains(element)
|
||||
filters[offset].isSelected = selectedFilters.contains(element)
|
||||
cellsViewModels[offset].isSelected = selectedProperties.contains(element)
|
||||
properties[offset].isSelected = selectedProperties.contains(element)
|
||||
}
|
||||
|
||||
let changedItems = changedFilters
|
||||
|
|
@ -80,30 +71,13 @@ open class DefaultFiltersViewModel<CellViewModelType: FilterCellViewModelProtoco
|
|||
return changedItems
|
||||
}
|
||||
|
||||
open func rebuildCellsViewModels() {
|
||||
cellsViewModels = filters.compactMap {
|
||||
CellViewModelType(id: $0.id,
|
||||
title: $0.title,
|
||||
appearance: $0.cellAppearance,
|
||||
isSelected: $0.isSelected)
|
||||
}
|
||||
open func getCellsViewModels() -> [CellViewModelType] {
|
||||
cellsViewModels
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
public func getCellsViewModels() -> [FilterCellViewModelProtocol] {
|
||||
cellsViewModels
|
||||
}
|
||||
|
||||
public func isFilterInArray(_ filter: DefaultFilterPropertyValue, filters: [DefaultFilterPropertyValue]) -> Bool {
|
||||
public func isFilterInArray(_ filter: PropertyValue, filters: [PropertyValue]) -> Bool {
|
||||
filters.contains(where: { $0.id == filter.id })
|
||||
}
|
||||
|
||||
public func reselectFilters() {
|
||||
let selectedFilters = Array(selectedFilters)
|
||||
|
||||
filters.enumerated().forEach {
|
||||
filters[$0.offset].isSelected = isFilterInArray($0.element, filters: selectedFilters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,17 +24,18 @@ public struct DefaultFilterCellViewModel: FilterCellViewModelProtocol, Hashable
|
|||
|
||||
public var id: String
|
||||
public var title: String
|
||||
public var appearance: FilterCellAppearanceProtocol
|
||||
public var isSelected: Bool
|
||||
|
||||
public var appearance: FilterCellAppearanceProtocol {
|
||||
BaseFilterCellAppearance.defaultFilterCellAppearance
|
||||
}
|
||||
|
||||
public init(id: String,
|
||||
title: String,
|
||||
appearance: FilterCellAppearanceProtocol,
|
||||
isSelected: Bool) {
|
||||
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.appearance = appearance
|
||||
self.isSelected = isSelected
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
open class DefaultFilterViewModel: BaseFilterViewModel<DefaultFilterCellViewModel, DefaultFilterPropertyValue> {
|
||||
|
||||
private var cellsViewModels: [DefaultFilterCellViewModel] = []
|
||||
|
||||
public override init(filters: [DefaultFilterPropertyValue]) {
|
||||
super.init(filters: filters)
|
||||
self.cellsViewModels = filters.compactMap {
|
||||
DefaultFilterCellViewModel(id: $0.id,
|
||||
title: $0.title,
|
||||
isSelected: $0.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,40 +24,37 @@ import TIUIKitCore
|
|||
import UIKit
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
open class BaseFiltersCollectionView<CellType: UICollectionViewCell & ConfigurableView>: UICollectionView,
|
||||
InitializableViewProtocol,
|
||||
UpdatableView,
|
||||
UICollectionViewDelegate where CellType.ViewModelType: FilterCellViewModelProtocol & Hashable {
|
||||
|
||||
public enum Section {
|
||||
open class BaseFiltersCollectionView<CellType: UICollectionViewCell & ConfigurableView,
|
||||
PropertyValue: FilterPropertyValueRepresenter & Hashable>: UICollectionView,
|
||||
InitializableViewProtocol,
|
||||
UpdatableView,
|
||||
UICollectionViewDelegate where CellType.ViewModelType: FilterCellViewModelProtocol & Hashable {
|
||||
public enum DefaultSection: String {
|
||||
case main
|
||||
}
|
||||
|
||||
public typealias DataSource = UICollectionViewDiffableDataSource<Section, CellType.ViewModelType>
|
||||
public typealias Snapshot = NSDiffableDataSourceSnapshot<Section, CellType.ViewModelType>
|
||||
public typealias DataSource = UICollectionViewDiffableDataSource<String, CellType.ViewModelType>
|
||||
public typealias Snapshot = NSDiffableDataSourceSnapshot<String, CellType.ViewModelType>
|
||||
|
||||
public var layout: UICollectionViewLayout
|
||||
|
||||
public weak var viewModel: DefaultFiltersViewModel<CellType.ViewModelType>?
|
||||
public weak var viewModel: BaseFilterViewModel<CellType.ViewModelType, PropertyValue>?
|
||||
|
||||
public lazy var collectionViewDataSource = createDataSource()
|
||||
|
||||
open var cellsReusedIdentifier: String {
|
||||
"filter-cells-identifier"
|
||||
}
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
public init(layout: UICollectionViewLayout, viewModel: DefaultFiltersViewModel<CellType.ViewModelType>? = nil) {
|
||||
public init(layout: UICollectionViewLayout, viewModel: BaseFilterViewModel<CellType.ViewModelType, PropertyValue>? = nil) {
|
||||
self.layout = layout
|
||||
self.viewModel = viewModel
|
||||
|
||||
|
||||
super.init(frame: .zero, collectionViewLayout: layout)
|
||||
|
||||
initializeView()
|
||||
viewDidLoad()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
|
@ -85,7 +82,8 @@ open class BaseFiltersCollectionView<CellType: UICollectionViewCell & Configurab
|
|||
}
|
||||
|
||||
open func viewDidLoad() {
|
||||
register(CellType.self, forCellWithReuseIdentifier: cellsReusedIdentifier)
|
||||
registerCell()
|
||||
|
||||
viewModel?.filtersCollection = self
|
||||
|
||||
applySnapshot()
|
||||
|
|
@ -109,6 +107,10 @@ open class BaseFiltersCollectionView<CellType: UICollectionViewCell & Configurab
|
|||
|
||||
// MARK: - Open methods
|
||||
|
||||
open func registerCell() {
|
||||
register(CellType.self, forCellWithReuseIdentifier: CellType().reuseIdentifier ?? "")
|
||||
}
|
||||
|
||||
open func applySnapshot() {
|
||||
guard let viewModel = viewModel else {
|
||||
return
|
||||
|
|
@ -116,15 +118,15 @@ open class BaseFiltersCollectionView<CellType: UICollectionViewCell & Configurab
|
|||
|
||||
var snapshot = Snapshot()
|
||||
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(viewModel.getCellsViewModels() as! [CellType.ViewModelType], toSection: .main)
|
||||
snapshot.appendSections([DefaultSection.main.rawValue])
|
||||
snapshot.appendItems(viewModel.getCellsViewModels(), toSection: DefaultSection.main.rawValue)
|
||||
|
||||
collectionViewDataSource.apply(snapshot, animatingDifferences: true)
|
||||
}
|
||||
|
||||
open func createDataSource() -> DataSource {
|
||||
let cellProvider: DataSource.CellProvider = { [weak self] collectionView, indexPath, itemIdentifier in
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self?.cellsReusedIdentifier ?? "",
|
||||
let cellProvider: DataSource.CellProvider = {collectionView, indexPath, itemIdentifier in
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellType().reuseIdentifier ?? "",
|
||||
for: indexPath) as? CellType
|
||||
|
||||
cell?.configure(with: itemIdentifier)
|
||||
|
|
@ -135,7 +137,7 @@ open class BaseFiltersCollectionView<CellType: UICollectionViewCell & Configurab
|
|||
return DataSource(collectionView: self, cellProvider: cellProvider)
|
||||
}
|
||||
|
||||
open func applyChange(_ changes: [DefaultFiltersViewModel<CellType.ViewModelType>.Change]) {
|
||||
open func applyChange(_ changes: [BaseFilterViewModel<CellType.ViewModelType, PropertyValue>.Change]) {
|
||||
for change in changes {
|
||||
guard let cell = cellForItem(at: change.indexPath) as? CellType else {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ open class DefaultFilterCollectionCell: ContainerCollectionViewCell<UILabel>,
|
|||
|
||||
public var viewModel: DefaultFilterCellViewModel?
|
||||
|
||||
open override var reuseIdentifier: String? {
|
||||
"default-filter-cell"
|
||||
}
|
||||
|
||||
open override func configureAppearance() {
|
||||
super.configureAppearance()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
open class DefaultFiltersCollectionView: BaseFiltersCollectionView<DefaultFilterCollectionCell, DefaultFilterPropertyValue> {
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue