From fe6c4540422d61d7034e410dd5fc04693c48209e Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 19 Jul 2023 12:30:13 +0400 Subject: [PATCH 01/30] added universal stackview --- .../Common/Models/Styles/StackStyle.swift | 27 ++++ .../Sources/Common/Views/StackView.swift | 152 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 Components/Sources/Common/Models/Styles/StackStyle.swift create mode 100644 Components/Sources/Common/Views/StackView.swift diff --git a/Components/Sources/Common/Models/Styles/StackStyle.swift b/Components/Sources/Common/Models/Styles/StackStyle.swift new file mode 100644 index 00000000..34ab9ec3 --- /dev/null +++ b/Components/Sources/Common/Models/Styles/StackStyle.swift @@ -0,0 +1,27 @@ +// +// StackStyle.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 19.07.2023. +// + +import UIKit + +public struct StackStyle: Equatable { + + public let axis: NSLayoutConstraint.Axis + public let spacing: CGFloat + public let alignment: UIStackView.Alignment + public let distribution: UIStackView.Distribution + + public init(axis: NSLayoutConstraint.Axis, + spacing: CGFloat, + alignment: UIStackView.Alignment, + distribution: UIStackView.Distribution) { + self.axis = axis + self.spacing = spacing + self.alignment = alignment + self.distribution = distribution + } + +} diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift new file mode 100644 index 00000000..67c856e2 --- /dev/null +++ b/Components/Sources/Common/Views/StackView.swift @@ -0,0 +1,152 @@ +// +// StackView.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 19.07.2023. +// + +import UIKit +import ReactiveDataDisplayManager + +final public class StackView: UIView { + + // MARK: - Private Properties + + private let stackView = UIStackView() + private lazy var adapter = stackView.rddm.baseBuilder.build() + +} + +// MARK: - ConfigurableItem + +extension StackView: ConfigurableItem { + + // MARK: - Model + + public struct Model: AlignmentProvider { + + // MARK: - Editor + + public struct Property: Editor { + public typealias Model = StackView.Model + + private let closure: (Model) -> Model + + public init(closure: @escaping (Model) -> Model) { + self.closure = closure + } + + public func edit(_ model: Model) -> Model { + return closure(model) + } + + public static func children(_ value: [StackCellGenerator]) -> Property { + .init(closure: { model in + var model = model + model.set(children: value) + return model + }) + } + + public static func style(_ value: StackStyle) -> Property { + .init(closure: { model in + var model = model + model.set(style: value) + return model + }) + } + + public static func background(_ value: BackgroundStyle?) -> Property { + .init(closure: { model in + var model = model + model.set(background: value) + return model + }) + } + + public static func alignment(_ value: Alignment) -> Property { + .init(closure: { model in + var model = model + model.set(alignment: value) + return model + }) + } + + } + + // MARK: - Public properties + + private(set) public var children: [StackCellGenerator] = [] + private(set) public var style: StackStyle = .init(axis: .horizontal, + spacing: 0, + alignment: .fill, + distribution: .fill) + private(set) public var background: BackgroundStyle? + private(set) public var alignment: Alignment = .all(.zero) + + // MARK: - Mutation + + mutating func set(children: [StackCellGenerator]) { + self.children = children + } + + mutating func set(style: StackStyle) { + self.style = style + } + + mutating func set(background: BackgroundStyle?) { + self.background = background + } + + mutating func set(alignment: Alignment) { + self.alignment = alignment + } + + // MARK: - Builder + + public static func build(@EditorBuilder content: (Property.Type) -> [Property]) -> Self { + return content(Property.self).reduce(.init(), { model, editor in + editor.edit(model) + }) + } + } + + // MARK: - Methods + + public func configure(with model: Model) { + configureConstraints() + apply(style: model.style) + applyBackground(style: model.background) + + adapter -= .all + adapter += model.children + adapter => .reload + } + +} + +// MARK: - Private + +private extension StackView { + + func configureConstraints() { + wrap(subview: stackView, with: .zero) + } + + func apply(style: StackStyle) { + stackView.axis = style.axis + stackView.spacing = style.spacing + stackView.alignment = style.alignment + stackView.distribution = style.distribution + } + + func applyBackground(style: BackgroundStyle?) { + switch style { + case .solid(let color): + stackView.backgroundColor = color + case .none: + stackView.backgroundColor = nil + } + } + +} From 1fe17cb80080dc06a6a08b2a7cc8aac956fb9ca8 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 19 Jul 2023 13:08:08 +0400 Subject: [PATCH 02/30] improve StackCellGenerator to support nib based views --- .../Generators/BaseStackCellGenerator.swift | 46 ++++++++++++++++++- Source/Stack/View+RDDM.swift | 4 +- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Source/Stack/Generators/BaseStackCellGenerator.swift b/Source/Stack/Generators/BaseStackCellGenerator.swift index 911dd184..ec6beb48 100644 --- a/Source/Stack/Generators/BaseStackCellGenerator.swift +++ b/Source/Stack/Generators/BaseStackCellGenerator.swift @@ -5,16 +5,60 @@ // Created by Никита Коробейников on 06.09.2021. // +import UIKit + open class BaseStackCellGenerator: StackCellGenerator, ViewBuilder { public let model: View.Model - public init(with model: View.Model) { + // MARK: - Private properties + + private let registerType: CellRegisterType + + public init(with model: View.Model, + registerType: CellRegisterType = .class) { self.model = model + self.registerType = registerType } public func build(view: View) { view.configure(with: model) } + public func generate(stackView: UIStackView, index: Int) -> UIView { + let view = createView() + self.build(view: view) + return view + } + +} + +// MARK: - Private + +private extension BaseStackCellGenerator { + + func createView() -> ViewType { + switch registerType { + case .nib: + return ViewType.loadFromNib(bundle: ViewType.bundle() ?? .main) + case .class: + return ViewType() + } + } + +} + +private extension ConfigurableItem { + + static func loadFromNib(bundle: Bundle) -> T { + let nibName = String(describing: self) + let nib = UINib(nibName: nibName, bundle: bundle) + + guard let view = nib.instantiate(withOwner: self, options: nil).first as? T else { + return T() + } + + return view + } + } diff --git a/Source/Stack/View+RDDM.swift b/Source/Stack/View+RDDM.swift index baab22ec..260a4705 100644 --- a/Source/Stack/View+RDDM.swift +++ b/Source/Stack/View+RDDM.swift @@ -7,8 +7,8 @@ public extension StaticDataDisplayWrapper where Base: ConfigurableItem { - func baseStackGenerator(with model: Base.Model) -> BaseStackCellGenerator { - .init(with: model) + func baseStackGenerator(with model: Base.Model, and registerType: CellRegisterType = .class) -> BaseStackCellGenerator { + .init(with: model, registerType: registerType) } } From f1ec47f9f1ccd0331e78b282510e13b023e08b47 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 19 Jul 2023 13:12:36 +0400 Subject: [PATCH 03/30] add example of usage stackview --- .../Sources/Common/Views/StackView.swift | 2 +- .../StackCellExampleViewController.swift | 30 ++++++++++++++++++- .../TitleTableViewCell.swift | 4 +++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index 67c856e2..35172b68 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -8,7 +8,7 @@ import UIKit import ReactiveDataDisplayManager -final public class StackView: UIView { +public final class StackView: UIView { // MARK: - Private Properties diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 8ea2c7be..56b248c2 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -49,7 +49,7 @@ private extension StackCellExampleViewController { func fillAdapter() { // Add section into adapter - adapter += Section(header: EmptyTableHeaderGenerator(), footer: EmptyTableFooterGenerator()) { + adapter += Section(header: TitleHeaderGenerator(model: "TableVStack"), footer: EmptyTableFooterGenerator()) { TableVStack { TitleTableViewCell.buildView(with: "Текст 1") TitleTableViewCell.buildView(with: "Текст 2") @@ -64,6 +64,34 @@ private extension StackCellExampleViewController { } } + // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible + adapter += Section(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { + StackView.rddm.tableGenerator(with: .build { vStack in + vStack.background(.solid(.rddm)) + vStack.style(.init(axis: .vertical, + spacing: 8, + alignment: .fill, + distribution: .fill)) + vStack.children([ + TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 1", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 2", and: .nib), + StackView.rddm.baseStackGenerator(with: .build { hStack in + hStack.background(.solid(.systemBlue)) + hStack.style(.init(axis: .horizontal, + spacing: 4, + alignment: .fill, + distribution: .fillEqually)) + + hStack.children([ + TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 4", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 5", and: .nib) + ]) + }), + TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 3", and: .nib) + ]) + }, and: .class) + } + // Tell adapter that we've changed generators adapter => .reload } diff --git a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift index 471e8773..c4e271b9 100644 --- a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift @@ -26,6 +26,10 @@ class TitleTableViewCell: UITableViewCell, CalculatableHeightItem { return self } + override var intrinsicContentSize: CGSize { + return CGSize(width: UIView.noIntrinsicMetric, height: 44) + } + // MARK: - CalculatableHeightItem static func getHeight(forWidth width: CGFloat, with model: String) -> CGFloat { From 54503a47b25bddfaf41ac196af5d117f927c1e76 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 19 Jul 2023 15:41:36 +0400 Subject: [PATCH 04/30] extend example of stack cell --- .../StackCellExampleViewController.swift | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 56b248c2..cc1fd2dc 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -51,13 +51,13 @@ private extension StackCellExampleViewController { // Add section into adapter adapter += Section(header: TitleHeaderGenerator(model: "TableVStack"), footer: EmptyTableFooterGenerator()) { TableVStack { - TitleTableViewCell.buildView(with: "Текст 1") - TitleTableViewCell.buildView(with: "Текст 2") + TitleTableViewCell.buildView(with: "1") + TitleTableViewCell.buildView(with: "2") TableHStack { - TitleTableViewCell.buildView(with: "Текст 4") - TitleTableViewCell.buildView(with: "Текст 5") + TitleTableViewCell.buildView(with: "4") + TitleTableViewCell.buildView(with: "5") } - TitleTableViewCell.buildView(with: "Текст 3") + TitleTableViewCell.buildView(with: "3") } .didSelectEvent { print("VerticalTableStack did select event") @@ -73,8 +73,8 @@ private extension StackCellExampleViewController { alignment: .fill, distribution: .fill)) vStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 1", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 2", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "1", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "2", and: .nib), StackView.rddm.baseStackGenerator(with: .build { hStack in hStack.background(.solid(.systemBlue)) hStack.style(.init(axis: .horizontal, @@ -83,13 +83,45 @@ private extension StackCellExampleViewController { distribution: .fillEqually)) hStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 4", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 5", and: .nib) + TitleTableViewCell.rddm.baseStackGenerator(with: "4", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "5", and: .nib) ]) }), - TitleTableViewCell.rddm.baseStackGenerator(with: "Текст 3", and: .nib) + TitleTableViewCell.rddm.baseStackGenerator(with: "3", and: .nib) ]) }, and: .class) + LabelView.rddm.tableGenerator(with: .build { label in + label.textAlignment(.center) + label.text(.string("Wrapped LabelView")) + label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) + }, and: .class) + TitleTableViewCell.rddm.baseGenerator(with: "Cell outside from stack", and: .nib) + StackView.rddm.tableGenerator(with: .build { hStack in + hStack.background(.solid(.systemGreen)) + hStack.style(.init(axis: .horizontal, + spacing: 0, + alignment: .fill, + distribution: .fillEqually)) + hStack.children([ + TitleTableViewCell.rddm.baseStackGenerator(with: "6", and: .nib), + StackView.rddm.baseStackGenerator(with: .build { vStack in + vStack.background(.solid(.systemPink)) + vStack.style(.init(axis: .vertical, + spacing: 20, + alignment: .fill, + distribution: .fillEqually)) + vStack.children([ + TitleTableViewCell.rddm.baseStackGenerator(with: "6", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "7", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "8", and: .nib), + TitleTableViewCell.rddm.baseStackGenerator(with: "9", and: .nib) + ]) + }, + and: .class) + ]) + + }, + and: .class) } // Tell adapter that we've changed generators From c1c5cc8eb98dd94e0a1cbcd8c80233638fa800b5 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Thu, 20 Jul 2023 18:27:15 +0400 Subject: [PATCH 05/30] wrap stack (table cell) with simple extension --- .../Common/Utils/ViewGeneratorsBuilder.swift | 17 +++++ .../Sources/Common/Views/StackView.swift | 6 ++ .../StackCellExampleViewController.swift | 76 +++++++++---------- .../Generators/BaseStackCellGenerator.swift | 6 +- Source/Stack/View+RDDM.swift | 4 +- 5 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift diff --git a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift new file mode 100644 index 00000000..625ff3d5 --- /dev/null +++ b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift @@ -0,0 +1,17 @@ +// +// ViewGeneratorsBuilder.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 20.07.2023. +// + +import Foundation +import ReactiveDataDisplayManager + +public func Stack(model: StackView.Model, + @GeneratorsBuilder_ content: () -> [StackCellGenerator] +) -> TableCellGenerator { + StackView.rddm.tableGenerator(with: .copy(of: model) { property in + property.children(content()) + }, and: .class) +} diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index 35172b68..356d48e1 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -109,6 +109,12 @@ extension StackView: ConfigurableItem { editor.edit(model) }) } + + public static func copy(of original: Model, @EditorBuilder content: (Property.Type) -> [Property]) -> Self { + return content(Property.self).reduce(original, { model, editor in + editor.edit(model) + }) + } } // MARK: - Methods diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index cc1fd2dc..aff33bb7 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -66,62 +66,58 @@ private extension StackCellExampleViewController { // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible adapter += Section(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { - StackView.rddm.tableGenerator(with: .build { vStack in + Stack(model: .build { vStack in vStack.background(.solid(.rddm)) vStack.style(.init(axis: .vertical, spacing: 8, alignment: .fill, distribution: .fill)) - vStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "1", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "2", and: .nib), - StackView.rddm.baseStackGenerator(with: .build { hStack in - hStack.background(.solid(.systemBlue)) - hStack.style(.init(axis: .horizontal, - spacing: 4, - alignment: .fill, - distribution: .fillEqually)) - - hStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "4", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "5", and: .nib) - ]) - }), - TitleTableViewCell.rddm.baseStackGenerator(with: "3", and: .nib) - ]) - }, and: .class) + }) { + TitleTableViewCell.rddm.viewGenerator(with: "1", and: .nib) + TitleTableViewCell.rddm.viewGenerator(with: "2", and: .nib) + StackView.rddm.viewGenerator(with: .build { hStack in + hStack.background(.solid(.systemBlue)) + hStack.style(.init(axis: .horizontal, + spacing: 4, + alignment: .fill, + distribution: .fillEqually)) + + hStack.children([ + TitleTableViewCell.rddm.viewGenerator(with: "4", and: .nib), + TitleTableViewCell.rddm.viewGenerator(with: "5", and: .nib) + ]) + }) + TitleTableViewCell.rddm.viewGenerator(with: "3", and: .nib) + } LabelView.rddm.tableGenerator(with: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) }, and: .class) TitleTableViewCell.rddm.baseGenerator(with: "Cell outside from stack", and: .nib) - StackView.rddm.tableGenerator(with: .build { hStack in + Stack(model: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, spacing: 0, alignment: .fill, distribution: .fillEqually)) - hStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "6", and: .nib), - StackView.rddm.baseStackGenerator(with: .build { vStack in - vStack.background(.solid(.systemPink)) - vStack.style(.init(axis: .vertical, - spacing: 20, - alignment: .fill, - distribution: .fillEqually)) - vStack.children([ - TitleTableViewCell.rddm.baseStackGenerator(with: "6", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "7", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "8", and: .nib), - TitleTableViewCell.rddm.baseStackGenerator(with: "9", and: .nib) - ]) - }, - and: .class) - ]) - - }, - and: .class) + }) { + TitleTableViewCell.rddm.viewGenerator(with: "6", and: .nib) + StackView.rddm.viewGenerator(with: .build { vStack in + vStack.background(.solid(.systemPink)) + vStack.style(.init(axis: .vertical, + spacing: 20, + alignment: .fill, + distribution: .fillEqually)) + vStack.children([ + TitleTableViewCell.rddm.viewGenerator(with: "6", and: .nib), + TitleTableViewCell.rddm.viewGenerator(with: "7", and: .nib), + TitleTableViewCell.rddm.viewGenerator(with: "8", and: .nib), + TitleTableViewCell.rddm.viewGenerator(with: "9", and: .nib) + ]) + }, + and: .class) + } } // Tell adapter that we've changed generators diff --git a/Source/Stack/Generators/BaseStackCellGenerator.swift b/Source/Stack/Generators/BaseStackCellGenerator.swift index ec6beb48..0682e7de 100644 --- a/Source/Stack/Generators/BaseStackCellGenerator.swift +++ b/Source/Stack/Generators/BaseStackCellGenerator.swift @@ -1,5 +1,5 @@ // -// BaseStackCellGenerator.swift +// BaseViewGenerator.swift // Pods // // Created by Никита Коробейников on 06.09.2021. @@ -7,7 +7,7 @@ import UIKit -open class BaseStackCellGenerator: StackCellGenerator, ViewBuilder { +open class BaseViewGenerator: StackCellGenerator, ViewBuilder { public let model: View.Model @@ -35,7 +35,7 @@ open class BaseStackCellGenerator: StackCellGenerator, V // MARK: - Private -private extension BaseStackCellGenerator { +private extension BaseViewGenerator { func createView() -> ViewType { switch registerType { diff --git a/Source/Stack/View+RDDM.swift b/Source/Stack/View+RDDM.swift index 260a4705..df8f28d9 100644 --- a/Source/Stack/View+RDDM.swift +++ b/Source/Stack/View+RDDM.swift @@ -5,9 +5,11 @@ // Created by Никита Коробейников on 06.09.2021. // +import UIKit + public extension StaticDataDisplayWrapper where Base: ConfigurableItem { - func baseStackGenerator(with model: Base.Model, and registerType: CellRegisterType = .class) -> BaseStackCellGenerator { + func viewGenerator(with model: Base.Model, and registerType: CellRegisterType = .class) -> BaseViewGenerator { .init(with: model, registerType: registerType) } From 0c37a3bb28e172f1901c0a34a7c6d0b7781d4038 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 21 Jul 2023 11:16:35 +0400 Subject: [PATCH 06/30] add factories --- .../Common/Utils/ViewGeneratorsBuilder.swift | 83 +++++++++++++++++-- .../StackCellExampleViewController.swift | 50 +++++------ 2 files changed, 99 insertions(+), 34 deletions(-) diff --git a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift index 625ff3d5..7de0f191 100644 --- a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift +++ b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift @@ -5,13 +5,84 @@ // Created by Никита Коробейников on 20.07.2023. // +import UIKit import Foundation import ReactiveDataDisplayManager -public func Stack(model: StackView.Model, - @GeneratorsBuilder_ content: () -> [StackCellGenerator] -) -> TableCellGenerator { - StackView.rddm.tableGenerator(with: .copy(of: model) { property in - property.children(content()) - }, and: .class) +public enum ViewFactory { + + public static func stack(model: StackView.Model, + @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] + ) -> StackCellGenerator { + StackView.rddm.viewGenerator(with: .copy(of: model) { property in + property.children(content(ViewFactory.self)) + }, and: .class) + } + + public static func viewClass(type: T.Type, + model: T.Model) -> BaseViewGenerator { + T.rddm.viewGenerator(with: model, and: .class) + } + + public static func viewNib(type: T.Type, + model: T.Model) -> BaseViewGenerator { + T.rddm.viewGenerator(with: model, and: .nib) + } + +} + +public enum TableFactory { + + public static func stack(model: StackView.Model, + @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] + ) -> TableCellGenerator { + StackView.rddm.tableGenerator(with: .copy(of: model) { property in + property.children(content(ViewFactory.self)) + }, and: .class) + } + + public static func cell(type: T.Type, + model: T.Model, + registerType: CellRegisterType) -> BaseCellGenerator { + T.rddm.baseGenerator(with: model, and: registerType) + } + + public static func viewNib(type: T.Type, + model: T.Model) -> BaseCellGenerator> { + T.rddm.tableGenerator(with: model, and: .nib) + } + + public static func viewClass(type: T.Type, + model: T.Model) -> BaseCellGenerator> { + T.rddm.tableGenerator(with: model, and: .class) + } + +} + +public enum CollectionFactory { + + public static func stack(model: StackView.Model, + @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] + ) -> CollectionCellGenerator { + StackView.rddm.collectionGenerator(with: .copy(of: model) { property in + property.children(content(ViewFactory.self)) + }, and: .class) + } + + public static func cell(type: T.Type, + model: T.Model, + registerType: CellRegisterType) -> BaseCollectionCellGenerator { + T.rddm.baseGenerator(with: model, and: registerType) + } + + public static func viewNib(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { + T.rddm.collectionGenerator(with: model, and: .nib) + } + + public static func viewClass(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { + T.rddm.collectionGenerator(with: model, and: .class) + } + } diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index aff33bb7..2b93826c 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -65,58 +65,52 @@ private extension StackCellExampleViewController { } // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible - adapter += Section(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { - Stack(model: .build { vStack in + adapter += TableSection(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { + TableFactory.stack(model: .build { vStack in vStack.background(.solid(.rddm)) vStack.style(.init(axis: .vertical, spacing: 8, alignment: .fill, distribution: .fill)) - }) { - TitleTableViewCell.rddm.viewGenerator(with: "1", and: .nib) - TitleTableViewCell.rddm.viewGenerator(with: "2", and: .nib) - StackView.rddm.viewGenerator(with: .build { hStack in + }) { context in + context.stack(model: .build { hStack in hStack.background(.solid(.systemBlue)) hStack.style(.init(axis: .horizontal, spacing: 4, alignment: .fill, distribution: .fillEqually)) - - hStack.children([ - TitleTableViewCell.rddm.viewGenerator(with: "4", and: .nib), - TitleTableViewCell.rddm.viewGenerator(with: "5", and: .nib) - ]) - }) - TitleTableViewCell.rddm.viewGenerator(with: "3", and: .nib) + }) { context in + context.viewNib(type: TitleTableViewCell.self, model: "4") + context.viewNib(type: TitleTableViewCell.self, model: "5") + } + context.viewNib(type: TitleTableViewCell.self, model: "3") } - LabelView.rddm.tableGenerator(with: .build { label in + TableFactory.viewClass(type: LabelView.self, model: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) - }, and: .class) - TitleTableViewCell.rddm.baseGenerator(with: "Cell outside from stack", and: .nib) - Stack(model: .build { hStack in + }) + TableFactory.cell(type: TitleTableViewCell.self, model: "Cell outside from stack", registerType: .nib) + TableFactory.stack(model: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, spacing: 0, alignment: .fill, distribution: .fillEqually)) - }) { - TitleTableViewCell.rddm.viewGenerator(with: "6", and: .nib) - StackView.rddm.viewGenerator(with: .build { vStack in + }) { context in + context.viewNib(type: TitleTableViewCell.self, model: "6") + context.stack(model: .build { vStack in vStack.background(.solid(.systemPink)) vStack.style(.init(axis: .vertical, spacing: 20, alignment: .fill, distribution: .fillEqually)) - vStack.children([ - TitleTableViewCell.rddm.viewGenerator(with: "6", and: .nib), - TitleTableViewCell.rddm.viewGenerator(with: "7", and: .nib), - TitleTableViewCell.rddm.viewGenerator(with: "8", and: .nib), - TitleTableViewCell.rddm.viewGenerator(with: "9", and: .nib) - ]) - }, - and: .class) + }) { context in + context.viewNib(type: TitleTableViewCell.self, model: "7") + context.viewNib(type: TitleTableViewCell.self, model: "8") + context.viewNib(type: TitleTableViewCell.self, model: "9") + context.viewNib(type: TitleTableViewCell.self, model: "10") + } } } From 8e21a5073a1bb7f49b8e594f455843c2e58ebe83 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 21 Jul 2023 11:23:29 +0400 Subject: [PATCH 07/30] add todos --- Components/Sources/Collection/CollectionWrappedCell.swift | 1 + Components/Sources/Table/TableWrappedCell.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/Components/Sources/Collection/CollectionWrappedCell.swift b/Components/Sources/Collection/CollectionWrappedCell.swift index 2d56ceee..213b777b 100644 --- a/Components/Sources/Collection/CollectionWrappedCell.swift +++ b/Components/Sources/Collection/CollectionWrappedCell.swift @@ -15,6 +15,7 @@ public final class CollectionWrappedCell: UICollectionVi // MARK: - Properties + // TODO: - Add way to construct nested view from nib (like in BaseViewGenerator) public let nestedView: View = .init(frame: .zero) public var cachedInsets: UIEdgeInsets? diff --git a/Components/Sources/Table/TableWrappedCell.swift b/Components/Sources/Table/TableWrappedCell.swift index d77a7c76..1e645162 100644 --- a/Components/Sources/Table/TableWrappedCell.swift +++ b/Components/Sources/Table/TableWrappedCell.swift @@ -15,6 +15,7 @@ public final class TableWrappedCell: UITableViewCell, Vi // MARK: - Properties + // TODO: - Add way to construct nested view from nib (like in BaseViewGenerator) public let nestedView: View = .init(frame: .zero) public var cachedInsets: UIEdgeInsets? From 9e452aa0fbf5191c3883d0a8e81cc89e0c0463b9 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 21 Jul 2023 11:43:31 +0400 Subject: [PATCH 08/30] use generators builder in stack property builder --- .../Common/Utils/ViewGeneratorsBuilder.swift | 32 ++++----- .../Sources/Common/Views/StackView.swift | 9 +++ .../StackCellExampleViewController.swift | 71 ++++++++++--------- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift index 7de0f191..dafef7cc 100644 --- a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift +++ b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift @@ -11,14 +11,10 @@ import ReactiveDataDisplayManager public enum ViewFactory { - public static func stack(model: StackView.Model, - @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] - ) -> StackCellGenerator { - StackView.rddm.viewGenerator(with: .copy(of: model) { property in - property.children(content(ViewFactory.self)) - }, and: .class) + public static func stack(model: StackView.Model) -> StackCellGenerator { + StackView.rddm.viewGenerator(with: model, and: .class) } - + public static func viewClass(type: T.Type, model: T.Model) -> BaseViewGenerator { T.rddm.viewGenerator(with: model, and: .class) @@ -31,14 +27,12 @@ public enum ViewFactory { } +// MARK: - Table + public enum TableFactory { - public static func stack(model: StackView.Model, - @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] - ) -> TableCellGenerator { - StackView.rddm.tableGenerator(with: .copy(of: model) { property in - property.children(content(ViewFactory.self)) - }, and: .class) + public static func stack(model: StackView.Model) -> TableCellGenerator { + StackView.rddm.tableGenerator(with: model, and: .class) } public static func cell(type: T.Type, @@ -59,16 +53,14 @@ public enum TableFactory { } +// MARK: - Collection + public enum CollectionFactory { - public static func stack(model: StackView.Model, - @GeneratorsBuilder_ content: (ViewFactory.Type) -> [StackCellGenerator] - ) -> CollectionCellGenerator { - StackView.rddm.collectionGenerator(with: .copy(of: model) { property in - property.children(content(ViewFactory.self)) - }, and: .class) + public static func stack(model: StackView.Model) -> CollectionCellGenerator { + StackView.rddm.collectionGenerator(with: model, and: .class) } - + public static func cell(type: T.Type, model: T.Model, registerType: CellRegisterType) -> BaseCollectionCellGenerator { diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index 356d48e1..f457458e 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -48,6 +48,15 @@ extension StackView: ConfigurableItem { }) } + /// Only for stack. Cannot be included in common macros. + public static func children(@GeneratorsBuilder_ content: @escaping (ViewFactory.Type) -> [StackCellGenerator]) -> Property { + .init(closure: { model in + var model = model + model.set(children: content(ViewFactory.self)) + return model + }) + } + public static func style(_ value: StackStyle) -> Property { .init(closure: { model in var model = model diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 2b93826c..907a7b34 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -66,25 +66,30 @@ private extension StackCellExampleViewController { // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible adapter += TableSection(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { - TableFactory.stack(model: .build { vStack in - vStack.background(.solid(.rddm)) - vStack.style(.init(axis: .vertical, - spacing: 8, - alignment: .fill, - distribution: .fill)) - }) { context in - context.stack(model: .build { hStack in - hStack.background(.solid(.systemBlue)) - hStack.style(.init(axis: .horizontal, - spacing: 4, + TableFactory.stack( + model: .build { vStack in + vStack.background(.solid(.rddm)) + vStack.style(.init(axis: .vertical, + spacing: 8, alignment: .fill, - distribution: .fillEqually)) - }) { context in - context.viewNib(type: TitleTableViewCell.self, model: "4") - context.viewNib(type: TitleTableViewCell.self, model: "5") - } - context.viewNib(type: TitleTableViewCell.self, model: "3") - } + distribution: .fill)) + vStack.children { it in + it.viewNib(type: TitleTableViewCell.self, model: "1") + it.viewNib(type: TitleTableViewCell.self, model: "2") + it.stack(model: .build { hStack in + hStack.background(.solid(.systemBlue)) + hStack.style(.init(axis: .horizontal, + spacing: 4, + alignment: .fill, + distribution: .fillEqually)) + hStack.children { it in + it.viewNib(type: TitleTableViewCell.self, model: "4") + it.viewNib(type: TitleTableViewCell.self, model: "5") + } + }) + it.viewNib(type: TitleTableViewCell.self, model: "3") + } + }) TableFactory.viewClass(type: LabelView.self, model: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) @@ -97,21 +102,23 @@ private extension StackCellExampleViewController { spacing: 0, alignment: .fill, distribution: .fillEqually)) - }) { context in - context.viewNib(type: TitleTableViewCell.self, model: "6") - context.stack(model: .build { vStack in - vStack.background(.solid(.systemPink)) - vStack.style(.init(axis: .vertical, - spacing: 20, - alignment: .fill, - distribution: .fillEqually)) - }) { context in - context.viewNib(type: TitleTableViewCell.self, model: "7") - context.viewNib(type: TitleTableViewCell.self, model: "8") - context.viewNib(type: TitleTableViewCell.self, model: "9") - context.viewNib(type: TitleTableViewCell.self, model: "10") + hStack.children { it in + it.viewNib(type: TitleTableViewCell.self, model: "6") + it.stack(model: .build { vStack in + vStack.background(.solid(.systemPink)) + vStack.style(.init(axis: .vertical, + spacing: 20, + alignment: .fill, + distribution: .fillEqually)) + vStack.children { it in + it.viewNib(type: TitleTableViewCell.self, model: "7") + it.viewNib(type: TitleTableViewCell.self, model: "8") + it.viewNib(type: TitleTableViewCell.self, model: "9") + it.viewNib(type: TitleTableViewCell.self, model: "10") + } + }) } - } + }) } // Tell adapter that we've changed generators From c1d9f20f5d99d49e34593394add24e46246cfa38 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 21 Jul 2023 11:57:38 +0400 Subject: [PATCH 09/30] add context to table section constructor with result builder --- .../StackCellExampleViewController.swift | 12 +++++++----- Source/Models/Section.swift | 8 ++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 907a7b34..9cd43e98 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -65,8 +65,10 @@ private extension StackCellExampleViewController { } // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible - adapter += TableSection(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { - TableFactory.stack( + adapter += TableSection.create(contextType: TableFactory.self, + header: TitleHeaderGenerator(model: "StackView based cells"), + footer: EmptyTableFooterGenerator()) { it in + it.stack( model: .build { vStack in vStack.background(.solid(.rddm)) vStack.style(.init(axis: .vertical, @@ -90,13 +92,13 @@ private extension StackCellExampleViewController { it.viewNib(type: TitleTableViewCell.self, model: "3") } }) - TableFactory.viewClass(type: LabelView.self, model: .build { label in + it.viewClass(type: LabelView.self, model: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) }) - TableFactory.cell(type: TitleTableViewCell.self, model: "Cell outside from stack", registerType: .nib) - TableFactory.stack(model: .build { hStack in + it.cell(type: TitleTableViewCell.self, model: "Cell outside from stack", registerType: .nib) + it.stack(model: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, spacing: 0, diff --git a/Source/Models/Section.swift b/Source/Models/Section.swift index b85010fc..01388d37 100644 --- a/Source/Models/Section.swift +++ b/Source/Models/Section.swift @@ -39,6 +39,14 @@ public struct Section { self.init(generators: generators(), header: header, footer: footer) } + /// Context based generic section for tables and collections with @resultBuilder support + public static func create(contextType: Context.Type, + header: HeaderGeneratorType, + footer: FooterGeneratorType, + @GeneratorsBuilder generators: (Context.Type) -> [GeneratorType]) -> Self { + Self(generators: generators(Context.self), header: header, footer: footer) + } + } public extension Section { From 4debacb6e452039d826e5902fb6390077b02613b Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 21 Jul 2023 12:20:50 +0400 Subject: [PATCH 10/30] move base contexts (ex factories) to core lib --- .../BaseCollectionManager+Extension.swift | 0 ...lectionContext+CollectionWrappedCell.swift | 28 +++++++ .../CollectionWrappedCell+RDDM.swift | 0 .../Common/Extensions/ViewContext+Stack.swift | 18 +++++ .../Common/Utils/ViewGeneratorsBuilder.swift | 80 ------------------- .../Sources/Common/Views/StackView.swift | 4 +- .../TableContext+TableWrappedCell.swift | 28 +++++++ .../TableWrappedCell+RDDM.swift | 0 .../StackCellExampleViewController.swift | 3 +- Source/Collection/CollectionSection.swift | 6 ++ .../Generators/CollectionContext.swift | 20 +++++ Source/Models/Section.swift | 8 +- Source/Stack/Generators/ViewContext.swift | 23 ++++++ Source/Table/Generators/TableContext.swift | 20 +++++ Source/Table/TableSection.swift | 6 ++ 15 files changed, 156 insertions(+), 88 deletions(-) rename Components/Sources/{Common => Collection}/Extensions/BaseCollectionManager+Extension.swift (100%) create mode 100644 Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift rename Components/Sources/{Common => Collection}/Extensions/CollectionWrappedCell+RDDM.swift (100%) create mode 100644 Components/Sources/Common/Extensions/ViewContext+Stack.swift delete mode 100644 Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift create mode 100644 Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift rename Components/Sources/Table/{ => Extensions}/TableWrappedCell+RDDM.swift (100%) create mode 100644 Source/Collection/Generators/CollectionContext.swift create mode 100644 Source/Stack/Generators/ViewContext.swift create mode 100644 Source/Table/Generators/TableContext.swift diff --git a/Components/Sources/Common/Extensions/BaseCollectionManager+Extension.swift b/Components/Sources/Collection/Extensions/BaseCollectionManager+Extension.swift similarity index 100% rename from Components/Sources/Common/Extensions/BaseCollectionManager+Extension.swift rename to Components/Sources/Collection/Extensions/BaseCollectionManager+Extension.swift diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift new file mode 100644 index 00000000..01ccd11d --- /dev/null +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -0,0 +1,28 @@ +// +// CollectionContext+CollectionWrappedCell.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation +import ReactiveDataDisplayManager + +public extension CollectionContext { + + static func stack(model: StackView.Model) -> CollectionCellGenerator { + StackView.rddm.collectionGenerator(with: model, and: .class) + } + + static func viewNib(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { + T.rddm.collectionGenerator(with: model, and: .nib) + } + + static func viewClass(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { + T.rddm.collectionGenerator(with: model, and: .class) + } + +} diff --git a/Components/Sources/Common/Extensions/CollectionWrappedCell+RDDM.swift b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift similarity index 100% rename from Components/Sources/Common/Extensions/CollectionWrappedCell+RDDM.swift rename to Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift diff --git a/Components/Sources/Common/Extensions/ViewContext+Stack.swift b/Components/Sources/Common/Extensions/ViewContext+Stack.swift new file mode 100644 index 00000000..c0044bc1 --- /dev/null +++ b/Components/Sources/Common/Extensions/ViewContext+Stack.swift @@ -0,0 +1,18 @@ +// +// ViewContext+Stack.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation +import ReactiveDataDisplayManager + +public extension ViewContext { + + static func stack(model: StackView.Model) -> StackCellGenerator { + StackView.rddm.viewGenerator(with: model, and: .class) + } + +} diff --git a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift b/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift deleted file mode 100644 index dafef7cc..00000000 --- a/Components/Sources/Common/Utils/ViewGeneratorsBuilder.swift +++ /dev/null @@ -1,80 +0,0 @@ -// -// ViewGeneratorsBuilder.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 20.07.2023. -// - -import UIKit -import Foundation -import ReactiveDataDisplayManager - -public enum ViewFactory { - - public static func stack(model: StackView.Model) -> StackCellGenerator { - StackView.rddm.viewGenerator(with: model, and: .class) - } - - public static func viewClass(type: T.Type, - model: T.Model) -> BaseViewGenerator { - T.rddm.viewGenerator(with: model, and: .class) - } - - public static func viewNib(type: T.Type, - model: T.Model) -> BaseViewGenerator { - T.rddm.viewGenerator(with: model, and: .nib) - } - -} - -// MARK: - Table - -public enum TableFactory { - - public static func stack(model: StackView.Model) -> TableCellGenerator { - StackView.rddm.tableGenerator(with: model, and: .class) - } - - public static func cell(type: T.Type, - model: T.Model, - registerType: CellRegisterType) -> BaseCellGenerator { - T.rddm.baseGenerator(with: model, and: registerType) - } - - public static func viewNib(type: T.Type, - model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model, and: .nib) - } - - public static func viewClass(type: T.Type, - model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model, and: .class) - } - -} - -// MARK: - Collection - -public enum CollectionFactory { - - public static func stack(model: StackView.Model) -> CollectionCellGenerator { - StackView.rddm.collectionGenerator(with: model, and: .class) - } - - public static func cell(type: T.Type, - model: T.Model, - registerType: CellRegisterType) -> BaseCollectionCellGenerator { - T.rddm.baseGenerator(with: model, and: registerType) - } - - public static func viewNib(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model, and: .nib) - } - - public static func viewClass(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model, and: .class) - } - -} diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index f457458e..67022ec7 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -49,10 +49,10 @@ extension StackView: ConfigurableItem { } /// Only for stack. Cannot be included in common macros. - public static func children(@GeneratorsBuilder_ content: @escaping (ViewFactory.Type) -> [StackCellGenerator]) -> Property { + public static func children(@GeneratorsBuilder_ content: @escaping (ViewContext.Type) -> [StackCellGenerator]) -> Property { .init(closure: { model in var model = model - model.set(children: content(ViewFactory.self)) + model.set(children: content(ViewContext.self)) return model }) } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift new file mode 100644 index 00000000..d0ca50c3 --- /dev/null +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -0,0 +1,28 @@ +// +// TableContext+TableWrappedCell.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation +import ReactiveDataDisplayManager + +public extension TableContext { + + static func stack(model: StackView.Model) -> TableCellGenerator { + StackView.rddm.tableGenerator(with: model, and: .class) + } + + static func viewNib(type: T.Type, + model: T.Model) -> BaseCellGenerator> { + T.rddm.tableGenerator(with: model, and: .nib) + } + + static func viewClass(type: T.Type, + model: T.Model) -> BaseCellGenerator> { + T.rddm.tableGenerator(with: model, and: .class) + } + +} diff --git a/Components/Sources/Table/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift similarity index 100% rename from Components/Sources/Table/TableWrappedCell+RDDM.swift rename to Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 9cd43e98..e95be2d1 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -65,8 +65,7 @@ private extension StackCellExampleViewController { } // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible - adapter += TableSection.create(contextType: TableFactory.self, - header: TitleHeaderGenerator(model: "StackView based cells"), + adapter += TableSection.create(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { it in it.stack( model: .build { vStack in diff --git a/Source/Collection/CollectionSection.swift b/Source/Collection/CollectionSection.swift index 3cce41ff..69ab1c29 100644 --- a/Source/Collection/CollectionSection.swift +++ b/Source/Collection/CollectionSection.swift @@ -21,4 +21,10 @@ public extension CollectionSection { self.init(generators: generators, header: header, footer: EmptyCollectionFooterGenerator()) } + static func create(header: HeaderGeneratorType, + footer: FooterGeneratorType, + @GeneratorsBuilder generators: (CollectionContext.Type) -> [GeneratorType]) -> Self { + Self(generators: generators(CollectionContext.self), header: header, footer: footer) + } + } diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift new file mode 100644 index 00000000..5f84765a --- /dev/null +++ b/Source/Collection/Generators/CollectionContext.swift @@ -0,0 +1,20 @@ +// +// CollectionContext.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation + +public enum CollectionContext { + + public static func cell(type: T.Type, + model: T.Model, + registerType: CellRegisterType) -> BaseCollectionCellGenerator { + T.rddm.baseGenerator(with: model, and: registerType) + } + + // TODO: - add support for other types of generators or make (decorated generator) +} diff --git a/Source/Models/Section.swift b/Source/Models/Section.swift index 01388d37..d9cfb722 100644 --- a/Source/Models/Section.swift +++ b/Source/Models/Section.swift @@ -40,10 +40,10 @@ public struct Section { } /// Context based generic section for tables and collections with @resultBuilder support - public static func create(contextType: Context.Type, - header: HeaderGeneratorType, - footer: FooterGeneratorType, - @GeneratorsBuilder generators: (Context.Type) -> [GeneratorType]) -> Self { + static func create(contextType: Context.Type, + header: HeaderGeneratorType, + footer: FooterGeneratorType, + @GeneratorsBuilder generators: (Context.Type) -> [GeneratorType]) -> Self { Self(generators: generators(Context.self), header: header, footer: footer) } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift new file mode 100644 index 00000000..7359fe2b --- /dev/null +++ b/Source/Stack/Generators/ViewContext.swift @@ -0,0 +1,23 @@ +// +// ViewContext.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation + +public enum ViewContext { + + public static func viewClass(type: T.Type, + model: T.Model) -> BaseViewGenerator { + T.rddm.viewGenerator(with: model, and: .class) + } + + public static func viewNib(type: T.Type, + model: T.Model) -> BaseViewGenerator { + T.rddm.viewGenerator(with: model, and: .nib) + } + +} diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift new file mode 100644 index 00000000..993be2f5 --- /dev/null +++ b/Source/Table/Generators/TableContext.swift @@ -0,0 +1,20 @@ +// +// TableContext.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 21.07.2023. +// + +import UIKit +import Foundation + +public enum TableContext { + + public static func cell(type: T.Type, + model: T.Model, + registerType: CellRegisterType) -> BaseCellGenerator { + T.rddm.baseGenerator(with: model, and: registerType) + } + + // TODO: - add support for other types of generators or make (decorated generator) +} diff --git a/Source/Table/TableSection.swift b/Source/Table/TableSection.swift index 559ddd9a..4dafe826 100644 --- a/Source/Table/TableSection.swift +++ b/Source/Table/TableSection.swift @@ -21,4 +21,10 @@ public extension TableSection { self.init(generators: generators, header: header, footer: EmptyTableFooterGenerator()) } + static func create(header: HeaderGeneratorType, + footer: FooterGeneratorType, + @GeneratorsBuilder generators: (TableContext.Type) -> [GeneratorType]) -> Self { + Self(generators: generators(TableContext.self), header: header, footer: footer) + } + } From 5763b4df1d231dc3ba3d2d825ed5fe420918e696 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 26 Jul 2023 17:00:32 +0400 Subject: [PATCH 11/30] fix requirement for CollectionContext --- .../Extensions/CollectionContext+CollectionWrappedCell.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 01ccd11d..8fdc8ed9 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -15,12 +15,12 @@ public extension CollectionContext { StackView.rddm.collectionGenerator(with: model, and: .class) } - static func viewNib(type: T.Type, + static func viewNib(type: T.Type, model: T.Model) -> BaseCollectionCellGenerator> { T.rddm.collectionGenerator(with: model, and: .nib) } - static func viewClass(type: T.Type, + static func viewClass(type: T.Type, model: T.Model) -> BaseCollectionCellGenerator> { T.rddm.collectionGenerator(with: model, and: .class) } From 6a0f777e58f224ad5c4a6617f73fe44dfd979c49 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 26 Jul 2023 18:16:45 +0400 Subject: [PATCH 12/30] add assotiated types to context to improve syntax --- ...lectionContext+CollectionWrappedCell.swift | 27 ++++++++++++++----- .../CollectionWrappedCell+RDDM.swift | 6 ++--- .../Extensions/ConfigurableItem+Builder.swift | 2 +- .../Extensions/ConfigurableItem+Context.swift | 17 ++++++++++++ .../Common/Extensions/ViewContext+Stack.swift | 2 +- .../Sources/Common/Views/LabelView.swift | 8 ++++++ .../Sources/Common/Views/MessageView.swift | 8 ++++++ .../Sources/Common/Views/SeparatorView.swift | 8 ++++++ .../Sources/Common/Views/SpacerView.swift | 8 ++++++ .../Sources/Common/Views/StackView.swift | 16 ++++++++--- .../TableContext+TableWrappedCell.swift | 23 +++++++++++++--- .../Extensions/TableWrappedCell+RDDM.swift | 4 +-- ...kCellExampleCollectionViewController.swift | 20 ++++++++++++++ .../Generators/ButtonStackCellGenerator.swift | 2 +- .../Generators/InnerStackCellGenerator.swift | 6 ++--- .../Generators/TextStackCellGenerator.swift | 2 +- .../Generators/TitleStackCellGenerator.swift | 2 +- .../Generators/UnrollStackCellGenerator.swift | 2 +- .../StackCellExampleViewController.swift | 24 ++++++++--------- .../TitleTableViewCell.swift | 8 ++++++ .../Stack/Manager/BaseStackManagerTests.swift | 2 +- Source/Collection/CollectionCell+RDDM.swift | 6 ++--- .../BaseCollectionCellGenerator.swift | 4 +-- ...latableHeightCollectionCellGenerator.swift | 2 +- ...ulatableWidthCollectionCellGenerator.swift | 2 +- .../Generators/CollectionContext.swift | 6 ++--- .../DiffableCollectionCellGenerator.swift | 6 ++--- ...isterType.swift => RegistrationType.swift} | 2 +- .../BuilderContext/BuilderContext.swift | 15 +++++++++++ .../RegistrationTypeProvider.swift | 11 ++++++++ Source/Protocols/Protocols.swift | 10 +++---- .../Generators/BaseStackCellGenerator.swift | 6 ++--- Source/Stack/Generators/ViewContext.swift | 11 +++++++- Source/Stack/Manager/BaseStackManager.swift | 16 +++++------ Source/Stack/View+RDDM.swift | 2 +- .../Table/Generators/BaseCellGenerator.swift | 4 +-- .../CalculatableHeightCellGenerator.swift | 2 +- ...atableHeightNonReusableCellGenerator.swift | 4 +-- .../Generators/DiffableCellGenerator.swift | 6 ++--- Source/Table/Generators/TableContext.swift | 7 ++--- Source/Table/TableCell+RDDM.swift | 6 ++--- 41 files changed, 238 insertions(+), 87 deletions(-) create mode 100644 Components/Sources/Common/Extensions/ConfigurableItem+Context.swift rename Source/Models/{CellRegisterType.swift => RegistrationType.swift} (92%) create mode 100644 Source/Protocols/BuilderContext/BuilderContext.swift create mode 100644 Source/Protocols/BuilderContext/RegistrationTypeProvider.swift diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 8fdc8ed9..e7d3ba47 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -9,19 +9,34 @@ import UIKit import Foundation import ReactiveDataDisplayManager -public extension CollectionContext { +extension CollectionContext: BuilderContext { - static func stack(model: StackView.Model) -> CollectionCellGenerator { + public typealias ViewType = UICollectionViewCell + public typealias GeneratorType = CollectionCellGenerator + + // TODO: - add support for other types of generators or make (decorated generator) + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ReactiveDataDisplayManager.ConfigurableItem, Item : ReactiveDataDisplayManager.RegistrationTypeProvider { + Item.rddm.collectionGenerator(with: model, and: Item.prefferedRegistration) + } + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ViewType, Item : ConfigurableItem, Item : RegistrationTypeProvider { + Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) + } + + public static func stack(model: StackView.Model) -> CollectionCellGenerator { StackView.rddm.collectionGenerator(with: model, and: .class) } - static func viewNib(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") + public static func viewNib(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { T.rddm.collectionGenerator(with: model, and: .nib) } - static func viewClass(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") + public static func viewClass(type: T.Type, + model: T.Model) -> BaseCollectionCellGenerator> { T.rddm.collectionGenerator(with: model, and: .class) } diff --git a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift index e4d75688..5c0514b0 100644 --- a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift +++ b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift @@ -11,7 +11,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem { func collectionGenerator(with model: Base.Model, - and registerType: CellRegisterType = .nib) -> BaseCollectionCellGenerator> { + and registerType: RegistrationType = .nib) -> BaseCollectionCellGenerator> { CollectionWrappedCell.rddm.baseGenerator(with: model, and: registerType) } @@ -25,7 +25,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem func tableCalculatableHightGenerator( with model: Base.Model, width: CGFloat, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> CalculatableHeightCollectionCellGenerator> { CalculatableHeightCollectionCellGenerator>(with: model, @@ -42,7 +42,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem func tableCalculatableWidthGenerator( with model: Base.Model, height: CGFloat, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> CalculatableWidthCollectionCellGenerator> { CalculatableWidthCollectionCellGenerator>(with: model, diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift b/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift index f3e39ad5..a2e46a6d 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift @@ -9,7 +9,7 @@ import ReactiveDataDisplayManager public extension ConfigurableItem { - static func buildView(with model: Self.Model, and type: CellRegisterType = .nib) -> Self { + static func buildView(with model: Self.Model, and type: RegistrationType = .nib) -> Self { let cell: Self? switch type { case .nib: diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift b/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift new file mode 100644 index 00000000..d5398c24 --- /dev/null +++ b/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift @@ -0,0 +1,17 @@ +// +// ConfigurableItem+Context.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 26.07.2023. +// + +import ReactiveDataDisplayManager + +public extension ConfigurableItem { + + static func build(in context: T.Type, with model: Self.Model) -> T.GeneratorType? { + // TODO: - TBD + return nil + } + +} diff --git a/Components/Sources/Common/Extensions/ViewContext+Stack.swift b/Components/Sources/Common/Extensions/ViewContext+Stack.swift index c0044bc1..2822eecc 100644 --- a/Components/Sources/Common/Extensions/ViewContext+Stack.swift +++ b/Components/Sources/Common/Extensions/ViewContext+Stack.swift @@ -11,7 +11,7 @@ import ReactiveDataDisplayManager public extension ViewContext { - static func stack(model: StackView.Model) -> StackCellGenerator { + static func stack(model: StackView.Model) -> ViewGenerator { StackView.rddm.viewGenerator(with: model, and: .class) } diff --git a/Components/Sources/Common/Views/LabelView.swift b/Components/Sources/Common/Views/LabelView.swift index d8947e32..5d41fd9d 100644 --- a/Components/Sources/Common/Views/LabelView.swift +++ b/Components/Sources/Common/Views/LabelView.swift @@ -222,3 +222,11 @@ extension LabelView.Model { } } + +// MARK: - RegistrationTypeProvider + +extension LabelView: RegistrationTypeProvider { + + public static var prefferedRegistration: RegistrationType { .class } + +} diff --git a/Components/Sources/Common/Views/MessageView.swift b/Components/Sources/Common/Views/MessageView.swift index 4f66a000..90f9e94e 100644 --- a/Components/Sources/Common/Views/MessageView.swift +++ b/Components/Sources/Common/Views/MessageView.swift @@ -331,5 +331,13 @@ extension MessageView.Model { } } +} + +// MARK: - RegistrationTypeProvider + +extension MessageView: RegistrationTypeProvider { + + public static var prefferedRegistration: RegistrationType { .class } + } #endif diff --git a/Components/Sources/Common/Views/SeparatorView.swift b/Components/Sources/Common/Views/SeparatorView.swift index 132c9424..93cb3c2d 100644 --- a/Components/Sources/Common/Views/SeparatorView.swift +++ b/Components/Sources/Common/Views/SeparatorView.swift @@ -89,3 +89,11 @@ private extension SeparatorView { } } + +// MARK: - RegistrationTypeProvider + +extension SeparatorView: RegistrationTypeProvider { + + public static var prefferedRegistration: RegistrationType { .class } + +} diff --git a/Components/Sources/Common/Views/SpacerView.swift b/Components/Sources/Common/Views/SpacerView.swift index d1070d38..a16b6638 100644 --- a/Components/Sources/Common/Views/SpacerView.swift +++ b/Components/Sources/Common/Views/SpacerView.swift @@ -109,3 +109,11 @@ public extension SpacerWrapper where Model == SpacerView.Model { } } + +// MARK: - RegistrationTypeProvider + +extension SpacerView: RegistrationTypeProvider { + + public static var prefferedRegistration: RegistrationType { .class } + +} diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index 67022ec7..42ac7c42 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -40,7 +40,7 @@ extension StackView: ConfigurableItem { return closure(model) } - public static func children(_ value: [StackCellGenerator]) -> Property { + public static func children(_ value: [ViewGenerator]) -> Property { .init(closure: { model in var model = model model.set(children: value) @@ -49,7 +49,7 @@ extension StackView: ConfigurableItem { } /// Only for stack. Cannot be included in common macros. - public static func children(@GeneratorsBuilder_ content: @escaping (ViewContext.Type) -> [StackCellGenerator]) -> Property { + public static func children(@GeneratorsBuilder_ content: @escaping (ViewContext.Type) -> [ViewGenerator]) -> Property { .init(closure: { model in var model = model model.set(children: content(ViewContext.self)) @@ -85,7 +85,7 @@ extension StackView: ConfigurableItem { // MARK: - Public properties - private(set) public var children: [StackCellGenerator] = [] + private(set) public var children: [ViewGenerator] = [] private(set) public var style: StackStyle = .init(axis: .horizontal, spacing: 0, alignment: .fill, @@ -95,7 +95,7 @@ extension StackView: ConfigurableItem { // MARK: - Mutation - mutating func set(children: [StackCellGenerator]) { + mutating func set(children: [ViewGenerator]) { self.children = children } @@ -165,3 +165,11 @@ private extension StackView { } } + +// MARK: - RegistrationTypeProvider + +extension StackView: RegistrationTypeProvider { + + public static var prefferedRegistration: RegistrationType { .class } + +} diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index d0ca50c3..bd3fc6d2 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -9,18 +9,33 @@ import UIKit import Foundation import ReactiveDataDisplayManager -public extension TableContext { +extension TableContext: BuilderContext { - static func stack(model: StackView.Model) -> TableCellGenerator { + public typealias ViewType = UITableViewCell + public typealias GeneratorType = TableCellGenerator + + // TODO: - add support for other types of generators or make (decorated generator) + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ConfigurableItem, Item : RegistrationTypeProvider { + Item.rddm.tableGenerator(with: model, and: Item.prefferedRegistration) + } + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ViewType, Item : ConfigurableItem, Item : RegistrationTypeProvider { + Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) + } + + public static func stack(model: StackView.Model) -> TableCellGenerator { StackView.rddm.tableGenerator(with: model, and: .class) } - static func viewNib(type: T.Type, + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") + public static func viewNib(type: T.Type, model: T.Model) -> BaseCellGenerator> { T.rddm.tableGenerator(with: model, and: .nib) } - static func viewClass(type: T.Type, + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") + public static func viewClass(type: T.Type, model: T.Model) -> BaseCellGenerator> { T.rddm.tableGenerator(with: model, and: .class) } diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift index 42913758..d130b263 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift @@ -11,7 +11,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem { func tableGenerator(with model: Base.Model, - and registerType: CellRegisterType = .nib) -> BaseCellGenerator> { + and registerType: RegistrationType = .nib) -> BaseCellGenerator> { TableWrappedCell.rddm.baseGenerator(with: model, and: registerType) } @@ -24,7 +24,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem func tableCalculatableHightGenerator( with model: Base.Model, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> CalculatableHeightCellGenerator> { CalculatableHeightCellGenerator>(with: model, diff --git a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift index 3d7aa094..49bb369e 100644 --- a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift @@ -103,6 +103,26 @@ private extension StackCellExampleCollectionViewController { SeparatorView.buildView(with: .init(size: .height(1), color: .black), and: .class) } + adapter += CollectionSection.create(header: EmptyCollectionHeaderGenerator(), footer: EmptyCollectionFooterGenerator()) { it in + it.viewClass(type: SeparatorView.self, model: .init(size: .height(1), color: .black)) + it.stack(model: .build { hStack in + hStack.style(.init(axis: .horizontal, + spacing: 0, + alignment: .fill, + distribution: .fillEqually)) + hStack.children { it in + it.viewClass(type: SeparatorView.self, model: .init(size: .width(1), color: .black)) + it.viewClass(type: SpacerView.self, model: .init(size: .width(64))) + + it.viewNib(type: TitleTableViewCell.self, model: "Some text") + + it.viewClass(type: SeparatorView.self, model: .init(size: .width(1), color: .black)) + + } + }) + it.viewClass(type: SeparatorView.self, model: .init(size: .height(1), color: .black)) + } + // Tell adapter that we've changed generators adapter => .reload } diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/ButtonStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/ButtonStackCellGenerator.swift index ee168850..e00f08e7 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/ButtonStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/ButtonStackCellGenerator.swift @@ -8,7 +8,7 @@ import ReactiveDataDisplayManager import UIKit -final class ButtonStackCellGenerator: StackCellGenerator { +final class ButtonStackCellGenerator: ViewGenerator { // MARK: - Nested diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift index f172b80a..3b57ec76 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift @@ -8,7 +8,7 @@ import UIKit import ReactiveDataDisplayManager -final class InnerStackCellGenerator: StackCellGenerator { +final class InnerStackCellGenerator: ViewGenerator { // MARK: - Model @@ -22,11 +22,11 @@ final class InnerStackCellGenerator: StackCellGenerator { // MARK: - Properties private let model: Model - private let childGenerators: [StackCellGenerator] + private let childGenerators: [ViewGenerator] // MARK: - Initialization - init(model: Model, childGenerators: [StackCellGenerator]) { + init(model: Model, childGenerators: [ViewGenerator]) { self.model = model self.childGenerators = childGenerators } diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TextStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TextStackCellGenerator.swift index 5bbbdb13..9a99cb6a 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TextStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TextStackCellGenerator.swift @@ -8,7 +8,7 @@ import UIKit import ReactiveDataDisplayManager -final class TextStackCellGenerator: StackCellGenerator { +final class TextStackCellGenerator: ViewGenerator { // MARK: - Model diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TitleStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TitleStackCellGenerator.swift index c93ab1c5..d263e948 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TitleStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/TitleStackCellGenerator.swift @@ -9,7 +9,7 @@ import ReactiveDataDisplayManager import UIKit -final class TitleStackCellGenerator: StackCellGenerator { +final class TitleStackCellGenerator: ViewGenerator { // MARK: - Properties diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/UnrollStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/UnrollStackCellGenerator.swift index a3f6055c..1feea7f0 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/UnrollStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/UnrollStackCellGenerator.swift @@ -7,7 +7,7 @@ import ReactiveDataDisplayManager -final class UnrollStackCellGenerator: StackCellGenerator { +final class UnrollStackCellGenerator: ViewGenerator { // MARK: - Properties diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index e95be2d1..85a296f7 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -75,8 +75,8 @@ private extension StackCellExampleViewController { alignment: .fill, distribution: .fill)) vStack.children { it in - it.viewNib(type: TitleTableViewCell.self, model: "1") - it.viewNib(type: TitleTableViewCell.self, model: "2") + it.gen(TitleTableViewCell.self, model: "1") + it.gen(TitleTableViewCell.self, model: "2") it.stack(model: .build { hStack in hStack.background(.solid(.systemBlue)) hStack.style(.init(axis: .horizontal, @@ -84,19 +84,19 @@ private extension StackCellExampleViewController { alignment: .fill, distribution: .fillEqually)) hStack.children { it in - it.viewNib(type: TitleTableViewCell.self, model: "4") - it.viewNib(type: TitleTableViewCell.self, model: "5") + it.gen(TitleTableViewCell.self, model: "4") + it.gen(TitleTableViewCell.self, model: "5") } }) - it.viewNib(type: TitleTableViewCell.self, model: "3") + it.gen(TitleTableViewCell.self, model: "3") } }) - it.viewClass(type: LabelView.self, model: .build { label in + it.gen(LabelView.self, model: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) }) - it.cell(type: TitleTableViewCell.self, model: "Cell outside from stack", registerType: .nib) + it.gen(TitleTableViewCell.self, model: "Cell outside from stack") it.stack(model: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, @@ -104,7 +104,7 @@ private extension StackCellExampleViewController { alignment: .fill, distribution: .fillEqually)) hStack.children { it in - it.viewNib(type: TitleTableViewCell.self, model: "6") + it.gen(TitleTableViewCell.self, model: "6") it.stack(model: .build { vStack in vStack.background(.solid(.systemPink)) vStack.style(.init(axis: .vertical, @@ -112,10 +112,10 @@ private extension StackCellExampleViewController { alignment: .fill, distribution: .fillEqually)) vStack.children { it in - it.viewNib(type: TitleTableViewCell.self, model: "7") - it.viewNib(type: TitleTableViewCell.self, model: "8") - it.viewNib(type: TitleTableViewCell.self, model: "9") - it.viewNib(type: TitleTableViewCell.self, model: "10") + it.gen(TitleTableViewCell.self, model: "7") + it.gen(TitleTableViewCell.self, model: "8") + it.gen(TitleTableViewCell.self, model: "9") + it.gen(TitleTableViewCell.self, model: "10") } }) } diff --git a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift index c4e271b9..d8508a99 100644 --- a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift @@ -62,3 +62,11 @@ extension TitleTableViewCell: ConfigurableItem { } } + +// MARK: - RegistrationTypeProvider + +extension TitleTableViewCell: RegistrationTypeProvider { + + static var prefferedRegistration: RegistrationType { .nib } + +} diff --git a/ReactiveDataDisplayManagerTests/Stack/Manager/BaseStackManagerTests.swift b/ReactiveDataDisplayManagerTests/Stack/Manager/BaseStackManagerTests.swift index e2084392..50bf8648 100644 --- a/ReactiveDataDisplayManagerTests/Stack/Manager/BaseStackManagerTests.swift +++ b/ReactiveDataDisplayManagerTests/Stack/Manager/BaseStackManagerTests.swift @@ -164,7 +164,7 @@ final class BaseStackManagerTests: XCTestCase { // MARK: - Mocks -fileprivate final class MockStackCellGenerator: StackCellGenerator { +fileprivate final class MockStackCellGenerator: ViewGenerator { var title: String var view: UIView? diff --git a/Source/Collection/CollectionCell+RDDM.swift b/Source/Collection/CollectionCell+RDDM.swift index dc0c7429..f45bbddb 100644 --- a/Source/Collection/CollectionCell+RDDM.swift +++ b/Source/Collection/CollectionCell+RDDM.swift @@ -10,7 +10,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem { - func baseGenerator(with model: Base.Model, and registerType: CellRegisterType = .nib) -> BaseCollectionCellGenerator { + func baseGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCollectionCellGenerator { .init(with: model, registerType: registerType) } @@ -19,7 +19,7 @@ public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & Con public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & CalculatableHeightItem { func calculatableHeightGenerator(with model: Base.Model, - and registerType: CellRegisterType = .nib, + and registerType: RegistrationType = .nib, referencedWidth: CGFloat) -> CalculatableHeightCollectionCellGenerator { .init(with: model, width: referencedWidth, registerType: registerType) } @@ -28,7 +28,7 @@ public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & Cal public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem & FoldableStateHolder { - func foldableGenerator(with model: Base.Model, and registerType: CellRegisterType = .nib) -> FoldableCollectionCellGenerator { + func foldableGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> FoldableCollectionCellGenerator { .init(with: model, registerType: registerType) } diff --git a/Source/Collection/Generators/BaseCollectionCellGenerator.swift b/Source/Collection/Generators/BaseCollectionCellGenerator.swift index feb4cdd8..08263c00 100644 --- a/Source/Collection/Generators/BaseCollectionCellGenerator.swift +++ b/Source/Collection/Generators/BaseCollectionCellGenerator.swift @@ -19,12 +19,12 @@ open class BaseCollectionCellGenerator: SelectableItem w // MARK: - Private Properties - private let registerType: CellRegisterType + private let registerType: RegistrationType // MARK: - Initialization public init(with model: Cell.Model, - registerType: CellRegisterType = .nib) { + registerType: RegistrationType = .nib) { self.model = model self.registerType = registerType } diff --git a/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift b/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift index a6a5dfa0..a7373098 100644 --- a/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift +++ b/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift @@ -20,7 +20,7 @@ public class CalculatableHeightCollectionCellGenerator(type: T.Type, model: T.Model, - registerType: CellRegisterType) -> BaseCollectionCellGenerator { + registerType: RegistrationType) -> BaseCollectionCellGenerator { T.rddm.baseGenerator(with: model, and: registerType) } - // TODO: - add support for other types of generators or make (decorated generator) } diff --git a/Source/Collection/Generators/DiffableCollectionCellGenerator.swift b/Source/Collection/Generators/DiffableCollectionCellGenerator.swift index 473d3f83..858aef75 100644 --- a/Source/Collection/Generators/DiffableCollectionCellGenerator.swift +++ b/Source/Collection/Generators/DiffableCollectionCellGenerator.swift @@ -16,7 +16,7 @@ open class DiffableCollectionCellGenerator DiffableCollectionCellGenerator { .init(uniqueId: uniqueId, with: model, registerType: registerType) } @@ -39,7 +39,7 @@ extension StaticDataDisplayWrapper where Base: UICollectionViewCell & Configurab public func diffableGenerator( with model: Base.Model, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> DiffableCollectionCellGenerator { .init(uniqueId: model.id, with: model, registerType: registerType) } diff --git a/Source/Models/CellRegisterType.swift b/Source/Models/RegistrationType.swift similarity index 92% rename from Source/Models/CellRegisterType.swift rename to Source/Models/RegistrationType.swift index d64703b5..49e757ad 100644 --- a/Source/Models/CellRegisterType.swift +++ b/Source/Models/RegistrationType.swift @@ -11,7 +11,7 @@ import UIKit /// Enum with different types of registering cells in collections /// - nib - register as nib /// - class - register as class -public enum CellRegisterType { +public enum RegistrationType { case nib case `class` } diff --git a/Source/Protocols/BuilderContext/BuilderContext.swift b/Source/Protocols/BuilderContext/BuilderContext.swift new file mode 100644 index 00000000..713b0245 --- /dev/null +++ b/Source/Protocols/BuilderContext/BuilderContext.swift @@ -0,0 +1,15 @@ +// +// BuilderContext.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 26.07.2023. +// + +import UIKit + +public protocol BuilderContext { + associatedtype ViewType: UIView + associatedtype GeneratorType + + static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType +} diff --git a/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift new file mode 100644 index 00000000..e004c9b5 --- /dev/null +++ b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift @@ -0,0 +1,11 @@ +// +// RegistrationTypeProvider.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 26.07.2023. +// + +public protocol RegistrationTypeProvider { + static var prefferedRegistration: RegistrationType { get } +} + diff --git a/Source/Protocols/Protocols.swift b/Source/Protocols/Protocols.swift index f283610e..746f0fcb 100644 --- a/Source/Protocols/Protocols.swift +++ b/Source/Protocols/Protocols.swift @@ -9,7 +9,7 @@ import UIKit // sourcery: AutoMockable -open class TableHeaderGenerator: ViewGenerator, IdOwner, TableHeaderRegisterableItem, AccessibilityStrategyProvider { +open class TableHeaderGenerator: AccessoryViewGenerator, IdOwner, TableHeaderRegisterableItem, AccessibilityStrategyProvider { public let id: AnyHashable @@ -37,7 +37,7 @@ open class TableHeaderGenerator: ViewGenerator, IdOwner, TableHeaderRegisterable } -open class TableFooterGenerator: ViewGenerator, TableFooterRegisterableItem { +open class TableFooterGenerator: AccessoryViewGenerator, TableFooterRegisterableItem { public let id: AnyHashable @@ -164,7 +164,7 @@ public extension CollectionCellGenerator { } /// Protocol that incapsulated build logics for current View -public protocol ViewGenerator: AnyObject { +public protocol AccessoryViewGenerator: AnyObject { associatedtype ViewType @@ -271,11 +271,11 @@ public extension CollectionFooterGenerator where Self: ViewBuilder { } /// Protocol that incapsulated type of current cell -public protocol StackCellGenerator: AnyObject { +public protocol ViewGenerator: AnyObject { func generate(stackView: UIStackView, index: Int) -> UIView } -public extension StackCellGenerator where Self: ViewBuilder { +public extension ViewGenerator where Self: ViewBuilder { func generate(stackView: UIStackView, index: Int) -> UIView { let view = Self.ViewType() self.build(view: view) diff --git a/Source/Stack/Generators/BaseStackCellGenerator.swift b/Source/Stack/Generators/BaseStackCellGenerator.swift index 0682e7de..b5817f24 100644 --- a/Source/Stack/Generators/BaseStackCellGenerator.swift +++ b/Source/Stack/Generators/BaseStackCellGenerator.swift @@ -7,16 +7,16 @@ import UIKit -open class BaseViewGenerator: StackCellGenerator, ViewBuilder { +open class BaseViewGenerator: ViewGenerator, ViewBuilder { public let model: View.Model // MARK: - Private properties - private let registerType: CellRegisterType + private let registerType: RegistrationType public init(with model: View.Model, - registerType: CellRegisterType = .class) { + registerType: RegistrationType = .class) { self.model = model self.registerType = registerType } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index 7359fe2b..c9f322c8 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -8,13 +8,22 @@ import UIKit import Foundation -public enum ViewContext { +public struct ViewContext: BuilderContext { + public typealias ViewType = UIView + public typealias GeneratorType = ViewGenerator + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ConfigurableItem, Item : RegistrationTypeProvider { + Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) + } + + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewClass(type: T.Type, model: T.Model) -> BaseViewGenerator { T.rddm.viewGenerator(with: model, and: .class) } + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewNib(type: T.Type, model: T.Model) -> BaseViewGenerator { T.rddm.viewGenerator(with: model, and: .nib) diff --git a/Source/Stack/Manager/BaseStackManager.swift b/Source/Stack/Manager/BaseStackManager.swift index 14081e33..d24c5c3a 100644 --- a/Source/Stack/Manager/BaseStackManager.swift +++ b/Source/Stack/Manager/BaseStackManager.swift @@ -14,13 +14,13 @@ open class BaseStackManager: DataDisplayManager { // MARK: - Typealias public typealias CollectionType = UIStackView - public typealias GeneratorType = StackCellGenerator + public typealias GeneratorType = ViewGenerator // MARK: - Properties // swiftlint:disable implicitly_unwrapped_optional public weak var view: UIStackView! - public var cellGenerators: [StackCellGenerator] = [] + public var cellGenerators: [ViewGenerator] = [] // swiftlint:enable implicitly_unwrapped_optional // MARK: - DataDisplayManager @@ -35,11 +35,11 @@ open class BaseStackManager: DataDisplayManager { } } - public func addCellGenerator(_ generator: StackCellGenerator) { + public func addCellGenerator(_ generator: ViewGenerator) { cellGenerators.append(generator) } - public func addCellGenerators(_ generators: [StackCellGenerator], after: StackCellGenerator) { + public func addCellGenerators(_ generators: [ViewGenerator], after: ViewGenerator) { if let index = index(of: after) { generators.enumerated().forEach { offset, generator in cellGenerators.insert(generator, at: index + offset + 1) @@ -49,7 +49,7 @@ open class BaseStackManager: DataDisplayManager { } } - public func addCellGenerator(_ generator: StackCellGenerator, after: StackCellGenerator) { + public func addCellGenerator(_ generator: ViewGenerator, after: ViewGenerator) { if let index = index(of: after) { cellGenerators.insert(generator, at: index + 1) } else { @@ -57,11 +57,11 @@ open class BaseStackManager: DataDisplayManager { } } - public func addCellGenerators(_ generators: [StackCellGenerator]) { + public func addCellGenerators(_ generators: [ViewGenerator]) { cellGenerators.append(contentsOf: generators) } - public func update(generators: [StackCellGenerator]) { + public func update(generators: [ViewGenerator]) { generators.forEach { generator in if let index = index(of: generator) { cellGenerators.remove(at: index) @@ -82,7 +82,7 @@ open class BaseStackManager: DataDisplayManager { private extension BaseStackManager { - func index(of generator: StackCellGenerator) -> Int? { + func index(of generator: ViewGenerator) -> Int? { return cellGenerators.firstIndex(where: { $0 === generator }) } diff --git a/Source/Stack/View+RDDM.swift b/Source/Stack/View+RDDM.swift index df8f28d9..1c8fe432 100644 --- a/Source/Stack/View+RDDM.swift +++ b/Source/Stack/View+RDDM.swift @@ -9,7 +9,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: ConfigurableItem { - func viewGenerator(with model: Base.Model, and registerType: CellRegisterType = .class) -> BaseViewGenerator { + func viewGenerator(with model: Base.Model, and registerType: RegistrationType = .class) -> BaseViewGenerator { .init(with: model, registerType: registerType) } diff --git a/Source/Table/Generators/BaseCellGenerator.swift b/Source/Table/Generators/BaseCellGenerator.swift index a8a0a138..c72d9f7b 100644 --- a/Source/Table/Generators/BaseCellGenerator.swift +++ b/Source/Table/Generators/BaseCellGenerator.swift @@ -22,12 +22,12 @@ open class BaseCellGenerator: SelectableTableCellGenerat // MARK: - Private Properties - private let registerType: CellRegisterType + private let registerType: RegistrationType // MARK: - Initialization public init(with model: Cell.Model, - registerType: CellRegisterType = .nib) { + registerType: RegistrationType = .nib) { self.model = model self.registerType = registerType } diff --git a/Source/Table/Generators/CalculatableHeightCellGenerator.swift b/Source/Table/Generators/CalculatableHeightCellGenerator.swift index 723f954a..f62eea4f 100644 --- a/Source/Table/Generators/CalculatableHeightCellGenerator.swift +++ b/Source/Table/Generators/CalculatableHeightCellGenerator.swift @@ -19,7 +19,7 @@ open class CalculatableHeightCellGenerator: BaseCe public init(with model: Cell.Model, cellWidth: CGFloat = UIScreen.main.bounds.width, - registerType: CellRegisterType = .nib) { + registerType: RegistrationType = .nib) { self.cellWidth = cellWidth super.init(with: model, registerType: registerType) } diff --git a/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift b/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift index 8afe8617..c5dda886 100644 --- a/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift +++ b/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift @@ -24,13 +24,13 @@ public class CalculatableHeightNonReusableCellGenerator: Base .init(id: id, state: AnyEquatable(model)) } - public init(uniqueId: AnyHashable, with model: Cell.Model, registerType: CellRegisterType = .nib) { + public init(uniqueId: AnyHashable, with model: Cell.Model, registerType: RegistrationType = .nib) { self.id = uniqueId super.init(with: model, registerType: registerType) } @@ -28,7 +28,7 @@ extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableIte public func diffableGenerator( uniqueId: AnyHashable, with model: Base.Model, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> DiffableCellGenerator { .init(uniqueId: uniqueId, with: model, registerType: registerType) } @@ -39,7 +39,7 @@ extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableIte public func diffableGenerator( with model: Base.Model, - and registerType: CellRegisterType = .nib + and registerType: RegistrationType = .nib ) -> DiffableCellGenerator { .init(uniqueId: model.id, with: model, registerType: registerType) } diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 993be2f5..4e9b628f 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -8,13 +8,14 @@ import UIKit import Foundation -public enum TableContext { +public struct TableContext { + @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func cell(type: T.Type, model: T.Model, - registerType: CellRegisterType) -> BaseCellGenerator { + registerType: RegistrationType) -> BaseCellGenerator { T.rddm.baseGenerator(with: model, and: registerType) } - // TODO: - add support for other types of generators or make (decorated generator) + } diff --git a/Source/Table/TableCell+RDDM.swift b/Source/Table/TableCell+RDDM.swift index 0a391824..3b3bb1d6 100644 --- a/Source/Table/TableCell+RDDM.swift +++ b/Source/Table/TableCell+RDDM.swift @@ -10,7 +10,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem { - func baseGenerator(with model: Base.Model, and registerType: CellRegisterType = .nib) -> BaseCellGenerator { + func baseGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCellGenerator { .init(with: model, registerType: registerType) } @@ -18,7 +18,7 @@ public extension StaticDataDisplayWrapper where Base: UITableViewCell & Configur public extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem & FoldableStateHolder { - func foldableGenerator(with model: Base.Model, and registerType: CellRegisterType = .nib) -> FoldableCellGenerator { + func foldableGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> FoldableCellGenerator { .init(with: model, registerType: registerType) } @@ -35,7 +35,7 @@ public extension StaticDataDisplayWrapper where Base: UITableViewCell & Configur public extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem & CalculatableHeightItem { func calculatableHeightGenerator(with model: Base.Model, - and registerType: CellRegisterType = .nib, + and registerType: RegistrationType = .nib, referenceWidth: CGFloat = UIScreen.main.bounds.width) -> CalculatableHeightCellGenerator { .init(with: model, cellWidth: referenceWidth, registerType: registerType) } From 8779dbc8278b6bd7904ff63e60638109632a9fbb Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Wed, 26 Jul 2023 18:41:25 +0400 Subject: [PATCH 13/30] add extension to imporve syntax --- ...lectionContext+CollectionWrappedCell.swift | 7 +- .../ConfigurableItem+BuilderContext.swift | 17 +++++ .../Extensions/ConfigurableItem+Context.swift | 17 ----- .../Sources/Common/Views/MessageView.swift | 7 +- .../TableContext+TableWrappedCell.swift | 7 +- .../StackCellExampleViewController.swift | 72 +++++++++---------- .../RegistrationTypeProvider.swift | 1 - Source/Stack/Generators/ViewContext.swift | 3 +- Source/Table/Generators/TableContext.swift | 1 - 9 files changed, 70 insertions(+), 62 deletions(-) create mode 100644 Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift delete mode 100644 Components/Sources/Common/Extensions/ConfigurableItem+Context.swift diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index e7d3ba47..2029e71d 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -16,11 +16,14 @@ extension CollectionContext: BuilderContext { // TODO: - add support for other types of generators or make (decorated generator) - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ReactiveDataDisplayManager.ConfigurableItem, Item : ReactiveDataDisplayManager.RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, + Item: RegistrationTypeProvider { Item.rddm.collectionGenerator(with: model, and: Item.prefferedRegistration) } - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ViewType, Item : ConfigurableItem, Item : RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, + Item: ConfigurableItem, + Item: RegistrationTypeProvider { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift new file mode 100644 index 00000000..bf525a0b --- /dev/null +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -0,0 +1,17 @@ +// +// ConfigurableItem+BuilderContext.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 26.07.2023. +// + +import UIKit +import ReactiveDataDisplayManager + +public extension ConfigurableItem where Self: RegistrationTypeProvider { + + static func build(in ctx: Context.Type, with model: Model) -> Context.GeneratorType { + ctx.gen(Self.self, model: model) + } + +} diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift b/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift deleted file mode 100644 index d5398c24..00000000 --- a/Components/Sources/Common/Extensions/ConfigurableItem+Context.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// ConfigurableItem+Context.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 26.07.2023. -// - -import ReactiveDataDisplayManager - -public extension ConfigurableItem { - - static func build(in context: T.Type, with model: Self.Model) -> T.GeneratorType? { - // TODO: - TBD - return nil - } - -} diff --git a/Components/Sources/Common/Views/MessageView.swift b/Components/Sources/Common/Views/MessageView.swift index 90f9e94e..32a17f1a 100644 --- a/Components/Sources/Common/Views/MessageView.swift +++ b/Components/Sources/Common/Views/MessageView.swift @@ -112,7 +112,7 @@ extension MessageView: ConfigurableItem { return model }) } - + /// To set it to **false**, dataDetection and tapHandler must be nil public static func selectable(_ selectable: Bool) -> Property { .init(closure: { model in @@ -292,7 +292,10 @@ private extension MessageView { extension MessageView: UITextViewDelegate { - public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { + public func textView(_ textView: UITextView, + shouldInteractWith URL: URL, + in characterRange: NSRange, + interaction: UITextItemInteraction) -> Bool { handleDataDetection(URL) return false } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index bd3fc6d2..a02d6c1d 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -16,11 +16,14 @@ extension TableContext: BuilderContext { // TODO: - add support for other types of generators or make (decorated generator) - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ConfigurableItem, Item : RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, + Item: RegistrationTypeProvider { Item.rddm.tableGenerator(with: model, and: Item.prefferedRegistration) } - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ViewType, Item : ConfigurableItem, Item : RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, + Item: ConfigurableItem, + Item: RegistrationTypeProvider { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 85a296f7..fe6e10b1 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -66,56 +66,56 @@ private extension StackCellExampleViewController { // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible adapter += TableSection.create(header: TitleHeaderGenerator(model: "StackView based cells"), - footer: EmptyTableFooterGenerator()) { it in - it.stack( - model: .build { vStack in - vStack.background(.solid(.rddm)) - vStack.style(.init(axis: .vertical, - spacing: 8, - alignment: .fill, - distribution: .fill)) - vStack.children { it in - it.gen(TitleTableViewCell.self, model: "1") - it.gen(TitleTableViewCell.self, model: "2") - it.stack(model: .build { hStack in - hStack.background(.solid(.systemBlue)) - hStack.style(.init(axis: .horizontal, - spacing: 4, - alignment: .fill, - distribution: .fillEqually)) - hStack.children { it in - it.gen(TitleTableViewCell.self, model: "4") - it.gen(TitleTableViewCell.self, model: "5") - } - }) - it.gen(TitleTableViewCell.self, model: "3") - } - }) - it.gen(LabelView.self, model: .build { label in + footer: EmptyTableFooterGenerator()) { ctx in + StackView.build(in: ctx, with: .build { vStack in + vStack.background(.solid(.rddm)) + vStack.style(.init(axis: .vertical, + spacing: 8, + alignment: .fill, + distribution: .fill)) + vStack.children { ctx in + TitleTableViewCell.build(in: ctx, with: "1") + TitleTableViewCell.build(in: ctx, with: "2") + StackView.build(in: ctx, with: .build { hStack in + hStack.background(.solid(.systemBlue)) + hStack.style(.init(axis: .horizontal, + spacing: 4, + alignment: .fill, + distribution: .fillEqually)) + hStack.children { ctx in + TitleTableViewCell.build(in: ctx, with: "4") + TitleTableViewCell.build(in: ctx, with: "5") + } + }) + TitleTableViewCell.build(in: ctx, with: "3") + } + }) + LabelView.build(in: ctx, with: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) }) - it.gen(TitleTableViewCell.self, model: "Cell outside from stack") - it.stack(model: .build { hStack in + // TODO: - resolve crash with neb loading +// TitleTableViewCell.build(in: ctx, with: "Cell outside from stack") + StackView.build(in: ctx, with: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, spacing: 0, alignment: .fill, distribution: .fillEqually)) - hStack.children { it in - it.gen(TitleTableViewCell.self, model: "6") - it.stack(model: .build { vStack in + hStack.children { ctx in + TitleTableViewCell.build(in: ctx, with: "6") + StackView.build(in: ctx, with: .build { vStack in vStack.background(.solid(.systemPink)) vStack.style(.init(axis: .vertical, spacing: 20, alignment: .fill, distribution: .fillEqually)) - vStack.children { it in - it.gen(TitleTableViewCell.self, model: "7") - it.gen(TitleTableViewCell.self, model: "8") - it.gen(TitleTableViewCell.self, model: "9") - it.gen(TitleTableViewCell.self, model: "10") + vStack.children { ctx in + TitleTableViewCell.build(in: ctx, with: "7") + TitleTableViewCell.build(in: ctx, with: "8") + TitleTableViewCell.build(in: ctx, with: "9") + TitleTableViewCell.build(in: ctx, with: "10") } }) } diff --git a/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift index e004c9b5..12a16c55 100644 --- a/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift +++ b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift @@ -8,4 +8,3 @@ public protocol RegistrationTypeProvider { static var prefferedRegistration: RegistrationType { get } } - diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index c9f322c8..012d3566 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -13,7 +13,8 @@ public struct ViewContext: BuilderContext { public typealias ViewType = UIView public typealias GeneratorType = ViewGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item : ConfigurableItem, Item : RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, + Item: RegistrationTypeProvider { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 4e9b628f..11493dc7 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -17,5 +17,4 @@ public struct TableContext { T.rddm.baseGenerator(with: model, and: registerType) } - } From b4311b696d87723dcc7795ba003fb4504b83fdf5 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Thu, 27 Jul 2023 13:20:55 +0400 Subject: [PATCH 14/30] add empty view generator for wrapped cells --- .../Collection/CollectionWrappedCell.swift | 5 ++--- .../Extensions/CollectionWrappedCell+RDDM.swift | 6 +++--- .../ConfigurableItem+BuilderContext.swift | 2 +- .../Extensions/TableWrappedCell+RDDM.swift | 4 ++-- Components/Sources/Table/TableWrappedCell.swift | 5 ++--- ...lGenerator.swift => BaseViewGenerator.swift} | 17 +++++++++++++++++ 6 files changed, 27 insertions(+), 12 deletions(-) rename Source/Stack/Generators/{BaseStackCellGenerator.swift => BaseViewGenerator.swift} (77%) diff --git a/Components/Sources/Collection/CollectionWrappedCell.swift b/Components/Sources/Collection/CollectionWrappedCell.swift index 213b777b..d54b9e79 100644 --- a/Components/Sources/Collection/CollectionWrappedCell.swift +++ b/Components/Sources/Collection/CollectionWrappedCell.swift @@ -9,14 +9,13 @@ import UIKit import ReactiveDataDisplayManager /// Empty collection cell with `View`. Configuration is implemented within `ViewWrapper`. -public final class CollectionWrappedCell: UICollectionViewCell, ViewWrapper { +public final class CollectionWrappedCell: UICollectionViewCell, ViewWrapper { public typealias Model = View.Model // MARK: - Properties - // TODO: - Add way to construct nested view from nib (like in BaseViewGenerator) - public let nestedView: View = .init(frame: .zero) + public let nestedView: View = EmptyViewGenerator().generate() public var cachedInsets: UIEdgeInsets? diff --git a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift index 5c0514b0..019a33c7 100644 --- a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift +++ b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift @@ -8,7 +8,7 @@ import ReactiveDataDisplayManager import UIKit -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem { +public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { func collectionGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCollectionCellGenerator> { @@ -20,7 +20,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem // MARK: - CalculatableHeightItem -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableHeightItem { +public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableHeightItem & RegistrationTypeProvider { func tableCalculatableHightGenerator( with model: Base.Model, @@ -37,7 +37,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem // MARK: - CalculatableWidthItem -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableWidthItem { +public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableWidthItem & RegistrationTypeProvider { func tableCalculatableWidthGenerator( with model: Base.Model, diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift index bf525a0b..3d7d5c38 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -9,7 +9,7 @@ import UIKit import ReactiveDataDisplayManager public extension ConfigurableItem where Self: RegistrationTypeProvider { - + static func build(in ctx: Context.Type, with model: Model) -> Context.GeneratorType { ctx.gen(Self.self, model: model) } diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift index d130b263..530b10fe 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift @@ -8,7 +8,7 @@ import ReactiveDataDisplayManager import UIKit -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem { +public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { func tableGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCellGenerator> { @@ -20,7 +20,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem // MARK: - CalculatableHeightItem -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableHeightItem { +public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableHeightItem & RegistrationTypeProvider { func tableCalculatableHightGenerator( with model: Base.Model, diff --git a/Components/Sources/Table/TableWrappedCell.swift b/Components/Sources/Table/TableWrappedCell.swift index 1e645162..78b477a2 100644 --- a/Components/Sources/Table/TableWrappedCell.swift +++ b/Components/Sources/Table/TableWrappedCell.swift @@ -9,14 +9,13 @@ import UIKit import ReactiveDataDisplayManager /// Empty table cell with `View`. Configuration is implemented within `ViewWrapper`. -public final class TableWrappedCell: UITableViewCell, ViewWrapper { +public final class TableWrappedCell: UITableViewCell, ViewWrapper { public typealias Model = View.Model // MARK: - Properties - // TODO: - Add way to construct nested view from nib (like in BaseViewGenerator) - public let nestedView: View = .init(frame: .zero) + public let nestedView: View = EmptyViewGenerator().generate() public var cachedInsets: UIEdgeInsets? diff --git a/Source/Stack/Generators/BaseStackCellGenerator.swift b/Source/Stack/Generators/BaseViewGenerator.swift similarity index 77% rename from Source/Stack/Generators/BaseStackCellGenerator.swift rename to Source/Stack/Generators/BaseViewGenerator.swift index b5817f24..39ba4791 100644 --- a/Source/Stack/Generators/BaseStackCellGenerator.swift +++ b/Source/Stack/Generators/BaseViewGenerator.swift @@ -7,6 +7,23 @@ import UIKit +final public class EmptyViewGenerator: AccessoryViewGenerator { + + public typealias ViewType = View + + public init() {} + + public func generate() -> View { + switch View.prefferedRegistration { + case .nib: + return View.loadFromNib(bundle: ViewType.bundle() ?? .main) + case .class: + return View() + } + } + +} + open class BaseViewGenerator: ViewGenerator, ViewBuilder { public let model: View.Model From a4a499d441cf0205e8f4897df76a27875d5c793e Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Thu, 27 Jul 2023 14:56:25 +0400 Subject: [PATCH 15/30] freeze registration type for wrapped cell generator --- .../CollectionContext+CollectionWrappedCell.swift | 8 ++++---- .../Extensions/CollectionWrappedCell+RDDM.swift | 5 ++--- .../Extensions/TableContext+TableWrappedCell.swift | 8 ++++---- .../Table/Extensions/TableWrappedCell+RDDM.swift | 5 ++--- .../ComponentsOverviewTableViewController.swift | 12 ++++++------ .../StackCellExampleViewController.swift | 7 ++++--- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 2029e71d..3f1a0db1 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -18,7 +18,7 @@ extension CollectionContext: BuilderContext { public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, Item: RegistrationTypeProvider { - Item.rddm.collectionGenerator(with: model, and: Item.prefferedRegistration) + Item.rddm.collectionGenerator(with: model) } public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, @@ -28,19 +28,19 @@ extension CollectionContext: BuilderContext { } public static func stack(model: StackView.Model) -> CollectionCellGenerator { - StackView.rddm.collectionGenerator(with: model, and: .class) + StackView.rddm.collectionGenerator(with: model) } @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewNib(type: T.Type, model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model, and: .nib) + T.rddm.collectionGenerator(with: model) } @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewClass(type: T.Type, model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model, and: .class) + T.rddm.collectionGenerator(with: model) } } diff --git a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift index 019a33c7..f17c2434 100644 --- a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift +++ b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift @@ -10,10 +10,9 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { - func collectionGenerator(with model: Base.Model, - and registerType: RegistrationType = .nib) -> BaseCollectionCellGenerator> { + func collectionGenerator(with model: Base.Model) -> BaseCollectionCellGenerator> { CollectionWrappedCell.rddm.baseGenerator(with: model, - and: registerType) + and: .class) } } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index a02d6c1d..736d6177 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -18,7 +18,7 @@ extension TableContext: BuilderContext { public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, Item: RegistrationTypeProvider { - Item.rddm.tableGenerator(with: model, and: Item.prefferedRegistration) + Item.rddm.tableGenerator(with: model) } public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, @@ -28,19 +28,19 @@ extension TableContext: BuilderContext { } public static func stack(model: StackView.Model) -> TableCellGenerator { - StackView.rddm.tableGenerator(with: model, and: .class) + StackView.rddm.tableGenerator(with: model) } @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewNib(type: T.Type, model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model, and: .nib) + T.rddm.tableGenerator(with: model) } @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") public static func viewClass(type: T.Type, model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model, and: .class) + T.rddm.tableGenerator(with: model) } } diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift index 530b10fe..860ffcc0 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift @@ -10,10 +10,9 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { - func tableGenerator(with model: Base.Model, - and registerType: RegistrationType = .nib) -> BaseCellGenerator> { + func tableGenerator(with model: Base.Model) -> BaseCellGenerator> { TableWrappedCell.rddm.baseGenerator(with: model, - and: registerType) + and: .class) } } diff --git a/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift b/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift index ff15d74d..9bb0e26d 100644 --- a/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift @@ -45,7 +45,7 @@ final class ComponentsOverviewTableViewController: UIViewController { right: 0))) } - private lazy var recievedMessageTimeGenerator = LabelView.rddm.tableGenerator(with: recievedMessageTimeModel, and: .class) + private lazy var recievedMessageTimeGenerator = LabelView.rddm.tableGenerator(with: recievedMessageTimeModel) // Sent message time private let sentTimeMessageStyle = TextStyle(color: .gray, font: .preferredFont(forTextStyle: .caption1)) @@ -61,7 +61,7 @@ final class ComponentsOverviewTableViewController: UIViewController { right: 16))) } - private lazy var sentMessageTimeGenerator = LabelView.rddm.tableGenerator(with: sentTimeMessageModel, and: .class) + private lazy var sentMessageTimeGenerator = LabelView.rddm.tableGenerator(with: sentTimeMessageModel) // Date private let dateStyle = TextStyle(color: .black, font: .preferredFont(forTextStyle: .caption1)) @@ -77,7 +77,7 @@ final class ComponentsOverviewTableViewController: UIViewController { right: 0))) } - private lazy var dateGenerator = LabelView.rddm.tableGenerator(with: dateModel, and: .class) + private lazy var dateGenerator = LabelView.rddm.tableGenerator(with: dateModel) // Sent message private let sentMessageStyle = TextStyle(color: .white, @@ -102,7 +102,7 @@ final class ComponentsOverviewTableViewController: UIViewController { property.text(.string("Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet")) } - private lazy var sentMessageGenerator = MessageView.rddm.tableGenerator(with: sentMessageModel, and: .class) + private lazy var sentMessageGenerator = MessageView.rddm.tableGenerator(with: sentMessageModel) // Recieved message private let recievedMessageStyle = TextStyle(color: .black, font: .preferredFont(forTextStyle: .body)) @@ -137,14 +137,14 @@ final class ComponentsOverviewTableViewController: UIViewController { property.selectable(true) } - private lazy var recievedMessageGenerator = MessageView.rddm.tableGenerator(with: recievedMessageModel, and: .class) + private lazy var recievedMessageGenerator = MessageView.rddm.tableGenerator(with: recievedMessageModel) // Separator private let separatorModel = SeparatorModel(size: .height(1), color: .lightGray, edgeInsets: UIEdgeInsets(top: 0, left: 32, bottom: 0, right: 32)) - private lazy var separatorGenerator = TableWrappedCell.rddm.baseGenerator(with: separatorModel, and: .class) + private lazy var separatorGenerator = SeparatorView.rddm.tableGenerator(with: separatorModel) // MARK: - UIViewController diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index fe6e10b1..eb6cb065 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -93,10 +93,11 @@ private extension StackCellExampleViewController { LabelView.build(in: ctx, with: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) - label.style(.init(color: .systemBlue, font: .systemFont(ofSize: 16))) + label.style(.init(color: .systemBlue, font: .preferredFont(forTextStyle: .body))) }) - // TODO: - resolve crash with neb loading -// TitleTableViewCell.build(in: ctx, with: "Cell outside from stack") + ctx.gen(TitleTableViewCell.self, model: "Cell outside from stack") + // TODO: - crash is fixed but we got `TableWrappedCell which is not correct` + TitleTableViewCell.build(in: ctx, with: "Cell outside from stack") StackView.build(in: ctx, with: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, From c9ad7199477aea0d5dae094934e5ea74c46f3cfa Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Thu, 27 Jul 2023 16:09:48 +0400 Subject: [PATCH 16/30] add common decorations and transformations for base generators --- ...lectionContext+CollectionWrappedCell.swift | 2 - .../ConfigurableItem+BuilderContext.swift | 2 +- .../TableContext+TableWrappedCell.swift | 4 +- .../Extensions/TableWrappedCell+RDDM.swift | 11 ++- .../CollectionViewController.swift | 15 ++-- .../FoldableCollectionViewController.swift | 8 +-- .../Landing/LandingStackViewController.swift | 2 +- .../Generators/InnerStackCellGenerator.swift | 8 +-- .../AllPluginsTableViewController.swift | 2 +- .../FoldableTableViewController.swift | 2 +- .../GravityTableViewController.swift | 2 +- .../Mocks/AutoMockable.generated.swift | 2 +- .../GravityFoldingHeaderGenerator.swift | 6 +- .../BaseCollectionCellGenerator.swift | 69 +++++++++++++++++++ .../FoldableCollectionCellGenerator.swift | 32 ++++++++- .../CollectionFoldablePlugin.swift | 4 +- .../Protocols/CollectionFoldableItem.swift | 4 +- .../Plugins/Generators/FoldableItem.swift | 4 +- .../Stack/Generators/BaseViewGenerator.swift | 4 +- .../Table/Generators/BaseCellGenerator.swift | 69 +++++++++++++++++++ .../Generators/FoldableCellGenerator.swift | 38 +++++++++- .../PluginAction/TableFoldablePlugin.swift | 18 ++--- 22 files changed, 257 insertions(+), 51 deletions(-) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 3f1a0db1..50082214 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -14,8 +14,6 @@ extension CollectionContext: BuilderContext { public typealias ViewType = UICollectionViewCell public typealias GeneratorType = CollectionCellGenerator - // TODO: - add support for other types of generators or make (decorated generator) - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, Item: RegistrationTypeProvider { Item.rddm.collectionGenerator(with: model) diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift index 3d7d5c38..ee6f4497 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -13,5 +13,5 @@ public extension ConfigurableItem where Self: RegistrationTypeProvider { static func build(in ctx: Context.Type, with model: Model) -> Context.GeneratorType { ctx.gen(Self.self, model: model) } - + } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index 736d6177..5f954687 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -14,11 +14,9 @@ extension TableContext: BuilderContext { public typealias ViewType = UITableViewCell public typealias GeneratorType = TableCellGenerator - // TODO: - add support for other types of generators or make (decorated generator) - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, Item: RegistrationTypeProvider { - Item.rddm.tableGenerator(with: model) + Item.rddm.tableGenerator(with: model) } public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift index 860ffcc0..63bef8f3 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift @@ -11,8 +11,15 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { func tableGenerator(with model: Base.Model) -> BaseCellGenerator> { - TableWrappedCell.rddm.baseGenerator(with: model, - and: .class) + TableWrappedCell.rddm.baseGenerator(with: model, and: .class) + } + +} + +public extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem & RegistrationTypeProvider { + + func tableGenerator(with model: Base.Model) -> BaseCellGenerator { + Base.rddm.baseGenerator(with: model, and: Base.prefferedRegistration) } } diff --git a/Example/ReactiveDataDisplayManager/Collection/CollectionViewController/CollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/CollectionViewController/CollectionViewController.swift index bbc6b5e7..050e47d9 100644 --- a/Example/ReactiveDataDisplayManager/Collection/CollectionViewController/CollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/CollectionViewController/CollectionViewController.swift @@ -64,14 +64,13 @@ private extension CollectionViewController { CollectionGenerators { titles.map { title -> CollectionCellGenerator in // Create generator - let generator = TitleCollectionViewCell.rddm.calculatableHeightGenerator(with: title, referencedWidth: 100) - generator.didSelectEvent += { - debugPrint("\(title) selected") - } - generator.didDeselectEvent += { - debugPrint("\(title) deselected") - } - return generator + return TitleCollectionViewCell.rddm.calculatableHeightGenerator(with: title, referencedWidth: 100) + .didSelectEvent { + debugPrint("\(title) selected") + } + .didDeselectEvent { + debugPrint("\(title) deselected") + } } } } diff --git a/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift index af329e46..88218bbb 100644 --- a/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift @@ -84,9 +84,9 @@ private extension FoldableCollectionViewController { let folder3 = makeFoldableCellGenerator(color: .lightGray, expanded: true) // Configure relationship - folder3.childGenerators = child3 - folder2.childGenerators = child2 + [folder3] - folder1.childGenerators = child1 + [folder2] + folder3.children = child3 + folder2.children = child2 + [folder3] + folder1.children = child1 + [folder2] // Add foldable cell generators to adapter let visibleGenerators = getVisibleGenerators(for: folder1) @@ -131,7 +131,7 @@ private extension FoldableCollectionViewController { func getVisibleGenerators(for generator: CollectionCellGenerator) -> [CollectionCellGenerator] { if let foldableItem = generator as? CollectionFoldableItem, foldableItem.isExpanded { - return foldableItem.childGenerators + return foldableItem.children .map { getVisibleGenerators(for: $0) } .reduce([generator], +) } else { diff --git a/Example/ReactiveDataDisplayManager/Stack/Landing/LandingStackViewController.swift b/Example/ReactiveDataDisplayManager/Stack/Landing/LandingStackViewController.swift index c02e92bf..81c67b37 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Landing/LandingStackViewController.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Landing/LandingStackViewController.swift @@ -80,7 +80,7 @@ private extension LandingStackViewController { alignment: .center, distribution: .fillEqually, spacing: 32), - childGenerators: [mainButton, secondaryButton]) + children: [mainButton, secondaryButton]) // Add generators to adapter adapter += title diff --git a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift index 3b57ec76..745205de 100644 --- a/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Stack/Views/Generators/InnerStackCellGenerator.swift @@ -22,13 +22,13 @@ final class InnerStackCellGenerator: ViewGenerator { // MARK: - Properties private let model: Model - private let childGenerators: [ViewGenerator] + private let children: [ViewGenerator] // MARK: - Initialization - init(model: Model, childGenerators: [ViewGenerator]) { + init(model: Model, children: [ViewGenerator]) { self.model = model - self.childGenerators = childGenerators + self.children = children } } @@ -47,7 +47,7 @@ extension InnerStackCellGenerator: ViewBuilder { let adapter = view.rddm.baseBuilder .build() - adapter += childGenerators + adapter += children adapter => .reload } diff --git a/Example/ReactiveDataDisplayManager/Table/AllPluginsTableViewController/AllPluginsTableViewController.swift b/Example/ReactiveDataDisplayManager/Table/AllPluginsTableViewController/AllPluginsTableViewController.swift index a1634e75..f07136e9 100644 --- a/Example/ReactiveDataDisplayManager/Table/AllPluginsTableViewController/AllPluginsTableViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/AllPluginsTableViewController/AllPluginsTableViewController.swift @@ -199,7 +199,7 @@ private extension AllPluginsTableViewController { let generator = FoldableTableViewCell.rddm.foldableGenerator(with: .init(title: "", isExpanded: false)) // Create and add child generators - generator.childGenerators = Constants.titles.map { TitleTableViewCell.rddm.baseGenerator(with: $0) } + generator.children = Constants.titles.map { TitleTableViewCell.rddm.baseGenerator(with: $0) } // Add generator to adapter adapter += generator diff --git a/Example/ReactiveDataDisplayManager/Table/FoldableTableViewController/FoldableTableViewController.swift b/Example/ReactiveDataDisplayManager/Table/FoldableTableViewController/FoldableTableViewController.swift index 7e1e289d..cae1e720 100644 --- a/Example/ReactiveDataDisplayManager/Table/FoldableTableViewController/FoldableTableViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/FoldableTableViewController/FoldableTableViewController.swift @@ -89,7 +89,7 @@ private extension FoldableTableViewController { let generator = FoldableTableViewCell.rddm.foldableGenerator(with: .init(title: id, isExpanded: false)) // Create and add child generators - generator.childGenerators = Constants.titleForSubcells.map { TitleTableViewCell.rddm.baseGenerator(with: $0) } + generator.children = Constants.titleForSubcells.map { TitleTableViewCell.rddm.baseGenerator(with: $0) } return generator } diff --git a/Example/ReactiveDataDisplayManager/Table/GravityTableViewController/GravityTableViewController.swift b/Example/ReactiveDataDisplayManager/Table/GravityTableViewController/GravityTableViewController.swift index dd04faac..4f645278 100644 --- a/Example/ReactiveDataDisplayManager/Table/GravityTableViewController/GravityTableViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/GravityTableViewController/GravityTableViewController.swift @@ -72,7 +72,7 @@ private extension GravityTableViewController { func makeGravityFoldableCellGenerator(with heaviness: Int) -> GravityFoldableCellGenerator { let generator = GravityFoldableCellGenerator(heaviness: heaviness) - generator.childGenerators = [ + generator.children = [ makeGravityCellGenerator(with: 1), makeGravityCellGenerator(with: 2) ] diff --git a/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift b/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift index 2d56a85a..6a88b33e 100644 --- a/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift +++ b/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift @@ -102,7 +102,7 @@ class CollectionFoldableItemMock: CollectionFoldableItem { set(value) { underlyingIsExpanded = value } } var underlyingIsExpanded: Bool! - var childGenerators: [CollectionCellGenerator] = [] + var children: [CollectionCellGenerator] = [] var labelStrategy: AccessibilityStringStrategy { get { return underlyingLabelStrategy } set(value) { underlyingLabelStrategy = value } diff --git a/ReactiveDataDisplayManagerTests/Table/Manager/GravityFoldingHeaderGenerator.swift b/ReactiveDataDisplayManagerTests/Table/Manager/GravityFoldingHeaderGenerator.swift index f6a48ee8..784ad459 100644 --- a/ReactiveDataDisplayManagerTests/Table/Manager/GravityFoldingHeaderGenerator.swift +++ b/ReactiveDataDisplayManagerTests/Table/Manager/GravityFoldingHeaderGenerator.swift @@ -16,7 +16,7 @@ final class GravityFoldingHeaderGenerator: GravityTableCellGenerator, FoldableIt var didFoldEvent = Event() var isExpanded = true - var childGenerators = [TableCellGenerator]() + var children = [TableCellGenerator]() // MARK: - GravityTableCellGenerator @@ -93,7 +93,7 @@ final class GravityFoldingTableDataDisplayManagerTests: XCTestCase { let childGenerator3 = GravityCellGenerator() let header = GravityFoldingHeaderGenerator() - header.childGenerators = [childGenerator1, childGenerator2, childGenerator3] + header.children = [childGenerator1, childGenerator2, childGenerator3] header.isExpanded = true ddm.addCellGenerators([header, childGenerator1, childGenerator2, childGenerator3]) @@ -116,7 +116,7 @@ final class GravityFoldingTableDataDisplayManagerTests: XCTestCase { let childGenerator3 = GravityCellGenerator() let header = GravityFoldingHeaderGenerator() - header.childGenerators = [childGenerator1, childGenerator2, childGenerator3] + header.children = [childGenerator1, childGenerator2, childGenerator3] header.isExpanded = false ddm.addCellGenerator(header) diff --git a/Source/Collection/Generators/BaseCollectionCellGenerator.swift b/Source/Collection/Generators/BaseCollectionCellGenerator.swift index 08263c00..66d0b748 100644 --- a/Source/Collection/Generators/BaseCollectionCellGenerator.swift +++ b/Source/Collection/Generators/BaseCollectionCellGenerator.swift @@ -63,3 +63,72 @@ extension BaseCollectionCellGenerator: CollectionCellGenerator { } } + +// MARK: - Decorations + +public extension BaseCollectionCellGenerator { + + /// - Parameter isNeedDeselect: defines if cell should be deselected after selection + func isNeedDeselect(_ isNeedDeselect: Bool) -> Self { + self.isNeedDeselect = isNeedDeselect + return self + } + + /// - Parameter closure: closure that will be called when cell is selected + func didSelectEvent(_ closure: @escaping () -> Void) -> Self { + self.didSelectEvent.addListner(closure) + return self + } + + /// - Parameter closure: closure that will be called when cell is deselected in multiple selection mode + func didDeselectEvent(_ closure: @escaping () -> Void) -> Self { + self.didDeselectEvent.addListner(closure) + return self + } + +} + +// MARK: - Transformations + +public extension BaseCollectionCellGenerator where Cell: FoldableStateHolder { + + /// Creates FoldableCellGenerator with predefined children + /// - Parameter children: array of children + func asFoldable(_ children: [CollectionCellGenerator]) -> FoldableCollectionCellGenerator { + return .init(with: model, + registerType: registerType) + .children(children) + } + + /// Creates FoldableCellGenerator with children generated by resultBuilder + /// - Parameter content: resultBuilder based closure that returns array of children + func asFoldable(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> FoldableCollectionCellGenerator { + return .init(with: model, + registerType: registerType) + .children(content) + } + +} + +public extension BaseCollectionCellGenerator where Cell.Model: Equatable { + + /// Creates DiffableCellGenerator with constant but unique Id + /// - Parameter uniqueId: uniqueId to identify cell + func asDiffable(uniqueId: AnyHashable) -> DiffableCollectionCellGenerator { + .init(uniqueId: uniqueId, + with: model, + registerType: registerType) + } + +} + +public extension BaseCollectionCellGenerator where Cell.Model: Equatable & IdOwner { + + /// Creates DiffableCellGenerator with uniqueId from model + func asDiffable() -> DiffableCollectionCellGenerator { + .init(uniqueId: model.id, + with: model, + registerType: registerType) + } + +} diff --git a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift b/Source/Collection/Generators/FoldableCollectionCellGenerator.swift index 9a517fab..6d9a0119 100644 --- a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift +++ b/Source/Collection/Generators/FoldableCollectionCellGenerator.swift @@ -21,7 +21,7 @@ open class FoldableCollectionCellGenerator Self { + self.isExpanded = isExpanded + return self + } + + /// - Parameter closure: handler closure for expand/collapse events + func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { + self.didFoldEvent.addListner(closure) + return self + } + + /// - Parameter children: array of child generators + func children(_ children: [CollectionCellGenerator]) -> Self { + self.children = children + return self + } + + /// - Parameter content: resultBuilder based closure that returns an array of child generators + func children(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> Self { + self.children = content(CollectionContext.self) + return self + } + +} diff --git a/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift b/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift index 575fdd72..4c7897a2 100644 --- a/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift +++ b/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift @@ -21,7 +21,7 @@ public class CollectionFoldablePlugin: BaseCollectionPlugin { return } - let visibleGenerators = foldable.childGenerators + let visibleGenerators = foldable.children .map { getVisibleGenerators(for: $0) } .reduce([], +) @@ -50,7 +50,7 @@ private extension CollectionFoldablePlugin { func getVisibleGenerators(for generator: CollectionCellGenerator) -> [CollectionCellGenerator] { if let foldableItem = generator as? CollectionFoldableItem, foldableItem.isExpanded { - return foldableItem.childGenerators + return foldableItem.children .map { getVisibleGenerators(for: $0) } .reduce([generator], +) } else { diff --git a/Source/Collection/Protocols/CollectionFoldableItem.swift b/Source/Collection/Protocols/CollectionFoldableItem.swift index 25f18fb0..e878a81f 100644 --- a/Source/Collection/Protocols/CollectionFoldableItem.swift +++ b/Source/Collection/Protocols/CollectionFoldableItem.swift @@ -12,10 +12,10 @@ import UIKit public protocol CollectionFoldableItem: AnyObject, AccessibilityStrategyProvider { var didFoldEvent: Event { get } var isExpanded: Bool { get set } - var childGenerators: [CollectionCellGenerator] { get set } + var children: [CollectionCellGenerator] { get set } } public extension CollectionFoldableItem { var labelStrategy: AccessibilityStringStrategy { .ignored } - var traitsStrategy: AccessibilityTraitsStrategy { childGenerators.isEmpty ? .ignored : .just(.button) } + var traitsStrategy: AccessibilityTraitsStrategy { children.isEmpty ? .ignored : .just(.button) } } diff --git a/Source/Protocols/Plugins/Generators/FoldableItem.swift b/Source/Protocols/Plugins/Generators/FoldableItem.swift index b5812dd5..98dc5d6d 100644 --- a/Source/Protocols/Plugins/Generators/FoldableItem.swift +++ b/Source/Protocols/Plugins/Generators/FoldableItem.swift @@ -26,7 +26,7 @@ public protocol FoldableItem: AnyObject, AccessibilityStrategyProvider { var isExpanded: Bool { get set } /// Generators describing cells to be inserted in expanded state - var childGenerators: [TableCellGenerator] { get set } + var children: [TableCellGenerator] { get set } } @@ -36,5 +36,5 @@ public extension FoldableItem { } var labelStrategy: AccessibilityStringStrategy { .ignored } - var traitsStrategy: AccessibilityTraitsStrategy { childGenerators.isEmpty ? .ignored : .just(.button) } + var traitsStrategy: AccessibilityTraitsStrategy { children.isEmpty ? .ignored : .just(.button) } } diff --git a/Source/Stack/Generators/BaseViewGenerator.swift b/Source/Stack/Generators/BaseViewGenerator.swift index 39ba4791..5a8b0b30 100644 --- a/Source/Stack/Generators/BaseViewGenerator.swift +++ b/Source/Stack/Generators/BaseViewGenerator.swift @@ -7,11 +7,11 @@ import UIKit -final public class EmptyViewGenerator: AccessoryViewGenerator { +public final class EmptyViewGenerator: AccessoryViewGenerator { public typealias ViewType = View - public init() {} + public init() { } public func generate() -> View { switch View.prefferedRegistration { diff --git a/Source/Table/Generators/BaseCellGenerator.swift b/Source/Table/Generators/BaseCellGenerator.swift index c72d9f7b..3bedf0c5 100644 --- a/Source/Table/Generators/BaseCellGenerator.swift +++ b/Source/Table/Generators/BaseCellGenerator.swift @@ -70,3 +70,72 @@ open class BaseCellGenerator: SelectableTableCellGenerat } } + +// MARK: - Decorations + +public extension BaseCellGenerator { + + /// - Parameter isNeedDeselect: defines if cell should be deselected after selection + func isNeedDeselect(_ isNeedDeselect: Bool) -> Self { + self.isNeedDeselect = isNeedDeselect + return self + } + + /// - Parameter closure: closure that will be called when cell is selected + func didSelectEvent(_ closure: @escaping () -> Void) -> Self { + self.didSelectEvent.addListner(closure) + return self + } + + /// - Parameter closure: closure that will be called when cell is deselected in multiple selection mode + func didDeselectEvent(_ closure: @escaping () -> Void) -> Self { + self.didDeselectEvent.addListner(closure) + return self + } + +} + +// MARK: - Transformations + +public extension BaseCellGenerator where Cell: FoldableStateHolder { + + /// Creates FoldableCellGenerator with predefined children + /// - Parameter children: array of children + func asFoldable(_ children: [TableCellGenerator]) -> FoldableCellGenerator { + return .init(with: model, + registerType: registerType) + .children(children) + } + + /// Creates FoldableCellGenerator with children generated by resultBuilder + /// - Parameter content: resultBuilder based closure that returns array of children + func asFoldable(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> FoldableCellGenerator { + return .init(with: model, + registerType: registerType) + .children(content) + } + +} + +public extension BaseCellGenerator where Cell.Model: Equatable { + + /// Creates DiffableCellGenerator with constant but unique Id + /// - Parameter uniqueId: uniqueId to identify cell + func asDiffable(uniqueId: AnyHashable) -> DiffableCellGenerator { + .init(uniqueId: uniqueId, + with: model, + registerType: registerType) + } + +} + +public extension BaseCellGenerator where Cell.Model: Equatable & IdOwner { + + /// Creates DiffableCellGenerator with uniqueId from model + func asDiffable() -> DiffableCellGenerator { + .init(uniqueId: model.id, + with: model, + registerType: registerType) + } + +} diff --git a/Source/Table/Generators/FoldableCellGenerator.swift b/Source/Table/Generators/FoldableCellGenerator.swift index 19a0bb34..a26baed3 100644 --- a/Source/Table/Generators/FoldableCellGenerator.swift +++ b/Source/Table/Generators/FoldableCellGenerator.swift @@ -22,7 +22,7 @@ open class FoldableCellGenerator Self { + self.animation = animation + return self + } + + /// - Parameter isExpanded: folded/unfolded state + func isExpanded(_ isExpanded: Bool) -> Self { + self.isExpanded = isExpanded + return self + } + + /// - Parameter closure: handler closure for folded/unfolded events + func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { + self.didFoldEvent.addListner(closure) + return self + } + + /// - Parameter children: array of child generators + func children(_ children: [TableCellGenerator]) -> Self { + self.children = children + return self + } + + /// - Parameter content: resultBuilder based closure that returns an array of child generators + func children(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> Self { + self.children = content(TableContext.self) + return self + } + +} diff --git a/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift b/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift index 8b80e581..a1b939e1 100644 --- a/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift +++ b/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift @@ -30,19 +30,19 @@ public class TableFoldablePlugin: BaseTablePlugin { } if foldable.isExpanded { - foldable.childGenerators.forEach { manager?.remove($0, + foldable.children.forEach { manager?.remove($0, with: .animated(foldable.animation.remove), needScrollAt: nil, needRemoveEmptySection: false) } } else { - addCellGenerators(foldable.childGenerators, after: generator, with: manager) + addCellGenerators(foldable.children, after: generator, with: manager) } foldable.isExpanded = !foldable.isExpanded foldable.didFoldEvent.invoke(with: (foldable.isExpanded)) - updateIfNeeded(foldable.childGenerators, with: manager) + updateIfNeeded(foldable.children, with: manager) default: break } @@ -54,21 +54,21 @@ public class TableFoldablePlugin: BaseTablePlugin { private extension TableFoldablePlugin { - func addCellGenerators(_ childGenerators: [TableCellGenerator], + func addCellGenerators(_ children: [TableCellGenerator], after generator: TableCellGenerator, with manager: BaseTableManager?) { if let manager = manager as? GravityTableManager { - manager.addCellGenerators(childGenerators, after: generator) + manager.addCellGenerators(children, after: generator) } else if let foldable = generator as? FoldableItem { - manager?.insertManual(after: generator, new: childGenerators, with: .animated(foldable.animation.insert)) + manager?.insertManual(after: generator, new: children, with: .animated(foldable.animation.insert)) } else { - manager?.insertManual(after: generator, new: childGenerators, with: .notAnimated) + manager?.insertManual(after: generator, new: children, with: .notAnimated) } } - func updateIfNeeded(_ childGenerators: [TableCellGenerator], with manager: BaseTableManager?) { + func updateIfNeeded(_ children: [TableCellGenerator], with manager: BaseTableManager?) { guard let manager = manager as? GravityTableManager else { return } - manager.update(generators: childGenerators) + manager.update(generators: children) } } From 3e1bef717cc115eb83dddd183d1819c8a75e49f8 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Thu, 27 Jul 2023 16:52:34 +0400 Subject: [PATCH 17/30] remove deprecated methods --- ...lectionContext+CollectionWrappedCell.swift | 12 ----------- .../TableContext+TableWrappedCell.swift | 12 ----------- ...kCellExampleCollectionViewController.swift | 20 +++++++++---------- .../Generators/CollectionContext.swift | 11 +--------- Source/Stack/Generators/ViewContext.swift | 12 ----------- Source/Table/Generators/TableContext.swift | 11 +--------- 6 files changed, 11 insertions(+), 67 deletions(-) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 50082214..60ac0b46 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -29,16 +29,4 @@ extension CollectionContext: BuilderContext { StackView.rddm.collectionGenerator(with: model) } - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewNib(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model) - } - - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewClass(type: T.Type, - model: T.Model) -> BaseCollectionCellGenerator> { - T.rddm.collectionGenerator(with: model) - } - } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index 5f954687..447105c8 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -29,16 +29,4 @@ extension TableContext: BuilderContext { StackView.rddm.tableGenerator(with: model) } - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewNib(type: T.Type, - model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model) - } - - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewClass(type: T.Type, - model: T.Model) -> BaseCellGenerator> { - T.rddm.tableGenerator(with: model) - } - } diff --git a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift index 49bb369e..9ce3817d 100644 --- a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift @@ -103,24 +103,22 @@ private extension StackCellExampleCollectionViewController { SeparatorView.buildView(with: .init(size: .height(1), color: .black), and: .class) } - adapter += CollectionSection.create(header: EmptyCollectionHeaderGenerator(), footer: EmptyCollectionFooterGenerator()) { it in - it.viewClass(type: SeparatorView.self, model: .init(size: .height(1), color: .black)) - it.stack(model: .build { hStack in + adapter += CollectionSection.create(header: EmptyCollectionHeaderGenerator(), footer: EmptyCollectionFooterGenerator()) { ctx in + SeparatorView.build(in: ctx, with: .init(size: .height(1), color: .black)) + StackView.build(in: ctx, with: .build { hStack in hStack.style(.init(axis: .horizontal, spacing: 0, alignment: .fill, distribution: .fillEqually)) - hStack.children { it in - it.viewClass(type: SeparatorView.self, model: .init(size: .width(1), color: .black)) - it.viewClass(type: SpacerView.self, model: .init(size: .width(64))) - - it.viewNib(type: TitleTableViewCell.self, model: "Some text") - - it.viewClass(type: SeparatorView.self, model: .init(size: .width(1), color: .black)) + hStack.children { ctx in + SeparatorView.build(in: ctx, with: .init(size: .width(1), color: .black)) + SpacerView.build(in: ctx, with: .init(size: .width(64))) + TitleTableViewCell.build(in: ctx, with: "Some text") + SeparatorView.build(in: ctx, with: .init(size: .width(1), color: .black)) } }) - it.viewClass(type: SeparatorView.self, model: .init(size: .height(1), color: .black)) + SeparatorView.build(in: ctx, with: .init(size: .height(1), color: .black)) } // Tell adapter that we've changed generators diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift index f057a2f1..0e61769d 100644 --- a/Source/Collection/Generators/CollectionContext.swift +++ b/Source/Collection/Generators/CollectionContext.swift @@ -8,13 +8,4 @@ import UIKit import Foundation -public struct CollectionContext { - - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func cell(type: T.Type, - model: T.Model, - registerType: RegistrationType) -> BaseCollectionCellGenerator { - T.rddm.baseGenerator(with: model, and: registerType) - } - -} +public struct CollectionContext { } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index 012d3566..d38c8bc2 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -18,16 +18,4 @@ public struct ViewContext: BuilderContext { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) } - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewClass(type: T.Type, - model: T.Model) -> BaseViewGenerator { - T.rddm.viewGenerator(with: model, and: .class) - } - - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func viewNib(type: T.Type, - model: T.Model) -> BaseViewGenerator { - T.rddm.viewGenerator(with: model, and: .nib) - } - } diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 11493dc7..f9d91b67 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -8,13 +8,4 @@ import UIKit import Foundation -public struct TableContext { - - @available(*, deprecated, renamed: "gen", message: "Please use `gen` method and `RegistrationTypeProvider` instead") - public static func cell(type: T.Type, - model: T.Model, - registerType: RegistrationType) -> BaseCellGenerator { - T.rddm.baseGenerator(with: model, and: registerType) - } - -} +public struct TableContext { } From 6e476153e4b7d9bb7178a08d5d454b094388102a Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 11:36:27 +0400 Subject: [PATCH 18/30] resolve generic in extension for ConfigurableItem --- .../ConfigurableItem+BuilderContext.swift | 18 +++++++++++++++++- .../StackCellExampleViewController.swift | 2 -- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift index ee6f4497..24343a40 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -10,7 +10,23 @@ import ReactiveDataDisplayManager public extension ConfigurableItem where Self: RegistrationTypeProvider { - static func build(in ctx: Context.Type, with model: Model) -> Context.GeneratorType { + static func build(in ctx: ViewContext.Type, with model: Model) -> ViewContext.GeneratorType { + ctx.gen(Self.self, model: model) + } + + static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType where Self: UITableViewCell { + ctx.gen(Self.self, model: model) + } + + static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType { + ctx.gen(Self.self, model: model) + } + + static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType where Self: UICollectionViewCell { + ctx.gen(Self.self, model: model) + } + + static func build(in ctx: CollectionContext.Type, with model: Model) -> CollectionContext.GeneratorType { ctx.gen(Self.self, model: model) } diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index eb6cb065..cc89239e 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -95,8 +95,6 @@ private extension StackCellExampleViewController { label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .preferredFont(forTextStyle: .body))) }) - ctx.gen(TitleTableViewCell.self, model: "Cell outside from stack") - // TODO: - crash is fixed but we got `TableWrappedCell which is not correct` TitleTableViewCell.build(in: ctx, with: "Cell outside from stack") StackView.build(in: ctx, with: .build { hStack in hStack.background(.solid(.systemGreen)) From 813f6463e688e50e303e525ae37b36b2ee421a3f Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 12:48:15 +0400 Subject: [PATCH 19/30] make common BaseCellGenerator for table and collection --- .../Collection/CollectionWrappedCell.swift | 2 +- .../CollectionDecorationProvider.swift | 2 +- ...lectionContext+CollectionWrappedCell.swift | 6 +- .../CollectionWrappedCell+RDDM.swift | 4 +- .../TableContext+TableWrappedCell.swift | 8 +- .../Extensions/TableWrappedCell+RDDM.swift | 4 +- .../Sources/Table/TableWrappedCell.swift | 2 +- .../DiffableCollectionViewController.swift | 2 +- .../DifferenceCollectionViewController.swift | 2 +- .../DynamicHeightTableViewCell.swift | 2 +- .../ImageCollectionCellGenerator.swift | 2 +- .../MovableCollectionCellGenerator.swift | 2 +- .../SwipeableCollectionGenerator.swift | 2 +- .../Generators/TitleCollectionGenerator.swift | 2 +- .../VerticalSizableTextGenerator.swift | 2 +- .../ImageCollectionViewGenerator.swift | 2 +- ...faultBehavoirCollectionViewGenerator.swift | 2 +- ...fetchableCollectionCellGeneratorMock.swift | 4 +- .../Mock/StubCollectionCellGenerator.swift | 2 +- Source/Collection/CollectionCell+RDDM.swift | 2 +- .../BaseCollectionCellGenerator.swift | 134 ------------------ ...latableHeightCollectionCellGenerator.swift | 2 +- ...ulatableWidthCollectionCellGenerator.swift | 2 +- .../DiffableCollectionCellGenerator.swift | 47 ------ .../FoldableCollectionCellGenerator.swift | 4 +- .../Generators/BaseCellGenerator.swift | 65 +++++++-- .../Generators/DiffableCellGenerator.swift | 6 +- .../BuilderContext/BuilderContext.swift | 2 +- .../Plugins/Generators/BaseItem.swift | 8 ++ .../Stack/Generators/BaseViewGenerator.swift | 4 +- Source/Stack/Generators/ViewContext.swift | 3 +- .../BaseNonReusableCellGenerator.swift | 2 +- ...atableHeightNonReusableCellGenerator.swift | 74 ---------- .../Generators/FoldableCellGenerator.swift | 2 +- 34 files changed, 98 insertions(+), 313 deletions(-) delete mode 100644 Source/Collection/Generators/BaseCollectionCellGenerator.swift delete mode 100644 Source/Collection/Generators/DiffableCollectionCellGenerator.swift rename Source/{Table => Common}/Generators/BaseCellGenerator.swift (75%) rename Source/{Table => Common}/Generators/DiffableCellGenerator.swift (78%) create mode 100644 Source/Protocols/Plugins/Generators/BaseItem.swift delete mode 100644 Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift diff --git a/Components/Sources/Collection/CollectionWrappedCell.swift b/Components/Sources/Collection/CollectionWrappedCell.swift index d54b9e79..6556039e 100644 --- a/Components/Sources/Collection/CollectionWrappedCell.swift +++ b/Components/Sources/Collection/CollectionWrappedCell.swift @@ -9,7 +9,7 @@ import UIKit import ReactiveDataDisplayManager /// Empty collection cell with `View`. Configuration is implemented within `ViewWrapper`. -public final class CollectionWrappedCell: UICollectionViewCell, ViewWrapper { +public final class CollectionWrappedCell: UICollectionViewCell, ViewWrapper { public typealias Model = View.Model diff --git a/Components/Sources/Collection/DecorationProviders/CollectionDecorationProvider.swift b/Components/Sources/Collection/DecorationProviders/CollectionDecorationProvider.swift index 6d64094a..31cb37f2 100644 --- a/Components/Sources/Collection/DecorationProviders/CollectionDecorationProvider.swift +++ b/Components/Sources/Collection/DecorationProviders/CollectionDecorationProvider.swift @@ -10,7 +10,7 @@ import ReactiveDataDisplayManager final class CollectionDecorationProvider: DecorationProvider where Cell.Model: Equatable { - typealias GeneratorType = DiffableCollectionCellGenerator + typealias GeneratorType = DiffableCellGenerator // MARK: - Properties diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift index 60ac0b46..036bbb82 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift @@ -14,14 +14,12 @@ extension CollectionContext: BuilderContext { public typealias ViewType = UICollectionViewCell public typealias GeneratorType = CollectionCellGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, - Item: RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { Item.rddm.collectionGenerator(with: model) } public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, - Item: ConfigurableItem, - Item: RegistrationTypeProvider { + Item: BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift index f17c2434..cf15bba2 100644 --- a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift +++ b/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift @@ -8,9 +8,9 @@ import ReactiveDataDisplayManager import UIKit -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { +public extension StaticDataDisplayWrapper where Base: UIView & BaseItem { - func collectionGenerator(with model: Base.Model) -> BaseCollectionCellGenerator> { + func collectionGenerator(with model: Base.Model) -> BaseCellGenerator> { CollectionWrappedCell.rddm.baseGenerator(with: model, and: .class) } diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift index 447105c8..6e936b62 100644 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift @@ -14,14 +14,12 @@ extension TableContext: BuilderContext { public typealias ViewType = UITableViewCell public typealias GeneratorType = TableCellGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, - Item: RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { Item.rddm.tableGenerator(with: model) } - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, - Item: ConfigurableItem, - Item: RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> any GeneratorType where Item: ViewType, + Item: BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift index 63bef8f3..e73043a0 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift @@ -8,7 +8,7 @@ import ReactiveDataDisplayManager import UIKit -public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & RegistrationTypeProvider { +public extension StaticDataDisplayWrapper where Base: UIView & BaseItem { func tableGenerator(with model: Base.Model) -> BaseCellGenerator> { TableWrappedCell.rddm.baseGenerator(with: model, and: .class) @@ -16,7 +16,7 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem } -public extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem & RegistrationTypeProvider { +public extension StaticDataDisplayWrapper where Base: UITableViewCell & BaseItem { func tableGenerator(with model: Base.Model) -> BaseCellGenerator { Base.rddm.baseGenerator(with: model, and: Base.prefferedRegistration) diff --git a/Components/Sources/Table/TableWrappedCell.swift b/Components/Sources/Table/TableWrappedCell.swift index 78b477a2..f80976ae 100644 --- a/Components/Sources/Table/TableWrappedCell.swift +++ b/Components/Sources/Table/TableWrappedCell.swift @@ -9,7 +9,7 @@ import UIKit import ReactiveDataDisplayManager /// Empty table cell with `View`. Configuration is implemented within `ViewWrapper`. -public final class TableWrappedCell: UITableViewCell, ViewWrapper { +public final class TableWrappedCell: UITableViewCell, ViewWrapper { public typealias Model = View.Model diff --git a/Example/ReactiveDataDisplayManager/Collection/DiffableCollectionViewController/DiffableCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/DiffableCollectionViewController/DiffableCollectionViewController.swift index f4ec6bab..65cbe2b8 100644 --- a/Example/ReactiveDataDisplayManager/Collection/DiffableCollectionViewController/DiffableCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/DiffableCollectionViewController/DiffableCollectionViewController.swift @@ -11,7 +11,7 @@ import ReactiveDataComponents @available(iOS 13.0, *) final class DiffableCollectionViewController: UIViewController { - typealias DiffableGenerator = DiffableCollectionCellGenerator + typealias DiffableGenerator = DiffableCellGenerator // MARK: - Constants diff --git a/Example/ReactiveDataDisplayManager/Collection/DifferenceCollectionViewController/DifferenceCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/DifferenceCollectionViewController/DifferenceCollectionViewController.swift index 0de1af2b..de753ae6 100644 --- a/Example/ReactiveDataDisplayManager/Collection/DifferenceCollectionViewController/DifferenceCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/DifferenceCollectionViewController/DifferenceCollectionViewController.swift @@ -9,7 +9,7 @@ import ReactiveDataDisplayManager final class DifferenceCollectionViewController: UIViewController { - typealias DiffableGenerator = DiffableCollectionCellGenerator + typealias DiffableGenerator = DiffableCellGenerator // MARK: - Constants diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/DynamicHeightViewCell/DynamicHeightTableViewCell.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/DynamicHeightViewCell/DynamicHeightTableViewCell.swift index aa3116ce..4cd9ae38 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/DynamicHeightViewCell/DynamicHeightTableViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/DynamicHeightViewCell/DynamicHeightTableViewCell.swift @@ -59,7 +59,7 @@ private extension DynamicHeightTableViewCell { } func makeDynamicHeightCellGenerators() -> [CollectionCellGenerator] { - return makeModels().map { BaseCollectionCellGenerator(with: $0) } + return makeModels().map { BaseCellGenerator(with: $0) } } func makeModels() -> [UIColor] { diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/ImageCollectionCellGenerator.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/ImageCollectionCellGenerator.swift index c7c1d593..f763248f 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/ImageCollectionCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/ImageCollectionCellGenerator.swift @@ -9,7 +9,7 @@ import Foundation import ReactiveDataDisplayManager -final class ImageCollectionCellGenerator: BaseCollectionCellGenerator, PrefetcherableItem { +final class ImageCollectionCellGenerator: BaseCellGenerator, PrefetcherableItem { // MARK: - PrefetcherableFlow diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/MovableCollectionCellGenerator.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/MovableCollectionCellGenerator.swift index 53f6bb95..0481fa0b 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/MovableCollectionCellGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/MovableCollectionCellGenerator.swift @@ -8,7 +8,7 @@ import Foundation import ReactiveDataDisplayManager -final class MovableCollectionCellGenerator: BaseCollectionCellGenerator, MovableItem { +final class MovableCollectionCellGenerator: BaseCellGenerator, MovableItem { // MARK: - Properties diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/SwipeableCollectionGenerator.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/SwipeableCollectionGenerator.swift index 4e060371..ceeb12ee 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/SwipeableCollectionGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/SwipeableCollectionGenerator.swift @@ -8,7 +8,7 @@ import ReactiveDataDisplayManager -final class SwipeableCollectionGenerator: BaseCollectionCellGenerator, SwipeableItem { +final class SwipeableCollectionGenerator: BaseCellGenerator, SwipeableItem { // MARK: - SwipeableItem diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/TitleCollectionGenerator.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/TitleCollectionGenerator.swift index 31ef5bfa..34cb57c8 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/TitleCollectionGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/TitleCollectionGenerator.swift @@ -9,7 +9,7 @@ import UIKit import ReactiveDataDisplayManager -final class TitleCollectionGenerator: BaseCollectionCellGenerator, IndexTitleDisplaybleItem { +final class TitleCollectionGenerator: BaseCellGenerator, IndexTitleDisplaybleItem { // MARK: - IndexTitleDisplayble diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/VerticalSizableTextGenerator.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/VerticalSizableTextGenerator.swift index 160b013e..db97b6a4 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/VerticalSizableTextGenerator.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/Generators/VerticalSizableTextGenerator.swift @@ -9,7 +9,7 @@ import UIKit import ReactiveDataDisplayManager -final class VerticalSizableTextGenerator: BaseCollectionCellGenerator { +final class VerticalSizableTextGenerator: BaseCellGenerator { // MARK: - Private Properties diff --git a/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageCollectionViewCell/ImageCollectionViewGenerator.swift b/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageCollectionViewCell/ImageCollectionViewGenerator.swift index 0d77c772..3d22f943 100644 --- a/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageCollectionViewCell/ImageCollectionViewGenerator.swift +++ b/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageCollectionViewCell/ImageCollectionViewGenerator.swift @@ -7,4 +7,4 @@ import ReactiveDataDisplayManager -final class ImageCollectionViewGenerator: BaseCollectionCellGenerator, FocusableItem { } +final class ImageCollectionViewGenerator: BaseCellGenerator, FocusableItem { } diff --git a/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageDefaultBehavoirCell/ImageDefaultBehavoirCollectionViewGenerator.swift b/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageDefaultBehavoirCell/ImageDefaultBehavoirCollectionViewGenerator.swift index 4306de54..ee57576b 100644 --- a/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageDefaultBehavoirCell/ImageDefaultBehavoirCollectionViewGenerator.swift +++ b/Example/ReactiveDataDisplayManagerExampleTv/Views/Cells/ImageDefaultBehavoirCell/ImageDefaultBehavoirCollectionViewGenerator.swift @@ -7,4 +7,4 @@ import ReactiveDataDisplayManager -final class ImageDefaultBehavoirCollectionViewGenerator: BaseCollectionCellGenerator, FocusableItem { } +final class ImageDefaultBehavoirCollectionViewGenerator: BaseCellGenerator, FocusableItem { } diff --git a/ReactiveDataDisplayManagerTests/Builder/Collection/Mocks/PrefetchableCollectionCellGeneratorMock.swift b/ReactiveDataDisplayManagerTests/Builder/Collection/Mocks/PrefetchableCollectionCellGeneratorMock.swift index c3524822..1f4dc072 100644 --- a/ReactiveDataDisplayManagerTests/Builder/Collection/Mocks/PrefetchableCollectionCellGeneratorMock.swift +++ b/ReactiveDataDisplayManagerTests/Builder/Collection/Mocks/PrefetchableCollectionCellGeneratorMock.swift @@ -9,13 +9,13 @@ import UIKit @testable import ReactiveDataDisplayManager -final class PrefetchableCollectionCellGeneratorMock: BaseCollectionCellGenerator, PrefetcherableItem { +final class PrefetchableCollectionCellGeneratorMock: BaseCellGenerator, PrefetcherableItem { // MARK: - PrefetcherableFlow var requestId: Int? - // MARK: - BaseCollectionCellGenerator + // MARK: - BaseCellGenerator init(with model: Bool, requestId: Int) { self.requestId = requestId diff --git a/ReactiveDataDisplayManagerTests/Collection/Mock/StubCollectionCellGenerator.swift b/ReactiveDataDisplayManagerTests/Collection/Mock/StubCollectionCellGenerator.swift index b16aa53e..72178299 100644 --- a/ReactiveDataDisplayManagerTests/Collection/Mock/StubCollectionCellGenerator.swift +++ b/ReactiveDataDisplayManagerTests/Collection/Mock/StubCollectionCellGenerator.swift @@ -9,7 +9,7 @@ import UIKit @testable import ReactiveDataDisplayManager -class StubCollectionCellGenerator: BaseCollectionCellGenerator { +class StubCollectionCellGenerator: BaseCellGenerator { init(model: String) { super.init(with: model, registerType: .class) diff --git a/Source/Collection/CollectionCell+RDDM.swift b/Source/Collection/CollectionCell+RDDM.swift index f45bbddb..7752bcf7 100644 --- a/Source/Collection/CollectionCell+RDDM.swift +++ b/Source/Collection/CollectionCell+RDDM.swift @@ -10,7 +10,7 @@ import UIKit public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem { - func baseGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCollectionCellGenerator { + func baseGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> BaseCellGenerator { .init(with: model, registerType: registerType) } diff --git a/Source/Collection/Generators/BaseCollectionCellGenerator.swift b/Source/Collection/Generators/BaseCollectionCellGenerator.swift deleted file mode 100644 index 66d0b748..00000000 --- a/Source/Collection/Generators/BaseCollectionCellGenerator.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// BaseCollectionCellGenerator.swift -// ReactiveDataDisplayManager -// -// Created by Maxim MAMEDOV on 28/03/2019. -// Copyright © 2019 Александр Кравченков. All rights reserved. -// - -import UIKit - -open class BaseCollectionCellGenerator: SelectableItem where Cell: UICollectionViewCell { - - // MARK: - Public Properties - - public var isNeedDeselect = true - public var didSelectEvent = EmptyEvent() - public var didDeselectEvent = EmptyEvent() - public let model: Cell.Model - - // MARK: - Private Properties - - private let registerType: RegistrationType - - // MARK: - Initialization - - public init(with model: Cell.Model, - registerType: RegistrationType = .nib) { - self.model = model - self.registerType = registerType - } - - // MARK: - Open methods - - open func configure(cell: Cell, with model: Cell.Model) { - cell.configure(with: model) - } - -} - -// MARK: - CollectionCellGenerator - -extension BaseCollectionCellGenerator: CollectionCellGenerator { - - public var identifier: String { - return String(describing: Cell.self) - } - - public func generate(collectionView: UICollectionView, for indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? Cell else { - return UICollectionViewCell() - } - configure(cell: cell, with: model) - return cell - } - - public func registerCell(in collectionView: UICollectionView) { - switch registerType { - case .nib: - collectionView.registerNib(identifier, bundle: Cell.bundle()) - case .class: - collectionView.register(Cell.self, forCellWithReuseIdentifier: identifier) - } - } - -} - -// MARK: - Decorations - -public extension BaseCollectionCellGenerator { - - /// - Parameter isNeedDeselect: defines if cell should be deselected after selection - func isNeedDeselect(_ isNeedDeselect: Bool) -> Self { - self.isNeedDeselect = isNeedDeselect - return self - } - - /// - Parameter closure: closure that will be called when cell is selected - func didSelectEvent(_ closure: @escaping () -> Void) -> Self { - self.didSelectEvent.addListner(closure) - return self - } - - /// - Parameter closure: closure that will be called when cell is deselected in multiple selection mode - func didDeselectEvent(_ closure: @escaping () -> Void) -> Self { - self.didDeselectEvent.addListner(closure) - return self - } - -} - -// MARK: - Transformations - -public extension BaseCollectionCellGenerator where Cell: FoldableStateHolder { - - /// Creates FoldableCellGenerator with predefined children - /// - Parameter children: array of children - func asFoldable(_ children: [CollectionCellGenerator]) -> FoldableCollectionCellGenerator { - return .init(with: model, - registerType: registerType) - .children(children) - } - - /// Creates FoldableCellGenerator with children generated by resultBuilder - /// - Parameter content: resultBuilder based closure that returns array of children - func asFoldable(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> FoldableCollectionCellGenerator { - return .init(with: model, - registerType: registerType) - .children(content) - } - -} - -public extension BaseCollectionCellGenerator where Cell.Model: Equatable { - - /// Creates DiffableCellGenerator with constant but unique Id - /// - Parameter uniqueId: uniqueId to identify cell - func asDiffable(uniqueId: AnyHashable) -> DiffableCollectionCellGenerator { - .init(uniqueId: uniqueId, - with: model, - registerType: registerType) - } - -} - -public extension BaseCollectionCellGenerator where Cell.Model: Equatable & IdOwner { - - /// Creates DiffableCellGenerator with uniqueId from model - func asDiffable() -> DiffableCollectionCellGenerator { - .init(uniqueId: model.id, - with: model, - registerType: registerType) - } - -} diff --git a/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift b/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift index a7373098..ccf8f55d 100644 --- a/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift +++ b/Source/Collection/Generators/CalculatableHeightCollectionCellGenerator.swift @@ -9,7 +9,7 @@ import UIKit // swiftlint:disable line_length -public class CalculatableHeightCollectionCellGenerator: BaseCollectionCellGenerator & SizableItem where Cell: UICollectionViewCell { +public class CalculatableHeightCollectionCellGenerator: BaseCellGenerator & SizableItem where Cell: UICollectionViewCell { // swiftlint:enable line_length // MARK: - Private Properties diff --git a/Source/Collection/Generators/CalculatableWidthCollectionCellGenerator.swift b/Source/Collection/Generators/CalculatableWidthCollectionCellGenerator.swift index 109905df..eb2d9e92 100644 --- a/Source/Collection/Generators/CalculatableWidthCollectionCellGenerator.swift +++ b/Source/Collection/Generators/CalculatableWidthCollectionCellGenerator.swift @@ -9,7 +9,7 @@ import UIKit // swiftlint:disable line_length -public class CalculatableWidthCollectionCellGenerator: BaseCollectionCellGenerator & SizableItem where Cell: UICollectionViewCell { +public class CalculatableWidthCollectionCellGenerator: BaseCellGenerator & SizableItem where Cell: UICollectionViewCell { // swiftlint:enable line_length // MARK: - Private Properties diff --git a/Source/Collection/Generators/DiffableCollectionCellGenerator.swift b/Source/Collection/Generators/DiffableCollectionCellGenerator.swift deleted file mode 100644 index 858aef75..00000000 --- a/Source/Collection/Generators/DiffableCollectionCellGenerator.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// DiffableCollectionCellGenerator.swift -// ReactiveDataDisplayManager -// -// Created by korshunov on 25.02.2022. -// - -import UIKit - -open class DiffableCollectionCellGenerator: BaseCollectionCellGenerator, - IdOwner, - DiffableItemSource where Cell.Model: Equatable { - public let id: AnyHashable - - public var diffableItem: DiffableItem { - .init(id: id, state: AnyEquatable(model)) - } - - public init(uniqueId: AnyHashable, with model: Cell.Model, registerType: RegistrationType = .nib) { - self.id = uniqueId - super.init(with: model, registerType: registerType) - } - -} - -extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem, Base.Model: Equatable { - - public func diffableGenerator( - uniqueId: AnyHashable, - with model: Base.Model, - and registerType: RegistrationType = .nib - ) -> DiffableCollectionCellGenerator { - .init(uniqueId: uniqueId, with: model, registerType: registerType) - } - -} - -extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem, Base.Model: Equatable & IdOwner { - - public func diffableGenerator( - with model: Base.Model, - and registerType: RegistrationType = .nib - ) -> DiffableCollectionCellGenerator { - .init(uniqueId: model.id, with: model, registerType: registerType) - } - -} diff --git a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift b/Source/Collection/Generators/FoldableCollectionCellGenerator.swift index 6d9a0119..291bd97b 100644 --- a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift +++ b/Source/Collection/Generators/FoldableCollectionCellGenerator.swift @@ -9,7 +9,7 @@ import UIKit // swiftlint:disable line_length /// A generator that can insert and remove child generators by tap -open class FoldableCollectionCellGenerator: BaseCollectionCellGenerator, CollectionFoldableItem { +open class FoldableCollectionCellGenerator: BaseCellGenerator, CollectionFoldableItem { // swiftlint:enable line_length // MARK: - FoldableItem @@ -23,7 +23,7 @@ open class FoldableCollectionCellGenerator: SelectableTableCellGenerator where Cell: UITableViewCell { +open class BaseCellGenerator: SelectableItem, RegisterableItem { // MARK: - Public properties @@ -44,14 +42,49 @@ open class BaseCellGenerator: SelectableTableCellGenerat return String(describing: Cell.self) } - public func generate(tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? Cell else { - return UITableViewCell() + // TODO: - add protocol to move it into extension + + open var cellHeight: CGFloat { + UITableView.automaticDimension + } + + open var estimatedCellHeight: CGFloat? { + nil + } + +} + +// MARK: - CollectionCell + +extension BaseCellGenerator: CollectionCellRegisterableItem where Cell: UICollectionViewCell { + + public func registerCell(in collectionView: UICollectionView) { + switch registerType { + case .nib: + collectionView.registerNib(identifier, bundle: Cell.bundle()) + case .class: + collectionView.register(Cell.self, forCellWithReuseIdentifier: identifier) + } + } + +} + +extension BaseCellGenerator: CollectionCellGenerator where Cell: UICollectionViewCell { + + public func generate(collectionView: UICollectionView, for indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? Cell else { + return UICollectionViewCell() } configure(cell: cell, with: model) return cell } +} + +// MARK: - TableCell + +extension BaseCellGenerator: TableCellRegisterableItem where Cell: UITableViewCell { + public func registerCell(in tableView: UITableView) { switch registerType { case .nib: @@ -61,12 +94,16 @@ open class BaseCellGenerator: SelectableTableCellGenerat } } - open var cellHeight: CGFloat { - UITableView.automaticDimension - } +} - open var estimatedCellHeight: CGFloat? { - nil +extension BaseCellGenerator: TableCellGenerator where Cell: UITableViewCell { + + public func generate(tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? Cell else { + return UITableViewCell() + } + configure(cell: cell, with: model) + return cell } } @@ -97,7 +134,7 @@ public extension BaseCellGenerator { // MARK: - Transformations -public extension BaseCellGenerator where Cell: FoldableStateHolder { +public extension BaseCellGenerator where Cell: FoldableStateHolder, Cell: UITableViewCell { /// Creates FoldableCellGenerator with predefined children /// - Parameter children: array of children @@ -117,7 +154,7 @@ public extension BaseCellGenerator where Cell: FoldableStateHolder { } -public extension BaseCellGenerator where Cell.Model: Equatable { +public extension BaseCellGenerator where Cell.Model: Equatable, Cell: UITableViewCell { /// Creates DiffableCellGenerator with constant but unique Id /// - Parameter uniqueId: uniqueId to identify cell @@ -129,7 +166,7 @@ public extension BaseCellGenerator where Cell.Model: Equatable { } -public extension BaseCellGenerator where Cell.Model: Equatable & IdOwner { +public extension BaseCellGenerator where Cell.Model: Equatable & IdOwner, Cell: UITableViewCell { /// Creates DiffableCellGenerator with uniqueId from model func asDiffable() -> DiffableCellGenerator { diff --git a/Source/Table/Generators/DiffableCellGenerator.swift b/Source/Common/Generators/DiffableCellGenerator.swift similarity index 78% rename from Source/Table/Generators/DiffableCellGenerator.swift rename to Source/Common/Generators/DiffableCellGenerator.swift index fd3856c5..dd9c0b06 100644 --- a/Source/Table/Generators/DiffableCellGenerator.swift +++ b/Source/Common/Generators/DiffableCellGenerator.swift @@ -7,7 +7,7 @@ import UIKit -open class DiffableCellGenerator: BaseCellGenerator, +open class DiffableCellGenerator: BaseCellGenerator, IdOwner, DiffableItemSource where Cell.Model: Equatable { public let id: AnyHashable @@ -23,7 +23,7 @@ open class DiffableCellGenerator: Base } -extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem, Base.Model: Equatable { +extension StaticDataDisplayWrapper where Base: ConfigurableItem, Base.Model: Equatable { public func diffableGenerator( uniqueId: AnyHashable, @@ -35,7 +35,7 @@ extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableIte } -extension StaticDataDisplayWrapper where Base: UITableViewCell & ConfigurableItem, Base.Model: Equatable & IdOwner { +extension StaticDataDisplayWrapper where Base: ConfigurableItem, Base.Model: Equatable & IdOwner { public func diffableGenerator( with model: Base.Model, diff --git a/Source/Protocols/BuilderContext/BuilderContext.swift b/Source/Protocols/BuilderContext/BuilderContext.swift index 713b0245..df850c25 100644 --- a/Source/Protocols/BuilderContext/BuilderContext.swift +++ b/Source/Protocols/BuilderContext/BuilderContext.swift @@ -11,5 +11,5 @@ public protocol BuilderContext { associatedtype ViewType: UIView associatedtype GeneratorType - static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType + static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType } diff --git a/Source/Protocols/Plugins/Generators/BaseItem.swift b/Source/Protocols/Plugins/Generators/BaseItem.swift new file mode 100644 index 00000000..dde33fdd --- /dev/null +++ b/Source/Protocols/Plugins/Generators/BaseItem.swift @@ -0,0 +1,8 @@ +// +// BaseItem.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 28.07.2023. +// + +public typealias BaseItem = ConfigurableItem & RegistrationTypeProvider diff --git a/Source/Stack/Generators/BaseViewGenerator.swift b/Source/Stack/Generators/BaseViewGenerator.swift index 5a8b0b30..5f64bb5e 100644 --- a/Source/Stack/Generators/BaseViewGenerator.swift +++ b/Source/Stack/Generators/BaseViewGenerator.swift @@ -7,7 +7,7 @@ import UIKit -public final class EmptyViewGenerator: AccessoryViewGenerator { +public final class EmptyViewGenerator: AccessoryViewGenerator { public typealias ViewType = View @@ -18,7 +18,7 @@ public final class EmptyViewGenerator(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ConfigurableItem, - Item: RegistrationTypeProvider { + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Table/Generators/BaseNonReusableCellGenerator.swift b/Source/Table/Generators/BaseNonReusableCellGenerator.swift index 49169829..187d226d 100644 --- a/Source/Table/Generators/BaseNonReusableCellGenerator.swift +++ b/Source/Table/Generators/BaseNonReusableCellGenerator.swift @@ -13,7 +13,7 @@ import UIKit /// Term *non-reusable* means that we are creating cell manually with constructor type defined in **ConstractableItem**. /// In other words this generator will not use `tableView.deqeueReusableCell`. /// - Warning: Do not use this generators in tables with many cells of same type. Because you may catch perfomance issues. -open class BaseNonReusableCellGenerator: SelectableTableCellGenerator where Cell: UITableViewCell { +open class BaseNonReusableCellGenerator: TableCellGenerator & SelectableItem where Cell: UITableViewCell { // MARK: - Public Properties diff --git a/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift b/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift deleted file mode 100644 index c5dda886..00000000 --- a/Source/Table/Generators/CalculatableHeightNonReusableCellGenerator.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// CalculatableHeightNonReusableCellGenerator.swift -// ReactiveDataDisplayManager -// -// Created by Alexander Filimonov on 02/03/2020. -// Copyright © 2020 Александр Кравченков. All rights reserved. -// - -import UIKit - -/// Class for generating non-reusable Configurable UITableViewCell with calculated height -public class CalculatableHeightNonReusableCellGenerator: SelectableTableCellGenerator where Cell: UITableViewCell { - - // MARK: - Public properties - - public var isNeedDeselect = true - public var didSelectEvent = EmptyEvent() - public var didDeselectEvent = EmptyEvent() - private(set) public var model: Cell.Model - private(set) public lazy var cell: Cell? = { - return Cell.fromXib(bundle: Cell.bundle()) - }() - - // MARK: - Private Properties - - private let cellWidth: CGFloat - private let registerType: RegistrationType - - // MARK: - Initialization - - public init(with model: Cell.Model, - cellWidth: CGFloat = UIScreen.main.bounds.width, - registerType: RegistrationType = .nib) { - self.model = model - self.cellWidth = cellWidth - self.registerType = registerType - } - - // MARK: - Public Methods - - public func update(model: Cell.Model) { - self.model = model - cell?.configure(with: model) - } - - // MARK: - TableCellGenerator - - public var identifier: String { - return String(describing: Cell.self) - } - - public var cellHeight: CGFloat { - return Cell.getHeight(forWidth: cellWidth, with: model) - } - - public var estimatedCellHeight: CGFloat? { - return Cell.getHeight(forWidth: cellWidth, with: model) - } - - public func generate(tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell { - cell?.configure(with: model) - return cell ?? UITableViewCell() - } - - public func registerCell(in tableView: UITableView) { - switch registerType { - case .nib: - tableView.registerNib(identifier, bundle: Cell.bundle()) - case .class: - tableView.register(Cell.self, forCellReuseIdentifier: identifier) - } - } - -} diff --git a/Source/Table/Generators/FoldableCellGenerator.swift b/Source/Table/Generators/FoldableCellGenerator.swift index a26baed3..d9a285ca 100644 --- a/Source/Table/Generators/FoldableCellGenerator.swift +++ b/Source/Table/Generators/FoldableCellGenerator.swift @@ -8,7 +8,7 @@ import UIKit /// A generator that can insert and remove child generators by tap -open class FoldableCellGenerator: BaseCellGenerator, FoldableItem { +open class FoldableCellGenerator: BaseCellGenerator, FoldableItem { // MARK: - FoldableItem From 6dde0e039032d10979612bdb8a28124f04b1a764 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 13:27:16 +0400 Subject: [PATCH 20/30] remove deprecated stackview implementation --- .../CollectionStack/CollectionStack.swift | 152 ------------------ .../HorizontalCollectionStack.swift | 28 ---- .../CollectionStack/StackCollectionCell.swift | 32 ---- .../VerticalCollectionStack.swift | 34 ---- .../Extensions/ConfigurableItem+Builder.swift | 52 ------ .../TableStack/HorizontalTableStack.swift | 34 ---- .../Table/TableStack/StackTableCell.swift | 33 ---- .../Sources/Table/TableStack/TableStack.swift | 152 ------------------ .../Table/TableStack/VerticalTableStack.swift | 34 ---- ...kCellExampleCollectionViewController.swift | 74 ++++----- .../StackCollectionCell+HighlitableItem.swift | 28 ---- .../TitleCollectionViewCell.swift | 10 ++ .../StackCellExampleViewController.swift | 16 -- .../StackTableCell+HighlitableItem.swift | 72 --------- 14 files changed, 39 insertions(+), 712 deletions(-) delete mode 100644 Components/Sources/Collection/CollectionStack/CollectionStack.swift delete mode 100644 Components/Sources/Collection/CollectionStack/HorizontalCollectionStack.swift delete mode 100644 Components/Sources/Collection/CollectionStack/StackCollectionCell.swift delete mode 100644 Components/Sources/Collection/CollectionStack/VerticalCollectionStack.swift delete mode 100644 Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift delete mode 100644 Components/Sources/Table/TableStack/HorizontalTableStack.swift delete mode 100644 Components/Sources/Table/TableStack/StackTableCell.swift delete mode 100644 Components/Sources/Table/TableStack/TableStack.swift delete mode 100644 Components/Sources/Table/TableStack/VerticalTableStack.swift delete mode 100644 Example/ReactiveDataDisplayManager/Collection/Views/Cells/HighlitableStackCells/StackCollectionCell+HighlitableItem.swift delete mode 100644 Example/ReactiveDataDisplayManager/Table/Views/Cells/HighlitableStackCells/StackTableCell+HighlitableItem.swift diff --git a/Components/Sources/Collection/CollectionStack/CollectionStack.swift b/Components/Sources/Collection/CollectionStack/CollectionStack.swift deleted file mode 100644 index 7b3a26cf..00000000 --- a/Components/Sources/Collection/CollectionStack/CollectionStack.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// CollectionStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 30.06.2023. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Base class for collection stack (generator) -open class CollectionStack: UIView, ConfigurableItem, SelectableItem { - - // MARK: - Public properties - - public var isNeedDeselect = true - public var didSelectEvent = EmptyEvent() - public var didDeselectEvent = EmptyEvent() - - public var views: [UIView] = [] - - // MARK: - Private properties - - private var cell: StackCollectionCell? - private let stackView = UIStackView() - - // MARK: - Initialization - - /// - Parameters: - /// - space: Space between items - /// - insets: Insets for stack - /// - axis: Axis for stack - /// - items: Items for stack - public init(space: CGFloat, - insets: UIEdgeInsets, - axis: NSLayoutConstraint.Axis, - @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - - self.views = items().compactMap { item in - return (item as? UICollectionViewCell)?.contentView - ?? (item as? UITableViewCell)?.contentView - ?? item - } - super.init(frame: .zero) - setupStackView(with: space, insets: insets, axis: axis) - configure(with: views) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - Public methods - - /// Update items in stack - /// - Parameter items: new items - public func updateItems(_ items: [any ConfigurableItem]) { - self.views = items.compactMap { item in - return (item as? UICollectionViewCell)?.contentView ?? (item as? UITableViewCell)?.contentView ?? item - } - configure(with: views) - } - - /// Remove item from stack - /// - Parameter item: item for remove - public func removeItem(_ item: any ConfigurableItem) { - let view = (item as? UICollectionViewCell)?.contentView ?? (item as? UITableViewCell)?.contentView ?? item - guard let index = views.firstIndex(where: { $0 === view }) else { - return - } - views.remove(at: index) - configure(with: views) - } - - /// Update size after update content - public func updateSizeIfNeaded() { - updateFrameByContent() - cell?.configure(with: self) - } - - // MARK: - ConfigurableItem - - public func configure(with model: [UIView]) { - views = model - - stackView.removeAllArrangedSubviews() - model.forEach { view in - stackView.addArrangedSubview(view) - } - updateFrameByContent() - cell?.configure(with: self) - } - - // MARK: - Private methods - - private func setupStackView(with spacing: CGFloat, insets: UIEdgeInsets, axis: NSLayoutConstraint.Axis) { - stackView.axis = axis - stackView.alignment = .fill - stackView.spacing = spacing - stackView.attach( - to: self, - topOffset: insets.top, - bottomOffset: insets.bottom, - leftOffset: insets.left, - rightOffset: insets.right - ) - } - -} - -// MARK: - CollectionCellGenerator - -extension CollectionStack: CollectionCellGenerator { - - public func generate(collectionView: UICollectionView, for indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? StackCollectionCell else { - return UICollectionViewCell() - } - self.cell = cell - configure(with: views) - return cell - } - - public func registerCell(in collectionView: UICollectionView) { - collectionView.register(StackCollectionCell.self, forCellWithReuseIdentifier: identifier) - } - - public var identifier: String { - return String(describing: StackCollectionCell.self) - } - - public static func bundle() -> Bundle? { - return .main - } - -} - -// MARK: - Events - -public extension CollectionStack { - - func didSelectEvent(_ closure: @escaping () -> Void) -> Self { - didSelectEvent.addListner(closure) - return self - } - - func didDeselectEvent(_ closure: @escaping () -> Void) -> Self { - didDeselectEvent.addListner(closure) - return self - } - -} diff --git a/Components/Sources/Collection/CollectionStack/HorizontalCollectionStack.swift b/Components/Sources/Collection/CollectionStack/HorizontalCollectionStack.swift deleted file mode 100644 index 71a68ea2..00000000 --- a/Components/Sources/Collection/CollectionStack/HorizontalCollectionStack.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// HorizontalCollectionStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 12.07.2023. -// - -import ReactiveDataDisplayManager -import UIKit - -/// Base class for horizontal collection stack (generator) -open class HorizontalCollectionStack: CollectionStack { - - // MARK: - Initialization - - public init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, insets: insets, axis: .horizontal, items: items) - } - - public init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: 0, insets: .zero, axis: .horizontal, items: items) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Components/Sources/Collection/CollectionStack/StackCollectionCell.swift b/Components/Sources/Collection/CollectionStack/StackCollectionCell.swift deleted file mode 100644 index c6746a78..00000000 --- a/Components/Sources/Collection/CollectionStack/StackCollectionCell.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// StackCollectionCell.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 29.06.2023. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Cell - container with horizontal layout. Accepts generators of other cells, creates a single press state for them -open class StackCollectionCell: UICollectionViewCell, ConfigurableItem, ExpandableItem { - - // MARK: - ExpandableItem - - public var onHeightChanged = Event() - public var animatedExpandable = true - - // MARK: - Public methods - - public func configure(with model: UIView) { - guard !contentView.contains(model) else { - if contentView.frame != model.frame { - onHeightChanged.invoke(with: nil) - } - return - } - model.attach(to: contentView) - onHeightChanged.invoke(with: nil) - } - -} diff --git a/Components/Sources/Collection/CollectionStack/VerticalCollectionStack.swift b/Components/Sources/Collection/CollectionStack/VerticalCollectionStack.swift deleted file mode 100644 index 1b8c67cf..00000000 --- a/Components/Sources/Collection/CollectionStack/VerticalCollectionStack.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// VerticalCollectionStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 12.07.2023. -// - -import ReactiveDataDisplayManager -import UIKit - -/// Base class for vertical collection stack (generator) -open class VerticalCollectionStack: CollectionStack { - - // MARK: - Initialization - - /// - Parameters: - /// - space: Space between items - /// - insets: Insets for stack - /// - items: Items for stack - public init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, insets: insets, axis: .vertical, items: items) - } - - /// - Parameters: - /// - items: Items for stack - public init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: .zero, insets: .zero, axis: .vertical, items: items) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift b/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift deleted file mode 100644 index a2e46a6d..00000000 --- a/Components/Sources/Common/Extensions/ConfigurableItem+Builder.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// ConfigurableItem+Builder.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 06.07.2023. -// - -import ReactiveDataDisplayManager - -public extension ConfigurableItem { - - static func buildView(with model: Self.Model, and type: RegistrationType = .nib) -> Self { - let cell: Self? - switch type { - case .nib: - cell = Self.loadFromNib(bundle: Self.bundle() ?? .main) as? Self - case .class: - cell = Self() - } - guard let cell = cell else { - fatalError("Can't load cell \(Self.self)") - } - cell.configure(with: model) - return cell - } - -} - -@resultBuilder -public enum ConfigurableItemBuilder { - - public static func buildExpression(_ expression: any ConfigurableItem) -> [any ConfigurableItem] { - return [expression] - } - - public static func buildExpression(_ expressions: [any ConfigurableItem]) -> [any ConfigurableItem] { - return expressions - } - - public static func buildExpression(_ expression: ()) -> [any ConfigurableItem] { - return [] - } - - public static func buildBlock(_ components: [any ConfigurableItem]...) -> [any ConfigurableItem] { - return components.flatMap { $0 } - } - - public static func buildArray(_ components: [[any ConfigurableItem]]) -> [any ConfigurableItem] { - Array(components.joined()) - } - -} diff --git a/Components/Sources/Table/TableStack/HorizontalTableStack.swift b/Components/Sources/Table/TableStack/HorizontalTableStack.swift deleted file mode 100644 index 8b834307..00000000 --- a/Components/Sources/Table/TableStack/HorizontalTableStack.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// HorizontalTableStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 12.07.2023. -// - -import ReactiveDataDisplayManager -import UIKit - -/// Base class for horizontal table stack (generator) -open class HorizontalTableStack: TableStack { - - // MARK: - Initialization - - /// - Parameters: - /// - space: Space between items - /// - insets: Insets for stack - /// - items: Items for stack - public init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, insets: insets, axis: .horizontal, items: items) - } - - /// - Parameters: - /// - items: Items for stack - public init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: .zero, insets: .zero, axis: .horizontal, items: items) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Components/Sources/Table/TableStack/StackTableCell.swift b/Components/Sources/Table/TableStack/StackTableCell.swift deleted file mode 100644 index 9791f833..00000000 --- a/Components/Sources/Table/TableStack/StackTableCell.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// StackTableCell.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 29.06.2023. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Cell - container with horizontal layout. Accepts generators of other cells, creates a single press state for them -open class StackTableCell: UITableViewCell, ConfigurableItem, ExpandableItem { - - // MARK: - ExpandableItem - - public var onHeightChanged = Event() - public var animatedExpandable = true - - // MARK: - Public methods - - public func configure(with model: UIView) { - guard !contentView.contains(model) else { - if contentView.frame != model.frame { - onHeightChanged.invoke(with: nil) - } - return - } - model.attach(to: contentView) - onHeightChanged.invoke(with: nil) - selectionStyle = .none - } - -} diff --git a/Components/Sources/Table/TableStack/TableStack.swift b/Components/Sources/Table/TableStack/TableStack.swift deleted file mode 100644 index 911fdb08..00000000 --- a/Components/Sources/Table/TableStack/TableStack.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// TableStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 30.06.2023. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Base class for table stack (generator) -open class TableStack: UIView, ConfigurableItem, SelectableItem { - - // MARK: - Public properties - - public var isNeedDeselect = true - public var didSelectEvent = EmptyEvent() - public var didDeselectEvent = EmptyEvent() - - public var cell: StackTableCell? - - // MARK: - Private properties - - private var views: [UIView] = [] - private let stackView = UIStackView() - - // MARK: - Initialization - - /// - Parameters: - /// - space: Space between items - /// - insets: Insets for stack - /// - axis: Axis for stack - /// - items: Items for stack - public init(space: CGFloat, - insets: UIEdgeInsets, - axis: NSLayoutConstraint.Axis, - @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - - self.views = items().compactMap { item in - return (item as? UICollectionViewCell)?.contentView - ?? (item as? UITableViewCell)?.contentView - ?? item - } - super.init(frame: .zero) - setupStackView(with: space, insets: insets, axis: axis) - configure(with: views) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - Public methods - - /// Update items in stack - /// - Parameter items: new items - public func updateItems(_ items: [any ConfigurableItem]) { - self.views = items.compactMap { item in - return (item as? UICollectionViewCell)?.contentView ?? (item as? UITableViewCell)?.contentView ?? item - } - configure(with: views) - } - - /// Remove item from stack - /// - Parameter item: item for remove - public func removeItem(_ item: any ConfigurableItem) { - let view = (item as? UICollectionViewCell)?.contentView ?? (item as? UITableViewCell)?.contentView ?? item - guard let index = views.firstIndex(where: { $0 === view }) else { - return - } - views.remove(at: index) - configure(with: views) - } - - /// Update size after update content - public func updateSizeIfNeaded() { - updateFrameByContent() - cell?.configure(with: self) - } - - // MARK: - ConfigurableItem - - public func configure(with model: [UIView]) { - views = model - - stackView.removeAllArrangedSubviews() - model.forEach { view in - stackView.addArrangedSubview(view) - } - updateFrameByContent() - cell?.configure(with: self) - } - - // MARK: - Private methods - - private func setupStackView(with spacing: CGFloat, insets: UIEdgeInsets, axis: NSLayoutConstraint.Axis) { - stackView.axis = axis - stackView.alignment = .fill - stackView.spacing = spacing - stackView.attach( - to: self, - topOffset: insets.top, - bottomOffset: insets.bottom, - leftOffset: insets.left, - rightOffset: insets.right - ) - } - -} - -// MARK: - TableCellGenerator - -extension TableStack: TableCellGenerator { - - public var identifier: String { - String(describing: StackTableCell.self) - } - - public func generate(tableView: UITableView, for indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? StackTableCell else { - return UITableViewCell() - } - self.cell = cell - configure(with: views) - return cell - } - - public func registerCell(in tableView: UITableView) { - tableView.register(StackTableCell.self, forCellReuseIdentifier: identifier) - } - - public static func bundle() -> Bundle? { - return .main - } - -} - -// MARK: - Events - -public extension TableStack { - - func didSelectEvent(_ closure: @escaping () -> Void) -> Self { - didSelectEvent.addListner(closure) - return self - } - - func didDeselectEvent(_ closure: @escaping () -> Void) -> Self { - didDeselectEvent.addListner(closure) - return self - } - -} diff --git a/Components/Sources/Table/TableStack/VerticalTableStack.swift b/Components/Sources/Table/TableStack/VerticalTableStack.swift deleted file mode 100644 index 4e9d5be4..00000000 --- a/Components/Sources/Table/TableStack/VerticalTableStack.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// VerticalTableStack.swift -// ReactiveDataDisplayManager -// -// Created by Konstantin Porokhov on 12.07.2023. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Base class for vertical table stack (generator) -open class VerticalTableStack: TableStack { - - // MARK: - Initialization - - /// - Parameters: - /// - space: Space between items - /// - insets: Insets for stack - /// - items: Items for stack - public init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, insets: insets, axis: .vertical, items: items) - } - - /// - Parameters: - /// - items: Items for stack - public init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: .zero, insets: .zero, axis: .vertical, items: items) - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift index 9ce3817d..876d9bf6 100644 --- a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift @@ -23,7 +23,6 @@ final class StackCellExampleCollectionViewController: UIViewController { // MARK: - IBOutlet @IBOutlet private weak var collectionView: UICollectionView! - private lazy var titleCell = TitleTableViewCell.buildView(with: "Title") // MARK: - Private Properties @@ -35,20 +34,6 @@ final class StackCellExampleCollectionViewController: UIViewController { .add(plugin: .accessibility()) .build() - lazy var horizontalNestedStackCell = HorizontalCollectionStack { - TitleTableViewCell.buildView(with: "Text 3") - TitleTableViewCell.buildView(with: "Text 4") - } - - lazy var verticalStackCell = VerticalCollectionStack(space: 8) { - titleCell - .set(font: UIFont.boldSystemFont(ofSize: 20)) - TitleTableViewCell.buildView(with: "Text 1") - TitleTableViewCell.buildView(with: "Text 2") - horizontalNestedStackCell - SeparatorView.buildView(with: .init(size: .height(1), color: .lightGray), and: .class) - } - // MARK: - UIViewController override func viewDidLoad() { @@ -80,45 +65,44 @@ private extension StackCellExampleCollectionViewController { /// This method is used to fill adapter func fillAdapter() { - // Add stack generators into adapter - adapter += verticalStackCell - .didSelectEvent { [weak self] in - self?.cellBaseState.toggle() - self?.titleCell.configure(with: (self?.cellBaseState ?? true) ? "Title" : "Very very very long title") - self?.verticalStackCell.updateSizeIfNeaded() - } - - adapter += VerticalCollectionStack { - SeparatorView.buildView(with: .init(size: .height(1), color: .black), and: .class) - - HorizontalCollectionStack { - SeparatorView.buildView(with: .init(size: .width(1), color: .black), and: .class) - SpacerView.buildView(with: .init(size: .width(64)), and: .class) - - TitleTableViewCell.buildView(with: "Some text") - - SeparatorView.buildView(with: .init(size: .width(1), color: .black), and: .class) - } - - SeparatorView.buildView(with: .init(size: .height(1), color: .black), and: .class) - } - adapter += CollectionSection.create(header: EmptyCollectionHeaderGenerator(), footer: EmptyCollectionFooterGenerator()) { ctx in - SeparatorView.build(in: ctx, with: .init(size: .height(1), color: .black)) StackView.build(in: ctx, with: .build { hStack in hStack.style(.init(axis: .horizontal, - spacing: 0, + spacing: 8, alignment: .fill, - distribution: .fillEqually)) + distribution: .fill)) + hStack.background(.solid(.gray)) hStack.children { ctx in SeparatorView.build(in: ctx, with: .init(size: .width(1), color: .black)) - SpacerView.build(in: ctx, with: .init(size: .width(64))) - TitleTableViewCell.build(in: ctx, with: "Some text") + LabelView.build(in: ctx, with: .build { label in + label.text(.string("Some title")) + label.textAlignment(.left) + label.style(.init(color: .black, font: .preferredFont(forTextStyle: .headline))) + }) + SpacerView.build(in: ctx, with: .init(size: .width(16))) + StackView.build(in: ctx, with: .build { vStack in + vStack.style(.init(axis: .vertical, + spacing: 2, + alignment: .center, + distribution: .fill)) + vStack.background(.solid(.rddm)) + vStack.children { ctx in + LabelView.build(in: ctx, with: .build { label in + label.text(.string("Body 1")) + label.textAlignment(.right) + label.style(.init(color: .black, font: .preferredFont(forTextStyle: .body))) + }) + LabelView.build(in: ctx, with: .build { label in + label.text(.string("Body 2")) + label.textAlignment(.right) + label.style(.init(color: .black, font: .preferredFont(forTextStyle: .body))) + }) + } + }) SeparatorView.build(in: ctx, with: .init(size: .width(1), color: .black)) - } }) - SeparatorView.build(in: ctx, with: .init(size: .height(1), color: .black)) + TitleCollectionViewCell.build(in: ctx, with: "Some text outside of stack") } // Tell adapter that we've changed generators diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/HighlitableStackCells/StackCollectionCell+HighlitableItem.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/HighlitableStackCells/StackCollectionCell+HighlitableItem.swift deleted file mode 100644 index 4279f6c3..00000000 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/HighlitableStackCells/StackCollectionCell+HighlitableItem.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// StackCollectionCell+HighlitableItem.swift -// ReactiveDataDisplayManagerExample_iOS -// -// Created by Konstantin Porokhov on 29.06.2023. -// - -import ReactiveDataComponents -import ReactiveDataDisplayManager -import UIKit - -extension StackCollectionCell: HighlightableItem { - - // MARK: - HighlightableItem - - public func applyUnhighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.contentView.backgroundColor = .white - } - } - - public func applyHighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.contentView.backgroundColor = .lightGray.withAlphaComponent(0.3) - } - } - -} diff --git a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/TitleCollectionViewCell/TitleCollectionViewCell.swift b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/TitleCollectionViewCell/TitleCollectionViewCell.swift index 8256c69c..b9976ecf 100644 --- a/Example/ReactiveDataDisplayManager/Collection/Views/Cells/TitleCollectionViewCell/TitleCollectionViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Collection/Views/Cells/TitleCollectionViewCell/TitleCollectionViewCell.swift @@ -99,3 +99,13 @@ private extension TitleCollectionViewCell { accessibilityInvalidator?.invalidateParameters() } } + +// MARK: - RegistrationTypeProvider + +extension TitleCollectionViewCell: RegistrationTypeProvider { + + static var prefferedRegistration: RegistrationType { + .nib + } + +} diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index cc89239e..2d554093 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -48,22 +48,6 @@ private extension StackCellExampleViewController { /// This method is used to fill adapter func fillAdapter() { - // Add section into adapter - adapter += Section(header: TitleHeaderGenerator(model: "TableVStack"), footer: EmptyTableFooterGenerator()) { - TableVStack { - TitleTableViewCell.buildView(with: "1") - TitleTableViewCell.buildView(with: "2") - TableHStack { - TitleTableViewCell.buildView(with: "4") - TitleTableViewCell.buildView(with: "5") - } - TitleTableViewCell.buildView(with: "3") - } - .didSelectEvent { - print("VerticalTableStack did select event") - } - } - // Note that using `UITableViewCell` or `UICollectionViewCell` inside stack is not recommended, but it possible adapter += TableSection.create(header: TitleHeaderGenerator(model: "StackView based cells"), footer: EmptyTableFooterGenerator()) { ctx in diff --git a/Example/ReactiveDataDisplayManager/Table/Views/Cells/HighlitableStackCells/StackTableCell+HighlitableItem.swift b/Example/ReactiveDataDisplayManager/Table/Views/Cells/HighlitableStackCells/StackTableCell+HighlitableItem.swift deleted file mode 100644 index 75230791..00000000 --- a/Example/ReactiveDataDisplayManager/Table/Views/Cells/HighlitableStackCells/StackTableCell+HighlitableItem.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// StackTableCell+HighlitableItem.swift -// ReactiveDataDisplayManagerExample_iOS -// -// Created by Konstantin Porokhov on 29.06.2023. -// - -import ReactiveDataComponents -import ReactiveDataDisplayManager -import UIKit - -// internal project custom stack -final class TableVStack: TableStack, HighlightableItem { - - public init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, insets: insets, axis: .vertical, items: items) - } - - public init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: .zero, insets: .zero, axis: .vertical, items: items) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - HighlightableItem - - public func applyUnhighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.cell?.contentView.backgroundColor = .white - } - } - - public func applyHighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.cell?.contentView.backgroundColor = .lightGray.withAlphaComponent(0.3) - } - } - -} - -// internal project custom stack -final class TableHStack: HorizontalTableStack, HighlightableItem { - - public override init(space: CGFloat, insets: UIEdgeInsets = .zero, @ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: space, items: items) - } - - public override init(@ConfigurableItemBuilder items: () -> [any ConfigurableItem]) { - super.init(space: .zero, items: items) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - HighlightableItem - - public func applyUnhighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.cell?.contentView.backgroundColor = .white - } - } - - public func applyHighlightedStyle() { - UIView.animate(withDuration: 0.2) { - self.cell?.contentView.backgroundColor = .lightGray.withAlphaComponent(0.3) - } - } - -} From 4cfd920ea02e713c8eee068e06a0700bdd855502 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 13:34:44 +0400 Subject: [PATCH 21/30] remove SpacerCell used in decorations --- .../Collection/CollectionSpacerCell.swift | 32 ------------------ .../Common/Utils/Decoration+Provider.swift | 12 +++---- .../Sources/Table/TableSpacerCell.swift | 33 ------------------- ...nPaginatableCollectionViewController.swift | 2 +- 4 files changed, 7 insertions(+), 72 deletions(-) delete mode 100644 Components/Sources/Collection/CollectionSpacerCell.swift delete mode 100644 Components/Sources/Table/TableSpacerCell.swift diff --git a/Components/Sources/Collection/CollectionSpacerCell.swift b/Components/Sources/Collection/CollectionSpacerCell.swift deleted file mode 100644 index a53ab8aa..00000000 --- a/Components/Sources/Collection/CollectionSpacerCell.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// CollectionSpacerCell.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 26.09.2022. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Empty collection cell with `SpacerView` -public final class CollectionSpacerCell: UICollectionViewCell, SpacerWrapper { - - public typealias Model = SpacerView.Model - - // MARK: - Properties - - public private(set) var spacer: SpacerView = .init(frame: .zero) - - // MARK: - Initialization - - public override init(frame: CGRect) { - super.init(frame: frame) - configureViews() - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Components/Sources/Common/Utils/Decoration+Provider.swift b/Components/Sources/Common/Utils/Decoration+Provider.swift index 7e0ad764..47c6fb87 100644 --- a/Components/Sources/Common/Utils/Decoration+Provider.swift +++ b/Components/Sources/Common/Utils/Decoration+Provider.swift @@ -13,18 +13,18 @@ extension Decoration { var tableProvider: any DecorationProvider { switch self { case .space(let model): - return TableDecorationProvider(model: model, - hash: "space", - hashCombiner: CommonHashCombiner()) + return TableDecorationProvider>(model: model, + hash: "space", + hashCombiner: CommonHashCombiner()) } } var collectionProvider: any DecorationProvider { switch self { case .space(let model): - return CollectionDecorationProvider(model: model, - hash: "space", - hashCombiner: CommonHashCombiner()) + return CollectionDecorationProvider>(model: model, + hash: "space", + hashCombiner: CommonHashCombiner()) } } diff --git a/Components/Sources/Table/TableSpacerCell.swift b/Components/Sources/Table/TableSpacerCell.swift deleted file mode 100644 index f1f1a9bf..00000000 --- a/Components/Sources/Table/TableSpacerCell.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// TableSpacerCell.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 26.09.2022. -// - -import UIKit -import ReactiveDataDisplayManager - -/// Empty table cell with `SpacerView` -public final class TableSpacerCell: UITableViewCell, SpacerWrapper { - - public typealias Model = SpacerView.Model - - // MARK: - Properties - - public private(set) var spacer: SpacerView = .init(frame: .zero) - - // MARK: - Initialization - - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - configureViews() - selectionStyle = .none - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/Example/ReactiveDataDisplayManager/Collection/TwoDirectionPaginatableCollectionViewController/TwoDirectionPaginatableCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/TwoDirectionPaginatableCollectionViewController/TwoDirectionPaginatableCollectionViewController.swift index f65514bb..e95bb9af 100644 --- a/Example/ReactiveDataDisplayManager/Collection/TwoDirectionPaginatableCollectionViewController/TwoDirectionPaginatableCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/TwoDirectionPaginatableCollectionViewController/TwoDirectionPaginatableCollectionViewController.swift @@ -57,7 +57,7 @@ final class TwoDirectionPaginatableCollectionViewController: UIViewController { private var currentTopPage = 0 private var currentBottomPage = 0 - private lazy var emptyCell = CollectionSpacerCell.rddm.baseGenerator(with: CollectionSpacerCell.Model(size: .height(0)), and: .class) + private lazy var emptyCell = SpacerView.rddm.collectionGenerator(with: .init(size: .height(0))) // MARK: - UIViewController From 30224c17cb7cf088797e4ee11456858906cdad78 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 13:51:26 +0400 Subject: [PATCH 22/30] move wrapped cell and context implementations into core module --- ...lectionContext+CollectionWrappedCell.swift | 30 ------------------- .../CollectionContext+StackView.swift | 16 ++++++++++ .../Extensions/TableContext+StackView.swift | 16 ++++++++++ .../TableContext+TableWrappedCell.swift | 30 ------------------- .../Generators/CollectionContext.swift | 16 +++++++++- .../Wrapper}/CollectionWrappedCell+RDDM.swift | 1 - .../Wrapper}/CollectionWrappedCell.swift | 1 - .../Common/Wrapper}/UIView+Constraints.swift | 0 .../Common/Wrapper}/ViewWrapper.swift | 1 - .../Common => Source}/Models/Alignment.swift | 0 .../Wrapper}/AlignmentProvider.swift | 0 Source/Table/Generators/TableContext.swift | 16 +++++++++- .../Wrapper}/TableWrappedCell+RDDM.swift | 1 - .../Table/Wrapper}/TableWrappedCell.swift | 1 - 14 files changed, 62 insertions(+), 67 deletions(-) delete mode 100644 Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift create mode 100644 Components/Sources/Collection/Extensions/CollectionContext+StackView.swift create mode 100644 Components/Sources/Table/Extensions/TableContext+StackView.swift delete mode 100644 Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift rename {Components/Sources/Collection/Extensions => Source/Collection/Wrapper}/CollectionWrappedCell+RDDM.swift (98%) rename {Components/Sources/Collection => Source/Collection/Wrapper}/CollectionWrappedCell.swift (98%) rename {Components/Sources/Common/Utils => Source/Common/Wrapper}/UIView+Constraints.swift (100%) rename {Components/Sources/Common/Utils => Source/Common/Wrapper}/ViewWrapper.swift (97%) rename {Components/Sources/Common => Source}/Models/Alignment.swift (100%) rename {Components/Sources/Common/Protocols => Source/Protocols/Wrapper}/AlignmentProvider.swift (100%) rename {Components/Sources/Table/Extensions => Source/Table/Wrapper}/TableWrappedCell+RDDM.swift (97%) rename {Components/Sources/Table => Source/Table/Wrapper}/TableWrappedCell.swift (97%) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift b/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift deleted file mode 100644 index 036bbb82..00000000 --- a/Components/Sources/Collection/Extensions/CollectionContext+CollectionWrappedCell.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// CollectionContext+CollectionWrappedCell.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 21.07.2023. -// - -import UIKit -import Foundation -import ReactiveDataDisplayManager - -extension CollectionContext: BuilderContext { - - public typealias ViewType = UICollectionViewCell - public typealias GeneratorType = CollectionCellGenerator - - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { - Item.rddm.collectionGenerator(with: model) - } - - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, - Item: BaseItem { - Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) - } - - public static func stack(model: StackView.Model) -> CollectionCellGenerator { - StackView.rddm.collectionGenerator(with: model) - } - -} diff --git a/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift new file mode 100644 index 00000000..2276054f --- /dev/null +++ b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift @@ -0,0 +1,16 @@ +// +// StackView+CollectionContext.swift +// ReactiveChat_iOS +// +// Created by Никита Коробейников on 28.07.2023. +// + +import ReactiveDataDisplayManager + +public extension CollectionContext { + + static func stack(model: StackView.Model) -> CollectionCellGenerator { + StackView.rddm.collectionGenerator(with: model) + } + +} diff --git a/Components/Sources/Table/Extensions/TableContext+StackView.swift b/Components/Sources/Table/Extensions/TableContext+StackView.swift new file mode 100644 index 00000000..2fd310e9 --- /dev/null +++ b/Components/Sources/Table/Extensions/TableContext+StackView.swift @@ -0,0 +1,16 @@ +// +// StackView+TableContext.swift +// ReactiveChat_iOS +// +// Created by Никита Коробейников on 28.07.2023. +// + +import ReactiveDataDisplayManager + +public extension TableContext { + + static func stack(model: StackView.Model) -> TableCellGenerator { + StackView.rddm.tableGenerator(with: model) + } + +} diff --git a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift b/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift deleted file mode 100644 index 6e936b62..00000000 --- a/Components/Sources/Table/Extensions/TableContext+TableWrappedCell.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// TableContext+TableWrappedCell.swift -// ReactiveDataDisplayManager -// -// Created by Никита Коробейников on 21.07.2023. -// - -import UIKit -import Foundation -import ReactiveDataDisplayManager - -extension TableContext: BuilderContext { - - public typealias ViewType = UITableViewCell - public typealias GeneratorType = TableCellGenerator - - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { - Item.rddm.tableGenerator(with: model) - } - - public static func gen(_ type: Item.Type, model: Item.Model) -> any GeneratorType where Item: ViewType, - Item: BaseItem { - Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) - } - - public static func stack(model: StackView.Model) -> TableCellGenerator { - StackView.rddm.tableGenerator(with: model) - } - -} diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift index 0e61769d..99156036 100644 --- a/Source/Collection/Generators/CollectionContext.swift +++ b/Source/Collection/Generators/CollectionContext.swift @@ -8,4 +8,18 @@ import UIKit import Foundation -public struct CollectionContext { } +public struct CollectionContext: BuilderContext { + + public typealias ViewType = UICollectionViewCell + public typealias GeneratorType = CollectionCellGenerator + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { + Item.rddm.collectionGenerator(with: model) + } + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, + Item: BaseItem { + Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) + } + +} diff --git a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift b/Source/Collection/Wrapper/CollectionWrappedCell+RDDM.swift similarity index 98% rename from Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift rename to Source/Collection/Wrapper/CollectionWrappedCell+RDDM.swift index cf15bba2..7222701d 100644 --- a/Components/Sources/Collection/Extensions/CollectionWrappedCell+RDDM.swift +++ b/Source/Collection/Wrapper/CollectionWrappedCell+RDDM.swift @@ -5,7 +5,6 @@ // Created by Никита Коробейников on 05.06.2023. // -import ReactiveDataDisplayManager import UIKit public extension StaticDataDisplayWrapper where Base: UIView & BaseItem { diff --git a/Components/Sources/Collection/CollectionWrappedCell.swift b/Source/Collection/Wrapper/CollectionWrappedCell.swift similarity index 98% rename from Components/Sources/Collection/CollectionWrappedCell.swift rename to Source/Collection/Wrapper/CollectionWrappedCell.swift index 6556039e..5b66d882 100644 --- a/Components/Sources/Collection/CollectionWrappedCell.swift +++ b/Source/Collection/Wrapper/CollectionWrappedCell.swift @@ -6,7 +6,6 @@ // import UIKit -import ReactiveDataDisplayManager /// Empty collection cell with `View`. Configuration is implemented within `ViewWrapper`. public final class CollectionWrappedCell: UICollectionViewCell, ViewWrapper { diff --git a/Components/Sources/Common/Utils/UIView+Constraints.swift b/Source/Common/Wrapper/UIView+Constraints.swift similarity index 100% rename from Components/Sources/Common/Utils/UIView+Constraints.swift rename to Source/Common/Wrapper/UIView+Constraints.swift diff --git a/Components/Sources/Common/Utils/ViewWrapper.swift b/Source/Common/Wrapper/ViewWrapper.swift similarity index 97% rename from Components/Sources/Common/Utils/ViewWrapper.swift rename to Source/Common/Wrapper/ViewWrapper.swift index fc453c89..e8935e35 100644 --- a/Components/Sources/Common/Utils/ViewWrapper.swift +++ b/Source/Common/Wrapper/ViewWrapper.swift @@ -6,7 +6,6 @@ // import UIKit -import ReactiveDataDisplayManager public protocol ViewWrapper: ConfigurableItem { diff --git a/Components/Sources/Common/Models/Alignment.swift b/Source/Models/Alignment.swift similarity index 100% rename from Components/Sources/Common/Models/Alignment.swift rename to Source/Models/Alignment.swift diff --git a/Components/Sources/Common/Protocols/AlignmentProvider.swift b/Source/Protocols/Wrapper/AlignmentProvider.swift similarity index 100% rename from Components/Sources/Common/Protocols/AlignmentProvider.swift rename to Source/Protocols/Wrapper/AlignmentProvider.swift diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index f9d91b67..75bc8b08 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -8,4 +8,18 @@ import UIKit import Foundation -public struct TableContext { } +public struct TableContext: BuilderContext { + + public typealias ViewType = UITableViewCell + public typealias GeneratorType = TableCellGenerator + + public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { + Item.rddm.tableGenerator(with: model) + } + + public static func gen(_ type: Item.Type, model: Item.Model) -> any GeneratorType where Item: ViewType, + Item: BaseItem { + Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) + } + +} diff --git a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift b/Source/Table/Wrapper/TableWrappedCell+RDDM.swift similarity index 97% rename from Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift rename to Source/Table/Wrapper/TableWrappedCell+RDDM.swift index e73043a0..5458ebb9 100644 --- a/Components/Sources/Table/Extensions/TableWrappedCell+RDDM.swift +++ b/Source/Table/Wrapper/TableWrappedCell+RDDM.swift @@ -5,7 +5,6 @@ // Created by Никита Коробейников on 05.06.2023. // -import ReactiveDataDisplayManager import UIKit public extension StaticDataDisplayWrapper where Base: UIView & BaseItem { diff --git a/Components/Sources/Table/TableWrappedCell.swift b/Source/Table/Wrapper/TableWrappedCell.swift similarity index 97% rename from Components/Sources/Table/TableWrappedCell.swift rename to Source/Table/Wrapper/TableWrappedCell.swift index f80976ae..c1cd32db 100644 --- a/Components/Sources/Table/TableWrappedCell.swift +++ b/Source/Table/Wrapper/TableWrappedCell.swift @@ -6,7 +6,6 @@ // import UIKit -import ReactiveDataDisplayManager /// Empty table cell with `View`. Configuration is implemented within `ViewWrapper`. public final class TableWrappedCell: UITableViewCell, ViewWrapper { From df6434e98436b614aeb981d5b10bb1e5aefb81e5 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Fri, 28 Jul 2023 14:43:49 +0400 Subject: [PATCH 23/30] SPT-1469 optimize FoldableItem, remove CollectionFoldableItem --- .../FoldableCollectionViewController.swift | 10 +- .../Mocks/AutoMockable.generated.swift | 33 ---- Source/Collection/CollectionCell+RDDM.swift | 2 +- .../FoldableCollectionCellGenerator.swift | 68 --------- .../Plugins/CollectionPluginsChecker.swift | 2 +- .../CollectionFoldablePlugin.swift | 16 +- ...m.swift => CollectionChildrenHolder.swift} | 10 +- .../Generators/FoldableCellGenerator.swift | 141 ++++++++++++++++++ .../Plugins/Generators/FoldableItem.swift | 21 +-- .../Generators/FoldableCellGenerator.swift | 75 ---------- .../PluginAction/TableFoldablePlugin.swift | 10 +- .../Table/Protocols/TableChildrenHolder.swift | 31 ++++ 12 files changed, 205 insertions(+), 214 deletions(-) delete mode 100644 Source/Collection/Generators/FoldableCollectionCellGenerator.swift rename Source/Collection/Protocols/{CollectionFoldableItem.swift => CollectionChildrenHolder.swift} (64%) create mode 100644 Source/Common/Generators/FoldableCellGenerator.swift delete mode 100644 Source/Table/Generators/FoldableCellGenerator.swift create mode 100644 Source/Table/Protocols/TableChildrenHolder.swift diff --git a/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift index 88218bbb..2550fb48 100644 --- a/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/FoldableCollectionViewController/FoldableCollectionViewController.swift @@ -79,9 +79,9 @@ private extension FoldableCollectionViewController { let child3 = makeRegularCellWithTitlesGenerators(count: 2) // Create foldable generators - let folder1 = makeFoldableCellGenerator(color: .lightGray, expanded: false) - let folder2 = makeFoldableCellGenerator(color: .lightGray, expanded: false) - let folder3 = makeFoldableCellGenerator(color: .lightGray, expanded: true) + var folder1 = makeFoldableCellGenerator(color: .lightGray, expanded: false) + var folder2 = makeFoldableCellGenerator(color: .lightGray, expanded: false) + var folder3 = makeFoldableCellGenerator(color: .lightGray, expanded: true) // Configure relationship folder3.children = child3 @@ -96,7 +96,7 @@ private extension FoldableCollectionViewController { adapter => .reload } - func makeFoldableCellGenerator(color: UIColor, expanded: Bool) -> CollectionCellGenerator & CollectionFoldableItem { + func makeFoldableCellGenerator(color: UIColor, expanded: Bool) -> CollectionCellGenerator & CollectionChildrenHolder { // Create foldable generator let generator = FoldableCollectionViewCell.rddm.foldableGenerator(with: .init(color: color)) @@ -130,7 +130,7 @@ private extension FoldableCollectionViewController { } func getVisibleGenerators(for generator: CollectionCellGenerator) -> [CollectionCellGenerator] { - if let foldableItem = generator as? CollectionFoldableItem, foldableItem.isExpanded { + if let foldableItem = generator as? FoldableItem & CollectionChildrenHolder, foldableItem.isExpanded { return foldableItem.children .map { getVisibleGenerators(for: $0) } .reduce([generator], +) diff --git a/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift b/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift index 6a88b33e..494e9ade 100644 --- a/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift +++ b/ReactiveDataDisplayManagerTests/Mocks/AutoMockable.generated.swift @@ -91,40 +91,7 @@ class CollectionCellGeneratorMock: CollectionCellGenerator { } } -class CollectionFoldableItemMock: CollectionFoldableItem { - var didFoldEvent: Event { - get { return underlyingDidFoldEvent } - set(value) { underlyingDidFoldEvent = value } - } - var underlyingDidFoldEvent: Event! - var isExpanded: Bool { - get { return underlyingIsExpanded } - set(value) { underlyingIsExpanded = value } - } - var underlyingIsExpanded: Bool! - var children: [CollectionCellGenerator] = [] - var labelStrategy: AccessibilityStringStrategy { - get { return underlyingLabelStrategy } - set(value) { underlyingLabelStrategy = value } - } - var underlyingLabelStrategy: AccessibilityStringStrategy! - var valueStrategy: AccessibilityStringStrategy { - get { return underlyingValueStrategy } - set(value) { underlyingValueStrategy = value } - } - var underlyingValueStrategy: AccessibilityStringStrategy! - var traitsStrategy: AccessibilityTraitsStrategy { - get { return underlyingTraitsStrategy } - set(value) { underlyingTraitsStrategy = value } - } - var underlyingTraitsStrategy: AccessibilityTraitsStrategy! - var isAccessibilityIgnored: Bool { - get { return underlyingIsAccessibilityIgnored } - set(value) { underlyingIsAccessibilityIgnored = value } - } - var underlyingIsAccessibilityIgnored: Bool! -} class CollectionFooterGeneratorMock: CollectionFooterGenerator { var identifier: UICollectionReusableView.Type { get { return underlyingIdentifier } diff --git a/Source/Collection/CollectionCell+RDDM.swift b/Source/Collection/CollectionCell+RDDM.swift index 7752bcf7..9bc55389 100644 --- a/Source/Collection/CollectionCell+RDDM.swift +++ b/Source/Collection/CollectionCell+RDDM.swift @@ -28,7 +28,7 @@ public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & Cal public extension StaticDataDisplayWrapper where Base: UICollectionViewCell & ConfigurableItem & FoldableStateHolder { - func foldableGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> FoldableCollectionCellGenerator { + func foldableGenerator(with model: Base.Model, and registerType: RegistrationType = .nib) -> FoldableCellGenerator { .init(with: model, registerType: registerType) } diff --git a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift b/Source/Collection/Generators/FoldableCollectionCellGenerator.swift deleted file mode 100644 index 291bd97b..00000000 --- a/Source/Collection/Generators/FoldableCollectionCellGenerator.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// FoldableCollectionCellGenerator.swift -// ReactiveDataDisplayManager -// -// Created by korshunov on 23.06.2023. -// - -import UIKit - -// swiftlint:disable line_length -/// A generator that can insert and remove child generators by tap -open class FoldableCollectionCellGenerator: BaseCellGenerator, CollectionFoldableItem { -// swiftlint:enable line_length - - // MARK: - FoldableItem - - /// Event on changed `isExpanded` state - open var didFoldEvent = Event() - - /// Folded/unfolded state - open var isExpanded = false - - /// Child generators which can be folded/unfolded - open var children: [CollectionCellGenerator] = [] - - // MARK: - BaseCellGenerator - - open override func configure(cell: Cell, with model: Cell.Model) { - super.configure(cell: cell, with: model) - - cell.setExpanded(isExpanded) - - didFoldEvent.addListner(with: "rddm.foldable-on-dequeue") { [weak cell] isExpanded in - cell?.setExpanded(isExpanded) - } - } - -} - -// MARK: - Decorations - -public extension FoldableCollectionCellGenerator { - - /// - Parameter isExpanded: folded/unfolded state - func isExpanded(_ isExpanded: Bool) -> Self { - self.isExpanded = isExpanded - return self - } - - /// - Parameter closure: handler closure for expand/collapse events - func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { - self.didFoldEvent.addListner(closure) - return self - } - - /// - Parameter children: array of child generators - func children(_ children: [CollectionCellGenerator]) -> Self { - self.children = children - return self - } - - /// - Parameter content: resultBuilder based closure that returns an array of child generators - func children(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> Self { - self.children = content(CollectionContext.self) - return self - } - -} diff --git a/Source/Collection/Plugins/CollectionPluginsChecker.swift b/Source/Collection/Plugins/CollectionPluginsChecker.swift index eb4e65f9..59ef8207 100644 --- a/Source/Collection/Plugins/CollectionPluginsChecker.swift +++ b/Source/Collection/Plugins/CollectionPluginsChecker.swift @@ -31,7 +31,7 @@ final class CollectionPluginsChecker { func checkPlugins() { sections.flatMap(\.generators).forEach { checkPlugin(for: $0 as? SelectableItem) - checkPlugin(for: $0 as? CollectionFoldableItem, pluginName: CollectionFoldablePlugin.pluginName) + checkPlugin(for: $0 as? FoldableItem, pluginName: CollectionFoldablePlugin.pluginName) } } diff --git a/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift b/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift index 4c7897a2..0b3ae389 100644 --- a/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift +++ b/Source/Collection/Plugins/PluginAction/CollectionFoldablePlugin.swift @@ -5,18 +5,24 @@ // Created by Vadim Tikhonov on 11.02.2021. // -/// Plugin to support `CollectionFoldableItem` +/// Plugin to support `FoldableItem` in `UICollectionView` /// /// Allow expand or collapse child cells public class CollectionFoldablePlugin: BaseCollectionPlugin { + // MARK: - Nested types + + public typealias GeneratorType = FoldableItem & CollectionChildrenHolder & FoldableStateToggling + + // MARK: - Plugin body + public override func process(event: CollectionEvent, with manager: BaseCollectionManager?) { switch event { case .didSelect(let indexPath): guard let generator = manager?.sections[indexPath.section].generators[indexPath.row], - let foldable = generator as? CollectionFoldableItem + let foldable = generator as? GeneratorType else { return } @@ -35,7 +41,7 @@ public class CollectionFoldablePlugin: BaseCollectionPlugin { } } - foldable.isExpanded = !foldable.isExpanded + foldable.toggleEpanded() foldable.didFoldEvent.invoke(with: (foldable.isExpanded)) default: break @@ -49,7 +55,7 @@ public class CollectionFoldablePlugin: BaseCollectionPlugin { private extension CollectionFoldablePlugin { func getVisibleGenerators(for generator: CollectionCellGenerator) -> [CollectionCellGenerator] { - if let foldableItem = generator as? CollectionFoldableItem, foldableItem.isExpanded { + if let foldableItem = generator as? GeneratorType, foldableItem.isExpanded { return foldableItem.children .map { getVisibleGenerators(for: $0) } .reduce([generator], +) @@ -64,7 +70,7 @@ private extension CollectionFoldablePlugin { public extension BaseCollectionPlugin { - /// Plugin to support `CollectionFoldableItem` + /// Plugin to support `FoldableItem` in `UICollectionView` /// /// Allow expand or collapse child cells static func foldable() -> BaseCollectionPlugin { diff --git a/Source/Collection/Protocols/CollectionFoldableItem.swift b/Source/Collection/Protocols/CollectionChildrenHolder.swift similarity index 64% rename from Source/Collection/Protocols/CollectionFoldableItem.swift rename to Source/Collection/Protocols/CollectionChildrenHolder.swift index e878a81f..508faf99 100644 --- a/Source/Collection/Protocols/CollectionFoldableItem.swift +++ b/Source/Collection/Protocols/CollectionChildrenHolder.swift @@ -1,5 +1,5 @@ // -// CollectionFoldableItem.swift +// CollectionChildrenHolder.swift // ReactiveDataDisplayManager // // Created by Vadim Tikhonov on 11.02.2021. @@ -9,13 +9,13 @@ import UIKit // sourcery: AutoMockable -public protocol CollectionFoldableItem: AnyObject, AccessibilityStrategyProvider { - var didFoldEvent: Event { get } - var isExpanded: Bool { get set } +public protocol CollectionChildrenHolder: AccessibilityStrategyProvider { var children: [CollectionCellGenerator] { get set } } -public extension CollectionFoldableItem { +// MARK: - Defaults + +public extension CollectionChildrenHolder { var labelStrategy: AccessibilityStringStrategy { .ignored } var traitsStrategy: AccessibilityTraitsStrategy { children.isEmpty ? .ignored : .just(.button) } } diff --git a/Source/Common/Generators/FoldableCellGenerator.swift b/Source/Common/Generators/FoldableCellGenerator.swift new file mode 100644 index 00000000..1fa62cab --- /dev/null +++ b/Source/Common/Generators/FoldableCellGenerator.swift @@ -0,0 +1,141 @@ +// +// FoldableCellGenerator.swift +// ReactiveDataDisplayManager +// +// Created by korshunov on 23.06.2023. +// + +import UIKit + +/// A generator that can insert and remove child generators by tap +open class FoldableCellGenerator: BaseCellGenerator, FoldableItem, FoldableStateToggling { + + // MARK: - Private + + private var tableAnimation: TableChildrenAnimationGroup = (.left, .top) + private var tableChildren: [TableCellGenerator] = [] + + private var collectionChildren: [CollectionCellGenerator] = [] + + // MARK: - Public + + /// Event on changed `isExpanded` state + public var didFoldEvent = Event() + + /// Folded/unfolded state + public var isExpanded = false + + // MARK: - BaseCellGenerator + + public override func configure(cell: Cell, with model: Cell.Model) { + super.configure(cell: cell, with: model) + + cell.setExpanded(isExpanded) + + didFoldEvent.addListner(with: "rddm.foldable-on-dequeue") { [weak cell] isExpanded in + cell?.setExpanded(isExpanded) + } + } + + // MARK: - FoldableStateToggling + + public func toggleEpanded() { + isExpanded.toggle() + } + +} + +// MARK: - TableChildrenHolder + +extension FoldableCellGenerator: TableChildrenHolder where Cell: UITableViewCell { + + public var children: [TableCellGenerator] { + get { + tableChildren + } + set { + tableChildren = newValue + } + } + + public var animation: TableChildrenAnimationGroup { + get { + tableAnimation + } + set { + tableAnimation = newValue + } + } + +} + +// MARK: - CollectionChildrenHolder + +extension FoldableCellGenerator: CollectionChildrenHolder where Cell: UICollectionViewCell { + + public var children: [CollectionCellGenerator] { + get { + collectionChildren + } + set { + collectionChildren = newValue + } + } + +} + +// MARK: - Decorations + +public extension FoldableCellGenerator { + + /// - Parameter isExpanded: folded/unfolded state + func isExpanded(_ isExpanded: Bool) -> Self { + self.isExpanded = isExpanded + return self + } + + /// - Parameter closure: handler closure for folded/unfolded events + func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { + self.didFoldEvent.addListner(closure) + return self + } + +} + +public extension FoldableCellGenerator where Cell: UITableViewCell { + + /// - Parameter animation: animations for cells insertion and deletion + func animation(_ animation: TableChildrenAnimationGroup) -> Self { + self.animation = animation + return self + } + + /// - Parameter children: array of child generators + func children(_ children: [TableCellGenerator]) -> Self { + self.children = children + return self + } + + /// - Parameter content: resultBuilder based closure that returns an array of child generators + func children(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> Self { + self.children = content(TableContext.self) + return self + } + +} + +public extension FoldableCellGenerator where Cell: UICollectionViewCell { + + /// - Parameter children: array of child generators + func children(_ children: [CollectionCellGenerator]) -> Self { + self.children = children + return self + } + + /// - Parameter content: resultBuilder based closure that returns an array of child generators + func children(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> Self { + self.children = content(CollectionContext.self) + return self + } + +} diff --git a/Source/Protocols/Plugins/Generators/FoldableItem.swift b/Source/Protocols/Plugins/Generators/FoldableItem.swift index 98dc5d6d..7cecee9e 100644 --- a/Source/Protocols/Plugins/Generators/FoldableItem.swift +++ b/Source/Protocols/Plugins/Generators/FoldableItem.swift @@ -13,11 +13,12 @@ public protocol FoldableStateHolder: AnyObject { func setExpanded(_ isExpanded: Bool) } -/// Protocol for `TableCellGenerator` to manage expand/collapse state -public protocol FoldableItem: AnyObject, AccessibilityStrategyProvider { +public protocol FoldableStateToggling { + func toggleEpanded() +} - /// Set animation for folder's expand / shrink - var animation: TableFoldablePlugin.AnimationGroup { get } +/// Protocol for `TableCellGenerator` to manage expand/collapse state +public protocol FoldableItem: AnyObject { /// Invokes when cell `didSelect` var didFoldEvent: Event { get } @@ -25,16 +26,4 @@ public protocol FoldableItem: AnyObject, AccessibilityStrategyProvider { /// `true` if cell where expanded, `false` if cell where collapsed var isExpanded: Bool { get set } - /// Generators describing cells to be inserted in expanded state - var children: [TableCellGenerator] { get set } - -} - -public extension FoldableItem { - var animation: TableFoldablePlugin.AnimationGroup { - return (.none, .fade) - } - - var labelStrategy: AccessibilityStringStrategy { .ignored } - var traitsStrategy: AccessibilityTraitsStrategy { children.isEmpty ? .ignored : .just(.button) } } diff --git a/Source/Table/Generators/FoldableCellGenerator.swift b/Source/Table/Generators/FoldableCellGenerator.swift deleted file mode 100644 index d9a285ca..00000000 --- a/Source/Table/Generators/FoldableCellGenerator.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// FoldableCellGenerator.swift -// ReactiveDataDisplayManager -// -// Created by korshunov on 23.06.2023. -// - -import UIKit - -/// A generator that can insert and remove child generators by tap -open class FoldableCellGenerator: BaseCellGenerator, FoldableItem { - - // MARK: - FoldableItem - - /// Animations for cells insertion and deletion - open var animation: TableFoldablePlugin.AnimationGroup = (.left, .top) - - /// Event on changed `isExpanded` state - open var didFoldEvent = Event() - - /// Folded/unfolded state - open var isExpanded = false - - /// Child generators which can be folded/unfolded - open var children: [TableCellGenerator] = [] - - // MARK: - BaseCellGenerator - - open override func configure(cell: Cell, with model: Cell.Model) { - super.configure(cell: cell, with: model) - - cell.setExpanded(isExpanded) - - didFoldEvent.addListner(with: "rddm.foldable-on-dequeue") { [weak cell] isExpanded in - cell?.setExpanded(isExpanded) - } - } - -} - -// MARK: - Decorations - -public extension FoldableCellGenerator { - - /// - Parameter animation: animations for cells insertion and deletion - func animation(_ animation: TableFoldablePlugin.AnimationGroup) -> Self { - self.animation = animation - return self - } - - /// - Parameter isExpanded: folded/unfolded state - func isExpanded(_ isExpanded: Bool) -> Self { - self.isExpanded = isExpanded - return self - } - - /// - Parameter closure: handler closure for folded/unfolded events - func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { - self.didFoldEvent.addListner(closure) - return self - } - - /// - Parameter children: array of child generators - func children(_ children: [TableCellGenerator]) -> Self { - self.children = children - return self - } - - /// - Parameter content: resultBuilder based closure that returns an array of child generators - func children(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> Self { - self.children = content(TableContext.self) - return self - } - -} diff --git a/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift b/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift index a1b939e1..b526c6e6 100644 --- a/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift +++ b/Source/Table/Plugins/PluginAction/TableFoldablePlugin.swift @@ -15,16 +15,16 @@ public class TableFoldablePlugin: BaseTablePlugin { // MARK: - Nested types - public typealias AnimationGroup = (remove: UITableView.RowAnimation, insert: UITableView.RowAnimation) + public typealias GeneratorType = FoldableItem & TableChildrenHolder & FoldableStateToggling - // MARK: - BaseTablePlugin + // MARK: - Plugin body public override func process(event: TableEvent, with manager: BaseTableManager?) { switch event { case .didSelect(let indexPath): guard let generator = manager?.sections[indexPath.section].generators[indexPath.row], - let foldable = generator as? FoldableItem + let foldable = generator as? GeneratorType else { return } @@ -39,7 +39,7 @@ public class TableFoldablePlugin: BaseTablePlugin { addCellGenerators(foldable.children, after: generator, with: manager) } - foldable.isExpanded = !foldable.isExpanded + foldable.toggleEpanded() foldable.didFoldEvent.invoke(with: (foldable.isExpanded)) updateIfNeeded(foldable.children, with: manager) @@ -59,7 +59,7 @@ private extension TableFoldablePlugin { with manager: BaseTableManager?) { if let manager = manager as? GravityTableManager { manager.addCellGenerators(children, after: generator) - } else if let foldable = generator as? FoldableItem { + } else if let foldable = generator as? GeneratorType { manager?.insertManual(after: generator, new: children, with: .animated(foldable.animation.insert)) } else { manager?.insertManual(after: generator, new: children, with: .notAnimated) diff --git a/Source/Table/Protocols/TableChildrenHolder.swift b/Source/Table/Protocols/TableChildrenHolder.swift new file mode 100644 index 00000000..ede50c62 --- /dev/null +++ b/Source/Table/Protocols/TableChildrenHolder.swift @@ -0,0 +1,31 @@ +// +// TableChildrenHolder.swift +// ReactiveDataDisplayManager +// +// Created by Никита Коробейников on 28.07.2023. +// + +import UIKit + +public typealias TableChildrenAnimationGroup = (remove: UITableView.RowAnimation, insert: UITableView.RowAnimation) + +public protocol TableChildrenHolder: AccessibilityStrategyProvider { + + /// Set animation for folder's expand / shrink + var animation: TableChildrenAnimationGroup { get set } + + /// Generators describing cells to be inserted in expanded state + var children: [TableCellGenerator] { get set } + +} + +// MARK: - Defaults + +public extension TableChildrenHolder { + var animation: TableChildrenAnimationGroup { + return (.none, .fade) + } + + var labelStrategy: AccessibilityStringStrategy { .ignored } + var traitsStrategy: AccessibilityTraitsStrategy { children.isEmpty ? .ignored : .just(.button) } +} From 8e1cfc80620d68538efe6e9fd6005e3996530d58 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Mon, 31 Jul 2023 12:21:17 +0400 Subject: [PATCH 24/30] add concrete type for buildIn func and prepare example of decorations and transformations --- .../CollectionContext+StackView.swift | 2 +- .../ConfigurableItem+BuilderContext.swift | 10 ++++---- .../Common/Extensions/ViewContext+Stack.swift | 2 +- .../Extensions/TableContext+StackView.swift | 2 +- ...kCellExampleCollectionViewController.swift | 3 +++ .../StackCellExampleViewController.swift | 23 ++++++++++++++++++- .../FoldableTableViewCell.swift | 8 +++++++ .../Generators/CollectionContext.swift | 5 ++-- .../BuilderContext/BuilderContext.swift | 3 --- Source/Stack/Generators/ViewContext.swift | 2 +- Source/Table/Generators/TableContext.swift | 5 ++-- 11 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift index 2276054f..ed46c2e9 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift @@ -9,7 +9,7 @@ import ReactiveDataDisplayManager public extension CollectionContext { - static func stack(model: StackView.Model) -> CollectionCellGenerator { + static func stack(model: StackView.Model) -> BaseCellGenerator> { StackView.rddm.collectionGenerator(with: model) } diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift index 24343a40..b46913f9 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -10,23 +10,23 @@ import ReactiveDataDisplayManager public extension ConfigurableItem where Self: RegistrationTypeProvider { - static func build(in ctx: ViewContext.Type, with model: Model) -> ViewContext.GeneratorType { + static func build(in ctx: ViewContext.Type, with model: Model) -> BaseViewGenerator { ctx.gen(Self.self, model: model) } - static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType where Self: UITableViewCell { + static func build(in ctx: TableContext.Type, with model: Model) -> BaseCellGenerator where Self: UITableViewCell { ctx.gen(Self.self, model: model) } - static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType { + static func build(in ctx: TableContext.Type, with model: Model) -> BaseCellGenerator> { ctx.gen(Self.self, model: model) } - static func build(in ctx: TableContext.Type, with model: Model) -> TableContext.GeneratorType where Self: UICollectionViewCell { + static func build(in ctx: CollectionContext.Type, with model: Model) -> BaseCellGenerator where Self: UICollectionViewCell { ctx.gen(Self.self, model: model) } - static func build(in ctx: CollectionContext.Type, with model: Model) -> CollectionContext.GeneratorType { + static func build(in ctx: CollectionContext.Type, with model: Model) -> BaseCellGenerator> { ctx.gen(Self.self, model: model) } diff --git a/Components/Sources/Common/Extensions/ViewContext+Stack.swift b/Components/Sources/Common/Extensions/ViewContext+Stack.swift index 2822eecc..46bc9c05 100644 --- a/Components/Sources/Common/Extensions/ViewContext+Stack.swift +++ b/Components/Sources/Common/Extensions/ViewContext+Stack.swift @@ -11,7 +11,7 @@ import ReactiveDataDisplayManager public extension ViewContext { - static func stack(model: StackView.Model) -> ViewGenerator { + static func stack(model: StackView.Model) -> BaseViewGenerator { StackView.rddm.viewGenerator(with: model, and: .class) } diff --git a/Components/Sources/Table/Extensions/TableContext+StackView.swift b/Components/Sources/Table/Extensions/TableContext+StackView.swift index 2fd310e9..78506d5d 100644 --- a/Components/Sources/Table/Extensions/TableContext+StackView.swift +++ b/Components/Sources/Table/Extensions/TableContext+StackView.swift @@ -9,7 +9,7 @@ import ReactiveDataDisplayManager public extension TableContext { - static func stack(model: StackView.Model) -> TableCellGenerator { + static func stack(model: StackView.Model) -> BaseCellGenerator> { StackView.rddm.tableGenerator(with: model) } diff --git a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift index 876d9bf6..abdcabc9 100644 --- a/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift +++ b/Example/ReactiveDataDisplayManager/Collection/StackCellExampleCollectionViewController/StackCellExampleCollectionViewController.swift @@ -103,6 +103,9 @@ private extension StackCellExampleCollectionViewController { } }) TitleCollectionViewCell.build(in: ctx, with: "Some text outside of stack") + .didSelectEvent { + print("Did select cell outside of stack") + } } // Tell adapter that we've changed generators diff --git a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift index 2d554093..da0c2b00 100644 --- a/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/StackCellExampleViewController/StackCellExampleViewController.swift @@ -26,6 +26,7 @@ final class StackCellExampleViewController: UIViewController { private lazy var adapter = tableView.rddm.manualBuilder .add(plugin: .selectable()) + .add(plugin: .foldable()) .add(plugin: .highlightable()) .add(plugin: .accessibility()) .build() @@ -73,13 +74,18 @@ private extension StackCellExampleViewController { }) TitleTableViewCell.build(in: ctx, with: "3") } - }) + }).didSelectEvent { + print("StackView did select") + } LabelView.build(in: ctx, with: .build { label in label.textAlignment(.center) label.text(.string("Wrapped LabelView")) label.style(.init(color: .systemBlue, font: .preferredFont(forTextStyle: .body))) }) TitleTableViewCell.build(in: ctx, with: "Cell outside from stack") + .didSelectEvent { + print("Cell outside from stack did select") + } StackView.build(in: ctx, with: .build { hStack in hStack.background(.solid(.systemGreen)) hStack.style(.init(axis: .horizontal, @@ -103,6 +109,21 @@ private extension StackCellExampleViewController { }) } }) + FoldableTableViewCell.build(in: ctx, with: .init(title: "example", isExpanded: false)) + .asFoldable { ctx in + TitleTableViewCell.build(in: ctx, with: "first child") + .didSelectEvent { + print("first child did select") + } + TitleTableViewCell.build(in: ctx, with: "second child") + .didSelectEvent { + print("second child did select") + } + } + .animation((.bottom, .top)) + .didFoldEvent { + print("Foldable cell is \($0 ? "expanded" : "collapsed")") + } } // Tell adapter that we've changed generators diff --git a/Example/ReactiveDataDisplayManager/Table/Views/Cells/FoldableTableViewCell/FoldableTableViewCell.swift b/Example/ReactiveDataDisplayManager/Table/Views/Cells/FoldableTableViewCell/FoldableTableViewCell.swift index 6117b9d8..a400f8cc 100644 --- a/Example/ReactiveDataDisplayManager/Table/Views/Cells/FoldableTableViewCell/FoldableTableViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Table/Views/Cells/FoldableTableViewCell/FoldableTableViewCell.swift @@ -80,6 +80,14 @@ extension FoldableTableViewCell: ConfigurableItem { } +// MARK: - RegistrationTypeProvider + +extension FoldableTableViewCell: RegistrationTypeProvider { + + static var prefferedRegistration: RegistrationType { .nib } + +} + // MARK: - Configuration private extension FoldableTableViewCell { diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift index 99156036..56957c78 100644 --- a/Source/Collection/Generators/CollectionContext.swift +++ b/Source/Collection/Generators/CollectionContext.swift @@ -13,12 +13,11 @@ public struct CollectionContext: BuilderContext { public typealias ViewType = UICollectionViewCell public typealias GeneratorType = CollectionCellGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { + public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.collectionGenerator(with: model) } - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: ViewType, - Item: BaseItem { + public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator where Item: ViewType & BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Protocols/BuilderContext/BuilderContext.swift b/Source/Protocols/BuilderContext/BuilderContext.swift index df850c25..ace4ca41 100644 --- a/Source/Protocols/BuilderContext/BuilderContext.swift +++ b/Source/Protocols/BuilderContext/BuilderContext.swift @@ -9,7 +9,4 @@ import UIKit public protocol BuilderContext { associatedtype ViewType: UIView - associatedtype GeneratorType - - static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index df65ccdf..b9eb5d40 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -13,7 +13,7 @@ public struct ViewContext: BuilderContext { public typealias ViewType = UIView public typealias GeneratorType = ViewGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { + public static func gen(_ type: Item.Type, model: Item.Model) -> BaseViewGenerator where Item: BaseItem { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 75bc8b08..8d0d7551 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -13,12 +13,11 @@ public struct TableContext: BuilderContext { public typealias ViewType = UITableViewCell public typealias GeneratorType = TableCellGenerator - public static func gen(_ type: Item.Type, model: Item.Model) -> GeneratorType where Item: BaseItem { + public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.tableGenerator(with: model) } - public static func gen(_ type: Item.Type, model: Item.Model) -> any GeneratorType where Item: ViewType, - Item: BaseItem { + public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator where Item: ViewType & BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } From cf4176eb476664a5371c8ca52105b3296ca8f0e4 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Mon, 31 Jul 2023 12:55:24 +0400 Subject: [PATCH 25/30] add HighlightableItem to WrappedCells --- .../Sources/Common/Views/StackView.swift | 2 +- Source/Collection/CollectionSection.swift | 2 +- .../Generators/CollectionContext.swift | 2 +- .../Wrapper/CollectionWrappedCell.swift | 22 +++++++++++++++++++ .../Common/Generators/BaseCellGenerator.swift | 2 +- .../Generators/FoldableCellGenerator.swift | 6 ++--- Source/Stack/Generators/ViewContext.swift | 2 +- .../BaseNonReusableCellGenerator.swift | 3 ++- Source/Table/Generators/TableContext.swift | 2 +- Source/Table/TableSection.swift | 2 +- Source/Table/Wrapper/TableWrappedCell.swift | 22 +++++++++++++++++++ 11 files changed, 56 insertions(+), 11 deletions(-) diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index 42ac7c42..cd24165b 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -49,7 +49,7 @@ extension StackView: ConfigurableItem { } /// Only for stack. Cannot be included in common macros. - public static func children(@GeneratorsBuilder_ content: @escaping (ViewContext.Type) -> [ViewGenerator]) -> Property { + public static func children(@GeneratorsBuilder_ content: @escaping ViewContext.CellsBuilder) -> Property { .init(closure: { model in var model = model model.set(children: content(ViewContext.self)) diff --git a/Source/Collection/CollectionSection.swift b/Source/Collection/CollectionSection.swift index 69ab1c29..e4a13d8a 100644 --- a/Source/Collection/CollectionSection.swift +++ b/Source/Collection/CollectionSection.swift @@ -23,7 +23,7 @@ public extension CollectionSection { static func create(header: HeaderGeneratorType, footer: FooterGeneratorType, - @GeneratorsBuilder generators: (CollectionContext.Type) -> [GeneratorType]) -> Self { + @GeneratorsBuilder generators: CollectionContext.CellsBuilder) -> Self { Self(generators: generators(CollectionContext.self), header: header, footer: footer) } diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift index 56957c78..08806ee6 100644 --- a/Source/Collection/Generators/CollectionContext.swift +++ b/Source/Collection/Generators/CollectionContext.swift @@ -11,7 +11,7 @@ import Foundation public struct CollectionContext: BuilderContext { public typealias ViewType = UICollectionViewCell - public typealias GeneratorType = CollectionCellGenerator + public typealias CellsBuilder = (CollectionContext.Type) -> [CollectionCellGenerator] public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.collectionGenerator(with: model) diff --git a/Source/Collection/Wrapper/CollectionWrappedCell.swift b/Source/Collection/Wrapper/CollectionWrappedCell.swift index 5b66d882..c80b3440 100644 --- a/Source/Collection/Wrapper/CollectionWrappedCell.swift +++ b/Source/Collection/Wrapper/CollectionWrappedCell.swift @@ -57,3 +57,25 @@ extension CollectionWrappedCell: CalculatableWidthItem where View: CalculatableW } } + +// MARK: - HighlightableItem + +extension CollectionWrappedCell: HighlightableItem where View: HighlightableItem { + + public func applyUnhighlightedStyle() { + nestedView.applyUnhighlightedStyle() + } + + public func applyHighlightedStyle() { + nestedView.applyHighlightedStyle() + } + + public func applySelectedStyle() { + nestedView.applySelectedStyle() + } + + public func applyDeselectedStyle() { + nestedView.applyDeselectedStyle() + } + +} diff --git a/Source/Common/Generators/BaseCellGenerator.swift b/Source/Common/Generators/BaseCellGenerator.swift index c4d841f6..e320435c 100644 --- a/Source/Common/Generators/BaseCellGenerator.swift +++ b/Source/Common/Generators/BaseCellGenerator.swift @@ -146,7 +146,7 @@ public extension BaseCellGenerator where Cell: FoldableStateHolder, Cell: UITabl /// Creates FoldableCellGenerator with children generated by resultBuilder /// - Parameter content: resultBuilder based closure that returns array of children - func asFoldable(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> FoldableCellGenerator { + func asFoldable(@GeneratorsBuilder_ content: @escaping TableContext.CellsBuilder) -> FoldableCellGenerator { return .init(with: model, registerType: registerType) .children(content) diff --git a/Source/Common/Generators/FoldableCellGenerator.swift b/Source/Common/Generators/FoldableCellGenerator.swift index 1fa62cab..c33e3502 100644 --- a/Source/Common/Generators/FoldableCellGenerator.swift +++ b/Source/Common/Generators/FoldableCellGenerator.swift @@ -93,7 +93,7 @@ public extension FoldableCellGenerator { self.isExpanded = isExpanded return self } - + /// - Parameter closure: handler closure for folded/unfolded events func didFoldEvent(_ closure: @escaping (Bool) -> Void) -> Self { self.didFoldEvent.addListner(closure) @@ -117,7 +117,7 @@ public extension FoldableCellGenerator where Cell: UITableViewCell { } /// - Parameter content: resultBuilder based closure that returns an array of child generators - func children(@GeneratorsBuilder_ content: @escaping (TableContext.Type) -> [TableCellGenerator]) -> Self { + func children(@GeneratorsBuilder_ content: @escaping TableContext.CellsBuilder) -> Self { self.children = content(TableContext.self) return self } @@ -133,7 +133,7 @@ public extension FoldableCellGenerator where Cell: UICollectionViewCell { } /// - Parameter content: resultBuilder based closure that returns an array of child generators - func children(@GeneratorsBuilder_ content: @escaping (CollectionContext.Type) -> [CollectionCellGenerator]) -> Self { + func children(@GeneratorsBuilder_ content: @escaping CollectionContext.CellsBuilder) -> Self { self.children = content(CollectionContext.self) return self } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index b9eb5d40..0cb19bba 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -11,7 +11,7 @@ import Foundation public struct ViewContext: BuilderContext { public typealias ViewType = UIView - public typealias GeneratorType = ViewGenerator + public typealias CellsBuilder = (ViewContext.Type) -> [ViewGenerator] public static func gen(_ type: Item.Type, model: Item.Model) -> BaseViewGenerator where Item: BaseItem { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) diff --git a/Source/Table/Generators/BaseNonReusableCellGenerator.swift b/Source/Table/Generators/BaseNonReusableCellGenerator.swift index 187d226d..d743b2fe 100644 --- a/Source/Table/Generators/BaseNonReusableCellGenerator.swift +++ b/Source/Table/Generators/BaseNonReusableCellGenerator.swift @@ -13,7 +13,8 @@ import UIKit /// Term *non-reusable* means that we are creating cell manually with constructor type defined in **ConstractableItem**. /// In other words this generator will not use `tableView.deqeueReusableCell`. /// - Warning: Do not use this generators in tables with many cells of same type. Because you may catch perfomance issues. -open class BaseNonReusableCellGenerator: TableCellGenerator & SelectableItem where Cell: UITableViewCell { +open class BaseNonReusableCellGenerator: TableCellGenerator & SelectableItem +where Cell: UITableViewCell { // MARK: - Public Properties diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 8d0d7551..02089281 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -11,7 +11,7 @@ import Foundation public struct TableContext: BuilderContext { public typealias ViewType = UITableViewCell - public typealias GeneratorType = TableCellGenerator + public typealias CellsBuilder = (TableContext.Type) -> [TableCellGenerator] public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.tableGenerator(with: model) diff --git a/Source/Table/TableSection.swift b/Source/Table/TableSection.swift index 4dafe826..384ad06e 100644 --- a/Source/Table/TableSection.swift +++ b/Source/Table/TableSection.swift @@ -23,7 +23,7 @@ public extension TableSection { static func create(header: HeaderGeneratorType, footer: FooterGeneratorType, - @GeneratorsBuilder generators: (TableContext.Type) -> [GeneratorType]) -> Self { + @GeneratorsBuilder generators: TableContext.CellsBuilder) -> Self { Self(generators: generators(TableContext.self), header: header, footer: footer) } diff --git a/Source/Table/Wrapper/TableWrappedCell.swift b/Source/Table/Wrapper/TableWrappedCell.swift index c1cd32db..3e9d7db2 100644 --- a/Source/Table/Wrapper/TableWrappedCell.swift +++ b/Source/Table/Wrapper/TableWrappedCell.swift @@ -39,3 +39,25 @@ extension TableWrappedCell: CalculatableHeightItem where View: CalculatableHeigh } } + +// MARK: - HighlightableItem + +extension TableWrappedCell: HighlightableItem where View: HighlightableItem { + + public func applyUnhighlightedStyle() { + nestedView.applyUnhighlightedStyle() + } + + public func applyHighlightedStyle() { + nestedView.applyHighlightedStyle() + } + + public func applySelectedStyle() { + nestedView.applySelectedStyle() + } + + public func applyDeselectedStyle() { + nestedView.applyDeselectedStyle() + } + +} From 7bfcfcabbe041842bb17d5353ec0f5844aded640 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Mon, 31 Jul 2023 14:50:03 +0400 Subject: [PATCH 26/30] fix intrinsict content size for TitleTableCell --- .../Views/Cells/TitleTableViewCell/TitleTableViewCell.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift index d8508a99..dd57f3b7 100644 --- a/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift +++ b/Example/ReactiveDataDisplayManager/Table/Views/Cells/TitleTableViewCell/TitleTableViewCell.swift @@ -27,7 +27,9 @@ class TitleTableViewCell: UITableViewCell, CalculatableHeightItem { } override var intrinsicContentSize: CGSize { - return CGSize(width: UIView.noIntrinsicMetric, height: 44) + CGSize(width: UIView.noIntrinsicMetric, + height: Self.getHeight(forWidth: UIScreen.main.bounds.width, + with: titleLabel.text ?? "")) } // MARK: - CalculatableHeightItem From b76143ffd5f442bc1085b387932686719f357dfd Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Mon, 31 Jul 2023 15:43:30 +0400 Subject: [PATCH 27/30] optimize coomon styles and apply --- .../Common/Models/Styles/BakgroundStyle.swift | 25 +++++++++++++++++ .../Common/Models/Styles/BorderStyle.swift | 28 +++++++++++++++++++ .../Common/Models/Styles/TextValue.swift | 24 ++++++++++++++++ .../Sources/Common/Views/LabelView.swift | 2 +- .../Sources/Common/Views/MessageView.swift | 28 ++----------------- .../Sources/Common/Views/StackView.swift | 11 +------- 6 files changed, 82 insertions(+), 36 deletions(-) diff --git a/Components/Sources/Common/Models/Styles/BakgroundStyle.swift b/Components/Sources/Common/Models/Styles/BakgroundStyle.swift index 3109f557..c284cc6d 100644 --- a/Components/Sources/Common/Models/Styles/BakgroundStyle.swift +++ b/Components/Sources/Common/Models/Styles/BakgroundStyle.swift @@ -15,3 +15,28 @@ public enum BackgroundStyle: Equatable { // TODO: - gradient, image, bezierPath, bordered } + +// MARK: - Defaults + +public extension BackgroundStyle { + + func apply(in view: UIView) { + switch self { + case .solid(let color): + view.backgroundColor = color + } + } + +} + +public extension Optional { + + func apply(in view: UIView) { + if let self { + self.apply(in: view) + } else { + view.backgroundColor = nil + } + } + +} diff --git a/Components/Sources/Common/Models/Styles/BorderStyle.swift b/Components/Sources/Common/Models/Styles/BorderStyle.swift index a0c2ded3..a592c6d7 100644 --- a/Components/Sources/Common/Models/Styles/BorderStyle.swift +++ b/Components/Sources/Common/Models/Styles/BorderStyle.swift @@ -25,3 +25,31 @@ public struct BorderStyle: Equatable { } } + +// MARK: - Defaults + +public extension BorderStyle { + + func apply(in view: UIView) { + view.layer.cornerRadius = cornerRadius + view.layer.borderColor = borderColor + view.layer.borderWidth = borderWidth + view.layer.maskedCorners = maskedCorners + } + +} + +public extension Optional { + + func apply(in view: UIView) { + if let self { + self.apply(in: view) + } else { + view.layer.cornerRadius = 0 + view.layer.borderColor = UIColor.clear.cgColor + view.layer.borderWidth = 0 + view.layer.maskedCorners = .init() + } + } + +} diff --git a/Components/Sources/Common/Models/Styles/TextValue.swift b/Components/Sources/Common/Models/Styles/TextValue.swift index 181ef0d2..32b4d41e 100644 --- a/Components/Sources/Common/Models/Styles/TextValue.swift +++ b/Components/Sources/Common/Models/Styles/TextValue.swift @@ -12,3 +12,27 @@ public enum TextValue: Equatable { /// Keep in mind that attributed string may re-configure other model's properties. case attributedString(NSAttributedString) } + +// MARK: - Defaults + +public extension TextValue { + + func apply(in view: UILabel) { + switch self { + case .string(let string): + view.text = string + case .attributedString(let attributedString): + view.attributedText = attributedString + } + } + + func apply(in view: UITextView) { + switch self { + case .string(let string): + view.text = string + case .attributedString(let attributedString): + view.attributedText = attributedString + } + } + +} diff --git a/Components/Sources/Common/Views/LabelView.swift b/Components/Sources/Common/Views/LabelView.swift index 5d41fd9d..30dbdfbe 100644 --- a/Components/Sources/Common/Views/LabelView.swift +++ b/Components/Sources/Common/Views/LabelView.swift @@ -135,7 +135,7 @@ extension LabelView: ConfigurableItem { label.lineBreakMode = model.layout.lineBreakMode label.numberOfLines = model.layout.numberOfLines - configureText(with: model.text) + model.text.apply(in: label) setNeedsLayout() } diff --git a/Components/Sources/Common/Views/MessageView.swift b/Components/Sources/Common/Views/MessageView.swift index 32a17f1a..9762f890 100644 --- a/Components/Sources/Common/Views/MessageView.swift +++ b/Components/Sources/Common/Views/MessageView.swift @@ -203,8 +203,8 @@ extension MessageView: ConfigurableItem { wrap(subview: textView, with: model.internalEdgeInsets) - applyBackground(style: model.backgroundStyle) - applyBorder(style: model.borderStyle) + model.backgroundStyle.apply(in: self) + model.borderStyle?.apply(in: self) layoutIfNeeded() } @@ -244,12 +244,7 @@ extension MessageView: CalculatableWidthItem { private extension MessageView { func configureTextView(_ textView: UITextView, with model: Model) { - switch model.text { - case .string(let string): - textView.text = string - case .attributedString(let attributedString): - textView.attributedText = attributedString - } + model.text.apply(in: textView) textView.dataDetectorTypes = model.dataDetection?.dataDetectorTypes ?? [] textView.linkTextAttributes = model.dataDetection?.linkTextAttributes @@ -257,23 +252,6 @@ private extension MessageView { dataDetectionHandler = model.dataDetection?.handler } - func applyBackground(style: BackgroundStyle) { - switch style { - case .solid(let color): - backgroundColor = color - } - } - - func applyBorder(style: BorderStyle?) { - guard let borderStyle = style else { - return - } - layer.cornerRadius = borderStyle.cornerRadius - layer.borderColor = borderStyle.borderColor - layer.borderWidth = borderStyle.borderWidth - layer.maskedCorners = borderStyle.maskedCorners - } - func handleDataDetection(_ data: URL) { dataDetectionHandler?(data) } diff --git a/Components/Sources/Common/Views/StackView.swift b/Components/Sources/Common/Views/StackView.swift index cd24165b..e281ef52 100644 --- a/Components/Sources/Common/Views/StackView.swift +++ b/Components/Sources/Common/Views/StackView.swift @@ -131,7 +131,7 @@ extension StackView: ConfigurableItem { public func configure(with model: Model) { configureConstraints() apply(style: model.style) - applyBackground(style: model.background) + model.background.apply(in: stackView) adapter -= .all adapter += model.children @@ -155,15 +155,6 @@ private extension StackView { stackView.distribution = style.distribution } - func applyBackground(style: BackgroundStyle?) { - switch style { - case .solid(let color): - stackView.backgroundColor = color - case .none: - stackView.backgroundColor = nil - } - } - } // MARK: - RegistrationTypeProvider From ed56c73f8531dff5e31ec01b986b4bc38708f3d9 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Mon, 31 Jul 2023 17:13:20 +0400 Subject: [PATCH 28/30] add more docs --- .../CollectionContext+StackView.swift | 2 ++ .../ConfigurableItem+BuilderContext.swift | 20 +++++++++++++++++++ .../Common/Extensions/ViewContext+Stack.swift | 2 ++ .../Extensions/TableContext+StackView.swift | 2 ++ .../Generators/CollectionContext.swift | 9 +++++++++ .../BuilderContext/BuilderContext.swift | 2 ++ .../RegistrationTypeProvider.swift | 3 +++ Source/Stack/Generators/ViewContext.swift | 5 +++++ Source/Table/Generators/TableContext.swift | 9 +++++++++ 9 files changed, 54 insertions(+) diff --git a/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift index ed46c2e9..36fa1145 100644 --- a/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift +++ b/Components/Sources/Collection/Extensions/CollectionContext+StackView.swift @@ -9,6 +9,8 @@ import ReactiveDataDisplayManager public extension CollectionContext { + /// Used to place `StackView` into other `UICollectionView` as cell + /// - Parameter model: model which contains styles and children static func stack(model: StackView.Model) -> BaseCellGenerator> { StackView.rddm.collectionGenerator(with: model) } diff --git a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift index b46913f9..97e4457c 100644 --- a/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift +++ b/Components/Sources/Common/Extensions/ConfigurableItem+BuilderContext.swift @@ -10,22 +10,42 @@ import ReactiveDataDisplayManager public extension ConfigurableItem where Self: RegistrationTypeProvider { + /// This method is used to build generator for some `UIView` which can be used as child for `StackView` + /// - Parameters: + /// - ctx: may be `ViewContext.self` + /// - model: configurable model for `UIView` static func build(in ctx: ViewContext.Type, with model: Model) -> BaseViewGenerator { ctx.gen(Self.self, model: model) } + /// This method is used to build generator for some `UITableViewCell` to place it in `UITableView` + /// - Parameters: + /// - ctx: may be `TableContext.self` + /// - model: configurable model for `UITableViewCell` static func build(in ctx: TableContext.Type, with model: Model) -> BaseCellGenerator where Self: UITableViewCell { ctx.gen(Self.self, model: model) } + /// This method is used to build generator for some `UIView` wrapped in `TableWrappedCell` to place it in `UITableView` + /// - Parameters: + /// - ctx: may be `TableContext.self` + /// - model: configurable model for `UIView` static func build(in ctx: TableContext.Type, with model: Model) -> BaseCellGenerator> { ctx.gen(Self.self, model: model) } + /// This method is used to build generator for some `UICollectionViewCell` to place it in `UICollectionView` + /// - Parameters: + /// - ctx: may be `CollectionContext.self` + /// - model: configurable model for `UIView` static func build(in ctx: CollectionContext.Type, with model: Model) -> BaseCellGenerator where Self: UICollectionViewCell { ctx.gen(Self.self, model: model) } + /// This method is used to build generator for some `UIView` wrapped in `CollectionWrappedCell` to place it in `UICollectionView` + /// - Parameters: + /// - ctx: may be `CollectionContext.self` + /// - model: configurable model for `UIView` static func build(in ctx: CollectionContext.Type, with model: Model) -> BaseCellGenerator> { ctx.gen(Self.self, model: model) } diff --git a/Components/Sources/Common/Extensions/ViewContext+Stack.swift b/Components/Sources/Common/Extensions/ViewContext+Stack.swift index 46bc9c05..da0862d9 100644 --- a/Components/Sources/Common/Extensions/ViewContext+Stack.swift +++ b/Components/Sources/Common/Extensions/ViewContext+Stack.swift @@ -11,6 +11,8 @@ import ReactiveDataDisplayManager public extension ViewContext { + /// Used to place `StackView` into other `StackView` + /// - Parameter model: model which contains styles and children static func stack(model: StackView.Model) -> BaseViewGenerator { StackView.rddm.viewGenerator(with: model, and: .class) } diff --git a/Components/Sources/Table/Extensions/TableContext+StackView.swift b/Components/Sources/Table/Extensions/TableContext+StackView.swift index 78506d5d..4965b769 100644 --- a/Components/Sources/Table/Extensions/TableContext+StackView.swift +++ b/Components/Sources/Table/Extensions/TableContext+StackView.swift @@ -9,6 +9,8 @@ import ReactiveDataDisplayManager public extension TableContext { + /// Used to place `StackView` into other `UITableView` as cell + /// - Parameter model: model which contains styles and children static func stack(model: StackView.Model) -> BaseCellGenerator> { StackView.rddm.tableGenerator(with: model) } diff --git a/Source/Collection/Generators/CollectionContext.swift b/Source/Collection/Generators/CollectionContext.swift index 08806ee6..33afecb5 100644 --- a/Source/Collection/Generators/CollectionContext.swift +++ b/Source/Collection/Generators/CollectionContext.swift @@ -8,15 +8,24 @@ import UIKit import Foundation +/// Context which is used to prepare generators for `UIView` or `UICollectionViewCell` to place them into `UICollectionView` public struct CollectionContext: BuilderContext { public typealias ViewType = UICollectionViewCell public typealias CellsBuilder = (CollectionContext.Type) -> [CollectionCellGenerator] + /// This method is used to build generator for some `UIView` to place it in `UICollectionView` + /// - Parameters: + /// - type: may be `SomeView.self` + /// - model: configurable model for generic `SomeView` public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.collectionGenerator(with: model) } + /// This method is used to build generator for some `UICollectionViewCell` to place it in `UICollectionView` + /// - Parameters: + /// - type: may be `SomeCell.self` + /// - model: configurable model for generic `SomeCell` public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator where Item: ViewType & BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Protocols/BuilderContext/BuilderContext.swift b/Source/Protocols/BuilderContext/BuilderContext.swift index ace4ca41..5d98517c 100644 --- a/Source/Protocols/BuilderContext/BuilderContext.swift +++ b/Source/Protocols/BuilderContext/BuilderContext.swift @@ -7,6 +7,8 @@ import UIKit +/// Context which is used to build `UIView` in some container view which can be on of: `UIStackView`, `UICollectionView`, `UITableView` public protocol BuilderContext { + /// Base type of child view associatedtype ViewType: UIView } diff --git a/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift index 12a16c55..6cf4c0ed 100644 --- a/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift +++ b/Source/Protocols/BuilderContext/RegistrationTypeProvider.swift @@ -5,6 +5,9 @@ // Created by Никита Коробейников on 26.07.2023. // +/// Protocol which is used to provide link `RegistrationType` with dedicated view public protocol RegistrationTypeProvider { + /// `nib` or `class` to choose registration type in `UICollectionView` or `UITableView` + /// or creation method for nested views static var prefferedRegistration: RegistrationType { get } } diff --git a/Source/Stack/Generators/ViewContext.swift b/Source/Stack/Generators/ViewContext.swift index 0cb19bba..f34a1ca8 100644 --- a/Source/Stack/Generators/ViewContext.swift +++ b/Source/Stack/Generators/ViewContext.swift @@ -8,11 +8,16 @@ import UIKit import Foundation +/// Context which is used to build `UIView` which can be used as child for `StackView` public struct ViewContext: BuilderContext { public typealias ViewType = UIView public typealias CellsBuilder = (ViewContext.Type) -> [ViewGenerator] + /// This method is used to build generator for some `UIView` which can be used as child for `StackView` + /// - Parameters: + /// - type: may be `SomeView.self` + /// - model: configurable model for generic `SomeView` public static func gen(_ type: Item.Type, model: Item.Model) -> BaseViewGenerator where Item: BaseItem { Item.rddm.viewGenerator(with: model, and: Item.prefferedRegistration) } diff --git a/Source/Table/Generators/TableContext.swift b/Source/Table/Generators/TableContext.swift index 02089281..b425d6bf 100644 --- a/Source/Table/Generators/TableContext.swift +++ b/Source/Table/Generators/TableContext.swift @@ -8,15 +8,24 @@ import UIKit import Foundation +/// Context which is used to prepare generators for `UIView` or `UITableViewCell` to place them into `UITableView` public struct TableContext: BuilderContext { public typealias ViewType = UITableViewCell public typealias CellsBuilder = (TableContext.Type) -> [TableCellGenerator] + /// This method is used to build generator for some `UIView` to place it in `UITableView` + /// - Parameters: + /// - type: may be `SomeView.self` + /// - model: configurable model for generic `SomeView` public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator> where Item: BaseItem { Item.rddm.tableGenerator(with: model) } + /// This method is used to build generator for some `UITableViewCell` to place it in `UITableView` + /// - Parameters: + /// - type: may be `SomeCell.self` + /// - model: configurable model for generic `SomeCell` public static func gen(_ type: Item.Type, model: Item.Model) -> BaseCellGenerator where Item: ViewType & BaseItem { Item.rddm.baseGenerator(with: model, and: Item.prefferedRegistration) } From ea60f8ceb0f8b73f049534365c3e6cefad0d3164 Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Tue, 1 Aug 2023 10:22:30 +0400 Subject: [PATCH 29/30] fix checking of xcodebuild.log --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 450c05cd..5d60fd3d 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ test_lib_iOS: ## Count failures in xcodebuild.log and `exit 0` if no failures or `exit 1` otherwise check_test_log: echo "Test results: xcodebuild.log" - $(eval failures_count := $(shell cat xcodebuild.log | grep -Eo "[0-9]+ failures" | grep -Eo "[0-9]+")) + $(eval failures_count := $(shell cat xcodebuild.log | grep -Eo "[0-9]+ (failure|failures)" | grep -Eo "[0-9]+")) echo "Failures count: $(failures_count)" @if [ $(failures_count) == "0" ]; then\ echo "Tests passed";\ From b75c607e3522baae33d837353a9c615e057711ac Mon Sep 17 00:00:00 2001 From: Nikita Korobeinikov Date: Tue, 1 Aug 2023 11:42:25 +0400 Subject: [PATCH 30/30] improve components example --- ...omponentsOverviewTableViewController.swift | 116 ++++++++++-------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift b/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift index 9bb0e26d..6d9770c1 100644 --- a/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift +++ b/Example/ReactiveDataDisplayManager/Table/ComponentsOverviewTableViewController/ComponentsOverviewTableViewController.swift @@ -17,8 +17,33 @@ final class ComponentsOverviewTableViewController: UIViewController { // MARK: - Constants - private enum Constants { - static let titleForRegularCell = "Lorem ipsum dolor sit amet" + private enum Messages: String, CaseIterable { + case hi + case hello + case question = "Are you here?" + case answer = "Yes, I'm here" + case bye + case long = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed nunc id nisl aliquet ultrices. Integer auctor, nisl euismod efficitur maximus, urna diam aliquam tellus, sed lacinia velit nibh eget sem. Nullam sed nisi eget nisl tincidunt malesuada. Donec euismod, turpis et tincidunt luctus, nisl nunc ultricies nunc, non aliquam velit magna id urna. Nullam vel nunc auctor, luctus urna in, aliquet libero. Donec euismod, turpis et tincidunt luctus, nisl nunc ultricies nunc, non aliquam velit magna id urna. Nullam vel nunc auctor, luctus urna in, aliquet libero." + case link = "Check out link: https://stackoverflow.com" + + var preparedForSent: Bool { + switch self { + case .link, .hi, .answer: + return false + default: + return true + } + } + + var preparedForReceived: Bool { + switch self { + case .hello, .question: + return false + default: + return true + } + } + } // MARK: - IBOutlet @@ -84,25 +109,6 @@ final class ComponentsOverviewTableViewController: UIViewController { font: .preferredFont(forTextStyle: .body)) private let sentMessageBorderStyle = BorderStyle(cornerRadius: 9, maskedCorners: [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner]) - private lazy var sentMessageModel: MessageView.Model = .build { property in - let backgorundColor: UIColor? = Bool.random() ? .systemBlue : .rddm - property.background(.solid(backgorundColor)) - property.border(sentMessageBorderStyle) - property.style(sentMessageStyle) - property.textAlignment(.right) - property.alignment(.trailing(UIEdgeInsets(top: 12, - left: UIScreen.main.bounds.width / 2, - bottom: 12, - right: 16) - )) - property.insets(UIEdgeInsets(top: 3, - left: 5, - bottom: 3, - right: 5)) - property.text(.string("Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet")) - } - - private lazy var sentMessageGenerator = MessageView.rddm.tableGenerator(with: sentMessageModel) // Recieved message private let recievedMessageStyle = TextStyle(color: .black, font: .preferredFont(forTextStyle: .body)) @@ -121,23 +127,6 @@ final class ComponentsOverviewTableViewController: UIViewController { linkTextAttributes: [.foregroundColor: UIColor.blue], handler: dataDetectionHandler, dataDetectorTypes: [.link]) - private lazy var recievedMessageModel: MessageView.Model = .build { property in - property.border(recievedMessageBorderStyle) - property.style(recievedMessageStyle) - property.alignment(.leading(UIEdgeInsets(top: 12, - left: 16, - bottom: 12, - right: UIScreen.main.bounds.width / 2))) - property.insets(UIEdgeInsets(top: 3, - left: 5, - bottom: 3, - right: 5)) - property.text(.string("Check out link: https://stackoverflow.com/")) - property.dataDetection(dataDetection) - property.selectable(true) - } - - private lazy var recievedMessageGenerator = MessageView.rddm.tableGenerator(with: recievedMessageModel) // Separator @@ -179,19 +168,50 @@ private extension ComponentsOverviewTableViewController { } func generateSentMessages() -> [TableCellGenerator] { - var generators = [TableCellGenerator]() - for _ in 0..<20 { - generators.append(sentMessageGenerator) - } - return generators + Messages.allCases + .filter { $0.preparedForSent } + .map { $0.rawValue } + .map { message in + MessageView.rddm.tableGenerator(with: .build { property in + property.background(.solid(.rddm)) + property.border(sentMessageBorderStyle) + property.style(sentMessageStyle) + property.textAlignment(.right) + property.alignment(.trailing(UIEdgeInsets(top: 12, + left: UIScreen.main.bounds.width / 2, + bottom: 12, + right: 16) + )) + property.insets(UIEdgeInsets(top: 3, + left: 5, + bottom: 3, + right: 5)) + property.text(.string(message)) + }) + } } func generateRecievedMessages() -> [TableCellGenerator] { - var generators = [TableCellGenerator]() - for _ in 0..<30 { - generators.append(recievedMessageGenerator) - } - return generators + Messages.allCases + .filter { $0.preparedForReceived } + .map { $0.rawValue } + .map { message in + MessageView.rddm.tableGenerator(with: .build { property in + property.border(recievedMessageBorderStyle) + property.style(recievedMessageStyle) + property.alignment(.leading(UIEdgeInsets(top: 12, + left: 16, + bottom: 12, + right: UIScreen.main.bounds.width / 2))) + property.insets(UIEdgeInsets(top: 3, + left: 5, + bottom: 3, + right: 5)) + property.dataDetection(dataDetection) + property.selectable(true) + property.text(.string(message)) + }) + } } }