-
Notifications
You must be signed in to change notification settings - Fork 3
Add FlatSection
#21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JosephDuffy
wants to merge
52
commits into
2.0-beta
Choose a base branch
from
feature/FlatSection
base: 2.0-beta
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add FlatSection
#21
Changes from 12 commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
3946a41
Add FlatSection
JosephDuffy babdadf
Mark `append(_:)` public
JosephDuffy 59daa65
Add `section(at:)`
JosephDuffy c4fe225
Add support for flat UI sections, with mixed cells
JosephDuffy aa527de
Aid migration from `CollectionSectionProvider`
JosephDuffy 0b5350f
Add `public init` to `FlatSection`
JosephDuffy d3dee27
Fix `section(at:)` logic
JosephDuffy 66d5fed
Conform `FlatSection` to `CustomReflectable`
JosephDuffy f51dc04
Become update delegate of inserted children
JosephDuffy e1e7fd5
Add more insert and removal functions
JosephDuffy c597da9
Remove associated type from `CollectionElement`
JosephDuffy fd21a2f
Add header invalidation
JosephDuffy ec63ce7
[SBI-519] Fix crash due to using removed section inside didEndDisplay…
bill201207 ad9dc00
[SBI-519] Cache registered nib names to avoid multiple redundant call…
bill201207 7320206
Merge pull request #1 from opennetltd/hotfix/SBI-519-ComposedUI-issues
bill201207 7b27a38
Merge branch 'main' of github.com:opennetltd/Composed into feature/Fl…
JosephDuffy f0ab34c
Fix test compilation
JosephDuffy 06449c3
Fix `cellSectionMap` for per-row cells
JosephDuffy f6a4b2c
Delegate `SelectionHandler` calls to children
JosephDuffy eb3a33a
Add `FlatUICollectionViewSection`
JosephDuffy 986674a
Support adding `SectionProvider`s to `FlatSection`
JosephDuffy ad73a5a
Reload header when `header` is set
JosephDuffy f6cd79c
Cache nib registrations to improve performance
JosephDuffy b35ea17
Merge branch 'cache-nib-registrations'
JosephDuffy 1614657
Merge branch 'main' into feature/FlatSection
JosephDuffy ecdd0fa
Fix `SectionProvider` sections not being removed
JosephDuffy fd0fb6a
Account for child `AggregateSectionProvider`s
JosephDuffy ee87162
Update `sectionOffset(for:)` to return an optional
JosephDuffy 9684f62
Fix `ComposedSectionProvider` compilation
JosephDuffy 987e496
Account for empty sections
JosephDuffy ad450d5
Remove `defer`s to ease debugging
JosephDuffy c1a438e
Become delegate of inserted sections
JosephDuffy 00cfff2
Document `sectionIndex(of:)`
JosephDuffy 90db5e5
Call `willAppear` for headers/footers
JosephDuffy e7c88de
Configure headers/footers on appear
JosephDuffy c52b6e4
Fix element offset when inserting in `FlatSection`
JosephDuffy e45ea84
Fix incorrect index when provider removes sections
JosephDuffy 9e1b8bd
Mark `updateDelegate` as `weak`
JosephDuffy 710efde
Remove/reduce some `FlatSection` bugs
JosephDuffy f1cdd0d
Add foundation of `FlatSection` tests
JosephDuffy 42c05c9
Do not check to unset update delegate of sections
JosephDuffy 3fb3c8f
Remove `Child` from public API
JosephDuffy a9a3c94
Add more `FlatSection` tests
JosephDuffy 791b088
Change `index` to `childIndex`
JosephDuffy a1cafc9
Remove check for unsetting update delegate
JosephDuffy f49d0c5
Add more `FlatSection` tests
JosephDuffy 0345565
Propagate updates from sections
JosephDuffy eb49837
Fix incorrect header and footer in flat sections
JosephDuffy 6e3c578
Add support for footers
JosephDuffy 5532266
Merge branch '2.0-beta' into feature/FlatSection
JosephDuffy 75df0f0
Unset `updateDelegate` on section provider removal
JosephDuffy 1813669
Update assertion message to ease debugging
JosephDuffy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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,176 @@ | ||
/// A section that flattens each of its children in to a single section. | ||
open class FlatSection: Section, CustomReflectable { | ||
open private(set) var children: [Section] = [] | ||
|
||
public var numberOfElements: Int { | ||
children.map(\.numberOfElements).reduce(0, +) | ||
} | ||
|
||
public var updateDelegate: SectionUpdateDelegate? | ||
|
||
public var customMirror: Mirror { | ||
Mirror( | ||
self, | ||
children: [ | ||
"children": children, | ||
] | ||
) | ||
} | ||
|
||
public init() {} | ||
|
||
public func append(_ section: Section) { | ||
updateDelegate?.willBeginUpdating(self) | ||
|
||
let indexOfFirstChildElement = numberOfElements | ||
children.append(section) | ||
section.updateDelegate = self | ||
|
||
(0..<section.numberOfElements) | ||
.map { $0 + indexOfFirstChildElement } | ||
.forEach { index in | ||
updateDelegate?.section(self, didInsertElementAt: index) | ||
} | ||
|
||
updateDelegate?.didEndUpdating(self) | ||
} | ||
|
||
public func insert(_ section: Section, at index: Int) { | ||
updateDelegate?.willBeginUpdating(self) | ||
|
||
let sectionOffset = index > 0 | ||
? offset(for: children[index - 1])! | ||
: 0 | ||
children.insert(section, at: index) | ||
section.updateDelegate = self | ||
|
||
(0..<section.numberOfElements) | ||
.map { $0 + sectionOffset } | ||
.forEach { index in | ||
updateDelegate?.section(self, didInsertElementAt: index) | ||
} | ||
|
||
updateDelegate?.didEndUpdating(self) | ||
} | ||
|
||
public func insert(_ section: Section, after existingSection: Section) { | ||
guard let existingSectionIndex = children.firstIndex(where: { $0 === existingSection }) else { return } | ||
|
||
insert(section, at: existingSectionIndex + 1) | ||
} | ||
|
||
public func remove(_ section: Section) { | ||
guard let index = children.firstIndex(where: { $0 === section }) else { return } | ||
|
||
updateDelegate?.willBeginUpdating(self) | ||
|
||
let sectionOffset = offset(for: section)! | ||
children.remove(at: index) | ||
if section.updateDelegate === self { | ||
section.updateDelegate = nil | ||
} | ||
|
||
(0..<section.numberOfElements).forEach { index in | ||
updateDelegate?.section(self, didRemoveElementAt: index + sectionOffset) | ||
} | ||
|
||
updateDelegate?.didEndUpdating(self) | ||
} | ||
|
||
public func section(at index: Int) -> (section: Section, offset: Int)? { | ||
var offset = 0 | ||
|
||
for child in children { | ||
if offset == index { | ||
return (child, offset) | ||
} else if index < offset + child.numberOfElements { | ||
return (child, offset) | ||
} | ||
|
||
offset += child.numberOfElements | ||
} | ||
|
||
return nil | ||
} | ||
|
||
private func offset(for section: Section) -> Int? { | ||
var offset = 0 | ||
|
||
for child in children { | ||
if child === section { | ||
return offset | ||
} | ||
|
||
offset += child.numberOfElements | ||
} | ||
|
||
return nil | ||
} | ||
|
||
private func indexesRange(for section: Section) -> Range<Int>? { | ||
guard let sectionOffset = offset(for: section) else { return nil } | ||
return (sectionOffset..<sectionOffset + section.numberOfElements) | ||
} | ||
} | ||
|
||
extension FlatSection: SectionUpdateDelegate { | ||
public func willBeginUpdating(_ section: Section) { | ||
updateDelegate?.willBeginUpdating(self) | ||
} | ||
|
||
public func didEndUpdating(_ section: Section) { | ||
updateDelegate?.didEndUpdating(self) | ||
} | ||
|
||
public func invalidateAll(_ section: Section) { | ||
updateDelegate?.invalidateAll(self) | ||
} | ||
|
||
public func section(_ section: Section, didInsertElementAt index: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, didInsertElementAt: sectionOffset + index) | ||
} | ||
|
||
public func section(_ section: Section, didRemoveElementAt index: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, didRemoveElementAt: sectionOffset + index) | ||
} | ||
|
||
public func section(_ section: Section, didUpdateElementAt index: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, didUpdateElementAt: sectionOffset + index) | ||
} | ||
|
||
public func section(_ section: Section, didMoveElementAt index: Int, to newIndex: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, didMoveElementAt: sectionOffset + index, to: newIndex + index) | ||
} | ||
|
||
public func selectedIndexes(in section: Section) -> [Int] { | ||
guard let allSelectedIndexes = updateDelegate?.selectedIndexes(in: self) else { return [] } | ||
guard let sectionIndexes = indexesRange(for: section) else { return [] } | ||
|
||
return allSelectedIndexes | ||
.filter(sectionIndexes.contains(_:)) | ||
.map { $0 - sectionIndexes.startIndex } | ||
} | ||
|
||
public func section(_ section: Section, select index: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, select: sectionOffset + index) | ||
} | ||
|
||
public func section(_ section: Section, deselect index: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, deselect: sectionOffset + index) | ||
} | ||
|
||
public func section(_ section: Section, move sourceIndex: Int, to destinationIndex: Int) { | ||
guard let sectionOffset = offset(for: section) else { return } | ||
updateDelegate?.section(self, move: sourceIndex + sectionOffset, to: destinationIndex + sectionOffset) | ||
} | ||
|
||
public func sectionDidInvalidateHeader(_ section: Section) { | ||
// Headers of children are currently ignored. | ||
} | ||
} |
This file contains hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your trickery haha