Commit graph

238 commits

Author SHA1 Message Date
Kent Sutherland
3cd3a111dd Update deployment targets to silence Xcode 14 warnings (#1573)
Summary:
## Changes in this pull request

Xcode 14 changed the minimum deployment target to iOS/tvOS 11.0 and macOS 10.13. This PR moves up the deployment targets so that a warning isn't shown on every build.

I also silenced the development region and base localization warnings.

### Checklist

- [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.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/main/.github/CONTRIBUTING.md)

Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1573

Differential Revision: D45223095

Pulled By: TimOliver

fbshipit-source-id: 57fbd284809c09f86a9731d0676332de35fbe0df
2023-05-01 22:48:23 -07:00
Tim Oliver
425cee4cef Split out checks for methods that throw
Summary:
I'm still not sure if there's an easier way to test throwing methods that work on both GitHub Actions and our internal build tooling (Since GitHub does throw at asserts, and our internal tools don't), but this way at least works.

Each statement has to be contained in its own separate `try` because the first throwing method will cancel execution in the rest of the code block.

This diff separates out each throwing test into its own `try` block

Reviewed By: candance

Differential Revision: D45147876

fbshipit-source-id: 95d587d5abe4a695b1ca1f76ebf3bda3984c6065
2023-04-20 14:26:11 -07:00
Tim Oliver
f66a0ae1e7 Add remaining test coverage for IGListBindingSingleSectionController
Summary: Adds additional tests to `IGListBindingSingleSectionControllerTests` to give `IGListBindingSingleSectionController` 100% code coverage

Reviewed By: candance

Differential Revision: D45147830

fbshipit-source-id: 0753888ab7f8058d72eb463f6444458bae65d964
2023-04-20 14:26:11 -07:00
Tim Oliver
b746af936d Added extra test case to IGTestDelegateController
Summary: Added making a call to the supplementary view data source in IGTestDelegateController so that codepath gets the same test exposure as the regular cell mechanism.

Reviewed By: candance

Differential Revision: D45004843

fbshipit-source-id: 6d3140ebc59da5ba4b7a151f6f104cdbd63418c2
2023-04-17 20:41:49 -07:00
Tim Oliver
bec019925c Added remaining test coverage for IGListSectionMap
Summary: Added remaining test coverage to IGListSectionMap

Reviewed By: candance

Differential Revision: D45004860

fbshipit-source-id: 30e4988a8b3ce56551aceb52c0cd99be2286fffa
2023-04-17 20:41:49 -07:00
Tim Oliver
d7574152d3 Add test coverage for list adapter debugger class
Summary: Adds additional functionality and coverage testing to the adapter debugger class

Reviewed By: candance

Differential Revision: D45004651

fbshipit-source-id: 40330f5f2fed2946cc5ead89b30cf4030b596b65
2023-04-17 20:41:49 -07:00
Tim Oliver
7d9ccfc9ea Added test coverage to collection view and collection view layout
Summary: Adds additional test coverage to the collection view and collection view layout test suites

Reviewed By: candance

Differential Revision: D45004591

fbshipit-source-id: 21587df6f9595cb54481067322aae6443e089152
2023-04-17 20:41:49 -07:00
Tim Oliver
97120d288d Added remaining test coverage to IGListBindingSectionController
Summary: Added remaining test cases to cover `IGListBindingSectionController`

Reviewed By: candance

Differential Revision: D45004640

fbshipit-source-id: 2dd1662af849841ab5dccc1f6731ddac800657a0
2023-04-17 20:41:49 -07:00
Tim Oliver
2b0ca81c0b Added more coverage cases to list adapter tests
Summary: I reenabled a couple of tests that had previously been marked disabled, but work properly now, and I added additional tests to cover some of the coverage cases that had previously been missed.

Reviewed By: candance

Differential Revision: D45004625

fbshipit-source-id: dacf49b2f0f420f269e3071ad4fc76762c95365c
2023-04-17 20:41:49 -07:00
Tim Oliver
1bc993381c Reenable some disabled tests in list adapter E2E tests
Summary:
There were several tests in the E2E test suite that had been deliberately disabled. I reenabled them and tested them, and they all passed correctly.

I've left them reenabled in this diff, but we can disable them down the line again if they start to fail again.

Differential Revision: D45004373

fbshipit-source-id: c0bc96e1d364d702d12e945059daedf2ae21cfa5
2023-04-17 20:41:49 -07:00
Tim Oliver
95e19a1430 Renamed IGReloadDataUpdaterTests to IGListReloadDataUpdaterTests
Summary: This diff renames `IGReloadDataUpdaterTests` to `IGListReloadDataUpdaterTests` to be consistent with the naming scheme of the other classes

Differential Revision: D45004236

fbshipit-source-id: 8ecc2ca60740ff6cca1028400621a22c7b1d3406
2023-04-17 20:41:49 -07:00
Tim Oliver
965025d2d3 Add new test files to IGListKit
Summary: This diff adds several new test classes to IGListKit's test suite, covering a variety of objects and use cases that weren't covered before.

Reviewed By: candance

Differential Revision: D45004015

fbshipit-source-id: 5e6cc3f56e62328173657c09c955c320e6067936
2023-04-17 20:41:49 -07:00
Tim Oliver
ceda03a0e1 Bring IGListDiffKit test coverage to 100%
Summary: Fills in the remaining gaps in the tests in order to bring the code coverage of IGListDiffKit (ie, the diffing engine portion of IGListKit) up to 100%.

Differential Revision: D45002512

fbshipit-source-id: b4795946400f7e5ead8882b5d0f5003fb1d17aed
2023-04-17 20:41:49 -07:00
Tim Oliver
f92b9339ee Standarize the copyright notice in all source files
Summary:
The standardized Meta copyright notice is "Copyright (c) Meta Platforms, Inc. and affiliates." and not "Copyright (c) Meta Platforms, Inc. and its affiliates." (Dropping the "its")

This diff updates the copyright notice in each source file to the correct this.

Reviewed By: willbailey

Differential Revision: D44737667

fbshipit-source-id: 643bf36df76723e70d9d826c53cf8f29b8a0c8cc
2023-04-06 02:44:16 -07:00
Tim Oliver
501cccc6f0 Provide full test coverage for IGListDiffKit model description strings
Summary:
Five model classes in IGListDiffKit: `IGListBatchUpdateData`, `IGListIndexPathResult`, `IGListIndexSetResult`, `IGListMoveIndex`, and `IGListMoveIndexPath` didn't have 100% test coverage because their `description` debug string methods weren't being tested.

I added a new unit test file specifically for testing description strings in IGListDiffKit wrote a basic test to verify each one.

This brings IGListDiffKit's test coverage back up to 100%.

Differential Revision: D44002058

fbshipit-source-id: ebb1bbb3c9a6d380540fc6bbedf5b8c5e5b254f1
2023-03-21 19:12:01 -07:00
Tim Oliver
a41026d93d Provide full test coverage for IGListBatchUpdateData.mm
Summary:
There were some codepaths in `IGListBatchUpdateData.mm` that weren't completely covered by our unit test suite. Namely the equality checks where the object addresses are compared, and when incompatible objects are compared.

This diff adds 2 extra tests to cover those cases, bringing `IGListBatchUpdateData.mm`'s test coverage up to 100%.

Differential Revision: D44001262

fbshipit-source-id: 516851ca6ebdcbf3a1a4e7e6e0bd2efcef69920a
2023-03-21 19:12:01 -07:00
Ryan Mathews
c708a10757 Adds viewForSupplementaryElementOfKind method to IGListCollectionContext
Summary:
Returns the supplementary view in the collection at the specified index for the section controller.

 param `elementKind` The element kind of the supplementary view.
 param `index` The index of the desired cell.
 param `sectionController` The section controller requesting this information.

 return The collection reusable view, or `nil` if not found.

 warning This method may return `nil` if the cell is offscreen.

Reviewed By: maxolls

Differential Revision: D42726375

fbshipit-source-id: d9873440bd94140b88e7d2d56c0737ecf94925a8
2023-02-01 14:15:50 -08:00
Tim Oliver
a1b9c2ddb3 Updated corporate branding in IGListKit source files
Summary:
A quick push to fix something I noticed while studying how IGListKit works. This simply replaces "Facebook, Inc" with "Meta Platforms, Inc" in all of the source files where the company copyright notice is posted. This should help bring our external facing projects more in line with our new corporate branding.

There's still a lot more references to "Facebook" as a company in the library (especially around linking to other Meta sponsored open source libraries), but this might need additional scrutiny and review on a case-by-case basis, so let's handle those ones separately.

Reviewed By: lorixx

Differential Revision: D41207363

fbshipit-source-id: 57cdbf5eb1023b41a5f32c0c05e01628686a19fe
2022-11-15 21:47:29 -08:00
Dustin Williams
987055532a Get index path or scroll position of first visible item in list (#1544)
Summary:
Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1544

Refactored and added functions to IGListAdapter for getting index path or scroll position of first visible item in list.

This makes it possible to see which item is the current first visible item scrolled to in the list, and determine how far it is scrolled into (analogous to additionalOffset in scrollToObject:).

Reviewed By: lorixx

Differential Revision: D32196398

fbshipit-source-id: d809d5f96bb4e1d95055dbebe4e55c1a428a40ed
2021-11-09 00:04:10 -08:00
3a4oT
a1036e06e3 SPM number10 (#1487)
Summary:
## Changes in this pull request

 A better version of https://github.com/Instagram/IGListKit/issues/1465 =)

- SPM support with script-based generations.

- added macOS Catalyst support

 ### Generate SPM layout

1. From **project's root** run:

   `bash scripts/generate_spm_sources_layout.sh`

  2. Commit Changes

 Repeat those steps each time you delete/add the project's files. **Make sure** to have this CI step which will check that `generate_spm_sources_layout.sh` is not broken.

Issue fixed: https://github.com/Instagram/IGListKit/issues/1368 #1406

### Checklist

- [ ] 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.
- [ ] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)

Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1487

Reviewed By: DimaVartanian, candance

Differential Revision: D30428297

Pulled By: lorixx

fbshipit-source-id: 655291ff03445dec9b0b8cd97916f0c88207e9a7
2021-08-31 19:28:37 -07:00
3a4oT
cd0fe69983 Run tests from Xcode12. Github workflow (#1478)
Summary:
## Changes in this pull request

- set header `IGListAdapterUpdaterCompatible.h` to - public which fixed Xcode 12 unit test iOS build.
- include `IGListTransitionData.m` to tvOS trget which fixed Xcode 12 tvOS framework build.
- Added GitHub workflow `CI`.

### Checklist

- [x] All tests pass. Demo project builds and runs.
- [x] 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)

Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1478

Reviewed By: candance

Differential Revision: D25504500

Pulled By: lorixx

fbshipit-source-id: 91f477838f176f662dd74928b75df670a4106968
2021-08-16 13:36:42 -07:00
Anna Tang
f2166c358b Scroll to focused media below header
Summary:
## Context
We want the post-tap headers to be sticky so that context is maintained as the user scrolls down the media chain.

## In this diff
When clicking on a media tile in a media module (rather than the See All CTA), the sticky header was covering part of the media post's header. We want to shift the scroll-to view down so that the sticky header is sitting on top of the media post's header.

- Create new version of IGListAdapter API's `scrollToObject` function that contains an additional parameter `additionalYOffset`
- Call new `scrollToObject` function with offset of 48.0f (height of header)

## In this stack
Add sticky headers for post-taps, excluding SERP

Reviewed By: maxolls

Differential Revision: D29961626

fbshipit-source-id: c8644cc868e8d7ec92cad5f6c7742d93d001f67d
2021-08-10 19:59:39 -07:00
Krzysztof Jordan
6f7cee5345 FastMod @(number) to @number to for efficiency in .m, .mm, .h files
Summary:
fastmod --extensions m,mm,h '@\((-)?([\d\.]+)\)([\s\)\],])' '@${1}${2}${3}' --dir fbobjc/*/
Regex updated to capture cases for @(number), and @(number)]

Reviewed By: adamjernst

Differential Revision: D27513888

fbshipit-source-id: aacfc12ad46fef90fe7a7cb46cc8c7a68b2b8c32
2021-04-13 02:12:02 -07:00
Maxime Ollivier
9a11f6b55f graduate IGListExperimentBackgroundDiffing to a property
Summary:
`IGListExperimentBackgroundDiffing` has been running on Instagram for a couple months now, and we're seeing nice scroll performance improvements (less frame drops) without increasing crashes. Lets move the experiment to a real property!

Should it be enabled by default?
   * I'm leaning toward no, but I could be convinced otherwise. This optimization is good for large/complex applications with lots of diffing, but I'm not sure the more common apps would need it initially. It does make updates more complicated and the order of operation will be a bit different. For example, we've seen some places call `-performUpdatesAnimated` and almost immediately expect the `IGListAdapter` data to be updated, leading to missing views. This issue can still happen without background diffing, but less often.

Reviewed By: joetam

Differential Revision: D25884786

fbshipit-source-id: 3c8755a774f63868b7dfbc8e7a2e5c012a9e7e27
2021-01-21 19:58:49 -08:00
Maxime Ollivier
032e1b0b83 goodbye allowsBackgroundReloading
Summary:
Originally, `allowsBackgroundReloading` was added to improve performance, but ironically, it's causing lots of performance issues among other issues.
* Performance: Looking back, it's not too surprising that it causes perf issues. We're falling back to a full `-reloadData` if the view is not in the window, which can happen pretty often. For example, if a view-controller is within a `UINavigationController` stack but not on top, or within a `UITabBarController`. Because a full `-reloadData` will re-query the cells and re-create the entire layout, it's going to be more expensive than an incremental update via `-performUpdatesAnimated`. The proof is in the data and we have a few examples where this flag was the cause of significant UI stalls.
* Bugs: Because we might reload cells often, it can create strange animation artifacts. Specifically, it was breaking the `UIView` snapshots just before a transition, like the new zoom animator.

Overall, we ended disabling this feature and I think most apps will be in the same boat.

But what if this flag does improve my app's performance?
* File an issue and lets chat! I'd be curious to understand why that's the case. If a full `-reloadData` is more performant than an incremental `-performUpdatesAnimated`, than something odd is happening and I don't think this flag is the right solution.

Reviewed By: joetam

Differential Revision: D25884777

fbshipit-source-id: c4626a52082ef4c7b7300b21077529f26c551e70
2021-01-21 19:58:48 -08:00
Maxime Ollivier
9994d5abc2 clean up performExperimentalUpdateAnimated
Summary:
Lets clean up `-performExperimentalUpdateAnimated`
* Remove the "experimental"
* Re-order the params to match the other method
* Rename dataBlock -> sectionDataBlock to make it clear we mean sections
* Rename applyDataBlock -> applySectionDataBlock

Reviewed By: Haud

Differential Revision: D25884784

fbshipit-source-id: e24c54b43c08c02538c83ba044b1a547cd0f38ae
2021-01-21 19:58:48 -08:00
Maxime Ollivier
43af8838df merge IGListUpdatingDelegateExperimental into IGListUpdatingDelegate
Summary:
Now that the new updater has shipped, lets update `IGListUpdatingDelegate` with the new methods:
* `-performExperimentalUpdateAnimated` is the new section update method (renaming coming in the next diff)
* `-performDataSourceChange` lets us safely update the `UICollectionView` dataSource

Also, something I've been wanting to do for a long time, lets group related methods in `IGListUpdatingDelegate.h`.

Reviewed By: Haud

Differential Revision: D25884780

fbshipit-source-id: 5d9201ace8bf6b281d71ff03463cb7c911e7f967
2021-01-21 19:58:47 -08:00
Maxime Ollivier
247e7cac65 ship the new updater
Summary:
It's time to ship the new updater! `IGListExperimentalAdapterUpdater` has been running on Instagram for a couple months with better performance and stability. In this diff, we're renaming `IGListExperimentalAdapterUpdater` (and related classes) to `IGListAdapterUpdater`.

Here's a recap:

## Stability

* `[IGListAdapter setDataSource]` isn't safe
  * We're changing the underlying data without telling the `UICollectionView`.
  * Fix: Lets invalidate the `UICollectionView` data by changing its dataSource.
* `[IGListAdapter setCollectionView]` isn't safe
  * This is synchronous, but we might have pending or on-going updates. The `UICollectionView` might get synced before the pending update actually start executing, so the diff results will be off.
  * Fix: Lets wrap updates in a transaction that can be cancelled.
* Returning a nil `IGListSectionController` from `IGListAdapterDataSource` could crash
  * The `IGListAdapterUpdater` will still perform the diffing assuming that all the objects will have a section, which isn't the case.
  * Fix: Lets generate the `IGListSectionController` before the diffing.
* Other improvements
  * Lets ask for the `fromObject` just before diffing, instead of asking when scheduling the update.
  * If the `UICollectionView` section count doesn't match `fromObject`, lets fallback to a reload.

## Performance

* Re-test background diffing
  * `IGListExperimentBackgroundDiffing` and coalescing updates wasn't safe because of the issues mentioned above. The longer we wait, the more likely we'll end up in a race condition. Lets try re-testing with the stability improvements.
* Unblocks background layout calculation
  * This is a larger project, but these improvements are required to make background work safe.
* Only create the `backgroundView` if needed (although this doesn't really require the new updater)

## Other

* Transactions
  * `IGListAdapterUpdater` is the workhorse of `IGListKit` and has become a bit hard to follow over the years. We want to break it apart into simpler, more manageable parts.
* Avoid blocks
  * There's a lot of blocks flying around, making crash logs hard to read. Lets try to use methods/functions where possible.

Reviewed By: Haud, lorixx

Differential Revision: D25884782

fbshipit-source-id: 1357fa23513a239051d5b1766823effa3199f656
2021-01-21 19:58:47 -08:00
Maxime Ollivier
329a4d300d ship IGListExperimentSectionCountValidation
Summary: This makes sure the `UICollectionView` section count matches what we expect before applying a diff results, if not, we fallback to a `reloadData`. This doesn't decrease the crash rate significantly, but it's nice to have a last line of defense. We do tradeoff crashes for performance issues, but it's better that an app works at all and we'll see the issue via asserts.

Reviewed By: lorixx

Differential Revision: D25884778

fbshipit-source-id: 5011d0907ce0f971ea3a0bf95c1549d52f615982
2021-01-21 19:58:47 -08:00
Zhisheng Huang
2c519b0b10 Improve the visibleObjects performance
Summary:
Trying to improve my previous QE regression on all the perf: https://www.internalfb.com/intern/qe2/ig_ios_listkit_improvements_universe/ig_ios_listkit_improvements_skip_view_section_controller_map/review

My theory is that it's incresing the load in the -visibleObjects call, then we call -[UICollectionView cellForIndexPath:] which is expensive in the `_sectionControllerForCell:`

Thus my new approach is to optimize this -visibleObjects entirely and instead of dealing with visible cells, we can use the `indexPathsForVisibleItems` which can give us the indexpath instead and make it faster. It would be O(N) instead of O(N^2) compared to before.

Reviewed By: calimarkus

Differential Revision: D24663555

fbshipit-source-id: 69fcf2d0b44f8bc06351c92f96c3cbe227c22479
2020-11-02 11:18:54 -08:00
Maxime Ollivier
cbaa7a8dce fix invalidateLayout crash
Summary:
Pretty sure in `-invalidateLayout`, we should calculate the `NSIndexPaths` after the delay. Otherwise, those `NSIndexPaths` might be incorrect after the update.

Before this change, running `test_whenInvalidatingInsideBatchUpdate_andRemoveThatSectionController_thatCollectionViewDoesntCrash` crashes with:
> Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempting to invalidate an item at an invalid indexPath: <NSIndexPath: 0x9566e79c2077363c> {length = 2, path = 1 - 0} globalIndex: 1 numItems: 1'

Reviewed By: candance

Differential Revision: D23742819

fbshipit-source-id: 39496d04025ff3554673313df3c7516c33c305d4
2020-09-16 16:19:09 -07:00
Maxime Ollivier
0693ca6be5 skip performBatchUpdates if possible
Summary: We don't actually need to call `[UICollectionVew performBatchUpdates ...]` if we don't have changes.

Reviewed By: patters

Differential Revision: D23386181

fbshipit-source-id: 469a22a35b9ead5181e95f36a8bc59ba36373bbe
2020-09-08 09:11:12 -07:00
Maxime Ollivier
fc8c4ba640 validate the section count before a performBatchUpdate
Summary:
We're seeing some crashes where the `UICollectionView`'s section count doesn't match the `fromObjets`. Ideally that shouldn't happen, but in case it does, lets fallback to a `reloadData` instead of crashing. Lets `IGFailAssert()` to keep an eye on it.

EDIT: Turns out `UICollectionView` will sometimes already do that for item-level inconsistencies! Example error message:
>  The number of items contained in an existing section after the update (9) must be equal to the number of items contained in that section before the update (10), plus or minus the number of items inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out). - will perform reloadData.

But it still throws a `NSInternalInconsistencyException` for section-level inconsistencies.

Reviewed By: patters

Differential Revision: D23386178

fbshipit-source-id: a9930b619701cffd37d0d6e2bcb1268ef7c9d0ce
2020-09-08 09:11:12 -07:00
Maxime Ollivier
c9144620e5 add dealloc tests
Summary:
It's easy to create a retain cycle or just forget to release a pointer, so lets test that the expendable parts of `IGListExperimentalAdapterUpdater` get deallocated after an update.

Lets also try to group related tests together. It's getting kind of hard to tell which tests already exist.

Reviewed By: patters

Differential Revision: D23386180

fbshipit-source-id: 90f0e6c7532287ee245e788dd752d45f368dc27e
2020-09-08 09:11:12 -07:00
Maxime Ollivier
4b4388d967 safer collectionView and dataSource changes
Summary:
Changing the `IGListAdapter`'s `collectionView` or `dataSource` isn't safe. For example:
  * If we change the `dataSource`, the `collectionView` will be out of sync with the `IGListAdapter`'s data and can easily crash.
  * If we change the `collectionView` or `dataSource` during background diffing, the diffing result will be out of date by the time we get back to to the main main thread.

To fix this:
* On `[IGListAdapter setDataSource: ...]`, lets also change the `UICollectionView`'s `dataSource` to invalidate any section/item counts. We don't have to call `[UICollectionView reloadData]` just yet, we just want to let the collectionView know that the counts might have changed.
* On `[IGListAdapter setDataSource: ...]` and `[IGListAdapter setCollectionView:...]`, we should cancel any pending or on-going updates. The tricky part is that we should still execute the `itemUpdateBlocks` and `completionBlocks` in the right order.

I kind of want to make the `collectionView` readonly, but I think it would be too large of a public API change at this point.

Reviewed By: patters

Differential Revision: D23151919

fbshipit-source-id: 61cf025127706acaf22f153ec148ac0ea575bc98
2020-09-08 09:11:12 -07:00
Maxime Ollivier
13ad185227 create update transactions
Summary:
Lets move things to the right transaction:
* `performBatchUpdate` path to `IGListBatchUpdateTransaction`
* `reloadData` path to `IGListReloadTransaction`

Reviewed By: patters

Differential Revision: D23145770

fbshipit-source-id: e80fc05d2783e165354a147453083b449c92a61c
2020-09-08 09:11:12 -07:00
Maxime Ollivier
8c1253246f replace IGListBatchUpdates with IGListItemUpdatesCollector
Summary:
Before adding `transactions`, lets clarify what information is collected before vs during the update. We can split apart `IGListBatchUpdates`.
* Before the update
  * Collect the update blocks in `itemUpdateBlocks` which will be executed later during the update.
  * Collect completion blocks in the same `completionBlocks` list as the other updates.
* During the update
  * Collect item updates in `IGListItemUpdatesCollector`, like inserts and deletes.
  * Collect new completion blocks (in case a section-controller schedules an update in -didUpdateToObject) in a separete list `inUpdateCompletionBlocks`

Reviewed By: patters

Differential Revision: D23145778

fbshipit-source-id: cae2c0689ac1ef0d93e3c04856b0495856e305b6
2020-09-08 09:11:12 -07:00
Maxime Ollivier
3f1a2fb0ac unit test missing section-controller fix
Summary: Lets test that the new updater (`IGListExperimentalAdapterUpdater`) can handle a missing section-controller. The old adapater `IGListAdapterUpdater` would crash.

Reviewed By: patters

Differential Revision: D23145773

fbshipit-source-id: 4589dcb11ddef5c7400947aea4b6827f1b2caaa8
2020-09-08 09:11:12 -07:00
Maxime Ollivier
caf058c85a implement performExperimentalUpdateAnimated
Summary:
Lets implement `performExperimentalUpdateAnimated`. There's a couple of things happening:
* We're now using the `IGListTransitionData` container object
* We don't need `pendingTransitionToObjects` anymore because we query the `fromObjects` just before performing the diffing.
* We should update the unit tests to use `performExperimentalUpdateAnimated` since the regular `performUpdateAnimated` will now fail.

Reviewed By: patters

Differential Revision: D23145781

fbshipit-source-id: 0b896e918241e709c5eb23f56a6b7323521a2222
2020-09-08 09:11:11 -07:00
Maxime Ollivier
088d932707 duplicate IGListAdapterUpdater to begin refactor
Summary:
There's a few issues with `IGListAdapterUpdater` which would be difficult to safely fix "in place", so lets create a duplicate updater that we can test separatly.

Ugh, copy paste?
* The alternative would be to change `IGListAdapterUpdater` directly and have lots of `if/else` branching. I've tried it and it's hard to follow and easy to break. By creating a separate class, we do run the risk of having 2 diverging updaters, but I think it's worth the risk since it rarely gets changed. I'll try to ship (or burn) this new updater quickly.

Why duplicate `IGListAdapterUpdater` rather then starting from scratch?
* I want to take advantage of the existing unit tests. I can make small incremental changes and make sure the tests still pass.
* There's a lot going on in `IGListAdapterUpdater` and it's easier to refactor it by moving things around, rather then writing it from nothing.

Why does `IGListAdapterUpdater` need a clean up?
* Check out the first diff in the stack or task T74605897.

Reviewed By: patters

Differential Revision: D23145777

fbshipit-source-id: 360e980a89a5681ce38d1b5f6f1ca035eb1eb195
2020-09-08 09:11:11 -07:00
Maxime Ollivier
aca18c7470 ship IGListExperimentSkipLayoutBeforeUpdate
Summary: Experiment looks good, so lets ship.

Reviewed By: patters

Differential Revision: D23145775

fbshipit-source-id: 16da69f220a2247490bb99b4965bcba33f498ced
2020-09-08 09:11:11 -07:00
Maxime Ollivier
254c04196a remove unused experiment param
Summary: We pass `experiments` to places that don't need it, so lets clean that up.

Reviewed By: patters

Differential Revision: D23145782

fbshipit-source-id: affcfe0f38d1b8e544940af89e5692dbdc36dd76
2020-09-08 09:11:11 -07:00
Maxime Ollivier
af78523453 rename movesAsDeletesInserts to sectionMovesAsDeletesInserts
Summary: Lets clarify that we're taking about section moves

Reviewed By: Haud

Differential Revision: D22897102

fbshipit-source-id: ea77ef695ddae8e7b1df96d51002bc8c0cc7fab7
2020-08-03 07:19:18 -07:00
Maxime Ollivier
56fa344508 check for a valid section NSInterger in IGListAdapter
Summary:
Issue: Invalidating the layout of a `IGListSectionController` that's been removed from the map crashes, because we're passing `NSNotFound` to `[UICollectionView numberOfItemsInSection:...]`. This can easily happen if the section-controller invalidates its layout in a `performBatchAnimated` completion block, but the associated object was deleted during the update or after a full reload.

Fix: Like the rest of `IGListAdapter`, lets check for a valid `NSInteger` and bail early if we don't have it.

Reviewed By: mariajayne

Differential Revision: D22588010

fbshipit-source-id: bf0c26f313795bb10682ef6b660d6ea8a7ce9f1e
2020-07-17 08:45:24 -07:00
Maxime Ollivier
d5c7076063 add IGListAdapterUpdaterDelegate calls to measure diffing performance
Summary: To prepare testing `Foundation` vs `IGListKit` diffing, lets measure how long it takes.

Reviewed By: Haud

Differential Revision: D22295546

fbshipit-source-id: 8023717f66ea68cbc24981272e8c134dd893274a
2020-07-02 13:07:03 -07:00
Maxime Ollivier
97b0a13a59 add animated to IGListAdapterUpdaterDelegate
Summary: The duration of an update depends a lot of if it's animated, so lets pass that info to the delegate.

Reviewed By: lorixx

Differential Revision: D22265405

fbshipit-source-id: 4d164447384b84eb6f41c7f8365d0b28670e1372
2020-06-30 10:13:03 -07:00
Maxime Ollivier
e3e26c4b4b test skipping layout before performing updates
Summary: We call `[collectionView layoutIfNeeded]` before performing updates, but it's not clear why. It leads to some strange animation issues when performing updates while scrolling. So lets try to skip it?

Reviewed By: Haud

Differential Revision: D22244053

fbshipit-source-id: 0c01a73860ebc16f430fed04d5c29a5bde038286
2020-06-26 10:07:14 -07:00
Maxime Ollivier
86ecc60085 clean up IGListExperimentReloadDataFallback
Summary: This experiment shipped so we can remove it. We still need a way to disable it with `allowsReloadingOnTooManyUpdates` in case we don't want to resign the first responder on large updates.

Reviewed By: Haud

Differential Revision: D22219238

fbshipit-source-id: 98e78f3ed040809db6c4b4c8da8fd0e976aca0a2
2020-06-26 10:07:13 -07:00
Maxime Ollivier
34c935c1a5 clean up IGListExperimentGetCollectionViewAtUpdate
Summary: Experiment shipped.

Reviewed By: Haud, lorixx

Differential Revision: D22219242

fbshipit-source-id: 60dbb5f008656ae67b02294ef16138703ebe392f
2020-06-26 10:07:13 -07:00
Maxime Ollivier
29bf582f47 fix IGListAdapterUpdaterDelegate
Summary:
Issue: There's a couple of situations where `IGListAdapterUpdater` updates the `collectionView` without notifying the `IGListAdapterUpdater`.
* If we call `reloadDataFallback()` because of a missing window, there's no delegate calls.
* If we call `reloadDataFallback()` because of too many diff updates, we call `willPerformBatchUpdatesWithCollectionView` but not `didPerformBatchUpdates`.

Fix: Lets clean up the delegate calls
* If we `[UICollectioView performBatchUpdates:]` lets call `willPerformBatchUpdatesWithCollectionView` & `didPerformBatchUpdates`
* If we fallback to `[UICollectionView reloadData]` lets call `willReloadDataWithCollectionView` & `didReloadDataWithCollectionView`
* If we fallback to doing nothing, lets call `didFinishWithoutUpdates`

Reviewed By: Haud

Differential Revision: D22219236

fbshipit-source-id: 1afb4df8dbbaf4725424027bb52c1a5cc5100b30
2020-06-26 10:07:13 -07:00