Skip to content

Commit 11c72b6

Browse files
committed
add generic node event
1 parent 1aefcc9 commit 11c72b6

13 files changed

+295
-124
lines changed

Ark.xcodeproj/project.pbxproj

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
/* Begin PBXBuildFile section */
1010
35B204DE2BBBE9F4FD20E04E /* Pods_ArkDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0C766C3C5A77FD675545DA9 /* Pods_ArkDemo.framework */; };
1111
6DFA35176F2E68C10B888F2D /* Pods_Ark.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A4B4EE553955500C312EBAA /* Pods_Ark.framework */; };
12-
A64FD07824F681D000EB0D38 /* CollectionNodeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64FD07724F681CF00EB0D38 /* CollectionNodeModel.swift */; };
12+
A64FD07824F681D000EB0D38 /* NodeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64FD07724F681CF00EB0D38 /* NodeModel.swift */; };
1313
A64FD07A24F688D000EB0D38 /* HomeFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64FD07924F688D000EB0D38 /* HomeFeed.swift */; };
1414
A655BE0F24F73CC400DB6F02 /* Banner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A655BE0E24F73CC400DB6F02 /* Banner.swift */; };
1515
A655BE1124F73D2800DB6F02 /* ArticleFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = A655BE1024F73D2800DB6F02 /* ArticleFeed.swift */; };
1616
A655BE1324F73D5C00DB6F02 /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A655BE1224F73D5C00DB6F02 /* SectionHeader.swift */; };
17-
A6E81FA624F7E99E00AAE8B0 /* CollectionNodeContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E81FA524F7E99E00AAE8B0 /* CollectionNodeContext.swift */; };
17+
A6E81FA624F7E99E00AAE8B0 /* NodeContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E81FA524F7E99E00AAE8B0 /* NodeContext.swift */; };
1818
B4256DC724ED1715000DF13C /* Ark.h in Headers */ = {isa = PBXBuildFile; fileRef = B4256DC524ED1715000DF13C /* Ark.h */; settings = {ATTRIBUTES = (Public, ); }; };
1919
B42875AB24EE10ED00933413 /* ListDiff.swift in Sources */ = {isa = PBXBuildFile; fileRef = B42875AA24EE10ED00933413 /* ListDiff.swift */; };
2020
B42875B324EE137D00933413 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B42875B224EE137D00933413 /* AppDelegate.swift */; };
@@ -27,6 +27,7 @@
2727
B42875CA24EE7A7700933413 /* Ark.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4256DC224ED1715000DF13C /* Ark.framework */; };
2828
B42875CB24EE7A7700933413 /* Ark.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B4256DC224ED1715000DF13C /* Ark.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2929
B4E5581B24FCA9DA004C2477 /* DateFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E81FA224F7A8C600AAE8B0 /* DateFormat.swift */; };
30+
B4E5581E24FCC530004C2477 /* NodeChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E5581D24FCC530004C2477 /* NodeChannel.swift */; };
3031
/* End PBXBuildFile section */
3132

3233
/* Begin PBXContainerItemProxy section */
@@ -69,13 +70,13 @@
6970
73A9113722B6957CF7BB8838 /* Pods-GLFeedKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GLFeedKitDemo.debug.xcconfig"; path = "Target Support Files/Pods-GLFeedKitDemo/Pods-GLFeedKitDemo.debug.xcconfig"; sourceTree = "<group>"; };
7071
9500F7B816029FB5A309BFA3 /* Pods-ArkDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ArkDemo.release.xcconfig"; path = "Target Support Files/Pods-ArkDemo/Pods-ArkDemo.release.xcconfig"; sourceTree = "<group>"; };
7172
A52E228118AFF2DB46C48C21 /* Pods-GLFeedKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GLFeedKit.debug.xcconfig"; path = "Target Support Files/Pods-GLFeedKit/Pods-GLFeedKit.debug.xcconfig"; sourceTree = "<group>"; };
72-
A64FD07724F681CF00EB0D38 /* CollectionNodeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionNodeModel.swift; sourceTree = "<group>"; };
73+
A64FD07724F681CF00EB0D38 /* NodeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeModel.swift; sourceTree = "<group>"; };
7374
A64FD07924F688D000EB0D38 /* HomeFeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFeed.swift; sourceTree = "<group>"; };
7475
A655BE0E24F73CC400DB6F02 /* Banner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Banner.swift; sourceTree = "<group>"; };
7576
A655BE1024F73D2800DB6F02 /* ArticleFeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleFeed.swift; sourceTree = "<group>"; };
7677
A655BE1224F73D5C00DB6F02 /* SectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeader.swift; sourceTree = "<group>"; };
7778
A6E81FA224F7A8C600AAE8B0 /* DateFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormat.swift; sourceTree = "<group>"; };
78-
A6E81FA524F7E99E00AAE8B0 /* CollectionNodeContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionNodeContext.swift; sourceTree = "<group>"; };
79+
A6E81FA524F7E99E00AAE8B0 /* NodeContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeContext.swift; sourceTree = "<group>"; };
7980
B4256DC224ED1715000DF13C /* Ark.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Ark.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8081
B4256DC524ED1715000DF13C /* Ark.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Ark.h; sourceTree = "<group>"; };
8182
B4256DC624ED1715000DF13C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -89,6 +90,7 @@
8990
B42875BE24EE138100933413 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
9091
B42875C024EE138100933413 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9192
B42875C524EE2CBB00933413 /* DiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableDataSource.swift; sourceTree = "<group>"; };
93+
B4E5581D24FCC530004C2477 /* NodeChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeChannel.swift; sourceTree = "<group>"; };
9294
F0C766C3C5A77FD675545DA9 /* Pods_ArkDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ArkDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9395
F61531B872BE69FE4C5901BD /* Pods-Ark.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Ark.release.xcconfig"; path = "Target Support Files/Pods-Ark/Pods-Ark.release.xcconfig"; sourceTree = "<group>"; };
9496
/* End PBXFileReference section */
@@ -155,8 +157,9 @@
155157
B4256DC524ED1715000DF13C /* Ark.h */,
156158
B42875AA24EE10ED00933413 /* ListDiff.swift */,
157159
B42875C524EE2CBB00933413 /* DiffableDataSource.swift */,
158-
A64FD07724F681CF00EB0D38 /* CollectionNodeModel.swift */,
159-
A6E81FA524F7E99E00AAE8B0 /* CollectionNodeContext.swift */,
160+
A64FD07724F681CF00EB0D38 /* NodeModel.swift */,
161+
A6E81FA524F7E99E00AAE8B0 /* NodeContext.swift */,
162+
B4E5581D24FCC530004C2477 /* NodeChannel.swift */,
160163
B4256DC624ED1715000DF13C /* Info.plist */,
161164
);
162165
path = Ark;
@@ -391,10 +394,11 @@
391394
isa = PBXSourcesBuildPhase;
392395
buildActionMask = 2147483647;
393396
files = (
397+
B4E5581E24FCC530004C2477 /* NodeChannel.swift in Sources */,
394398
B42875AB24EE10ED00933413 /* ListDiff.swift in Sources */,
395-
A6E81FA624F7E99E00AAE8B0 /* CollectionNodeContext.swift in Sources */,
399+
A6E81FA624F7E99E00AAE8B0 /* NodeContext.swift in Sources */,
396400
B42875C624EE2CBB00933413 /* DiffableDataSource.swift in Sources */,
397-
A64FD07824F681D000EB0D38 /* CollectionNodeModel.swift in Sources */,
401+
A64FD07824F681D000EB0D38 /* NodeModel.swift in Sources */,
398402
);
399403
runOnlyForDeploymentPostprocessing = 0;
400404
};

Ark/CollectionNodeModel.swift

Lines changed: 0 additions & 36 deletions
This file was deleted.

Ark/DiffableDataSource.swift

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@
77
//
88

99
import Foundation
10+
import RxSwift
11+
import RxCocoa
1012
import AsyncDisplayKit
1113

1214

13-
public struct DiffableDataSourceSnapshot<T: CollectionNodeModel> {
15+
public struct DiffableDataSourceSnapshot<T: SectionInflator> {
1416
public private(set) var sections: [T]
1517

1618
public init(sections: [T]) {
1719
self.sections = sections
1820
}
1921

20-
public func item(for indexPath: IndexPath) -> CollectionNodeModel {
22+
public func item(for indexPath: IndexPath) -> NodeModel {
2123
sections[indexPath.section].items[indexPath.item]
2224
}
2325

@@ -26,13 +28,14 @@ public struct DiffableDataSourceSnapshot<T: CollectionNodeModel> {
2628
}
2729
}
2830

29-
public class DiffableDataSource<Model: CollectionNodeModel & Equatable>: NSObject,
31+
public class DiffableDataSource<Target: SectionInflator>: NSObject,
3032
ASCollectionDelegate & ASCollectionDataSource {
31-
public typealias Snapshot = DiffableDataSourceSnapshot<Model>
33+
public typealias Snapshot = DiffableDataSourceSnapshot<Target>
3234

3335
public private(set) var snapshot: Snapshot!
3436

3537
public private(set) weak var collectionNode: ASCollectionNode!
38+
fileprivate let rx_channel = NodeChannel()
3639

3740
public init(collectionNode: ASCollectionNode) {
3841
self.collectionNode = collectionNode
@@ -47,9 +50,10 @@ public class DiffableDataSource<Model: CollectionNodeModel & Equatable>: NSObjec
4750
return
4851
}
4952
self.snapshot = snapshot
50-
let result = List.diffing(oldArray: oldSnapshot.sections, newArray: snapshot.sections).forBatchUpdates()
51-
// TODO: combine diff result with requested index paths updates
53+
let result = List.diffing(oldArray: oldSnapshot.sections, newArray: snapshot.sections)
54+
5255
collectionNode.performBatch(animated: animatingDifferences, updates: { [node = self.collectionNode] in
56+
5357
for move in result.moves {
5458
node?.moveSection(move.from, toSection: move.to)
5559
}
@@ -75,16 +79,31 @@ public class DiffableDataSource<Model: CollectionNodeModel & Equatable>: NSObjec
7579

7680
public func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
7781
let item = snapshot.item(for: indexPath)
78-
return item.viewBlock
82+
return item.nodeBlock(with: rx_channel, indexPath: indexPath)
7983
}
8084

8185
public func collectionNode(_ collectionNode: ASCollectionNode, constrainedSizeForItemAt indexPath: IndexPath) -> ASSizeRange {
82-
let section = snapshot.sections[indexPath.section]
8386
let item = snapshot.item(for: indexPath)
84-
let context = CollectionNodeContext(
85-
section: section,
87+
let context = NodeContext(
8688
containerSize: collectionNode.calculatedSize,
8789
contentInset: collectionNode.contentInset)
8890
return item.sizeRange(in: context)
8991
}
92+
93+
public func collectionNode(_ collectionNode: ASCollectionNode, didSelectItemAt indexPath: IndexPath) {
94+
let item = snapshot.item(for: indexPath)
95+
let event = NodeEvent(model: item, kind: .selection, indexPath: indexPath, userInfo: [:])
96+
rx_channel.onNext(event)
97+
}
98+
}
99+
100+
extension Reactive {
101+
102+
public func nodeEventChannel<Model: SectionInflator, T: NodeModel>() -> Observable<GenericNodeEvent<T>>
103+
where Base: DiffableDataSource<Model> {
104+
base.rx_channel
105+
.asObserver()
106+
.compactMap(GenericNodeEvent<T>.init)
107+
.observeOn(MainScheduler.instance)
108+
}
90109
}

Ark/NodeChannel.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// NodeEvent.swift
3+
// Ark
4+
//
5+
// Created by Dwight CHENG on 2020/8/31.
6+
// Copyright © 2020 Glow. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import RxSwift
11+
import RxCocoa
12+
13+
public typealias NodeChannel = PublishSubject<NodeEvent>
14+
15+
public struct NodeEvent {
16+
public let model: NodeModel
17+
public let kind: Kind
18+
public let indexPath: IndexPath
19+
public let userInfo: [String: Any]
20+
21+
public enum Kind {
22+
case selection, refresh, action, dismiss
23+
}
24+
25+
public func on<T: NodeModel>(completion: (GenericNodeEvent<T>) -> Void) -> NodeEvent {
26+
GenericNodeEvent<T>(self).map(completion)
27+
return self
28+
}
29+
}
30+
31+
public struct GenericNodeEvent<T: NodeModel> {
32+
public let model: T
33+
public let kind: NodeEvent.Kind
34+
public let indexPath: IndexPath
35+
public let userInfo: [String: Any]
36+
37+
public init?(_ nodeEvent: NodeEvent) {
38+
guard let model = nodeEvent.model as? T else {
39+
return nil
40+
}
41+
self.model = model
42+
self.kind = nodeEvent.kind
43+
self.indexPath = nodeEvent.indexPath
44+
self.userInfo = nodeEvent.userInfo
45+
}
46+
}

Ark/CollectionNodeContext.swift renamed to Ark/NodeContext.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// CollectionNodeContext.swift
2+
// NodeContext.swift
33
// Ark
44
//
55
// Created by Dwight CHENG on 8/27/20.
@@ -9,8 +9,8 @@
99
import UIKit
1010
import AsyncDisplayKit
1111

12-
public struct CollectionNodeContext {
13-
public let section: CollectionNodeModel
12+
13+
public struct NodeContext {
1414
public let containerSize: CGSize
1515
public let contentInset: UIEdgeInsets
1616

Ark/NodeModel.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// NodeModel.swift
3+
// Ark
4+
//
5+
// Created by Dwight CHENG on 8/26/20.
6+
// Copyright © 2020 Glow. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import RxSwift
11+
import RxCocoa
12+
import AsyncDisplayKit
13+
14+
public protocol SectionInflator: Diffable, Equatable {
15+
var items: [NodeModel] { get }
16+
}
17+
18+
open class NodeModel: NSObject, Diffable {
19+
20+
open var diffIdentifier: AnyHashable {
21+
self
22+
}
23+
24+
open func nodeBlock(with channel: NodeChannel, indexPath: IndexPath) -> ASCellNodeBlock {
25+
ASCellNode.init
26+
}
27+
28+
open func sizeRange(in context: NodeContext) -> ASSizeRange {
29+
context.automaticDimension
30+
}
31+
}

0 commit comments

Comments
 (0)