From 0e03e6634c322b88b78581539680b123036dd368 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 5 Feb 2024 10:26:05 -0800 Subject: [PATCH 1/2] Initial commit --- .../CollectionView/CollectionView.swift | 127 ++++++++++++++++++ .../Sources/Internal/ReusableViewCache.swift | 16 +-- .../ListView/ListView+FeatureFlag.swift | 16 +++ 3 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 ListableUI/Sources/CollectionView/CollectionView.swift create mode 100644 ListableUI/Sources/ListView/ListView+FeatureFlag.swift diff --git a/ListableUI/Sources/CollectionView/CollectionView.swift b/ListableUI/Sources/CollectionView/CollectionView.swift new file mode 100644 index 000000000..260be88d9 --- /dev/null +++ b/ListableUI/Sources/CollectionView/CollectionView.swift @@ -0,0 +1,127 @@ +// +// CollectionView.swift +// ListableUI +// +// Created by Kyle Van Essen on 11/29/23. +// + +import Foundation + + +final class LSTCollectionView : UIView { + + 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: 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+FeatureFlag.swift b/ListableUI/Sources/ListView/ListView+FeatureFlag.swift new file mode 100644 index 000000000..89d672731 --- /dev/null +++ b/ListableUI/Sources/ListView/ListView+FeatureFlag.swift @@ -0,0 +1,16 @@ +// +// ListView+FeatureFlag.swift +// ListableUI +// +// Created by Kyle Van Essen on 11/29/23. +// + +import Foundation + + +extension ListView { + + public static let isNewBackingViewEnabled : Bool = { + UserDefaults.standard.bool(forKey: "Listable.isNewBackingViewEnabled") + }() +} From 2e3f97cef039c705f2c043ddccfaf95f68c4aebf Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 4 Mar 2024 10:33:56 -0800 Subject: [PATCH 2/2] more --- .../CollectionView/CollectionView.swift | 8 +++++- .../ListView/ListView+FeatureFlag.swift | 16 ----------- ListableUI/Sources/ListView/ListView.swift | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) delete mode 100644 ListableUI/Sources/ListView/ListView+FeatureFlag.swift diff --git a/ListableUI/Sources/CollectionView/CollectionView.swift b/ListableUI/Sources/CollectionView/CollectionView.swift index 260be88d9..2fb400146 100644 --- a/ListableUI/Sources/CollectionView/CollectionView.swift +++ b/ListableUI/Sources/CollectionView/CollectionView.swift @@ -8,7 +8,7 @@ import Foundation -final class LSTCollectionView : UIView { +final class LSTCollectionView : UIScrollView { private let queue : ListChangesQueue @@ -32,6 +32,12 @@ final class LSTCollectionView : UIView { self.addSubview(self.view) } + // MARK: UIScrollView + + override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) { + super.setContentOffset(contentOffset, animated: animated) + } + // MARK: UIView override func layoutSubviews() { diff --git a/ListableUI/Sources/ListView/ListView+FeatureFlag.swift b/ListableUI/Sources/ListView/ListView+FeatureFlag.swift deleted file mode 100644 index 89d672731..000000000 --- a/ListableUI/Sources/ListView/ListView+FeatureFlag.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// ListView+FeatureFlag.swift -// ListableUI -// -// Created by Kyle Van Essen on 11/29/23. -// - -import Foundation - - -extension ListView { - - public static let isNewBackingViewEnabled : Bool = { - UserDefaults.standard.bool(forKey: "Listable.isNewBackingViewEnabled") - }() -} 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 //