-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
WIP: Auto diffing section controller #449
Conversation
@rnystrom How about |
Sounds amazing! I'd say we should definitely try and create some examples with this, an easy way to show usage and will be easier to spot most/some Swift interop issues! |
That's so true! I worry about stepping on their toes though w/ naming. I should probably leave all the "react" stuff in their court. But I like where you're going w/ this. @Sherlouk agreed! I'll probably include all of the changes in this PR so we can get a feel for things, but then split it up into 3 PRs (updater changes, new SC, example). Btw forgot to mention that the updater changes should also fix #288. |
@rnystrom I prefer |
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.
This is extremely exciting @rnystrom!
Source/IGListAutoSectionController.m
Outdated
@interface IGListAutoSectionController() | ||
|
||
@property (nonatomic, strong) id object; | ||
@property (nonatomic, strong) NSArray<id<IGListDiffable>> *viewModels; |
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.
Should we make this publicly readable? Or add a viewModelAtIndex:
method to access this internal store? As a client it would be good to know what the state-of-the-world for this section controller is.
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.
Yes! Absolutely we should. I can imagine plenty of cases where someone would need to grab the view model.
Source/IGListAutoSectionController.h
Outdated
|
||
- (NSArray<id<IGListDiffable>> *)viewModelsForObject:(id)object; | ||
- (UICollectionViewCell<IGListBindable> *)cellForViewModel:(id)viewModel atIndex:(NSInteger)index; | ||
- (CGSize)sizeForViewModel:(id)viewModel; |
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.
Should these pass sender i.e. - (CGSize)autoSectionController:(IGListAutoSectionController *)sectionController sizeForViewModel:(id)viewModel
? It's more formally correct but uglier.
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.
Hrm, good point. I guess to be proper they probably should.
Source/IGListAutoSectionController.m
Outdated
result = IGListDiff(oldViewModels, self.viewModels, IGListDiffEquality); | ||
|
||
[collectionContext deleteInSectionController:self atIndexes:result.deletes]; | ||
[collectionContext insertInSectionController:self atIndexes:result.inserts]; |
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.
Should we support formally reloading
the item for an updated view-model, rather than only binding a new view model to the existing cell?
One idea is, we add a data source method like:
- (BOOL)shouldReloadCellForUpdatedViewModel:(id)viewModel atIndex:(NSInteger)index
And call it for each updated view model to decide whether to reload or just -bindToViewModel:
.
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.
What would the purpose be for actual reloading? Bear in mind that we don't actually call reloadItemsAtIndexPaths:
b/c of UICollectionView
issues, we convert it to a delete+insert under the hood (that's the whole thing about moving alongside reload/bind here).
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.
If the model changes in such a way that we need a new cell class to represent it, a reload (or delete/insert) is the only way to achieve the update. It's not a huge requirement, but I think it's worth considering at this early stage since it would affect the API bigly.
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.
@Adlai-Holler interesting point. I could see that.
I'm leaning towards not supporting this yet and filling it in later if someone really-really needs it (who knows, we might run into it). I'd love to see some concrete use-cases before we design the API too.
Plus it shouldn't be breaking when we add it, only an enhancement.
bigly
🙊 😅
Some other naming ideas:
|
@rnystrom updated the pull request - view changes |
Summary: Closes #472 Differential Revision: D4524473 Pulled By: jessesquires fbshipit-source-id: b72f3dde2cf3eb1c8f9b53ee73cf87cc04e34d08
Summary: Before the diff, you can lookup the object for a given section, and then lookup the section controller for that object, but this seems like a pretty valuable/common operation. Closes #477 Differential Revision: D4537479 Pulled By: rnystrom fbshipit-source-id: ad47a243f0bb0fc72a362863dff2f00b0b640fab
Summary: Working on porting our collection view layout to IGListKit. I'm doing this because its a solid layout, and we just finished preparing it to work with inline sections. It is designed to work in tandem with IGListKit, so we're adding it. This is still a WIP as I add more tests, but I'd love as much feedback as possible. Aside from the glob of header documentation, this has the following features: - Infinite sections that each have infinite items. Sections and items can fall inline. When they break the width of their container they will fall on the next row. - Sections can have their own insets, line spacing, and interitem spacing. - Sticky header support! When you use headers, it will always newline the section. - Maximum width with a border decoration view - Use this to pinch in your content on larger devices Followup to #423 - [ ] ~~Move decoration view support to delegate~~ removed - [x] Unit test changing [top y sticky inset](https://coveralls.io/builds/9977284/source?filen Closes #450 Reviewed By: jessesquires Differential Revision: D4521797 Pulled By: rnystrom fbshipit-source-id: 20b36ae573d38ca3125a6f3d5faec181c290ab94
Summary: - [x] All tests pass. Demo project builds and runs. - [ ] I added tests, an experiment, or detailed why my change isn't tested. - [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes. - [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) I guess there's some mistake in unavailable hints Closes #479 Differential Revision: D4543489 Pulled By: rnystrom fbshipit-source-id: fb925fad04d2931fbfd0e26a87d36f85eee0b2e9
…orting inline sections Summary: This reverts commit 20b36ae573d38ca3125a6f3d5faec181c290ab94 Differential Revision: D4521797 fbshipit-source-id: 447de6cf2b30de9c2109dffb266326aceceec7fc
Summary: Adding an API to do item-level (cell) moves on the collection view. This complicates things a little bit because of all the issues that moving sections have while in batch updates (e.g. simultaneous animation UICV bugs). Thankfully we use pretty strict types so the compiler does most of the work for us. Closes #145 - [x] Tests build and pass - [x] Add `IGListBatchUpdateData` tests to check moves during - [x] ~~Moving within a reloaded section (no op)~~ can't reload sections - [x] Moving within a deleted section (no op) - [x] Moving within a moved section (convert section ops to delete+insert) - [x] Moving an index path that is also reloaded (convert to delete+insert path) - [x] Add move unit tests to `IGListAdapterUpdater` - [x] Add move unit tests to `IGListReloadDataUpdater` (mostly for code coverage...) - [x] Add move unit tests to `IGListStackedSectionController` - [x] Add `CHANGELOG.md` entry for 3.0.0 - [x] Test moving without batch Closes #418 Reviewed By: jessesquires Differential Revision: D4521732 Pulled By: rnystrom fbshipit-source-id: 99a46d1cbb0cc1f857a62ff6ca257aff6e8b7f25
Summary: Working on porting our collection view layout to IGListKit. I'm doing this because its a solid layout, and we just finished preparing it to work with inline sections. It is designed to work in tandem with IGListKit, so we're adding it. This is still a WIP as I add more tests, but I'd love as much feedback as possible. Aside from the glob of header documentation, this has the following features: - Infinite sections that each have infinite items. Sections and items can fall inline. When they break the width of their container they will fall on the next row. - Sections can have their own insets, line spacing, and interitem spacing. - Sticky header support! When you use headers, it will always newline the section. - Maximum width with a border decoration view - Use this to pinch in your content on larger devices Followup to #423 - [ ] ~~Move decoration view support to delegate~~ removed - [x] Unit test changing [top y sticky inset](https://coveralls.io/builds/9977284/source?filen Closes #484 Differential Revision: D4547760 Pulled By: rnystrom fbshipit-source-id: 879e2da16eb78bb6a90967e77d9ad0bbf7c69594
Summary: This diff isn't correct, and the Instagram cut happens today. Pulling back so I have time to test the correct change more throughly. Reviewed By: rnystrom Differential Revision: D4550149 fbshipit-source-id: 2e882caeb9ef999b7fd57562740b352ea8edfa5f
Summary: This was a little bit of an invasive change with the display handler, but I think that this is the right call. When sending display events for objects, we should account for the supplementary view as part of the section controller. This is especially useful for headers and footers. Note that this wont effect the working range API at all. Fixes #300 Closes #470 Differential Revision: D4551338 Pulled By: rnystrom fbshipit-source-id: dda6fbf18bcfc2c941d80ee2314a543d1ab83843
Summary: Follow from #450, this layout has been replaced. You served us well! - [x] All tests pass. Demo project builds and runs. - [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes. Closes #482 Differential Revision: D4553897 Pulled By: rnystrom fbshipit-source-id: caccb386ba8914fbbf5e81d997524efb78c6e4ea
Summary: Removing the assert and handling `nil` section controllers. This wont effect Swift code which demands a non-optional section controller, but Objective-C is more nuanced. There is evidence that some callers do not have a default state and are returning `nil`. Unfortunately this will [OOB here](https://github.com/Instagram/IGListKit/blob/master/Source/Internal/IGListSectionMap.m#L63) if using the original `objects` array provided by the data source. Instead we prune the array, only allowing in objects that have a matching section controller. Fixes t15773862 internally. - [x] All tests pass. Demo project builds and runs. - [x] I added tests, an experiment, or detailed why my change isn't tested. - [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes. Closes #488 Reviewed By: dshahidehpour Differential Revision: D4553886 Pulled By: rnystrom fbshipit-source-id: a473a99b5eb513e4b610019dba0394a014193fc4
|
Summary: Reduce and avoid unnecessary copies in IGListAdapter and IGListSectionMap. Reviewed By: rnystrom Differential Revision: D4555347 fbshipit-source-id: 3ade3311955fe5d12fc7617ad72feba9dafb60fb
@rnystrom updated the pull request - view changes |
History got messed up, recreated and moving to #494 |
Started work on the plane to get this moving since #418 is up and ready to land. We'll likely need to spend some time fleshing out the API of this, and I think I'll split it up into a couple different PRs once ready for review. Putting this up now to get early feedback.
What is this?
This adds an auto-diffing section controller as outlined in #38. There are several key parts:
IGListAutoSectionController
(naming wip)IGListBindable
so that we can control when the cell is updated w/ the view model.UICollectionView
TODO
reloadObjects:
didSelectItemAtIndex:
supportIGListAdapterUpdater
changesIGListAdapter
I had to make some changes to
IGListAdapterUpdater
in order for this to work. The biggest challenge is when the section controller receives a new object, it has to split it up into view models and then apply changes.However,
didUpdateToObject:
will be called insideperformBatchUpdates:
, so we need to diff and fire off the changes on the collection view immediately. A few issues:-[IGListCollectionContext performBatchAnimated:updates:completion:]
insidedidUpdateToObject:
and have it update immediately (async updates)didUpdateToObject:
gets called, so we can't just insert/delete/moveDiffing top-level models
One super important piece to getting this right is having top-level (the ones given to
IGListAdapter
and handed to the SC indidUpdateToObject:
always equal itself, even if its values change. I solved this in the unit tests w/ an object that implements diffing like:If you use a traditional
isEqualToDiffableObject:
(where you check all props/values) you'll end up reloading the section, avoiding all the nice cell animations.I started making a stock object that does this, something like
IGListAutoObject
, but its so simple that it's kind of annoying. It's essentially a model box that will probably end up more confusing than having to learn how to diff w/ the auto SC.Would love thoughts here.
Selection
didSelectItemAtIndex:
is totally broken. Options are:We've discussed splitting off
didSelectItemAtIndex:
into aselectionDelegate
(like the display/scroll/etc delegate) in #184 and elsewhere. That might help, though the view models array is private, so we'd have to expose that or create another delegate API.How can I help?
Since this is super early, please hold on nit picks, formatting, etc. I'll work on that as we go along. But there are some big things I'd love your thoughts on:
IGListAutoSectionController
. Anything better out there? I thoughtIGListDiffableSectionController
but idkIGListSingleSectionController
). I thought the API was kind of gross though, and you have to subclass the SC anyways.IGListBindable
is great, but you can't just use the view model to config the cell. For instance, how do you make the SC the cell delegate? That's why I'm leaving the method to still return a cell, but we will call bind before returning it. Is this ok?