diff --git a/ListableUI/Sources/CollectionView/CollectionView.swift b/ListableUI/Sources/CollectionView/CollectionView.swift new file mode 100644 index 000000000..2fb400146 --- /dev/null +++ b/ListableUI/Sources/CollectionView/CollectionView.swift @@ -0,0 +1,133 @@ +// +// CollectionView.swift +// ListableUI +// +// Created by Kyle Van Essen on 11/29/23. +// + +import Foundation + + +final class LSTCollectionView : UIScrollView { + + private let queue : ListChangesQueue + + private(set) var content : Content + + private var reuseCache : ReusableViewCache + + private let view : ContentView + + // MARK: Initialization + + override init(frame: CGRect) { + + self.queue = .init() + self.content = .empty + self.reuseCache = .init() + self.view = .init(frame: .init(origin: .zero, size: frame.size)) + + super.init(frame: frame) + + self.addSubview(self.view) + } + + // MARK: UIScrollView + + override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) { + super.setContentOffset(contentOffset, animated: animated) + } + + // MARK: UIView + + override func layoutSubviews() { + super.layoutSubviews() + + self.view.frame = bounds + } + + required init?(coder: NSCoder) { fatalError() } + + func set( + content : Content, + changes: SectionedDiff, + completion : @escaping () -> () + ) { + queue.add { + + } + } + +} + +extension LSTCollectionView { + final class ContentView : UIScrollView { + + } +} + +open class LSTCollectionReusableView : UIView { + +} + +open class LSTCollectionSupplementaryView : LSTCollectionReusableView { + +} + +open class LSTCollectionItemView : LSTCollectionReusableView { + +} + + +extension LSTCollectionView { + + struct Content { + + static var empty : Self { + fatalError() + } + + var supplementaries : Supplementaries + + var sections : [Section] + } + + struct Section { + var supplementaries : Supplementaries + + var items : [Item] + } + + struct Item { + var value : AnyItem + + var state : State + + final class State { + + } + } + + struct Supplementaries { + + private var byType : [ObjectIdentifier:Supplementary] + + } + + struct Supplementary { + var value : AnyHeaderFooter + + var state : State + + final class State { + + } + } +} + +protocol SupplementaryTypeKey { + +} diff --git a/ListableUI/Sources/Internal/ReusableViewCache.swift b/ListableUI/Sources/Internal/ReusableViewCache.swift index cf0f41087..3ab90d08a 100644 --- a/ListableUI/Sources/Internal/ReusableViewCache.swift +++ b/ListableUI/Sources/Internal/ReusableViewCache.swift @@ -10,34 +10,32 @@ import Foundation final class ReusableViewCache { - private var views : [String:[AnyObject]] = [:] - - init() {} + private var views : [AnyHashable:[AnyObject]] = [:] func count(for reuseIdentifier : ReuseIdentifier) -> Int { - let views = self.views[reuseIdentifier.stringValue, default: []] + let views = self.views[reuseIdentifier, default: []] return views.count } func push(_ view : View, with reuseIdentifier: ReuseIdentifier) { - var views = self.views[reuseIdentifier.stringValue, default: []] + var views = self.views[reuseIdentifier, default: []] listableInternalPrecondition(views.contains { $0 === view } == false, "Cannot push a view which is already in the cache.") views.append(view) - self.views[reuseIdentifier.stringValue] = views + self.views[reuseIdentifier] = views } func pop(with reuseIdentifier: ReuseIdentifier, _ create : () -> View) -> View { - var views = self.views[reuseIdentifier.stringValue, default: []] + var views = self.views[reuseIdentifier, default: []] if let view = views.popLast() { - self.views[reuseIdentifier.stringValue] = views + self.views[reuseIdentifier] = views return view as! View } else { return create() @@ -46,7 +44,7 @@ final class ReusableViewCache func use(with reuseIdentifier: ReuseIdentifier, create : () -> View, _ use : (View) -> Result) -> Result { - let views = self.views[reuseIdentifier.stringValue, default: []] + let views = self.views[reuseIdentifier, default: []] if let view = views.last { // Fast path: Already in the cache, just reference it here. diff --git a/ListableUI/Sources/ListView/ListView.swift b/ListableUI/Sources/ListView/ListView.swift index 097b19f08..28aa8dafe 100644 --- a/ListableUI/Sources/ListView/ListView.swift +++ b/ListableUI/Sources/ListView/ListView.swift @@ -221,6 +221,34 @@ public final class ListView : UIView self.updateCollectionViewWithCurrentLayoutProperties() } + // + // MARK: Replace UICollectionView Feature Flag + // + + public static var isNewBackingViewEnabled : Bool { + get { + UserDefaults.standard.bool(forKey: "Listable.isNewBackingViewEnabled") + } + + set { + UserDefaults.standard.setValue(newValue, forKey: "Listable.isNewBackingViewEnabled") + } + } + + public let isNewBackingViewEnabled : Bool = ListView.isNewBackingViewEnabled + + public func ifNew( + _ ifNew : () throws -> Output, + ifOld : () throws -> Output + ) rethrows -> Output { + + if Self.isNewBackingViewEnabled { + try ifNew() + } else { + try ifOld() + } + } + // // MARK: Layout //