-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from traderepublic/develop
Release 0.7
- Loading branch information
Showing
13 changed files
with
240 additions
and
16 deletions.
There are no files selected for viewing
89 changes: 89 additions & 0 deletions
89
DiffingSectionKit/Sources/ManualDiffingListSectionController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import DifferenceKit | ||
import Foundation | ||
import SectionKit | ||
|
||
/** | ||
A `SectionController` that contains a list of items and calculates the difference whenever there is an update. | ||
|
||
This `SectionController` is typically used when there are multiple semantically similar items | ||
of a model to be displayed and the list of items may dynamically change. | ||
|
||
- Note: Compared to `DiffingListSectionController` this doesn't have a `Differentiable` constraint on the generic | ||
`Item` type, instead it requires closures to get diffing information for an item. | ||
*/ | ||
open class ManualDiffingListSectionController< | ||
Model: SectionModel, | ||
Item, | ||
ItemId: Hashable | ||
>: ListSectionController<Model, Item> { | ||
private let itemId: (Item) -> ItemId | ||
private let itemContentIsEqual: (Item, Item) -> Bool | ||
|
||
/** | ||
Initialize an instance of `ManualDiffingListSectionController`. | ||
|
||
- Parameter model: The model of this `SectionController`. | ||
|
||
- Parameter itemId: A closure that returns the identifier for a given item. | ||
|
||
- Parameter itemContentIsEqual: A closure that checks two items for equality. | ||
*/ | ||
public init(model: Model, itemId: @escaping (Item) -> ItemId, itemContentIsEqual: @escaping (Item, Item) -> Bool) { | ||
self.itemId = itemId | ||
self.itemContentIsEqual = itemContentIsEqual | ||
super.init(model: model) | ||
} | ||
|
||
override open func calculateUpdate(from oldData: [Item], | ||
to newData: [Item]) -> CollectionViewSectionUpdate<[Item]>? { | ||
let changeSet = StagedChangeset( | ||
source: oldData.map { DifferentiableBox(value: $0, id: itemId, isContentEqual: itemContentIsEqual) }, | ||
target: newData.map { DifferentiableBox(value: $0, id: itemId, isContentEqual: itemContentIsEqual) } | ||
) | ||
return CollectionViewSectionUpdate(sectionId: model.sectionId, | ||
batchOperations: changeSet.mapData(\.value).map(\.sectionBatchOperation), | ||
setData: { [weak self] in self?.collectionViewItems = $0 }, | ||
shouldReload: { $0.changes.count > 100 }) | ||
} | ||
} | ||
|
||
extension ManualDiffingListSectionController where Item: Equatable { | ||
/** | ||
Initialize an instance of `ManualDiffingListSectionController`. | ||
|
||
- Parameter model: The model of this `SectionController`. | ||
|
||
- Parameter itemId: A closure that returns the identifier for a given item. | ||
*/ | ||
public convenience init(model: Model, itemId: @escaping (Item) -> ItemId) { | ||
self.init(model: model, itemId: itemId, itemContentIsEqual: ==) | ||
} | ||
} | ||
|
||
@available(OSX 10.15, iOS 13, tvOS 13, watchOS 6, *) | ||
extension ManualDiffingListSectionController where Item: Identifiable, Item.ID == ItemId { | ||
/** | ||
Initialize an instance of `ManualDiffingListSectionController`. | ||
|
||
- Parameter model: The model of this `SectionController`. | ||
|
||
- Parameter itemContentIsEqual: A closure that checks two items for equality. | ||
*/ | ||
public convenience init(model: Model, itemContentIsEqual: @escaping (Item, Item) -> Bool) { | ||
self.init(model: model, itemId: \.id, itemContentIsEqual: itemContentIsEqual) | ||
} | ||
} | ||
|
||
// NOTE: the following unfortunately doesn't compile since declaring `init(model: Model)` would require | ||
// to override the parent initialiser | ||
//@available(OSX 10.15, iOS 13, tvOS 13, watchOS 6, *) | ||
//extension ManualDiffingListSectionController where Item: Identifiable & Equatable, Item.ID == ItemId { | ||
// /** | ||
// Initialize an instance of `ManualDiffingListSectionController`. | ||
// | ||
// - Parameter model: The model of this `SectionController`. | ||
// */ | ||
// public convenience init(model: Model) { | ||
// self.init(model: model, itemId: \.id, itemContentIsEqual: ==) | ||
// } | ||
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import DifferenceKit | ||
import Foundation | ||
|
||
public class DifferentiableBox<Value, Id: Hashable>: Differentiable { | ||
public let value: Value | ||
|
||
@usableFromInline | ||
internal let id: (Value) -> Id | ||
|
||
@usableFromInline | ||
internal let isContentEqual: (Value, Value) -> Bool | ||
|
||
public init(value: Value, id: @escaping (Value) -> Id, isContentEqual: @escaping (Value, Value) -> Bool) { | ||
self.value = value | ||
self.id = id | ||
self.isContentEqual = isContentEqual | ||
} | ||
|
||
@inlinable | ||
public var differenceIdentifier: Id { id(value) } | ||
|
||
@inlinable | ||
public func isContentEqual(to source: DifferentiableBox<Value, Id>) -> Bool { | ||
isContentEqual(value, source.value) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...ViewAdapter/Generic/ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import UIKit | ||
|
||
@available(iOS 10.0, *) | ||
extension ListCollectionViewAdapter: UICollectionViewDataSourcePrefetching { | ||
open func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { | ||
let validIndexPaths = indexPaths.filter { $0.isSectionIndexValid(for: sections) } | ||
validIndexPaths.group(by: \.section).forEach { sectionIndex, indexPaths in | ||
guard let prefetchingDelegate = sections[sectionIndex].controller.dataSourcePrefetchingDelegate else { | ||
return | ||
} | ||
let sectionIndexPaths = indexPaths.map(SectionIndexPath.init) | ||
prefetchingDelegate.prefetchItems(at: sectionIndexPaths) | ||
} | ||
} | ||
|
||
open func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) { | ||
let validIndexPaths = indexPaths.filter { $0.isSectionIndexValid(for: sections) } | ||
validIndexPaths.group(by: \.section).forEach { sectionIndex, indexPaths in | ||
guard let prefetchingDelegate = sections[sectionIndex].controller.dataSourcePrefetchingDelegate else { | ||
return | ||
} | ||
let sectionIndexPaths = indexPaths.map(SectionIndexPath.init) | ||
prefetchingDelegate.cancelPrefetchingForItems(at: sectionIndexPaths) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
SectionKit/Sources/Section/SectionDataSourcePrefetchingDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import UIKit | ||
|
||
/// The delegate for datasource prefetching. | ||
@available(iOS 10.0, *) | ||
public protocol SectionDataSourcePrefetchingDelegate: AnyObject { | ||
/** | ||
Tells the delegate to start prefetching items at the specified indexPaths. | ||
|
||
- Parameter indexPaths: The index paths of the items to be prefetched. | ||
*/ | ||
func prefetchItems(at indexPaths: [SectionIndexPath]) | ||
|
||
/** | ||
Tells the delegate to cancel prefetching items at the specified indexPaths. | ||
|
||
- Parameter indexPaths: The index paths of the items that previously were considered as candidates for pre-fetching, but were not actually used. | ||
*/ | ||
func cancelPrefetchingForItems(at indexPaths: [SectionIndexPath]) | ||
} | ||
|
||
@available(iOS 10.0, *) | ||
extension SectionDataSourcePrefetchingDelegate { | ||
public func cancelPrefetchingForItems(at indexPaths: [SectionIndexPath]) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.