From 42f798682d049f24eeba80b2e7ee19117bf7656d Mon Sep 17 00:00:00 2001 From: "grant.zhou" Date: Mon, 7 May 2018 14:47:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=88=B0IGListKit=203.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZaloMessageUI/Podfile | 1 + ZaloMessageUI/Podfile.lock | 16 +- ZaloMessageUI/Pods/IGListKit/LICENSE.md | 43 +- ZaloMessageUI/Pods/IGListKit/README.md | 31 +- .../IGListKit/Source/Common/IGListAssert.h | 10 +- .../Source/Common/IGListBatchUpdateData.h | 34 +- .../Source/Common/IGListBatchUpdateData.mm | 70 +- .../Source/Common/IGListCompatibility.h | 6 +- .../Pods/IGListKit/Source/Common/IGListDiff.h | 21 +- .../IGListKit/Source/Common/IGListDiff.mm | 129 +- .../IGListKit/Source/Common/IGListDiffKit.h | 6 +- .../IGListKit/Source/Common/IGListDiffable.h | 7 +- .../Source/Common/IGListExperiments.h | 38 +- .../Source/Common/IGListIndexPathResult.h | 7 +- .../Source/Common/IGListIndexPathResult.m | 28 +- .../Source/Common/IGListIndexSetResult.h | 7 +- .../Source/Common/IGListIndexSetResult.m | 28 +- .../IGListKit/Source/Common/IGListMacros.h | 10 +- .../IGListKit/Source/Common/IGListMoveIndex.h | 7 +- .../IGListKit/Source/Common/IGListMoveIndex.m | 8 +- .../Source/Common/IGListMoveIndexPath.h | 7 +- .../Source/Common/IGListMoveIndexPath.m | 6 +- .../Internal/IGListArrayUtilsInternal.h | 34 + .../Internal/IGListIndexPathResultInternal.h | 8 +- .../Internal/IGListIndexSetResultInternal.h | 8 +- .../Common/Internal/IGListMoveIndexInternal.h | 6 +- .../Internal/IGListMoveIndexPathInternal.h | 6 +- .../Source/Common/NSNumber+IGListDiffable.h | 6 +- .../Source/Common/NSNumber+IGListDiffable.m | 6 +- .../Source/Common/NSString+IGListDiffable.h | 6 +- .../Source/Common/NSString+IGListDiffable.m | 6 +- .../Pods/IGListKit/Source/IGListAdapter.h | 108 +- .../Pods/IGListKit/Source/IGListAdapter.m | 767 ++++++----- .../Source/IGListAdapterDataSource.h | 15 +- .../IGListKit/Source/IGListAdapterDelegate.h | 18 +- .../Source/IGListAdapterMoveDelegate.h | 35 + .../Source/IGListAdapterUpdateListener.h | 56 + .../IGListKit/Source/IGListAdapterUpdater.h | 14 +- .../IGListKit/Source/IGListAdapterUpdater.m | 320 +++-- .../Source/IGListAdapterUpdaterDelegate.h | 51 +- .../IGListKit/Source/IGListBatchContext.h | 100 ++ .../Pods/IGListKit/Source/IGListBindable.h | 9 +- .../Source/IGListBindingSectionController.h | 16 +- .../Source/IGListBindingSectionController.m | 61 +- ...IGListBindingSectionControllerDataSource.h | 10 +- ...indingSectionControllerSelectionDelegate.h | 46 +- .../Source/IGListCollectionContext.h | 212 ++-- .../IGListKit/Source/IGListCollectionView.h | 81 +- .../IGListKit/Source/IGListCollectionView.m | 123 +- .../IGListCollectionViewDelegateLayout.h | 36 + .../Source/IGListCollectionViewLayout.h | 77 +- .../Source/IGListCollectionViewLayout.mm | 463 +++++-- .../IGListKit/Source/IGListDisplayDelegate.h | 33 +- .../Source/IGListGenericSectionController.h | 40 + .../Source/IGListGenericSectionController.m | 16 + .../Pods/IGListKit/Source/IGListKit.h | 21 +- .../Source/IGListReloadDataUpdater.h | 13 +- .../Source/IGListReloadDataUpdater.m | 41 +- .../IGListKit/Source/IGListScrollDelegate.h | 39 +- .../Source/IGListSectionController.h | 136 +- .../Source/IGListSectionController.m | 42 +- .../Pods/IGListKit/Source/IGListSectionType.h | 91 -- .../Source/IGListSingleSectionController.h | 50 +- .../Source/IGListSingleSectionController.m | 14 +- .../Source/IGListStackedSectionController.h | 25 +- .../Source/IGListStackedSectionController.m | 333 +++-- .../Source/IGListSupplementaryViewSource.h | 11 +- .../Source/IGListTransitionDelegate.h | 34 + .../IGListKit/Source/IGListUpdatingDelegate.h | 75 +- .../Source/IGListWorkingRangeDelegate.h | 17 +- .../Internal/IGListAdapter+DebugDescription.h | 14 + .../Internal/IGListAdapter+DebugDescription.m | 76 ++ .../Internal/IGListAdapter+UICollectionView.h | 18 + .../Internal/IGListAdapter+UICollectionView.m | 296 +++++ .../Source/Internal/IGListAdapterInternal.h | 28 +- .../Source/Internal/IGListAdapterProxy.h | 22 +- .../Source/Internal/IGListAdapterProxy.m | 24 +- .../IGListAdapterUpdater+DebugDescription.h | 14 + .../IGListAdapterUpdater+DebugDescription.m | 75 ++ .../Internal/IGListAdapterUpdaterInternal.h | 9 +- .../IGListBatchUpdateData+DebugDescription.h | 14 + .../IGListBatchUpdateData+DebugDescription.m | 38 + .../Source/Internal/IGListBatchUpdateState.h | 6 +- .../Source/Internal/IGListBatchUpdates.h | 17 +- .../Source/Internal/IGListBatchUpdates.m | 14 +- ...indingSectionController+DebugDescription.h | 14 + ...indingSectionController+DebugDescription.m | 46 + .../IGListCollectionViewLayoutInternal.h | 6 +- .../Source/Internal/IGListDebugger.h | 28 + .../Source/Internal/IGListDebugger.m | 42 + .../Internal/IGListDebuggingUtilities.h | 14 + .../Internal/IGListDebuggingUtilities.m | 20 + .../Source/Internal/IGListDisplayHandler.h | 49 +- .../Source/Internal/IGListDisplayHandler.m | 39 +- .../Source/Internal/IGListReloadIndexPath.h | 52 + .../Source/Internal/IGListReloadIndexPath.m | 21 + .../IGListSectionControllerInternal.h | 13 +- .../IGListSectionMap+DebugDescription.h | 16 + .../IGListSectionMap+DebugDescription.m | 29 + .../Source/Internal/IGListSectionMap.h | 23 +- .../Source/Internal/IGListSectionMap.m | 39 +- .../IGListStackedSectionControllerInternal.h | 18 +- .../Internal/IGListWorkingRangeHandler.h | 12 +- .../Internal/IGListWorkingRangeHandler.mm | 16 +- .../UICollectionView+DebugDescription.h | 14 + .../UICollectionView+DebugDescription.m | 43 + .../UICollectionView+IGListBatchUpdateData.h | 6 +- .../UICollectionView+IGListBatchUpdateData.m | 13 +- ...llectionViewLayout+InteractiveReordering.h | 24 + ...llectionViewLayout+InteractiveReordering.m | 200 +++ .../Source/Internal/UIScrollView+IGListKit.h | 14 + .../Source/Internal/UIScrollView+IGListKit.m | 25 + .../Local Podspecs/IGListKit.podspec.json | 8 +- ZaloMessageUI/Pods/Manifest.lock | 16 +- .../Pods/Pods.xcodeproj/project.pbxproj | 1123 ++++++++++------- .../xcschemes/IGListKit.xcscheme | 60 + .../xcschemes/Pods-ZaloMessageUI.xcscheme | 71 ++ .../xcschemes/xcschememanagement.plist | 25 + .../IGListKit/IGListKit-umbrella.h | 7 +- .../IGListKit/IGListKit.xcconfig | 6 +- .../Target Support Files/IGListKit/Info.plist | 2 +- ...ds-ZaloMessageUI-acknowledgements.markdown | 51 +- .../Pods-ZaloMessageUI-acknowledgements.plist | 45 +- .../Pods-ZaloMessageUI-frameworks.sh | 63 +- .../Pods-ZaloMessageUI-resources.sh | 25 +- .../Pods-ZaloMessageUI.debug.xcconfig | 9 +- .../Pods-ZaloMessageUI.release.xcconfig | 9 +- .../ZaloMessageUI.xcodeproj/project.pbxproj | 8 +- .../xcschemes/xcschememanagement.plist | 14 + .../UserInterfaceState.xcuserstate | Bin 0 -> 46268 bytes .../EmbeddedCollectionViewCell.m | 2 +- .../ZaloMessageUI/IGCollapseSupplementary.h | 8 +- .../ZaloMessageUI/IGCollapseSupplementary.m | 2 +- .../IGEmbeddedAdapterSectionController.h | 4 +- .../IGEmbeddedAdapterSectionController.m | 12 +- .../ZaloMessageUI/IGFriendSectionController.h | 2 +- .../ZaloMessageUI/IGFriendSectionController.m | 4 +- .../IGIncomingMessageSectionController.h | 5 +- .../IGIncomingMessageSectionController.m | 32 +- .../ZaloMessageUI/IGMainMessageDataSource.m | 4 +- .../ZaloMessageUI/IGSuggestFriendDataSource.m | 2 +- .../ZaloMessageUI/MainMessageViewController.m | 2 +- 142 files changed, 5079 insertions(+), 2298 deletions(-) create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListArrayUtilsInternal.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterMoveDelegate.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdateListener.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListBatchContext.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewDelegateLayout.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.m delete mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListSectionType.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/IGListTransitionDelegate.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.m create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.h create mode 100644 ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.m create mode 100644 ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/IGListKit.xcscheme create mode 100644 ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/Pods-ZaloMessageUI.xcscheme create mode 100644 ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ZaloMessageUI/ZaloMessageUI.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ZaloMessageUI/ZaloMessageUI.xcworkspace/xcuserdata/grant.zhou.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/ZaloMessageUI/Podfile b/ZaloMessageUI/Podfile index 0f0cad0..21e34e4 100644 --- a/ZaloMessageUI/Podfile +++ b/ZaloMessageUI/Podfile @@ -1,3 +1,4 @@ +platform :ios, '9.0' target ‘ZaloMessageUI’ do use_frameworks! diff --git a/ZaloMessageUI/Podfile.lock b/ZaloMessageUI/Podfile.lock index fcd97b6..7c54228 100644 --- a/ZaloMessageUI/Podfile.lock +++ b/ZaloMessageUI/Podfile.lock @@ -1,9 +1,9 @@ PODS: - - IGListKit (2.1.0): - - IGListKit/Default (= 2.1.0) - - IGListKit/Default (2.1.0): + - IGListKit (3.4.0): + - IGListKit/Default (= 3.4.0) + - IGListKit/Default (3.4.0): - IGListKit/Diffing - - IGListKit/Diffing (2.1.0) + - IGListKit/Diffing (3.4.0) DEPENDENCIES: - IGListKit (from `https://github.com/Instagram/IGListKit.git`, branch `master`) @@ -15,12 +15,12 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: IGListKit: - :commit: 24308a9881f54fc190070c858ec520d93074d95d + :commit: cce5a462bb8e4e3cf5b4d0aeebfedb318e52cf09 :git: https://github.com/Instagram/IGListKit.git SPEC CHECKSUMS: - IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e + IGListKit: 7a5d788e9fb746bcd402baa8e8b24bc3bd2a5a07 -PODFILE CHECKSUM: 0582a7790dd44dbac3df902d378fdbbf2f2cc6ba +PODFILE CHECKSUM: 639ede2e3c835232264f72146840d6924fe954d8 -COCOAPODS: 1.2.0 +COCOAPODS: 1.4.0 diff --git a/ZaloMessageUI/Pods/IGListKit/LICENSE.md b/ZaloMessageUI/Pods/IGListKit/LICENSE.md index b11e968..5a14f28 100755 --- a/ZaloMessageUI/Pods/IGListKit/LICENSE.md +++ b/ZaloMessageUI/Pods/IGListKit/LICENSE.md @@ -1,30 +1,21 @@ -BSD License +MIT License -For `IGListKit` software +Copyright (c) 2016-present, Facebook, Inc. -Copyright (c) 2016, Facebook, Inc. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ZaloMessageUI/Pods/IGListKit/README.md b/ZaloMessageUI/Pods/IGListKit/README.md index 14b0afc..f07a226 100644 --- a/ZaloMessageUI/Pods/IGListKit/README.md +++ b/ZaloMessageUI/Pods/IGListKit/README.md @@ -46,10 +46,10 @@ We use the open source version `master` branch in the Instagram app. ## Requirements -- Xcode 8.0+ +- Xcode 9.0+ - iOS 8.0+ - tvOS 9.0+ -- macOS 10.10+ *(diffing algorithm components only)* +- macOS 10.11+ *(diffing algorithm components only)* - Interoperability with Swift 3.0+ ## Installation @@ -59,7 +59,7 @@ We use the open source version `master` branch in the Instagram app. The preferred installation method is with [CocoaPods](https://cocoapods.org). Add the following to your `Podfile`: ```ruby -pod 'IGListKit', '~> 2.0.0' +pod 'IGListKit', '~> 3.0' ``` ### Carthage @@ -67,27 +67,44 @@ pod 'IGListKit', '~> 2.0.0' For [Carthage](https://github.com/Carthage/Carthage), add the following to your `Cartfile`: ```ogdl -github "Instagram/IGListKit" ~> 2.0.0 +github "Instagram/IGListKit" ~> 3.0 ``` > For advanced usage, see our [Installation Guide](https://instagram.github.io/IGListKit/installation.html). ## Getting Started +```bash +$ git clone https://github.com/Instagram/IGListKit.git +$ cd IGListKit/ +$ ./scripts/setup.sh +``` + - Our [Getting Started guide](https://instagram.github.io/IGListKit/getting-started.html) - Ray Wenderlich's [IGListKit Tutorial: Better UICollectionViews](https://www.raywenderlich.com/147162/iglistkit-tutorial-better-uicollectionviews) -- Ryan Nystrom's [talk at try! Swift NYC](https://realm.io/news/tryswift-ryan-nystrom-refactoring-at-scale-lessons-learned-rewriting-instagram-feed/) +- Our [example projects](https://github.com/Instagram/IGListKit/tree/master/Examples) +- Ryan Nystrom's [talk at try! Swift NYC](https://realm.io/news/tryswift-ryan-nystrom-refactoring-at-scale-lessons-learned-rewriting-instagram-feed/) (Note: this talk was for an earlier version. Some APIs have changed.) +- [Migrating an UITableView to IGListCollectionView](https://medium.com/cocoaacademymag/iglistkit-migrating-an-uitableview-to-iglistkitcollectionview-65a30cf9bac9), by Rodrigo Cavalcante +- [Keeping data fresh in Buffer for iOS with AsyncDisplayKit, IGListKit & Pusher](https://overflow.buffer.com/2017/04/10/keeping-data-fresh-buffer-ios-asyncdisplaykit-iglistkit-pusher/), Andy Yates, Buffer ## Documentation You can find [the docs here](https://instagram.github.io/IGListKit). Documentation is generated with [jazzy](https://github.com/realm/jazzy) and hosted on [GitHub-Pages](https://pages.github.com). +To regenerate docs, run `./scripts/build_docs.sh` from the root directory in the repo. + +## Vision + +For the long-term goals and "vision" of `IGListKit`, please read our [Vision](https://github.com/Instagram/IGListKit/blob/master/Guides/VISION.md) doc. + ## Contributing -Please see the [CONTRIBUTING](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) file for how to help out. At Instagram we sync the open source version of `IGListKit` daily, so we're always testing the latest changes. But that requires all changes be thoroughly tested and follow our style guide. +Please see the [CONTRIBUTING](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md) file for how to help. At Instagram, we sync the open source version of `IGListKit` daily, so we're always testing the latest changes. But that requires all changes be thoroughly tested and follow our style guide. + +We have a set of [starter tasks](https://github.com/Instagram/IGListKit/issues?q=is%3Aissue+is%3Aopen+label%3Astarter-task) that are great for beginners to jump in on and start contributing. ## License -`IGListKit` is BSD-licensed. We also provide an additional patent grant. +`IGListKit` is [MIT-licensed](./LICENSE). The files in the `/Examples/` directory are licensed under a separate license as specified in each file. Documentation is licensed [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/). diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListAssert.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListAssert.h index 2781e0e..d2ece62 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListAssert.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListAssert.h @@ -1,16 +1,18 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #ifndef IGAssert #define IGAssert( condition, ... ) NSCAssert( (condition) , ##__VA_ARGS__) #endif // IGAssert +#ifndef IGFailAssert +#define IGFailAssert( ... ) IGAssert( (NO) , ##__VA_ARGS__) +#endif // IGFailAssert + #ifndef IGParameterAssert #define IGParameterAssert( condition ) IGAssert( (condition) , @"Invalid parameter not satisfying: %@", @#condition) #endif // IGParameterAssert diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.h index 81b9706..1dbeab1 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -21,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN update via `-[UICollectionView performBatchUpdates:completion:]`. */ IGLK_SUBCLASSING_RESTRICTED +NS_SWIFT_NAME(ListBatchUpdateData) @interface IGListBatchUpdateData : NSObject /** @@ -41,43 +40,36 @@ IGLK_SUBCLASSING_RESTRICTED /** Item insert index paths. */ -@property (nonatomic, strong, readonly) NSSet *insertIndexPaths; +@property (nonatomic, strong, readonly) NSArray *insertIndexPaths; /** Item delete index paths. */ -@property (nonatomic, strong, readonly) NSSet *deleteIndexPaths; +@property (nonatomic, strong, readonly) NSArray *deleteIndexPaths; /** Item moves. */ -@property (nonatomic, strong, readonly) NSSet *moveIndexPaths; - -/** - Item reload index paths. - */ -@property (nonatomic, strong, readonly) NSSet *reloadIndexPaths; +@property (nonatomic, strong, readonly) NSArray *moveIndexPaths; /** Creates a new batch update object with section and item operations. - @param insertSections Section indexes to insert. - @param deleteSections Section indexes to delete. - @param moveSections Section moves. + @param insertSections Section indexes to insert. + @param deleteSections Section indexes to delete. + @param moveSections Section moves. @param insertIndexPaths Item index paths to insert. @param deleteIndexPaths Item index paths to delete. - @param moveIndexPaths Item index paths to move. - @param reloadIndexPaths Item index paths to reload. + @param moveIndexPaths Item index paths to move. @return A new batch update object. */ - (instancetype)initWithInsertSections:(NSIndexSet *)insertSections deleteSections:(NSIndexSet *)deleteSections moveSections:(NSSet *)moveSections - insertIndexPaths:(NSSet *)insertIndexPaths - deleteIndexPaths:(NSSet *)deleteIndexPaths - moveIndexPaths:(NSSet *)moveIndexPaths - reloadIndexPaths:(NSSet *)reloadIndexPaths NS_DESIGNATED_INITIALIZER; + insertIndexPaths:(NSArray *)insertIndexPaths + deleteIndexPaths:(NSArray *)deleteIndexPaths + moveIndexPaths:(NSArray *)moveIndexPaths NS_DESIGNATED_INITIALIZER; /** :nodoc: diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.mm b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.mm index 168875a..2ccfa90 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.mm +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListBatchUpdateData.mm @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListBatchUpdateData.h" @@ -14,18 +12,6 @@ #import -// Filters indexPaths removing all paths that have a section in sections. -static NSMutableSet *indexPathsMinusSections(NSSet *indexPaths, NSIndexSet *sections) { - NSMutableSet *filteredIndexPaths = [indexPaths mutableCopy]; - for (NSIndexPath *indexPath in indexPaths) { - const NSInteger section = indexPath.section; - if ([sections containsIndex:section]) { - [filteredIndexPaths removeObject:indexPath]; - } - } - return filteredIndexPaths; -} - // Plucks the given move from available moves and turns it into a delete + insert static void convertMoveToDeleteAndInsert(NSMutableSet *moves, IGListMoveIndex *move, @@ -42,15 +28,16 @@ static void convertMoveToDeleteAndInsert(NSMutableSet *moves, @implementation IGListBatchUpdateData // Converts all section moves that have index path operations into a section delete + insert. -+ (void)cleanIndexPathsWithMap:(const std::unordered_map &)map ++ (void)_cleanIndexPathsWithMap:(const std::unordered_map &)map moves:(NSMutableSet *)moves - indexPaths:(NSMutableSet *)indexPaths + indexPaths:(NSMutableArray *)indexPaths deletes:(NSMutableIndexSet *)deletes inserts:(NSMutableIndexSet *)inserts { - for (NSIndexPath *path in [indexPaths copy]) { + for (NSInteger i = indexPaths.count - 1; i >= 0; i--) { + NSIndexPath *path = indexPaths[i]; const auto it = map.find(path.section); if (it != map.end() && it->second != nil) { - [indexPaths removeObject:path]; + [indexPaths removeObjectAtIndex:i]; convertMoveToDeleteAndInsert(moves, it->second, deletes, inserts); } } @@ -63,17 +50,15 @@ + (void)cleanIndexPathsWithMap:(const std::unordered_map *)moveSections - insertIndexPaths:(NSSet *)insertIndexPaths - deleteIndexPaths:(NSSet *)deleteIndexPaths - moveIndexPaths:(NSSet *)moveIndexPaths - reloadIndexPaths:(NSSet *)reloadIndexPaths { + insertIndexPaths:(NSArray *)insertIndexPaths + deleteIndexPaths:(NSArray *)deleteIndexPaths + moveIndexPaths:(NSArray *)moveIndexPaths { IGParameterAssert(insertSections != nil); IGParameterAssert(deleteSections != nil); IGParameterAssert(moveSections != nil); IGParameterAssert(insertIndexPaths != nil); IGParameterAssert(deleteIndexPaths != nil); IGParameterAssert(moveIndexPaths != nil); - IGParameterAssert(reloadIndexPaths != nil); if (self = [super init]) { NSMutableSet *mMoveSections = [moveSections mutableCopy]; NSMutableIndexSet *mDeleteSections = [deleteSections mutableCopy]; @@ -91,29 +76,27 @@ - (instancetype)initWithInsertSections:(NSIndexSet *)insertSections const NSInteger from = move.from; const NSInteger to = move.to; - // if the move is already deleted or inserted, discard it and use delete+insert instead + // if the move is already deleted or inserted, discard it because count-changing operations must match + // with data source changes if ([deleteSections containsIndex:from] || [insertSections containsIndex:to]) { - convertMoveToDeleteAndInsert(mMoveSections, move, mDeleteSections, mInsertSections); + [mMoveSections removeObject:move]; } else { fromMap[from] = move; toMap[to] = move; } } - NSMutableSet *mInsertIndexPaths = [insertIndexPaths mutableCopy]; - NSMutableSet *mDeleteIndexPaths = [deleteIndexPaths mutableCopy]; + NSMutableArray *mInsertIndexPaths = [insertIndexPaths mutableCopy]; - // UICollectionView will throw if reloading an index path in a section that is also deleted - NSMutableSet *mReloadIndexPaths = indexPathsMinusSections(reloadIndexPaths, deleteSections); - - // UICollectionView will throw about simultaneous animations when reloading and moving cells at the same time - [IGListBatchUpdateData cleanIndexPathsWithMap:fromMap moves:mMoveSections indexPaths:mReloadIndexPaths deletes:mDeleteSections inserts:mInsertSections]; + // avoid a flaky UICollectionView bug when deleting from the same index path twice + // exposes a possible data source inconsistency issue + NSMutableArray *mDeleteIndexPaths = [[[NSSet setWithArray:deleteIndexPaths] allObjects] mutableCopy]; // avoids a bug where a cell is animated twice and one of the snapshot cells is never removed from the hierarchy - [IGListBatchUpdateData cleanIndexPathsWithMap:fromMap moves:mMoveSections indexPaths:mDeleteIndexPaths deletes:mDeleteSections inserts:mInsertSections]; + [IGListBatchUpdateData _cleanIndexPathsWithMap:fromMap moves:mMoveSections indexPaths:mDeleteIndexPaths deletes:mDeleteSections inserts:mInsertSections]; // prevents a bug where UICollectionView corrupts the heap memory when inserting into a section that is moved - [IGListBatchUpdateData cleanIndexPathsWithMap:toMap moves:mMoveSections indexPaths:mInsertIndexPaths deletes:mDeleteSections inserts:mInsertSections]; + [IGListBatchUpdateData _cleanIndexPathsWithMap:toMap moves:mMoveSections indexPaths:mInsertIndexPaths deletes:mDeleteSections inserts:mInsertSections]; for (IGListMoveIndexPath *move in moveIndexPaths) { // if the section w/ an index path move is deleted, just drop the move @@ -121,14 +104,6 @@ - (instancetype)initWithInsertSections:(NSIndexSet *)insertSections [mMoveIndexPaths removeObject:move]; } - // if an index path is moved and reloaded, convert it into a delete+insert - if ([mReloadIndexPaths containsObject:move.from]) { - [mReloadIndexPaths removeObject:move.from]; - [mMoveIndexPaths removeObject:move]; - [mDeleteIndexPaths addObject:move.from]; - [mInsertIndexPaths addObject:move.to]; - } - // if a move is inside a section that is moved, convert the section move to a delete+insert const auto it = fromMap.find(move.from.section); if (it != fromMap.end() && it->second != nil) { @@ -146,15 +121,14 @@ - (instancetype)initWithInsertSections:(NSIndexSet *)insertSections _deleteIndexPaths = [mDeleteIndexPaths copy]; _insertIndexPaths = [mInsertIndexPaths copy]; _moveIndexPaths = [mMoveIndexPaths copy]; - _reloadIndexPaths = [mReloadIndexPaths copy]; } return self; } - (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p; deleteSections: %zi; insertSections: %zi; moveSections: %zi; deleteIndexPaths: %zi; insertIndexPaths: %zi; reloadIndexPaths: %zi;>", - NSStringFromClass(self.class), self, self.deleteSections.count, self.insertSections.count, self.moveSections.count, - self.deleteIndexPaths.count, self.insertIndexPaths.count, self.reloadIndexPaths.count]; + return [NSString stringWithFormat:@"<%@ %p; deleteSections: %lu; insertSections: %lu; moveSections: %lu; deleteIndexPaths: %lu; insertIndexPaths: %lu;>", + NSStringFromClass(self.class), self, (unsigned long)self.deleteSections.count, (unsigned long)self.insertSections.count, (unsigned long)self.moveSections.count, + (unsigned long)self.deleteIndexPaths.count, (unsigned long)self.insertIndexPaths.count]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListCompatibility.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListCompatibility.h index 2d59a92..4be26ce 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListCompatibility.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListCompatibility.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.h index efa8088..10f53a6 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -18,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN /** An option for how to do comparisons between similar objects. */ +NS_SWIFT_NAME(ListDiffOption) typedef NS_ENUM(NSInteger, IGListDiffOption) { /** Compare objects using pointer personality. @@ -34,11 +33,12 @@ typedef NS_ENUM(NSInteger, IGListDiffOption) { @param oldArray The old objects to diff against. @param newArray The new objects. - @param option An option on how to compare objects. + @param option An option on how to compare objects. @return A result object containing affected indexes. */ -FOUNDATION_EXTERN IGListIndexSetResult *IGListDiff(NSArray> *_Nullable oldArray, +NS_SWIFT_NAME(ListDiff(oldArray:newArray:option:)) +FOUNDATION_EXTERN IGListIndexSetResult *IGListDiff(NSArray> *_Nullable oldArray, NSArray> *_Nullable newArray, IGListDiffOption option); @@ -46,13 +46,14 @@ FOUNDATION_EXTERN IGListIndexSetResult *IGListDiff(NSArray> * Creates a diff using index paths between two collections. @param fromSection The old section. - @param toSection The new section. - @param oldArray The old objects to diff against. - @param newArray The new objects. - @param option An option on how to compare objects. + @param toSection The new section. + @param oldArray The old objects to diff against. + @param newArray The new objects. + @param option An option on how to compare objects. @return A result object containing affected indexes. */ +NS_SWIFT_NAME(ListDiffPaths(fromSection:toSection:oldArray:newArray:option:)) FOUNDATION_EXTERN IGListIndexPathResult *IGListDiffPaths(NSInteger fromSection, NSInteger toSection, NSArray> *_Nullable oldArray, diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.mm b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.mm index c6fcba3..6389da3 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.mm +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiff.mm @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListDiff.h" @@ -47,7 +45,7 @@ } }; -static id IGListTableKey(id object) { +static id IGListTableKey(__unsafe_unretained id object) { id key = [object diffIdentifier]; NSCAssert(key != nil, @"Cannot use a nil key for the diffIdentifier of object %@", object); return key; @@ -65,6 +63,35 @@ size_t operator()(const id o) const { } }; +static void addIndexToMap(BOOL useIndexPaths, NSInteger section, NSInteger index, __unsafe_unretained id object, __unsafe_unretained NSMapTable *map) { + id value; + if (useIndexPaths) { + value = [NSIndexPath indexPathForItem:index inSection:section]; + } else { + value = @(index); + } + [map setObject:value forKey:[object diffIdentifier]]; +} + +static void addIndexToCollection(BOOL useIndexPaths, __unsafe_unretained id collection, NSInteger section, NSInteger index) { + if (useIndexPaths) { + NSIndexPath *path = [NSIndexPath indexPathForItem:index inSection:section]; + [collection addObject:path]; + } else { + [collection addIndex:index]; + } +}; + +static NSArray *indexPathsAndPopulateMap(__unsafe_unretained NSArray> *array, NSInteger section, __unsafe_unretained NSMapTable *map) { + NSMutableArray *paths = [NSMutableArray new]; + [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSIndexPath *path = [NSIndexPath indexPathForItem:idx inSection:section]; + [paths addObject:path]; + [map setObject:paths forKey:[obj diffIdentifier]]; + }]; + return paths; +} + static id IGListDiffing(BOOL returnIndexPaths, NSInteger fromSection, NSInteger toSection, @@ -75,6 +102,55 @@ static id IGListDiffing(BOOL returnIndexPaths, const NSInteger newCount = newArray.count; const NSInteger oldCount = oldArray.count; + NSMapTable *oldMap = [NSMapTable strongToStrongObjectsMapTable]; + NSMapTable *newMap = [NSMapTable strongToStrongObjectsMapTable]; + + // if no new objects, everything from the oldArray is deleted + // take a shortcut and just build a delete-everything result + if (newCount == 0) { + if (returnIndexPaths) { + return [[IGListIndexPathResult alloc] initWithInserts:[NSArray new] + deletes:indexPathsAndPopulateMap(oldArray, fromSection, oldMap) + updates:[NSArray new] + moves:[NSArray new] + oldIndexPathMap:oldMap + newIndexPathMap:newMap]; + } else { + [oldArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + addIndexToMap(returnIndexPaths, fromSection, idx, obj, oldMap); + }]; + return [[IGListIndexSetResult alloc] initWithInserts:[NSIndexSet new] + deletes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, oldCount)] + updates:[NSIndexSet new] + moves:[NSArray new] + oldIndexMap:oldMap + newIndexMap:newMap]; + } + } + + // if no old objects, everything from the newArray is inserted + // take a shortcut and just build an insert-everything result + if (oldCount == 0) { + if (returnIndexPaths) { + return [[IGListIndexPathResult alloc] initWithInserts:indexPathsAndPopulateMap(newArray, toSection, newMap) + deletes:[NSArray new] + updates:[NSArray new] + moves:[NSArray new] + oldIndexPathMap:oldMap + newIndexPathMap:newMap]; + } else { + [newArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + addIndexToMap(returnIndexPaths, toSection, idx, obj, newMap); + }]; + return [[IGListIndexSetResult alloc] initWithInserts:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, newCount)] + deletes:[NSIndexSet new] + updates:[NSIndexSet new] + moves:[NSArray new] + oldIndexMap:oldMap + newIndexMap:newMap]; + } + } + // symbol table uses the old/new array diffIdentifier as the key and IGListEntry as the value // using id as the key provided by https://lists.gnu.org/archive/html/discuss-gnustep/2011-07/msg00019.html unordered_map, IGListEntry, IGListHashID, IGListEqualID> table; @@ -106,7 +182,7 @@ static id IGListDiffing(BOOL returnIndexPaths, IGListEntry &entry = table[key]; entry.oldCounter++; - // push the original indices where the item occured onto the index stack + // push the original indices where the item occurred onto the index stack entry.oldIndexes.push(i); // note: the entry is just a pointer to the entry which is stack-allocated in the table @@ -119,7 +195,7 @@ static id IGListDiffing(BOOL returnIndexPaths, IGListEntry *entry = newResultsArray[i].entry; // grab and pop the top original index. if the item was inserted this will be NSNotFound - NSCAssert(!entry->oldIndexes.empty(), @"Old indexes is empty while iterating new item %zi. Should have NSNotFound", i); + NSCAssert(!entry->oldIndexes.empty(), @"Old indexes is empty while iterating new item %li. Should have NSNotFound", (long)i); const NSInteger originalIndex = entry->oldIndexes.top(); entry->oldIndexes.pop(); @@ -166,31 +242,6 @@ static id IGListDiffing(BOOL returnIndexPaths, mMoves = [NSMutableArray new]; } - // populate a container based on whether we want NSIndexPaths or indexes - // section into INDEX SET - // item, section into ARRAY - // IGListMoveIndex or IGListMoveIndexPath into ARRAY - void (^addIndexToCollection)(id, NSInteger, NSInteger) = ^(id collection, NSInteger section, NSInteger index) { - if (returnIndexPaths) { - NSIndexPath *path = [NSIndexPath indexPathForItem:index inSection:section]; - [collection addObject:path]; - } else { - [collection addIndex:index]; - } - }; - - NSMapTable *oldMap = [NSMapTable strongToStrongObjectsMapTable]; - NSMapTable *newMap = [NSMapTable strongToStrongObjectsMapTable]; - void (^addIndexToMap)(NSInteger, NSInteger, NSArray *, NSMapTable *) = ^(NSInteger section, NSInteger index, NSArray *array, NSMapTable *map) { - id value; - if (returnIndexPaths) { - value = [NSIndexPath indexPathForItem:index inSection:section]; - } else { - value = @(index); - } - [map setObject:value forKey:[array[index] diffIdentifier]]; - }; - // track offsets from deleted items to calculate where items have moved vector deleteOffsets(oldCount), insertOffsets(newCount); NSInteger runningOffset = 0; @@ -202,11 +253,11 @@ static id IGListDiffing(BOOL returnIndexPaths, const IGListRecord record = oldResultsArray[i]; // if the record index in the new array doesn't exist, its a delete if (record.index == NSNotFound) { - addIndexToCollection(mDeletes, fromSection, i); + addIndexToCollection(returnIndexPaths, mDeletes, fromSection, i); runningOffset++; } - addIndexToMap(fromSection, i, oldArray, oldMap); + addIndexToMap(returnIndexPaths, fromSection, i, oldArray[i], oldMap); } // reset and track offsets from inserted items to calculate where items have moved @@ -218,12 +269,12 @@ static id IGListDiffing(BOOL returnIndexPaths, const NSInteger oldIndex = record.index; // add to inserts if the opposing index is NSNotFound if (record.index == NSNotFound) { - addIndexToCollection(mInserts, toSection, i); + addIndexToCollection(returnIndexPaths, mInserts, toSection, i); runningOffset++; } else { // note that an entry can be updated /and/ moved if (record.entry->updated) { - addIndexToCollection(mUpdates, fromSection, oldIndex); + addIndexToCollection(returnIndexPaths, mUpdates, fromSection, oldIndex); } // calculate the offset and determine if there was a move @@ -243,12 +294,12 @@ static id IGListDiffing(BOOL returnIndexPaths, } } - addIndexToMap(toSection, i, newArray, newMap); + addIndexToMap(returnIndexPaths, toSection, i, newArray[i], newMap); } NSCAssert((oldCount + [mInserts count] - [mDeletes count]) == newCount, - @"Sanity check failed applying %zi inserts and %zi deletes to old count %zi equaling new count %zi", - oldCount, [mInserts count], [mDeletes count], newCount); + @"Sanity check failed applying %li inserts and %lu deletes to old count %lu equaling new count %li", + (long)oldCount, (unsigned long)[mInserts count], (unsigned long)[mDeletes count], (long)newCount); if (returnIndexPaths) { return [[IGListIndexPathResult alloc] initWithInserts:mInserts diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffKit.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffKit.h index c40ddbe..70146f8 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffKit.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffKit.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffable.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffable.h index 937a1eb..16fd90b 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffable.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListDiffable.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,6 +10,7 @@ /** The `IGListDiffable` protocol provides methods needed to compare the identity and equality of two objects. */ +NS_SWIFT_NAME(ListDiffable) @protocol IGListDiffable /** diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListExperiments.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListExperiments.h index 680aa6c..3ea84d5 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListExperiments.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListExperiments.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,19 +12,31 @@ /** Bitmask-able options used for pre-release feature testing. */ +NS_SWIFT_NAME(ListExperiment) typedef NS_OPTIONS (NSInteger, IGListExperiment) { - /// Specifies no experiements. + /// Specifies no experiments. IGListExperimentNone = 1 << 1, + /// Test updater diffing performed on a background queue. + IGListExperimentBackgroundDiffing = 1 << 2, + /// Test fallback to reloadData when "too many" update operations. + IGListExperimentReloadDataFallback = 1 << 3, + /// Test a faster way to return visible section controllers. + IGListExperimentFasterVisibleSectionController = 1 << 4, + /// Test deduping item-level updates. + IGListExperimentDedupeItemUpdates = 1 << 5, + /// Test deferring object creation until just before diffing. + IGListExperimentDeferredToObjectCreation = 1 << 6, }; /** Check if an experiment is enabled in a bitmask. - @param mask The bitmask of experiments. + @param mask The bitmask of experiments. @param option The option to compare with. @return `YES` if the option is in the bitmask, otherwise `NO`. */ +NS_SWIFT_NAME(ListExperimentEnabled(mask:option:)) static inline BOOL IGListExperimentEnabled(IGListExperiment mask, IGListExperiment option) { return (mask & option) != 0; } @@ -36,15 +46,16 @@ NS_ASSUME_NONNULL_BEGIN /** Performs an index diff with an experiment bitmask. - @param oldArray The old array of objects. - @param newArray The new array of objects. - @param option Option to specify the type of diff. + @param oldArray The old array of objects. + @param newArray The new array of objects. + @param option Option to specify the type of diff. @param experiments Optional experiments. @return An index set result object contained the changed indexes. @see `IGListDiff()`. */ +NS_SWIFT_NAME(ListDiffExperiment(oldArray:newArray:option:experiments:)) FOUNDATION_EXTERN IGListIndexSetResult *IGListDiffExperiment(NSArray> *_Nullable oldArray, NSArray> *_Nullable newArray, IGListDiffOption option, @@ -54,16 +65,17 @@ FOUNDATION_EXTERN IGListIndexSetResult *IGListDiffExperiment(NSArray> *_Nullable oldArray, diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.h index c7f12f0..f5b6d53 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -16,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /** A result object returned when diffing with sections. */ +NS_SWIFT_NAME(ListIndexPathResult) @interface IGListIndexPathResult : NSObject /** diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.m index bbc1750..30a0f99 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexPathResult.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListIndexPathResult.h" @@ -22,18 +20,22 @@ - (instancetype)initWithInserts:(NSArray *)inserts oldIndexPathMap:(NSMapTable, NSIndexPath *> *)oldIndexPathMap newIndexPathMap:(NSMapTable, NSIndexPath *> *)newIndexPathMap { if (self = [super init]) { - _inserts = [inserts copy]; - _deletes = [deletes copy]; - _updates = [updates copy]; - _moves = [moves copy]; - _oldIndexPathMap = [oldIndexPathMap copy]; - _newIndexPathMap = [newIndexPathMap copy]; + _inserts = inserts; + _deletes = deletes; + _updates = updates; + _moves = moves; + _oldIndexPathMap = oldIndexPathMap; + _newIndexPathMap = newIndexPathMap; } return self; } - (BOOL)hasChanges { - return self.inserts.count || self.deletes.count || self.updates.count || self.moves.count; + return self.changeCount > 0; +} + +- (NSInteger)changeCount { + return self.inserts.count + self.deletes.count + self.updates.count + self.moves.count; } - (IGListIndexPathResult *)resultForBatchUpdates { @@ -82,8 +84,8 @@ - (NSIndexPath *)newIndexPathForIdentifier:(id)identifier { } - (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p; %zi inserts; %zi deletes; %zi updates; %zi moves>", - NSStringFromClass(self.class), self, self.inserts.count, self.deletes.count, self.updates.count, self.moves.count]; + return [NSString stringWithFormat:@"<%@ %p; %lu inserts; %lu deletes; %lu updates; %lu moves>", + NSStringFromClass(self.class), self, (unsigned long)self.inserts.count, (unsigned long)self.deletes.count, (unsigned long)self.updates.count, (unsigned long)self.moves.count]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.h index 62fd014..639cc35 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -16,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /** A result object returned when diffing with indexes. */ +NS_SWIFT_NAME(ListIndexSetResult) @interface IGListIndexSetResult : NSObject /** diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.m index ccc02d5..abe9c80 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListIndexSetResult.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListIndexSetResult.h" @@ -24,18 +22,22 @@ - (instancetype)initWithInserts:(NSIndexSet *)inserts oldIndexMap:(NSMapTable, NSNumber *> *)oldIndexMap newIndexMap:(NSMapTable, NSNumber *> *)newIndexMap { if (self = [super init]) { - _inserts = [inserts copy]; - _deletes = [deletes copy]; - _updates = [updates copy]; - _moves = [moves copy]; - _oldIndexMap = [oldIndexMap copy]; - _newIndexMap = [newIndexMap copy]; + _inserts = inserts; + _deletes = deletes; + _updates = updates; + _moves = moves; + _oldIndexMap = oldIndexMap; + _newIndexMap = newIndexMap; } return self; } - (BOOL)hasChanges { - return self.inserts.count || self.deletes.count || self.updates.count || self.moves.count; + return self.changeCount > 0; +} + +- (NSInteger)changeCount { + return self.inserts.count + self.deletes.count + self.updates.count + self.moves.count; } - (IGListIndexSetResult *)resultForBatchUpdates { @@ -86,8 +88,8 @@ - (NSInteger)newIndexForIdentifier:(id)identifier { } - (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p; %zi inserts; %zi deletes; %zi updates; %zi moves>", - NSStringFromClass(self.class), self, self.inserts.count, self.deletes.count, self.updates.count, self.moves.count]; + return [NSString stringWithFormat:@"<%@ %p; %lu inserts; %lu deletes; %lu updates; %lu moves>", + NSStringFromClass(self.class), self, (unsigned long)self.inserts.count, (unsigned long)self.deletes.count, (unsigned long)self.updates.count, (unsigned long)self.moves.count]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMacros.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMacros.h index 23c3b1f..e73851f 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMacros.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMacros.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #ifndef IGLK_SUBCLASSING_RESTRICTED @@ -24,3 +22,7 @@ #else #define IGLKLog( s, ... ) #endif + +#ifndef IGLK_DEBUG_DESCRIPTION_ENABLED +#define IGLK_DEBUG_DESCRIPTION_ENABLED DEBUG +#endif // #ifndef IGLK_DEBUG_DESCRIPTION_ENABLED diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.h index 8745bb3..8ffc712 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN /** An object representing a move between indexes. */ +NS_SWIFT_NAME(ListMoveIndex) @interface IGListMoveIndex : NSObject /** diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.m index 48d4e7c..9dcb2a8 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndex.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListMoveIndex.h" @@ -49,7 +47,7 @@ - (NSComparisonResult)compare:(id)object { } - (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p; from: %zi; to: %zi;>", NSStringFromClass(self.class), self, self.from, self.to]; + return [NSString stringWithFormat:@"<%@ %p; from: %li; to: %li;>", NSStringFromClass(self.class), self, (long)self.from, (long)self.to]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.h index 9cb91f8..3c00927 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN /** An object representing a move between indexes. */ +NS_SWIFT_NAME(ListMoveIndexPath) @interface IGListMoveIndexPath : NSObject /** diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.m index dacb848..28302cd 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/IGListMoveIndexPath.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListMoveIndexPath.h" diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListArrayUtilsInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListArrayUtilsInternal.h new file mode 100644 index 0000000..d6249fc --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListArrayUtilsInternal.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifndef IGListArrayUtilsInternal_h +#define IGListArrayUtilsInternal_h + +#import + +static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray> *objects) { + if (objects == nil) { + return nil; + } + + NSMapTable *identifierMap = [NSMapTable strongToStrongObjectsMapTable]; + NSMutableArray *uniqueObjects = [NSMutableArray new]; + for (id object in objects) { + id diffIdentifier = [object diffIdentifier]; + id previousObject = [identifierMap objectForKey:diffIdentifier]; + if (diffIdentifier != nil + && previousObject == nil) { + [identifierMap setObject:object forKey:diffIdentifier]; + [uniqueObjects addObject:object]; + } else { + IGFailAssert(@"Duplicate identifier %@ for object %@ with object %@", diffIdentifier, object, previousObject); + } + } + return uniqueObjects; +} + +#endif /* IGListArrayUtilsInternal_h */ diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexPathResultInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexPathResultInternal.h index f60b564..47112ba 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexPathResultInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexPathResultInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -22,6 +20,8 @@ NS_ASSUME_NONNULL_BEGIN oldIndexPathMap:(NSMapTable, NSIndexPath *> *)oldIndexPathMap newIndexPathMap:(NSMapTable, NSIndexPath *> *)newIndexPathMap; +@property (nonatomic, assign, readonly) NSInteger changeCount; + @end NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexSetResultInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexSetResultInternal.h index c66284e..68a4ead 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexSetResultInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListIndexSetResultInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -22,6 +20,8 @@ NS_ASSUME_NONNULL_BEGIN oldIndexMap:(NSMapTable, NSNumber *> *)oldIndexMap newIndexMap:(NSMapTable, NSNumber *> *)newIndexMap; +@property (nonatomic, assign, readonly) NSInteger changeCount; + @end NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexInternal.h index 5d4d532..0102e66 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexPathInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexPathInternal.h index c53fb19..15c083c 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexPathInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/Internal/IGListMoveIndexPathInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.h index 5d467c2..5caf1dd 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.m index e83b5c3..ce8ebf3 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSNumber+IGListDiffable.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "NSNumber+IGListDiffable.h" diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.h b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.h index e82a827..4101cfe 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.m b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.m index fe90c47..f98af84 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Common/NSString+IGListDiffable.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "NSString+IGListDiffable.h" diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.h index 6d46366..8e52cc1 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.h @@ -1,20 +1,19 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import #import #import +#import #import -#import +#import + #import -#import #import @protocol IGListUpdatingDelegate; @@ -24,21 +23,23 @@ NS_ASSUME_NONNULL_BEGIN /** - A block to execute when list updates completes. + A block to execute when the list updates are completed. - @param finished Specifies whether or not the updates finished. + @param finished Specifies whether or not the update animations completed successfully. */ +NS_SWIFT_NAME(ListUpdaterCompletion) typedef void (^IGListUpdaterCompletion)(BOOL finished); /** - `IGListAdapter` objects provide an abstraction for feeds of objects in a `UICollectionView` by breaking each object into - individual sections, called "section controllers". These controllers (objects conforming to `IGListSectionType`) act as a - data source and delegate for each section. + `IGListAdapter` objects provide an abstraction for feeds of objects in a `UICollectionView` by breaking each object + into individual sections, called "section controllers". These controllers (objects subclassing to + `IGListSectionController`) act as a data source and delegate for each section. Feed implementations must act as the data source for an `IGListAdapter` in order to drive the objects and section controllers in a collection view. */ IGLK_SUBCLASSING_RESTRICTED +NS_SWIFT_NAME(ListAdapter) @interface IGListAdapter : NSObject /** @@ -48,11 +49,13 @@ IGLK_SUBCLASSING_RESTRICTED /** The collection view used with the adapter. + + @note Setting this property will automatically set isPrefetchingEnabled to `NO` for performance reasons. */ -@property (nonatomic, nullable, weak) IGListCollectionView *collectionView; +@property (nonatomic, nullable, weak) UICollectionView *collectionView; /** - The object that acts as the data source for the list adapter. + The object that acts as the data source for the adapter. */ @property (nonatomic, nullable, weak) id dataSource; @@ -74,7 +77,14 @@ IGLK_SUBCLASSING_RESTRICTED @property (nonatomic, nullable, weak) id scrollViewDelegate; /** - The updater for this list adapter. + The object that receives `IGListAdapterMoveDelegate` events resulting from interactive reordering of sections. + + @note This works with UICollectionView interactive reordering available on iOS 9.0+ + */ +@property (nonatomic, nullable, weak) id moveDelegate NS_AVAILABLE_IOS(9_0); + +/** + The updater for the adapter. */ @property (nonatomic, strong, readonly) id updater; @@ -87,7 +97,7 @@ IGLK_SUBCLASSING_RESTRICTED Initializes a new `IGListAdapter` object. @param updater An object that manages updates to the collection view. - @param viewController The view controller that will house the adapter. + @param viewController The view controller that will house the adapter. @param workingRangeSize The number of objects before and after the viewport to consider within the working range. @return A new list adapter object. @@ -97,18 +107,29 @@ IGLK_SUBCLASSING_RESTRICTED the previous and succeeding 2 objects will be notified that they are within the working range. As you scroll the list the range is updated as objects enter and exit the working range. - To opt out of using the working range, you can provide a value of `0`. + To opt out of using the working range, use `initWithUpdater:viewController:` or provide a working range of `0`. */ - (instancetype)initWithUpdater:(id )updater viewController:(nullable UIViewController *)viewController workingRangeSize:(NSInteger)workingRangeSize NS_DESIGNATED_INITIALIZER; /** - Perform an update from the previous state of the data source. This is analagous to calling + Initializes a new `IGListAdapter` object with a working range of `0`. + + @param updater An object that manages updates to the collection view. + @param viewController The view controller that will house the adapter. + + @return A new list adapter object. + */ +- (instancetype)initWithUpdater:(id )updater + viewController:(nullable UIViewController *)viewController; + +/** + Perform an update from the previous state of the data source. This is analogous to calling `-[UICollectionView performBatchUpdates:completion:]`. - @param animated A flag indicating if the transition should be animated. - @param completion The block to execute when the update completes. + @param animated A flag indicating if the transition should be animated. + @param completion The block to execute when the updates complete. */ - (void)performUpdatesAnimated:(BOOL)animated completion:(nullable IGListUpdaterCompletion)completion; @@ -116,6 +137,9 @@ IGLK_SUBCLASSING_RESTRICTED Perform an immediate reload of the data in the data source, discarding the old objects. @param completion The block to execute when the reload completes. + + @warning Do not use this method to update without animations as it can be very expensive to teardown and rebuild all + section controllers. Use `-[IGListAdapter performUpdatesAnimated:completion]` instead. */ - (void)reloadDataWithCompletion:(nullable IGListUpdaterCompletion)completion; @@ -131,9 +155,9 @@ IGLK_SUBCLASSING_RESTRICTED @param section A section in the list. - @return An section controller or `nil` if the section does not exist. + @return A section controller or `nil` if the section does not exist. */ -- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section; +- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section; /** Query the section index of a list. Constant time lookup. @@ -142,27 +166,27 @@ IGLK_SUBCLASSING_RESTRICTED @return The section index of the list if it exists, otherwise `NSNotFound`. */ -- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController; +- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController; /** Returns the section controller for the specified object. Constant time lookup. @param object An object from the data source. - @return An section controller or `nil` if `object` is not in the list. + @return A section controller or `nil` if `object` is not in the list. @see `-[IGListAdapterDataSource listAdapter:sectionControllerForObject:]` */ -- (__kindof IGListSectionController * _Nullable)sectionControllerForObject:(id)object; +- (__kindof IGListSectionController * _Nullable)sectionControllerForObject:(id)object; /** Returns the object corresponding to the specified section controller in the list. Constant time lookup. @param sectionController A section controller in the list. - @return The object for the specified section controller, or nil if not found. + @return The object for the specified section controller, or `nil` if not found. */ -- (nullable id)objectForSectionController:(IGListSectionController *)sectionController; +- (nullable id)objectForSectionController:(IGListSectionController *)sectionController; /** Returns the object corresponding to a section in the list. Constant time lookup. @@ -183,7 +207,7 @@ IGLK_SUBCLASSING_RESTRICTED - (NSInteger)sectionForObject:(id)object; /** - Returns a copy of all the objects currently powering the adapter. + Returns a copy of all the objects currently driving the adapter. @return An array of objects. */ @@ -194,7 +218,7 @@ IGLK_SUBCLASSING_RESTRICTED @return An array of section controllers. */ -- (NSArray *> *)visibleSectionControllers; +- (NSArray *)visibleSectionControllers; /** An unordered array of the currently visible objects. @@ -213,13 +237,13 @@ IGLK_SUBCLASSING_RESTRICTED - (NSArray *)visibleCellsForObject:(id)object; /** - Scrolls to the sepcified object in the list adapter. + Scrolls to the specified object in the list adapter. - @param object The object to which to scroll. + @param object The object to which to scroll. @param supplementaryKinds The types of supplementary views in the section. - @param scrollDirection An option indicating the direction to scroll. - @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. - @param animated A flag indicating if the scrolling should be animated. + @param scrollDirection An option indicating the direction to scroll. + @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. + @param animated A flag indicating if the scrolling should be animated. */ - (void)scrollToObject:(id)object supplementaryKinds:(nullable NSArray *)supplementaryKinds @@ -240,13 +264,29 @@ IGLK_SUBCLASSING_RESTRICTED Returns the size of a supplementary view in the list at the specified index path. @param elementKind The kind of supplementary view. - @param indexPath The index path of the supplementary view. + @param indexPath The index path of the supplementary view. @return The size of the supplementary view. */ - (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath; +/** + Adds a listener to the list adapter. + + @param updateListener The object conforming to the `IGListAdapterUpdateListener` protocol. + + @note Listeners are held weakly so there is no need to call `-[IGListAdapter removeUpdateListener:]` on `dealloc`. + */ +- (void)addUpdateListener:(id)updateListener; + +/** + Removes a listener from the list adapter. + + @param updateListener The object conforming to the `IGListAdapterUpdateListener` protocol. + */ +- (void)removeUpdateListener:(id)updateListener; + /** :nodoc: */ diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.m index 6147d23..acdb268 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapter.m @@ -1,25 +1,27 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListAdapterInternal.h" #import #import -#import #import #import "IGListSectionControllerInternal.h" +#import "IGListDebugger.h" +#import "IGListArrayUtilsInternal.h" +#import "UIScrollView+IGListKit.h" +#import "UICollectionViewLayout+InteractiveReordering.h" @implementation IGListAdapter { - NSMapTable *> *_viewSectionControllerMap; - BOOL _isDequeuingCell; - BOOL _isSendingWorkingRangeDisplayUpdates; + NSMapTable *_viewSectionControllerMap; + // An array of blocks to execute once batch updates are finished + NSMutableArray *_queuedCompletionBlocks; + NSHashTable> *_updateListeners; } - (void)dealloc { @@ -29,6 +31,8 @@ - (void)dealloc { _collectionView.dataSource = nil; _collectionView.delegate = nil; } + + [self.sectionMap reset]; } @@ -46,34 +50,45 @@ - (instancetype)initWithUpdater:(id )updater NSMapTable *table = [[NSMapTable alloc] initWithKeyPointerFunctions:keyFunctions valuePointerFunctions:valueFunctions capacity:0]; _sectionMap = [[IGListSectionMap alloc] initWithMapTable:table]; - _displayHandler = [[IGListDisplayHandler alloc] init]; + _displayHandler = [IGListDisplayHandler new]; _workingRangeHandler = [[IGListWorkingRangeHandler alloc] initWithWorkingRangeSize:workingRangeSize]; + _updateListeners = [NSHashTable weakObjectsHashTable]; _viewSectionControllerMap = [NSMapTable mapTableWithKeyOptions:NSMapTableObjectPointerPersonality | NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory]; _updater = updater; _viewController = viewController; + + [IGListDebugger trackAdapter:self]; } return self; } -- (IGListCollectionView *)collectionView { - return (IGListCollectionView *)_collectionView; +- (instancetype)initWithUpdater:(id)updater + viewController:(UIViewController *)viewController { + return [self initWithUpdater:updater + viewController:viewController + workingRangeSize:0]; +} + +- (UICollectionView *)collectionView { + return _collectionView; } -- (void)setCollectionView:(IGListCollectionView *)collectionView { +- (void)setCollectionView:(UICollectionView *)collectionView { IGAssertMainThread(); // if collection view has been used by a different list adapter, treat it as if we were using a new collection view - // this happens when embedding a IGListCollectionView inside a UICollectionViewCell that is reused + // this happens when embedding a UICollectionView inside a UICollectionViewCell that is reused if (_collectionView != collectionView || _collectionView.dataSource != self) { // if the collection view was being used with another IGListAdapter (e.g. cell reuse) // destroy the previous association so the old adapter doesn't update the wrong collection view - static NSMapTable *globalCollectionViewAdapterMap = nil; + static NSMapTable *globalCollectionViewAdapterMap = nil; if (globalCollectionViewAdapterMap == nil) { globalCollectionViewAdapterMap = [NSMapTable weakToWeakObjectsMapTable]; } + [globalCollectionViewAdapterMap removeObjectForKey:_collectionView]; [[globalCollectionViewAdapterMap objectForKey:collectionView] setCollectionView:nil]; [globalCollectionViewAdapterMap setObject:self forKey:collectionView]; @@ -87,15 +102,22 @@ - (void)setCollectionView:(IGListCollectionView *)collectionView { _collectionView = collectionView; _collectionView.dataSource = self; - [self updateCollectionViewDelegate]; - [self updateAfterPublicSettingsChange]; + if (@available(iOS 10.0, tvOS 10, *)) { + _collectionView.prefetchingEnabled = NO; + } + + [_collectionView.collectionViewLayout ig_hijackLayoutInteractiveReorderingMethodForAdapter:self]; + [_collectionView.collectionViewLayout invalidateLayout]; + + [self _updateCollectionViewDelegate]; + [self _updateAfterPublicSettingsChange]; } } - (void)setDataSource:(id)dataSource { if (_dataSource != dataSource) { _dataSource = dataSource; - [self updateAfterPublicSettingsChange]; + [self _updateAfterPublicSettingsChange]; } } @@ -107,7 +129,7 @@ - (void)setCollectionViewDelegate:(id)collectionViewDe if (_collectionViewDelegate != collectionViewDelegate) { _collectionViewDelegate = collectionViewDelegate; - [self createProxyAndUpdateCollectionViewDelegate]; + [self _createProxyAndUpdateCollectionViewDelegate]; } } @@ -116,18 +138,19 @@ - (void)setScrollViewDelegate:(id)scrollViewDelegate { if (_scrollViewDelegate != scrollViewDelegate) { _scrollViewDelegate = scrollViewDelegate; - [self createProxyAndUpdateCollectionViewDelegate]; + [self _createProxyAndUpdateCollectionViewDelegate]; } } -- (void)updateAfterPublicSettingsChange { +- (void)_updateAfterPublicSettingsChange { id dataSource = _dataSource; if (_collectionView != nil && dataSource != nil) { - [self updateObjects:[[dataSource objectsForListAdapter:self] copy] dataSource:dataSource]; + NSArray *uniqueObjects = objectsWithDuplicateIdentifiersRemoved([dataSource objectsForListAdapter:self]); + [self _updateObjects:uniqueObjects dataSource:dataSource]; } } -- (void)createProxyAndUpdateCollectionViewDelegate { +- (void)_createProxyAndUpdateCollectionViewDelegate { // there is a known bug with accessibility and using an NSProxy as the delegate that will cause EXC_BAD_ACCESS // when voiceover is enabled. it will hold an unsafe ref to the delegate _collectionView.delegate = nil; @@ -135,10 +158,10 @@ - (void)createProxyAndUpdateCollectionViewDelegate { self.delegateProxy = [[IGListAdapterProxy alloc] initWithCollectionViewTarget:_collectionViewDelegate scrollViewTarget:_scrollViewDelegate interceptor:self]; - [self updateCollectionViewDelegate]; + [self _updateCollectionViewDelegate]; } -- (void)updateCollectionViewDelegate { +- (void)_updateCollectionViewDelegate { // set up the delegate to the proxy so the adapter can intercept events // default to the adapter simply being the delegate _collectionView.delegate = (id)self.delegateProxy ?: self; @@ -161,20 +184,41 @@ - (void)scrollToObject:(id)object } UICollectionView *collectionView = self.collectionView; - const NSInteger numberOfItems = [collectionView numberOfItemsInSection:section]; - if (numberOfItems == 0) { - return; - } + UICollectionViewLayout *layout = self.collectionView.collectionViewLayout; // force layout before continuing // this method is typcially called before pushing a view controller // thus, before the layout process has actually happened + [collectionView setNeedsLayout]; [collectionView layoutIfNeeded]; + NSIndexPath *indexPathFirstElement = [NSIndexPath indexPathForItem:0 inSection:section]; + // collect the layout attributes for the cell and supplementary views for the first index // this will break if there are supplementary views beyond item 0 - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section]; - NSArray *attributes = [self layoutAttributesForIndexPath:indexPath supplementaryKinds:supplementaryKinds]; + NSMutableArray *attributes = nil; + + const NSInteger numberOfItems = [collectionView numberOfItemsInSection:section]; + if (numberOfItems > 0) { + attributes = [self _layoutAttributesForIndexPath:indexPathFirstElement supplementaryKinds:supplementaryKinds].mutableCopy; + + if (numberOfItems > 1) { + NSIndexPath *indexPathLastElement = [NSIndexPath indexPathForItem:(numberOfItems - 1) inSection:section]; + UICollectionViewLayoutAttributes *lastElementattributes = [self _layoutAttributesForIndexPath:indexPathLastElement supplementaryKinds:supplementaryKinds].firstObject; + if (lastElementattributes != nil) { + [attributes addObject:lastElementattributes]; + } + } + } else { + NSMutableArray *supplementaryAttributes = [NSMutableArray new]; + for (NSString* supplementaryKind in supplementaryKinds) { + UICollectionViewLayoutAttributes *supplementaryAttribute = [layout layoutAttributesForSupplementaryViewOfKind:supplementaryKind atIndexPath:indexPathFirstElement]; + if (supplementaryAttribute != nil) { + [supplementaryAttributes addObject: supplementaryAttribute]; + } + } + attributes = supplementaryAttributes; + } CGFloat offsetMin = 0.0; CGFloat offsetMax = 0.0; @@ -206,10 +250,10 @@ - (void)scrollToObject:(id)object const CGFloat offsetMid = (offsetMin + offsetMax) / 2.0; const CGFloat collectionViewWidth = collectionView.bounds.size.width; const CGFloat collectionViewHeight = collectionView.bounds.size.height; - const UIEdgeInsets contentInset = collectionView.contentInset; + const UIEdgeInsets contentInset = collectionView.ig_contentInset; CGPoint contentOffset = collectionView.contentOffset; switch (scrollDirection) { - case UICollectionViewScrollDirectionHorizontal: + case UICollectionViewScrollDirectionHorizontal: { switch (scrollPosition) { case UICollectionViewScrollPositionRight: contentOffset.x = offsetMax - collectionViewWidth - contentInset.left; @@ -227,11 +271,16 @@ - (void)scrollToObject:(id)object contentOffset.x = offsetMin - contentInset.left; break; } + const CGFloat maxOffsetX = collectionView.contentSize.width - collectionView.frame.size.width + contentInset.right; + const CGFloat minOffsetX = -contentInset.left; + contentOffset.x = MIN(contentOffset.x, maxOffsetX); + contentOffset.x = MAX(contentOffset.x, minOffsetX); break; - case UICollectionViewScrollDirectionVertical: + } + case UICollectionViewScrollDirectionVertical: { switch (scrollPosition) { case UICollectionViewScrollPositionBottom: - contentOffset.y = offsetMax - collectionViewHeight - contentInset.top; + contentOffset.y = offsetMax - collectionViewHeight; break; case UICollectionViewScrollPositionCenteredVertically: { const CGFloat insets = (contentInset.top - contentInset.bottom) / 2.0; @@ -246,13 +295,17 @@ - (void)scrollToObject:(id)object contentOffset.y = offsetMin - contentInset.top; break; } + const CGFloat maxOffsetY = collectionView.contentSize.height - collectionView.frame.size.height + contentInset.bottom; + const CGFloat minOffsetY = -contentInset.top; + contentOffset.y = MIN(contentOffset.y, maxOffsetY); + contentOffset.y = MAX(contentOffset.y, minOffsetY); break; + } } [collectionView setContentOffset:contentOffset animated:animated]; } - #pragma mark - Editing - (void)performUpdatesAnimated:(BOOL)animated completion:(IGListUpdaterCompletion)completion { @@ -261,6 +314,7 @@ - (void)performUpdatesAnimated:(BOOL)animated completion:(IGListUpdaterCompletio id dataSource = self.dataSource; UICollectionView *collectionView = self.collectionView; if (dataSource == nil || collectionView == nil) { + IGLKLog(@"Warning: Your call to %s is ignored as dataSource or collectionView haven't been set.", __PRETTY_FUNCTION__); if (completion) { completion(NO); } @@ -268,26 +322,44 @@ - (void)performUpdatesAnimated:(BOOL)animated completion:(IGListUpdaterCompletio } NSArray *fromObjects = self.sectionMap.objects; - NSArray *newObjects = [dataSource objectsForListAdapter:self]; + IGListToObjectBlock toObjectsBlock; __weak __typeof__(self) weakSelf = self; + if (IGListExperimentEnabled(self.experiments, IGListExperimentDeferredToObjectCreation)) { + toObjectsBlock = ^NSArray *{ + __typeof__(self) strongSelf = weakSelf; + if (strongSelf == nil) { + return nil; + } + return [dataSource objectsForListAdapter:strongSelf]; + }; + } else { + NSArray *newObjects = [dataSource objectsForListAdapter:self]; + toObjectsBlock = ^NSArray *{ + return newObjects; + }; + } + + [self _enterBatchUpdates]; [self.updater performUpdateWithCollectionView:collectionView fromObjects:fromObjects - toObjects:newObjects + toObjectsBlock:toObjectsBlock animated:animated objectTransitionBlock:^(NSArray *toObjects) { // temporarily capture the item map that we are transitioning from in case // there are any item deletes at the same weakSelf.previousSectionMap = [weakSelf.sectionMap copy]; - [weakSelf updateObjects:toObjects dataSource:dataSource]; + [weakSelf _updateObjects:toObjects dataSource:dataSource]; } completion:^(BOOL finished) { // release the previous items weakSelf.previousSectionMap = nil; + [weakSelf _notifyDidUpdate:IGListAdapterUpdateTypePerformUpdates animated:animated]; if (completion) { completion(finished); } + [weakSelf _exitBatchUpdates]; }]; } @@ -297,30 +369,36 @@ - (void)reloadDataWithCompletion:(nullable IGListUpdaterCompletion)completion { id dataSource = self.dataSource; UICollectionView *collectionView = self.collectionView; if (dataSource == nil || collectionView == nil) { + IGLKLog(@"Warning: Your call to %s is ignored as dataSource or collectionView haven't been set.", __PRETTY_FUNCTION__); if (completion) { completion(NO); } return; } - NSArray *newItems = [[dataSource objectsForListAdapter:self] copy]; + NSArray *uniqueObjects = objectsWithDuplicateIdentifiersRemoved([dataSource objectsForListAdapter:self]); __weak __typeof__(self) weakSelf = self; [self.updater reloadDataWithCollectionView:collectionView reloadUpdateBlock:^{ // purge all section controllers from the item map so that they are regenerated [weakSelf.sectionMap reset]; - [weakSelf updateObjects:newItems dataSource:dataSource]; - } completion:completion]; + [weakSelf _updateObjects:uniqueObjects dataSource:dataSource]; + } completion:^(BOOL finished) { + [weakSelf _notifyDidUpdate:IGListAdapterUpdateTypeReloadData animated:NO]; + if (completion) { + completion(finished); + } + }]; } - (void)reloadObjects:(NSArray *)objects { IGAssertMainThread(); IGParameterAssert(objects); - NSMutableIndexSet *sections = [[NSMutableIndexSet alloc] init]; + NSMutableIndexSet *sections = [NSMutableIndexSet new]; // use the item map based on whether or not we're in an update block - IGListSectionMap *map = [self sectionMapUsingPreviousIfInUpdateBlock:YES]; + IGListSectionMap *map = [self _sectionMapUsingPreviousIfInUpdateBlock:YES]; for (id object in objects) { // look up the item using the map's lookup function. might not be the same item @@ -344,30 +422,50 @@ - (void)reloadObjects:(NSArray *)objects { [self.updater reloadCollectionView:collectionView sections:sections]; } +- (void)addUpdateListener:(id)updateListener { + IGAssertMainThread(); + IGParameterAssert(updateListener != nil); + + [_updateListeners addObject:updateListener]; +} + +- (void)removeUpdateListener:(id)updateListener { + IGAssertMainThread(); + IGParameterAssert(updateListener != nil); + + [_updateListeners removeObject:updateListener]; +} + +- (void)_notifyDidUpdate:(IGListAdapterUpdateType)update animated:(BOOL)animated { + for (id listener in _updateListeners) { + [listener listAdapter:self didFinishUpdate:update animated:animated]; + } +} + #pragma mark - List Items & Sections -- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section { +- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section { IGAssertMainThread(); return [self.sectionMap sectionControllerForSection:section]; } -- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController { +- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(sectionController != nil); return [self.sectionMap sectionForSectionController:sectionController]; } -- (id )sectionControllerForObject:(id)object { +- (IGListSectionController *)sectionControllerForObject:(id)object { IGAssertMainThread(); IGParameterAssert(object != nil); return [self.sectionMap sectionControllerForObject:object]; } -- (id)objectForSectionController:(IGListSectionController *)sectionController { +- (id)objectForSectionController:(IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(sectionController != nil); @@ -394,18 +492,27 @@ - (NSArray *)objects { return self.sectionMap.objects; } -- (id)supplementaryViewSourceAtIndexPath:(NSIndexPath *)indexPath { - IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; +- (id)_supplementaryViewSourceAtIndexPath:(NSIndexPath *)indexPath { + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; return [sectionController supplementaryViewSource]; } -- (NSArray *> *)visibleSectionControllers { +- (NSArray *)visibleSectionControllers { IGAssertMainThread(); - NSArray *visibleCells = [self.collectionView visibleCells]; + if (IGListExperimentEnabled(self.experiments, IGListExperimentFasterVisibleSectionController)) { + return [self _visibleSectionControllersFromDisplayHandler]; + } else { + return [self _visibleSectionControllersFromLayoutAttributes]; + } +} + +- (NSArray *)_visibleSectionControllersFromLayoutAttributes { NSMutableSet *visibleSectionControllers = [NSMutableSet new]; - for (UICollectionViewCell *cell in visibleCells) { - IGListSectionController *sectionController = [self sectionControllerForView:cell]; - IGAssert(sectionController != nil, @"Section controller nil for cell %@", cell); + NSArray *attributes = + [self.collectionView.collectionViewLayout layoutAttributesForElementsInRect:self.collectionView.bounds]; + for (UICollectionViewLayoutAttributes* attribute in attributes) { + IGListSectionController *sectionController = [self sectionControllerForSection:attribute.indexPath.section]; + IGAssert(sectionController != nil, @"Section controller nil for cell in section %ld", (long)attribute.indexPath.section); if (sectionController) { [visibleSectionControllers addObject:sectionController]; } @@ -413,17 +520,21 @@ - (NSArray *)objects { return [visibleSectionControllers allObjects]; } +- (NSArray *)_visibleSectionControllersFromDisplayHandler { + return [[self.displayHandler visibleListSections] allObjects]; +} + - (NSArray *)visibleObjects { IGAssertMainThread(); NSArray *visibleCells = [self.collectionView visibleCells]; NSMutableSet *visibleObjects = [NSMutableSet new]; for (UICollectionViewCell *cell in visibleCells) { - IGListSectionController *sectionController = [self sectionControllerForView:cell]; + IGListSectionController *sectionController = [self sectionControllerForView:cell]; IGAssert(sectionController != nil, @"Section controller nil for cell %@", cell); if (sectionController != nil) { const NSInteger section = [self sectionForSectionController:sectionController]; id object = [self objectAtSection:section]; - IGAssert(object != nil, @"Object not found for section controller %@ at section %zi", sectionController, section); + IGAssert(object != nil, @"Object not found for section controller %@ at section %li", sectionController, (long)section); if (object != nil) { [visibleObjects addObject:object]; } @@ -457,15 +568,17 @@ - (NSArray *)visibleObjects { - (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath { IGAssertMainThread(); - IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; - return [sectionController sizeForItemAtIndex:indexPath.item]; + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; + const CGSize size = [sectionController sizeForItemAtIndex:indexPath.item]; + return CGSizeMake(MAX(size.width, 0.0), MAX(size.height, 0.0)); } - (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { IGAssertMainThread(); - id supplementaryViewSource = [self supplementaryViewSourceAtIndexPath:indexPath]; + id supplementaryViewSource = [self _supplementaryViewSourceAtIndexPath:indexPath]; if ([[supplementaryViewSource supportedElementKinds] containsObject:elementKind]) { - return [supplementaryViewSource sizeForSupplementaryViewOfKind:elementKind atIndex:indexPath.item]; + const CGSize size = [supplementaryViewSource sizeForSupplementaryViewOfKind:elementKind atIndex:indexPath.item]; + return CGSizeMake(MAX(size.width, 0.0), MAX(size.height, 0.0)); } return CGSizeZero; } @@ -475,7 +588,7 @@ - (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NS // this method is what updates the "source of truth" // this should only be called just before the collection view is updated -- (void)updateObjects:(NSArray *)objects dataSource:(id)dataSource { +- (void)_updateObjects:(NSArray *)objects dataSource:(id)dataSource { IGParameterAssert(dataSource != nil); #if DEBUG @@ -484,7 +597,7 @@ - (void)updateObjects:(NSArray *)objects dataSource:(id } #endif - NSMutableArray *> *sectionControllers = [NSMutableArray new]; + NSMutableArray *sectionControllers = [NSMutableArray new]; NSMutableArray *validObjects = [NSMutableArray new]; IGListSectionMap *map = self.sectionMap; @@ -496,12 +609,9 @@ - (void)updateObjects:(NSArray *)objects dataSource:(id // for IGListSectionController subclasses after calling [super init] IGListSectionControllerPushThread(self.viewController, self); - id firstObject = objects.firstObject; - id lastObject = objects.lastObject; - for (id object in objects) { // infra checks to see if a controller exists - IGListSectionController *sectionController = [map sectionControllerForObject:object]; + IGListSectionController *sectionController = [map sectionControllerForObject:object]; // if not, query the data source for a new one if (sectionController == nil) { @@ -517,8 +627,6 @@ - (void)updateObjects:(NSArray *)objects dataSource:(id // in case the section controller was created outside of -listAdapter:sectionControllerForObject: sectionController.collectionContext = self; sectionController.viewController = self.viewController; - sectionController.isFirstSection = (object == firstObject); - sectionController.isLastSection = (object == lastObject); // check if the item has changed instances or is new const NSInteger oldSection = [map sectionForObject:object]; @@ -529,6 +637,11 @@ - (void)updateObjects:(NSArray *)objects dataSource:(id [sectionControllers addObject:sectionController]; [validObjects addObject:object]; } + +#if DEBUG + IGAssert([NSSet setWithArray:sectionControllers].count == sectionControllers.count, + @"Section controllers array is not filled with unique objects; section controllers are being reused"); +#endif // clear the view controller and collection context IGListSectionControllerPopThread(); @@ -541,14 +654,14 @@ - (void)updateObjects:(NSArray *)objects dataSource:(id } NSInteger itemCount = 0; - for (IGListSectionController *sectionController in sectionControllers) { + for (IGListSectionController *sectionController in sectionControllers) { itemCount += [sectionController numberOfItems]; } - [self updateBackgroundViewShouldHide:itemCount > 0]; + [self _updateBackgroundViewShouldHide:itemCount > 0]; } -- (void)updateBackgroundViewShouldHide:(BOOL)shouldHide { +- (void)_updateBackgroundViewShouldHide:(BOOL)shouldHide { if (self.isInUpdateBlock) { return; // will be called again when update block completes } @@ -563,9 +676,9 @@ - (void)updateBackgroundViewShouldHide:(BOOL)shouldHide { _collectionView.backgroundView.hidden = shouldHide; } -- (BOOL)itemCountIsZero { +- (BOOL)_itemCountIsZero { __block BOOL isZero = YES; - [self.sectionMap enumerateUsingBlock:^(id _Nonnull object, IGListSectionController * _Nonnull sectionController, NSInteger section, BOOL * _Nonnull stop) { + [self.sectionMap enumerateUsingBlock:^(id _Nonnull object, IGListSectionController * _Nonnull sectionController, NSInteger section, BOOL * _Nonnull stop) { if (sectionController.numberOfItems > 0) { isZero = NO; *stop = YES; @@ -574,7 +687,7 @@ - (BOOL)itemCountIsZero { return isZero; } -- (IGListSectionMap *)sectionMapUsingPreviousIfInUpdateBlock:(BOOL)usePreviousMapIfInUpdateBlock { +- (IGListSectionMap *)_sectionMapUsingPreviousIfInUpdateBlock:(BOOL)usePreviousMapIfInUpdateBlock { // if we are inside an update block, we may have to use the /previous/ item map for some operations IGListSectionMap *previousSectionMap = self.previousSectionMap; if (usePreviousMapIfInUpdateBlock && self.isInUpdateBlock && previousSectionMap != nil) { @@ -584,12 +697,12 @@ - (IGListSectionMap *)sectionMapUsingPreviousIfInUpdateBlock:(BOOL)usePreviousMa } } -- (NSArray *)indexPathsFromSectionController:(IGListSectionController *)sectionController +- (NSArray *)indexPathsFromSectionController:(IGListSectionController *)sectionController indexes:(NSIndexSet *)indexes usePreviousIfInUpdateBlock:(BOOL)usePreviousIfInUpdateBlock { - NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; + NSMutableArray *indexPaths = [NSMutableArray new]; - IGListSectionMap *map = [self sectionMapUsingPreviousIfInUpdateBlock:usePreviousIfInUpdateBlock]; + IGListSectionMap *map = [self _sectionMapUsingPreviousIfInUpdateBlock:usePreviousIfInUpdateBlock]; const NSInteger section = [map sectionForSectionController:sectionController]; if (section != NSNotFound) { [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { @@ -602,7 +715,7 @@ - (IGListSectionMap *)sectionMapUsingPreviousIfInUpdateBlock:(BOOL)usePreviousMa - (NSIndexPath *)indexPathForSectionController:(IGListSectionController *)controller index:(NSInteger)index usePreviousIfInUpdateBlock:(BOOL)usePreviousIfInUpdateBlock { - IGListSectionMap *map = [self sectionMapUsingPreviousIfInUpdateBlock:usePreviousIfInUpdateBlock]; + IGListSectionMap *map = [self _sectionMapUsingPreviousIfInUpdateBlock:usePreviousIfInUpdateBlock]; const NSInteger section = [map sectionForSectionController:controller]; if (section == NSNotFound) { return nil; @@ -611,10 +724,10 @@ - (NSIndexPath *)indexPathForSectionController:(IGListSectionController *)contro } } -- (NSArray *)layoutAttributesForIndexPath:(NSIndexPath *)indexPath +- (NSArray *)_layoutAttributesForIndexPath:(NSIndexPath *)indexPath supplementaryKinds:(NSArray *)supplementaryKinds { UICollectionViewLayout *layout = self.collectionView.collectionViewLayout; - NSMutableArray *attributes = [[NSMutableArray alloc] init]; + NSMutableArray *attributes = [NSMutableArray new]; UICollectionViewLayoutAttributes *cellAttributes = [layout layoutAttributesForItemAtIndexPath:indexPath]; if (cellAttributes) { @@ -631,14 +744,14 @@ - (NSIndexPath *)indexPathForSectionController:(IGListSectionController *)contro return attributes; } -- (void)mapView:(UICollectionReusableView *)view toSectionController:(IGListSectionController *)sectionController { +- (void)mapView:(UICollectionReusableView *)view toSectionController:(IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(view != nil); IGParameterAssert(sectionController != nil); [_viewSectionControllerMap setObject:sectionController forKey:view]; } -- (nullable IGListSectionController *)sectionControllerForView:(UICollectionReusableView *)view { +- (nullable IGListSectionController *)sectionControllerForView:(UICollectionReusableView *)view { IGAssertMainThread(); return [_viewSectionControllerMap objectForKey:view]; } @@ -648,129 +761,25 @@ - (void)removeMapForView:(UICollectionReusableView *)view { [_viewSectionControllerMap removeObjectForKey:view]; } -#pragma mark - UICollectionViewDataSource - -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { - return self.sectionMap.objects.count; -} - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - IGListSectionController * sectionController = [self sectionControllerForSection:section]; - IGAssert(sectionController != nil, @"Nil section controller for section %zi for item %@. Check your -diffIdentifier and -isEqual: implementations.", - section, [self.sectionMap objectForSection:section]); - const NSInteger numberOfItems = [sectionController numberOfItems]; - IGAssert(numberOfItems >= 0, @"Cannot return negative number of items %zi for section controller %@.", numberOfItems, sectionController); - return numberOfItems; -} - -- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; - - // flag that a cell is being dequeued in case it tries to access a cell in the process - _isDequeuingCell = YES; - UICollectionViewCell *cell = [sectionController cellForItemAtIndex:indexPath.item]; - _isDequeuingCell = NO; - - IGAssert(cell != nil, @"Returned a nil cell at indexPath <%@> from section controller: <%@>", indexPath, sectionController); - - // associate the section controller with the cell so that we know which section controller is using it - [self mapView:cell toSectionController:sectionController]; - - return cell; -} - -- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { - IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; - id supplementarySource = [sectionController supplementaryViewSource]; - UICollectionReusableView *view = [supplementarySource viewForSupplementaryElementOfKind:kind atIndex:indexPath.item]; - IGAssert(view != nil, @"Returned a nil supplementary view at indexPath <%@> from section controller: <%@>, supplementary source: <%@>", indexPath, sectionController, supplementarySource); - - // associate the section controller with the cell so that we know which section controller is using it - [self mapView:view toSectionController:sectionController]; - - return view; -} - - -#pragma mark - UICollectionViewDelegate - -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - // forward this method to the delegate b/c this implementation will steal the message from the proxy - id collectionViewDelegate = self.collectionViewDelegate; - if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) { - [collectionViewDelegate collectionView:collectionView didSelectItemAtIndexPath:indexPath]; - } - - IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; - [sectionController didSelectItemAtIndex:indexPath.item]; -} - -- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { - // forward this method to the delegate b/c this implementation will steal the message from the proxy - id collectionViewDelegate = self.collectionViewDelegate; - if ([collectionViewDelegate respondsToSelector:@selector(collectionView:willDisplayCell:forItemAtIndexPath:)]) { - [collectionViewDelegate collectionView:collectionView willDisplayCell:cell forItemAtIndexPath:indexPath]; - } - - IGListSectionController *sectionController = [self sectionControllerForView:cell]; - // if the section controller relationship was destroyed, reconnect it - // this happens with iOS 10 UICollectionView display range changes - if (sectionController == nil) { - sectionController = [self sectionControllerForSection:indexPath.section]; - [self mapView:cell toSectionController:sectionController]; - } - - id object = [self.sectionMap objectForSection:indexPath.section]; - [self.displayHandler willDisplayCell:cell forListAdapter:self sectionController:sectionController object:object indexPath:indexPath]; - - _isSendingWorkingRangeDisplayUpdates = YES; - [self.workingRangeHandler willDisplayItemAtIndexPath:indexPath forListAdapter:self]; - _isSendingWorkingRangeDisplayUpdates = NO; -} - -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { - // forward this method to the delegate b/c this implementation will steal the message from the proxy - id collectionViewDelegate = self.collectionViewDelegate; - if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:)]) { - [collectionViewDelegate collectionView:collectionView didEndDisplayingCell:cell forItemAtIndexPath:indexPath]; +- (void)_deferBlockBetweenBatchUpdates:(void (^)(void))block { + IGAssertMainThread(); + if (_queuedCompletionBlocks == nil) { + block(); + } else { + [_queuedCompletionBlocks addObject:block]; } - - IGListSectionController *sectionController = [self sectionControllerForView:cell]; - [self.displayHandler didEndDisplayingCell:cell forListAdapter:self sectionController:sectionController indexPath:indexPath]; - [self.workingRangeHandler didEndDisplayingItemAtIndexPath:indexPath forListAdapter:self]; - - // break the association between the cell and the section controller - [self removeMapForView:cell]; } -- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { - id collectionViewDelegate = self.collectionViewDelegate; - if ([collectionViewDelegate respondsToSelector:@selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:)]) { - [collectionViewDelegate collectionView:collectionView willDisplaySupplementaryView:view forElementKind:elementKind atIndexPath:indexPath]; - } - - IGListSectionController *sectionController = [self sectionControllerForView:view]; - // if the section controller relationship was destroyed, reconnect it - // this happens with iOS 10 UICollectionView display range changes - if (sectionController == nil) { - sectionController = [self.sectionMap sectionControllerForSection:indexPath.section]; - [self mapView:view toSectionController:sectionController]; - } - - id object = [self.sectionMap objectForSection:indexPath.section]; - [self.displayHandler willDisplaySupplementaryView:view forListAdapter:self sectionController:sectionController object:object indexPath:indexPath]; +- (void)_enterBatchUpdates { + _queuedCompletionBlocks = [NSMutableArray new]; } -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { - id collectionViewDelegate = self.collectionViewDelegate; - if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:)]) { - [collectionViewDelegate collectionView:collectionView didEndDisplayingSupplementaryView:view forElementOfKind:elementKind atIndexPath:indexPath]; +- (void)_exitBatchUpdates { + NSArray *blocks = [_queuedCompletionBlocks copy]; + _queuedCompletionBlocks = nil; + for (void (^block)(void) in blocks) { + block(); } - - IGListSectionController *sectionController = [self sectionControllerForView:view]; - [self.displayHandler didEndDisplayingSupplementaryView:view forListAdapter:self sectionController:sectionController indexPath:indexPath]; - - [self removeMapForView:view]; } #pragma mark - UIScrollViewDelegate @@ -781,8 +790,8 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if ([scrollViewDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { [scrollViewDelegate scrollViewDidScroll:scrollView]; } - NSArray *> *visibleSectionControllers = [self visibleSectionControllers]; - for (IGListSectionController *sectionController in visibleSectionControllers) { + NSArray *visibleSectionControllers = [self visibleSectionControllers]; + for (IGListSectionController *sectionController in visibleSectionControllers) { [[sectionController scrollDelegate] listAdapter:self didScrollSectionController:sectionController]; } } @@ -793,8 +802,8 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { if ([scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { [scrollViewDelegate scrollViewWillBeginDragging:scrollView]; } - NSArray *> *visibleSectionControllers = [self visibleSectionControllers]; - for (IGListSectionController *sectionController in visibleSectionControllers) { + NSArray *visibleSectionControllers = [self visibleSectionControllers]; + for (IGListSectionController *sectionController in visibleSectionControllers) { [[sectionController scrollDelegate] listAdapter:self willBeginDraggingSectionController:sectionController]; } } @@ -805,37 +814,65 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL if ([scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) { [scrollViewDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; } - NSArray *> *visibleSectionControllers = [self visibleSectionControllers]; - for (IGListSectionController *sectionController in visibleSectionControllers) { + NSArray *visibleSectionControllers = [self visibleSectionControllers]; + for (IGListSectionController *sectionController in visibleSectionControllers) { [[sectionController scrollDelegate] listAdapter:self didEndDraggingSectionController:sectionController willDecelerate:decelerate]; } } +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id scrollViewDelegate = self.scrollViewDelegate; + if ([scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) { + [scrollViewDelegate scrollViewDidEndDecelerating:scrollView]; + } + NSArray *visibleSectionControllers = [self visibleSectionControllers]; + for (IGListSectionController *sectionController in visibleSectionControllers) { + id scrollDelegate = [sectionController scrollDelegate]; + if ([scrollDelegate respondsToSelector:@selector(listAdapter:didEndDeceleratingSectionController:)]) { + [scrollDelegate listAdapter:self didEndDeceleratingSectionController:sectionController]; + } + } +} #pragma mark - IGListCollectionContext - (CGSize)containerSize { - return UIEdgeInsetsInsetRect(self.collectionView.bounds, self.collectionView.contentInset).size; + return self.collectionView.bounds.size; +} + +- (UIEdgeInsets)containerInset { + return self.collectionView.contentInset; +} + +- (UIEdgeInsets)adjustedContainerInset { + return self.collectionView.ig_contentInset; } -- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController { +- (CGSize)insetContainerSize { + UICollectionView *collectionView = self.collectionView; + return UIEdgeInsetsInsetRect(collectionView.bounds, collectionView.ig_contentInset).size; +} + +- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController { const UIEdgeInsets inset = sectionController.inset; return CGSizeMake(self.containerSize.width - inset.left - inset.right, self.containerSize.height - inset.top - inset.bottom); } -- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(nonnull IGListSectionController *)sectionController { +- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(nonnull IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(cell != nil); IGParameterAssert(sectionController != nil); NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell]; - IGAssert(indexPath.section == [self sectionForSectionController:sectionController], + IGAssert(indexPath == nil + || indexPath.section == [self sectionForSectionController:sectionController], @"Requesting a cell from another section controller is not allowed."); return indexPath != nil ? indexPath.item : NSNotFound; } - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index - sectionController:(IGListSectionController *)sectionController { + sectionController:(IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(sectionController != nil); @@ -844,7 +881,7 @@ - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index return nil; } - NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; + NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:YES]; // prevent querying the collection view if it isn't fully reloaded yet for the current data set if (indexPath != nil && indexPath.section < [self.collectionView numberOfSections]) { @@ -858,7 +895,7 @@ - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index return nil; } -- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController { +- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController { NSMutableArray *cells = [NSMutableArray new]; UICollectionView *collectionView = self.collectionView; NSArray *visibleCells = [collectionView visibleCells]; @@ -871,7 +908,7 @@ - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index return cells; } -- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *) sectionController { +- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *) sectionController { NSMutableArray *paths = [NSMutableArray new]; UICollectionView *collectionView = self.collectionView; NSArray *visiblePaths = [collectionView indexPathsForVisibleItems]; @@ -885,7 +922,7 @@ - (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index } - (void)deselectItemAtIndex:(NSInteger)index - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController animated:(BOOL)animated { IGAssertMainThread(); IGParameterAssert(sectionController != nil); @@ -893,16 +930,27 @@ - (void)deselectItemAtIndex:(NSInteger)index [self.collectionView deselectItemAtIndexPath:indexPath animated:animated]; } +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition { + IGAssertMainThread(); + IGParameterAssert(sectionController != nil); + NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; + [self.collectionView selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; +} + - (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass - forSectionController:(IGListSectionController *)sectionController - atIndex:(NSInteger)index { + withReuseIdentifier:(NSString *)reuseIdentifier + forSectionController:(IGListSectionController *)sectionController + atIndex:(NSInteger)index { IGAssertMainThread(); IGParameterAssert(sectionController != nil); IGParameterAssert(cellClass != nil); IGParameterAssert(index >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Dequeueing cell of class %@ from section controller %@ without a collection view at index %zi", NSStringFromClass(cellClass), sectionController, index); - NSString *identifier = IGListReusableViewIdentifier(cellClass, nil, nil); + IGAssert(collectionView != nil, @"Dequeueing cell of class %@ with reuseIdentifier %@ from section controller %@ without a collection view at index %li", NSStringFromClass(cellClass), reuseIdentifier, sectionController, (long)index); + NSString *identifier = IGListReusableViewIdentifier(cellClass, nil, nil, reuseIdentifier); NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; if (![self.registeredCellClasses containsObject:cellClass]) { [self.registeredCellClasses addObject:cellClass]; @@ -911,8 +959,14 @@ - (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass return [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; } +- (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass + forSectionController:(IGListSectionController *)sectionController + atIndex:(NSInteger)index { + return [self dequeueReusableCellOfClass:cellClass withReuseIdentifier:nil forSectionController:sectionController atIndex:index]; +} + - (__kindof UICollectionViewCell *)dequeueReusableCellFromStoryboardWithIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { IGAssertMainThread(); IGParameterAssert(sectionController != nil); @@ -925,14 +979,14 @@ - (__kindof UICollectionViewCell *)dequeueReusableCellFromStoryboardWithIdentifi - (UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { IGAssertMainThread(); IGParameterAssert([nibName length] > 0); IGParameterAssert(sectionController != nil); IGParameterAssert(index >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Dequeueing cell with nib name %@ and bundle %@ from section controller %@ without a collection view at index %zi.", nibName, bundle, sectionController, index); + IGAssert(collectionView != nil, @"Dequeueing cell with nib name %@ and bundle %@ from section controller %@ without a collection view at index %li.", nibName, bundle, sectionController, (long)index); NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; if (![self.registeredNibNames containsObject:nibName]) { [self.registeredNibNames addObject:nibName]; @@ -943,7 +997,7 @@ - (UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName } - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController class:(Class)viewClass atIndex:(NSInteger)index { IGAssertMainThread(); @@ -952,8 +1006,8 @@ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(N IGParameterAssert(viewClass != nil); IGParameterAssert(index >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Dequeueing cell of class %@ from section controller %@ without a collection view at index %zi with supplementary view %@", NSStringFromClass(viewClass), sectionController, index, elementKind); - NSString *identifier = IGListReusableViewIdentifier(viewClass, nil, elementKind); + IGAssert(collectionView != nil, @"Dequeueing cell of class %@ from section controller %@ without a collection view at index %li with supplementary view %@", NSStringFromClass(viewClass), sectionController, (long)index, elementKind); + NSString *identifier = IGListReusableViewIdentifier(viewClass, nil, elementKind, nil); NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; if (![self.registeredSupplementaryViewIdentifiers containsObject:identifier]) { [self.registeredSupplementaryViewIdentifiers addObject:identifier]; @@ -964,7 +1018,7 @@ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(N - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewFromStoryboardOfKind:(NSString *)elementKind withIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { IGAssertMainThread(); IGParameterAssert(elementKind.length > 0); @@ -972,13 +1026,13 @@ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewFromStory IGParameterAssert(sectionController != nil); IGParameterAssert(index >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Dequeueing Supplementary View from storyboard of kind %@ with identifier %@ for section controller %@ without a collection view at index %zi", elementKind, identifier, sectionController, index); + IGAssert(collectionView != nil, @"Dequeueing Supplementary View from storyboard of kind %@ with identifier %@ for section controller %@ without a collection view at index %li", elementKind, identifier, sectionController, (long)index); NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; return [collectionView dequeueReusableSupplementaryViewOfKind:elementKind withReuseIdentifier:identifier forIndexPath:indexPath]; } - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController nibName:(NSString *)nibName bundle:(NSBundle *)bundle atIndex:(NSInteger)index { @@ -996,7 +1050,68 @@ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(N return [collectionView dequeueReusableSupplementaryViewOfKind:elementKind withReuseIdentifier:nibName forIndexPath:indexPath]; } -- (void)reloadInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { +- (void)performBatchAnimated:(BOOL)animated updates:(void (^)(id))updates completion:(void (^)(BOOL))completion { + IGAssertMainThread(); + IGParameterAssert(updates != nil); + UICollectionView *collectionView = self.collectionView; + IGAssert(collectionView != nil, @"Performing batch updates without a collection view."); + + [self _enterBatchUpdates]; + + __weak __typeof__(self) weakSelf = self; + [self.updater performUpdateWithCollectionView:collectionView animated:animated itemUpdates:^{ + weakSelf.isInUpdateBlock = YES; + // the adapter acts as the batch context with its API stripped to just the IGListBatchContext protocol + updates(weakSelf); + weakSelf.isInUpdateBlock = NO; + } completion: ^(BOOL finished) { + [weakSelf _updateBackgroundViewShouldHide:![weakSelf _itemCountIsZero]]; + [weakSelf _notifyDidUpdate:IGListAdapterUpdateTypeItemUpdates animated:animated]; + if (completion) { + completion(finished); + } + [weakSelf _exitBatchUpdates]; + }]; +} + +- (void)scrollToSectionController:(IGListSectionController *)sectionController + atIndex:(NSInteger)index + scrollPosition:(UICollectionViewScrollPosition)scrollPosition + animated:(BOOL)animated { + IGAssertMainThread(); + IGParameterAssert(sectionController != nil); + + NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; + [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; +} + +- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController + completion:(void (^)(BOOL finished))completion{ + const NSInteger section = [self sectionForSectionController:sectionController]; + const NSInteger items = [_collectionView numberOfItemsInSection:section]; + + NSMutableArray *indexPaths = [NSMutableArray new]; + for (NSInteger item = 0; item < items; item++) { + [indexPaths addObject:[NSIndexPath indexPathForItem:item inSection:section]]; + } + + UICollectionViewLayout *layout = _collectionView.collectionViewLayout; + UICollectionViewLayoutInvalidationContext *context = [[[layout.class invalidationContextClass] alloc] init]; + [context invalidateItemsAtIndexPaths:indexPaths]; + + __weak __typeof__(_collectionView) weakCollectionView = _collectionView; + + // do not call -[UICollectionView performBatchUpdates:completion:] while already updating. defer it until completed. + [self _deferBlockBetweenBatchUpdates:^{ + [weakCollectionView performBatchUpdates:^{ + [layout invalidateLayoutWithContext:context]; + } completion:completion]; + }]; +} + +#pragma mark - IGListBatchContext + +- (void)reloadInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { IGAssertMainThread(); IGParameterAssert(indexes != nil); IGParameterAssert(sectionController != nil); @@ -1007,33 +1122,34 @@ - (void)reloadInSectionController:(IGListSectionController *) return; } - if (self.isInUpdateBlock) { - /** - UICollectionView is not designed to support -reloadSections: or -reloadItemsAtIndexPaths: during batch updates. - Internally it appears to convert these operations to a delete+insert. However the transformation is too simple - in that it doesn't account for the item's section being moved (naturally or explicitly) and can queue animation - collisions. - - If you have an object at section 2 with 4 items and attempt to reload item at index 1, you would create an - NSIndexPath at section: 2, item: 1. Within -performBatchUpdates:, UICollectionView converts this to a delete - and insert at the same NSIndexPath. - - If a section were inserted at position 2, the original section 2 has naturally shifted to section 3. However, - the insert NSIndexPath is section: 2, item: 1. Now the UICollectionView has a section animation at section 2, - as well as an item insert animation at section: 2, item: 1, and it will throw an exception. - - IGListAdapter tracks the before/after mapping of section controllers to make precise NSIndexPath conversions. - */ - [self deleteInSectionController:sectionController atIndexes:indexes]; - [self insertInSectionController:sectionController atIndexes:indexes]; - } else { - NSArray *indexPaths = [self indexPathsFromSectionController:sectionController indexes:indexes usePreviousIfInUpdateBlock:YES]; - [self.updater reloadItemsInCollectionView:collectionView indexPaths:indexPaths]; - [self updateBackgroundViewShouldHide:![self itemCountIsZero]]; - } + /** + UICollectionView is not designed to support -reloadSections: or -reloadItemsAtIndexPaths: during batch updates. + Internally it appears to convert these operations to a delete+insert. However the transformation is too simple + in that it doesn't account for the item's section being moved (naturally or explicitly) and can queue animation + collisions. + + If you have an object at section 2 with 4 items and attempt to reload item at index 1, you would create an + NSIndexPath at section: 2, item: 1. Within -performBatchUpdates:, UICollectionView converts this to a delete + and insert at the same NSIndexPath. + + If a section were inserted at position 2, the original section 2 has naturally shifted to section 3. However, + the insert NSIndexPath is section: 2, item: 1. Now the UICollectionView has a section animation at section 2, + as well as an item insert animation at section: 2, item: 1, and it will throw an exception. + + IGListAdapter tracks the before/after mapping of section controllers to make precise NSIndexPath conversions. + */ + [indexes enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) { + NSIndexPath *fromIndexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:YES]; + NSIndexPath *toIndexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; + // index paths could be nil if a section controller is prematurely reloading or a reload was batched with + // the section controller being deleted + if (fromIndexPath != nil && toIndexPath != nil) { + [self.updater reloadItemInCollectionView:collectionView fromIndexPath:fromIndexPath toIndexPath:toIndexPath]; + } + }]; } -- (void)insertInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { +- (void)insertInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { IGAssertMainThread(); IGParameterAssert(indexes != nil); IGParameterAssert(sectionController != nil); @@ -1046,10 +1162,10 @@ - (void)insertInSectionController:(IGListSectionController *) NSArray *indexPaths = [self indexPathsFromSectionController:sectionController indexes:indexes usePreviousIfInUpdateBlock:NO]; [self.updater insertItemsIntoCollectionView:collectionView indexPaths:indexPaths]; - [self updateBackgroundViewShouldHide:![self itemCountIsZero]]; + [self _updateBackgroundViewShouldHide:![self _itemCountIsZero]]; } -- (void)deleteInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { +- (void)deleteInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { IGAssertMainThread(); IGParameterAssert(indexes != nil); IGParameterAssert(sectionController != nil); @@ -1062,17 +1178,17 @@ - (void)deleteInSectionController:(IGListSectionController *) NSArray *indexPaths = [self indexPathsFromSectionController:sectionController indexes:indexes usePreviousIfInUpdateBlock:YES]; [self.updater deleteItemsFromCollectionView:collectionView indexPaths:indexPaths]; - [self updateBackgroundViewShouldHide:![self itemCountIsZero]]; + [self _updateBackgroundViewShouldHide:![self _itemCountIsZero]]; } -- (void)moveInSectionController:(IGListSectionController *)sectionController fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { +- (void)moveInSectionController:(IGListSectionController *)sectionController fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { IGAssertMainThread(); IGParameterAssert(sectionController != nil); IGParameterAssert(fromIndex >= 0); IGParameterAssert(toIndex >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Moving items from %@ without a collection view from index %zi to index %zi.", - sectionController, fromIndex, toIndex); + IGAssert(collectionView != nil, @"Moving items from %@ without a collection view from index %li to index %li.", + sectionController, (long)fromIndex, (long)toIndex); NSIndexPath *fromIndexPath = [self indexPathForSectionController:sectionController index:fromIndex usePreviousIfInUpdateBlock:YES]; NSIndexPath *toIndexPath = [self indexPathForSectionController:sectionController index:toIndex usePreviousIfInUpdateBlock:NO]; @@ -1084,13 +1200,13 @@ - (void)moveInSectionController:(IGListSectionController *)se [self.updater moveItemInCollectionView:collectionView fromIndexPath:fromIndexPath toIndexPath:toIndexPath]; } -- (void)reloadSectionController:(IGListSectionController *)sectionController { +- (void)reloadSectionController:(IGListSectionController *)sectionController { IGAssertMainThread(); IGParameterAssert(sectionController != nil); UICollectionView *collectionView = self.collectionView; IGAssert(collectionView != nil, @"Reloading items from %@ without a collection view.", sectionController); - IGListSectionMap *map = [self sectionMapUsingPreviousIfInUpdateBlock:YES]; + IGListSectionMap *map = [self _sectionMapUsingPreviousIfInUpdateBlock:YES]; const NSInteger section = [map sectionForSectionController:sectionController]; if (section == NSNotFound) { return; @@ -1098,92 +1214,73 @@ - (void)reloadSectionController:(IGListSectionController *)s NSIndexSet *sections = [NSIndexSet indexSetWithIndex:section]; [self.updater reloadCollectionView:collectionView sections:sections]; - [self updateBackgroundViewShouldHide:![self itemCountIsZero]]; + [self _updateBackgroundViewShouldHide:![self _itemCountIsZero]]; } -- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion { +- (void)moveSectionControllerInteractive:(IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0) { IGAssertMainThread(); - IGParameterAssert(updates != nil); + IGParameterAssert(sectionController != nil); + IGParameterAssert(fromIndex >= 0); + IGParameterAssert(toIndex >= 0); UICollectionView *collectionView = self.collectionView; - IGAssert(collectionView != nil, @"Performing batch updates without a collection view."); + IGAssert(collectionView != nil, @"Moving section %@ without a collection view from index %li to index %li.", + sectionController, (long)fromIndex, (long)toIndex); + IGAssert(self.moveDelegate != nil, @"Moving section %@ without a moveDelegate set", sectionController); + + if (fromIndex != toIndex) { + id dataSource = self.dataSource; - __weak __typeof__(self) weakSelf = self; - [self.updater performUpdateWithCollectionView:collectionView animated:animated itemUpdates:^{ - weakSelf.isInUpdateBlock = YES; - updates(); - weakSelf.isInUpdateBlock = NO; - } completion: ^(BOOL finished) { - [weakSelf updateBackgroundViewShouldHide:![weakSelf itemCountIsZero]]; - if (completion) { - completion(finished); - } - }]; -} + NSArray *previousObjects = [self.sectionMap objects]; -- (void)scrollToSectionController:(IGListSectionController *)sectionController - atIndex:(NSInteger)index - scrollPosition:(UICollectionViewScrollPosition)scrollPosition - animated:(BOOL)animated { - IGAssertMainThread(); - IGParameterAssert(sectionController != nil); + if (self.isLastInteractiveMoveToLastSectionIndex) { + self.isLastInteractiveMoveToLastSectionIndex = NO; + } + else if (fromIndex < toIndex) { + toIndex -= 1; + } - NSIndexPath *indexPath = [self indexPathForSectionController:sectionController index:index usePreviousIfInUpdateBlock:NO]; - [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; -} + NSMutableArray *mutObjects = [previousObjects mutableCopy]; + id object = [previousObjects objectAtIndex:fromIndex]; + [mutObjects removeObjectAtIndex:fromIndex]; + [mutObjects insertObject:object atIndex:toIndex]; -- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController - completion:(void (^)(BOOL finished))completion{ - const NSInteger section = [self sectionForSectionController:sectionController]; - const NSInteger items = [_collectionView numberOfItemsInSection:section]; + NSArray *objects = [mutObjects copy]; - NSMutableArray *indexPaths = [NSMutableArray new]; - for (NSInteger item = 0; item < items; item++) { - [indexPaths addObject:[NSIndexPath indexPathForItem:item inSection:section]]; + // inform the data source to update its model + [self.moveDelegate listAdapter:self moveObject:object from:previousObjects to:objects]; + + // update our model based on that provided by the data source + NSArray> *updatedObjects = [dataSource objectsForListAdapter:self]; + [self _updateObjects:updatedObjects dataSource:dataSource]; } - - UICollectionViewLayout *layout = _collectionView.collectionViewLayout; - UICollectionViewLayoutInvalidationContext *context = [[[layout.class invalidationContextClass] alloc] init]; - [context invalidateItemsAtIndexPaths:indexPaths]; - - void (^block)() = ^{ - [layout invalidateLayoutWithContext:context]; - }; - - [_collectionView performBatchUpdates:block completion:completion]; -} - -#pragma mark - UICollectionViewDelegateFlowLayout - -- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - return [self sizeForItemAtIndexPath:indexPath]; -} - -- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - return [[self sectionControllerForSection:section] inset]; -} - -- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - return [[self sectionControllerForSection:section] minimumLineSpacing]; -} - -- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - return [[self sectionControllerForSection:section] minimumInteritemSpacing]; + + // even if from and to index are equal, we need to perform the "move" + // iOS interactively moves items, not sections, so we might have actually moved the item + // to the end of the preceeding section or beginning of the following section + [self.updater moveSectionInCollectionView:collectionView fromIndex:fromIndex toIndex:toIndex]; } - -- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section]; - return [self sizeForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; + +- (void)moveInSectionControllerInteractive:(IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0) { + IGAssertMainThread(); + IGParameterAssert(sectionController != nil); + IGParameterAssert(fromIndex >= 0); + IGParameterAssert(toIndex >= 0); + + [sectionController moveObjectFromIndex:fromIndex toIndex:toIndex]; } -- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { - IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section]; - return [self sizeForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:indexPath]; +- (void)revertInvalidInteractiveMoveFromIndexPath:(NSIndexPath *)sourceIndexPath + toIndexPath:(NSIndexPath *)destinationIndexPath NS_AVAILABLE_IOS(9_0) { + UICollectionView *collectionView = self.collectionView; + IGAssert(collectionView != nil, @"Reverting move without a collection view from %@ to %@.", + sourceIndexPath, destinationIndexPath); + + // revert by moving back in the opposite direction + [collectionView moveItemAtIndexPath:destinationIndexPath toIndexPath:sourceIndexPath]; } - + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDataSource.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDataSource.h index f45ca43..0d44134 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDataSource.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDataSource.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,13 +12,12 @@ @class IGListAdapter; @class IGListSectionController; -@protocol IGListSectionType; - NS_ASSUME_NONNULL_BEGIN /** Implement this protocol to provide data to an `IGListAdapter`. */ +NS_SWIFT_NAME(ListAdapterDataSource) @protocol IGListAdapterDataSource /** @@ -36,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN Asks the data source for a section controller for the specified object in the list. @param listAdapter The list adapter requesting this information. - @param object An object in the list. + @param object An object in the list. @return A new section controller instance that can be displayed in the list. @@ -45,9 +42,9 @@ NS_ASSUME_NONNULL_BEGIN Section controllers are initialized for all objects whenever the `IGListAdapter` is created, updated, or reloaded. Section controllers are reused when objects are moved or updated. Maintaining the `-[IGListDiffable diffIdentifier]` - guarentees this. + guarantees this. */ -- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object; +- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object; /** Asks the data source for a view to use as the collection view background when the list is empty. diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDelegate.h index b141c9f..c07acd5 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterDelegate.h @@ -1,16 +1,16 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @class IGListAdapter; +NS_ASSUME_NONNULL_BEGIN + /** Conform to `IGListAdapterDelegate` to receive display events for objects in a list. */ @@ -20,8 +20,8 @@ Notifies the delegate that a list object is about to be displayed. @param listAdapter The list adapter sending this information. - @param object The object that will display. - @param index The index of the object in the list. + @param object The object that will display. + @param index The index of the object in the list. */ - (void)listAdapter:(IGListAdapter *)listAdapter willDisplayObject:(id)object atIndex:(NSInteger)index; @@ -29,9 +29,11 @@ Notifies the delegate that a list object is no longer being displayed. @param listAdapter The list adapter sending this information. - @param object The object that ended display. - @param index The index of the object in the list. + @param object The object that ended display. + @param index The index of the object in the list. */ - (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingObject:(id)object atIndex:(NSInteger)index; @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterMoveDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterMoveDelegate.h new file mode 100644 index 0000000..e7b2b7e --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterMoveDelegate.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class IGListAdapter; + +NS_ASSUME_NONNULL_BEGIN + +/** + Conform to `IGListAdapterMoveDelegate` to receive interactive reordering requests. + */ +NS_SWIFT_NAME(ListAdapterMoveDelegate) +@protocol IGListAdapterMoveDelegate + +/** + Asks the delegate to move a section object as the result of interactive reordering. + + @param listAdapter The list adapter sending this information. + @param object the object that was moved + @param previousObjects The array of objects prior to the move. + @param objects The array of objects after the move. + */ +- (void)listAdapter:(IGListAdapter *)listAdapter + moveObject:(id)object + from:(NSArray *)previousObjects + to:(NSArray *)objects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdateListener.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdateListener.h new file mode 100644 index 0000000..14f7604 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdateListener.h @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class IGListAdapter; + +NS_ASSUME_NONNULL_BEGIN + +/** + The type of update that was performed by an `IGListAdapter`. + */ +NS_SWIFT_NAME(ListAdapterUpdateType) +typedef NS_ENUM(NSInteger, IGListAdapterUpdateType) { + /** + `-[IGListAdapter performUpdatesAnimated:completion:]` was executed. + */ + IGListAdapterUpdateTypePerformUpdates, + /** + `-[IGListAdapter reloadDataWithCompletion:]` was executed. + */ + IGListAdapterUpdateTypeReloadData, + /** + `-[IGListCollectionContext performBatchAnimated:updates:completion:]` was executed by an `IGListSectionController`. + */ + IGListAdapterUpdateTypeItemUpdates, +}; + +/** + Conform to this protocol to receive events about `IGListAdapter` updates. + */ +NS_SWIFT_NAME(ListAdapterUpdateListener) +@protocol IGListAdapterUpdateListener + +/** + Notifies a listener that the listAdapter was updated. + + @param listAdapter The `IGListAdapter` that updated. + @param update The type of update executed. + @param animated A flag indicating if the update was animated. Always `NO` for `IGListAdapterUpdateTypeReloadData`. + + @note This event is sent before the completion block in `-[IGListAdapter performUpdatesAnimated:completion:]` and + `-[IGListAdapter reloadDataWithCompletion:]` is executed. This event is also delivered when an + `IGListSectionController` updates via `-[IGListCollectionContext performBatchAnimated:updates:completion:]`. + */ +- (void)listAdapter:(IGListAdapter *)listAdapter + didFinishUpdate:(IGListAdapterUpdateType)update + animated:(BOOL)animated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.h index 7ae34fa..7abc955 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -18,13 +16,14 @@ NS_ASSUME_NONNULL_BEGIN /** An `IGListAdapterUpdater` is a concrete type that conforms to `IGListUpdatingDelegate`. - It is an out-of-box upater for `IGListAdapter` objects to use. + It is an out-of-box updater for `IGListAdapter` objects to use. @note This updater performs re-entrant, coalesced updating for a list. It also uses a least-minimal diff for calculating UI updates when `IGListAdapter` calls `-performUpdateWithCollectionView:fromObjects:toObjects:completion:`. */ IGLK_SUBCLASSING_RESTRICTED +NS_SWIFT_NAME(ListAdapterUpdater) @interface IGListAdapterUpdater : NSObject /** @@ -48,6 +47,11 @@ IGLK_SUBCLASSING_RESTRICTED */ @property (nonatomic, assign) BOOL allowsBackgroundReloading; +/** + Time, in seconds, to wait and coalesce batch updates. Default is 0. + */ +@property (nonatomic, assign) NSTimeInterval coalescanceTime; + /** A bitmask of experiments to conduct on the updater. */ diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.m index 4c4d6cc..1ea295f 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdater.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListAdapterUpdater.h" @@ -13,9 +11,12 @@ #import #import #import +#import +#import #import "UICollectionView+IGListBatchUpdateData.h" -#import "IGListMoveIndexPathInternal.h" +#import "IGListReloadIndexPath.h" +#import "IGListArrayUtilsInternal.h" @implementation IGListAdapterUpdater @@ -32,14 +33,13 @@ - (instancetype)init { return self; } - #pragma mark - Private API - (BOOL)hasChanges { return self.hasQueuedReloadData || [self.batchUpdates hasChanges] || self.fromObjects != nil - || self.toObjects != nil; + || self.toObjectsBlock != nil; } - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView { @@ -51,10 +51,10 @@ - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView { } id delegate = self.delegate; - void (^reloadUpdates)() = self.reloadUpdates; + void (^reloadUpdates)(void) = self.reloadUpdates; IGListBatchUpdates *batchUpdates = self.batchUpdates; NSMutableArray *completionBlocks = [self.completionBlocks mutableCopy]; - + [self cleanStateBeforeUpdates]; // item updates must not send mutations to the collection view while we are reloading @@ -65,19 +65,19 @@ - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView { } // execute all stored item update blocks even if we are just calling reloadData. the actual collection view - // mutations will be discarded, but clients are encouraged to put their actually /data/ mutations inside the + // mutations will be discarded, but clients are encouraged to put their actual /data/ mutations inside the // update block as well, so if we don't execute the block the changes will never happen for (IGListItemUpdateBlock itemUpdateBlock in batchUpdates.itemUpdateBlocks) { itemUpdateBlock(); } - + // add any completion blocks from item updates. added after item blocks are executed in order to capture any // re-entrant updates [completionBlocks addObjectsFromArray:batchUpdates.itemCompletionBlocks]; - + self.state = IGListBatchUpdateStateExecutedBatchUpdateBlock; - [self cleanStateAfterUpdates]; + [self _cleanStateAfterUpdates]; [delegate listAdapterUpdater:self willReloadDataWithCollectionView:collectionView]; [collectionView reloadData]; @@ -92,21 +92,6 @@ - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView { self.state = IGListBatchUpdateStateIdle; } -static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray> *objects) { - NSMutableSet *identifiers = [NSMutableSet new]; - NSMutableArray *uniqueObjects = [NSMutableArray new]; - for (id object in objects) { - id diffIdentifier = [object diffIdentifier]; - if (![identifiers containsObject:diffIdentifier]) { - [identifiers addObject:diffIdentifier]; - [uniqueObjects addObject:object]; - } else { - IGLKLog(@"WARNING: Object %@ already appeared in objects array", object); - } - } - return uniqueObjects; -} - - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView { IGAssertMainThread(); IGAssert(self.state == IGListBatchUpdateStateIdle, @"Should not call batch updates when state isn't idle"); @@ -119,16 +104,29 @@ - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView // create local variables so we can immediately clean our state but pass these items into the batch update block id delegate = self.delegate; NSArray *fromObjects = [self.fromObjects copy]; - NSArray *toObjects = objectsWithDuplicateIdentifiersRemoved(self.toObjects); + IGListToObjectBlock toObjectsBlock = [self.toObjectsBlock copy]; NSMutableArray *completionBlocks = [self.completionBlocks mutableCopy]; void (^objectTransitionBlock)(NSArray *) = [self.objectTransitionBlock copy]; const BOOL animated = self.queuedUpdateIsAnimated; IGListBatchUpdates *batchUpdates = self.batchUpdates; + NSArray *toObjects = nil; + if (toObjectsBlock != nil) { + toObjects = objectsWithDuplicateIdentifiersRemoved(toObjectsBlock()); + } +#ifdef DEBUG + for (id obj in toObjects) { + IGAssert([obj conformsToProtocol:@protocol(IGListDiffable)], + @"In order to use IGListAdapterUpdater, object %@ must conform to IGListDiffable", obj); + IGAssert([obj diffIdentifier] != nil, + @"Cannot have a nil diffIdentifier for object %@", obj); + } +#endif + // clean up all state so that new updates can be coalesced while the current update is in flight [self cleanStateBeforeUpdates]; - void (^executeUpdateBlocks)() = ^{ + void (^executeUpdateBlocks)(void) = ^{ self.state = IGListBatchUpdateStateExecutingBatchUpdateBlock; // run the update block so that the adapter can set its items. this makes sure that just before the update is @@ -144,7 +142,7 @@ - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView for (IGListItemUpdateBlock itemUpdateBlock in batchUpdates.itemUpdateBlocks) { itemUpdateBlock(); } - + // add any completion blocks from item updates. added after item blocks are executed in order to capture any // re-entrant updates [completionBlocks addObjectsFromArray:batchUpdates.itemCompletionBlocks]; @@ -153,6 +151,7 @@ - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView }; void (^executeCompletionBlocks)(BOOL) = ^(BOOL finished) { + self.applyingUpdateData = nil; self.state = IGListBatchUpdateStateIdle; for (IGListUpdatingCompletion block in completionBlocks) { @@ -160,64 +159,100 @@ - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView } }; + void (^reloadDataFallback)(void) = ^{ + executeUpdateBlocks(); + [self _cleanStateAfterUpdates]; + [self _performBatchUpdatesItemBlockApplied]; + [collectionView reloadData]; + [collectionView layoutIfNeeded]; + executeCompletionBlocks(YES); + }; + // if the collection view isn't in a visible window, skip diffing and batch updating. execute all transition blocks, // reload data, execute completion blocks, and get outta here const BOOL iOS83OrLater = (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_8_3); if (iOS83OrLater && self.allowsBackgroundReloading && collectionView.window == nil) { - [self beginPerformBatchUpdatesToObjects:toObjects]; - executeUpdateBlocks(); - [self cleanStateAfterUpdates]; - [self performBatchUpdatesItemBlockApplied]; - [collectionView reloadData]; - executeCompletionBlocks(YES); + [self _beginPerformBatchUpdatesToObjects:toObjects]; + reloadDataFallback(); return; } - IGListIndexSetResult *result = IGListDiffExperiment(fromObjects, toObjects, IGListDiffEquality, self.experiments); - - // set the update data inside the update block. capture outside its scope to reference if an exception is thrown - __block IGListBatchUpdateData *updateData = nil; + // disables multiple performBatchUpdates: from happening at the same time + [self _beginPerformBatchUpdatesToObjects:toObjects]; + + const IGListExperiment experiments = self.experiments; - void (^updateBlock)() = ^{ + IGListIndexSetResult *(^performDiff)(void) = ^{ + return IGListDiffExperiment(fromObjects, toObjects, IGListDiffEquality, experiments); + }; + + // block executed in the first param block of -[UICollectionView performBatchUpdates:completion:] + void (^batchUpdatesBlock)(IGListIndexSetResult *result) = ^(IGListIndexSetResult *result){ executeUpdateBlocks(); - updateData = [self flushCollectionView:collectionView - withDiffResult:result - batchUpdates:self.batchUpdates - fromObjects:fromObjects]; + self.applyingUpdateData = [self _flushCollectionView:collectionView + withDiffResult:result + batchUpdates:self.batchUpdates + fromObjects:fromObjects]; - [self cleanStateAfterUpdates]; - [self performBatchUpdatesItemBlockApplied]; + [self _cleanStateAfterUpdates]; + [self _performBatchUpdatesItemBlockApplied]; }; - void (^completionBlock)(BOOL) = ^(BOOL finished) { + // block used as the second param of -[UICollectionView performBatchUpdates:completion:] + void (^batchUpdatesCompletionBlock)(BOOL) = ^(BOOL finished) { + IGListBatchUpdateData *oldApplyingUpdateData = self.applyingUpdateData; executeCompletionBlocks(finished); - [delegate listAdapterUpdater:self didPerformBatchUpdates:updateData collectionView:collectionView]; + [delegate listAdapterUpdater:self didPerformBatchUpdates:oldApplyingUpdateData collectionView:collectionView]; // queue another update in case something changed during batch updates. this method will bail next runloop if // there are no changes - [self queueUpdateWithCollectionView:collectionView]; + [self _queueUpdateWithCollectionView:collectionView]; }; - // disables multiple performBatchUpdates: from happening at the same time - [self beginPerformBatchUpdatesToObjects:toObjects]; - - @try { - [delegate listAdapterUpdater:self willPerformBatchUpdatesWithCollectionView:collectionView]; - if (animated) { - [collectionView performBatchUpdates:updateBlock completion:completionBlock]; - } else { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - [collectionView performBatchUpdates:updateBlock completion:^(BOOL finished) { - completionBlock(finished); - [CATransaction commit]; - }]; + // block that executes the batch update and exception handling + void (^performUpdate)(IGListIndexSetResult *) = ^(IGListIndexSetResult *result){ + @try { + [delegate listAdapterUpdater:self willPerformBatchUpdatesWithCollectionView:collectionView]; + if (result.changeCount > 100 && IGListExperimentEnabled(experiments, IGListExperimentReloadDataFallback)) { + reloadDataFallback(); + } else if (animated) { + [collectionView performBatchUpdates:^{ + batchUpdatesBlock(result); + } completion:batchUpdatesCompletionBlock]; + } else { + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [collectionView performBatchUpdates:^{ + batchUpdatesBlock(result); + } completion:^(BOOL finished) { + [CATransaction commit]; + batchUpdatesCompletionBlock(finished); + }]; + } + } @catch (NSException *exception) { + [delegate listAdapterUpdater:self + collectionView:collectionView + willCrashWithException:exception + fromObjects:fromObjects + toObjects:toObjects + updates:(id)self.applyingUpdateData]; + @throw exception; } - } @catch (NSException *exception) { - [delegate listAdapterUpdater:self willCrashWithException:exception fromObjects:fromObjects toObjects:toObjects updates:updateData]; - @throw exception; + }; + + // temporary test to try out background diffing + if (IGListExperimentEnabled(experiments, IGListExperimentBackgroundDiffing)) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + IGListIndexSetResult *result = performDiff(); + dispatch_async(dispatch_get_main_queue(), ^{ + performUpdate(result); + }); + }); + } else { + IGListIndexSetResult *result = performDiff(); + performUpdate(result); } } @@ -241,13 +276,13 @@ void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, [inserts addIndex:to]; } else { IGAssert([result.deletes containsIndex:idx], - @"Reloaded section %zi was not found in deletes with from: %zi, to: %zi, deletes: %@", - idx, from, to, deletes); + @"Reloaded section %lu was not found in deletes with from: %li, to: %li, deletes: %@, fromClass: %@", + (unsigned long)idx, (long)from, (long)to, deletes, [(id)fromObjects[idx] class]); } }]; } -- (IGListBatchUpdateData *)flushCollectionView:(UICollectionView *)collectionView +- (IGListBatchUpdateData *)_flushCollectionView:(UICollectionView *)collectionView withDiffResult:(IGListIndexSetResult *)diffResult batchUpdates:(IGListBatchUpdates *)batchUpdates fromObjects:(NSArray > *)fromObjects { @@ -271,23 +306,43 @@ - (IGListBatchUpdateData *)flushCollectionView:(UICollectionView *)collectionVie // reloadSections: is unsafe to use within performBatchUpdates:, so instead convert all reloads into deletes+inserts convertReloadToDeleteInsert(reloads, deletes, inserts, diffResult, fromObjects); + NSMutableArray *itemInserts = batchUpdates.itemInserts; + NSMutableArray *itemDeletes = batchUpdates.itemDeletes; + NSMutableArray *itemMoves = batchUpdates.itemMoves; + + NSSet *uniqueDeletes = [NSSet setWithArray:itemDeletes]; + NSMutableSet *reloadDeletePaths = [NSMutableSet new]; + NSMutableSet *reloadInsertPaths = [NSMutableSet new]; + for (IGListReloadIndexPath *reload in batchUpdates.itemReloads) { + if (![uniqueDeletes containsObject:reload.fromIndexPath]) { + [reloadDeletePaths addObject:reload.fromIndexPath]; + [reloadInsertPaths addObject:reload.toIndexPath]; + } + } + [itemDeletes addObjectsFromArray:[reloadDeletePaths allObjects]]; + [itemInserts addObjectsFromArray:[reloadInsertPaths allObjects]]; + + if (IGListExperimentEnabled(self.experiments, IGListExperimentDedupeItemUpdates)) { + itemDeletes = [[[NSSet setWithArray:itemDeletes] allObjects] mutableCopy]; + itemInserts = [[[NSSet setWithArray:itemInserts] allObjects] mutableCopy]; + } + IGListBatchUpdateData *updateData = [[IGListBatchUpdateData alloc] initWithInsertSections:inserts deleteSections:deletes moveSections:moves - insertIndexPaths:batchUpdates.itemInserts - deleteIndexPaths:batchUpdates.itemDeletes - moveIndexPaths:batchUpdates.itemMoves - reloadIndexPaths:batchUpdates.itemReloads]; + insertIndexPaths:itemInserts + deleteIndexPaths:itemDeletes + moveIndexPaths:itemMoves]; [collectionView ig_applyBatchUpdateData:updateData]; return updateData; } -- (void)beginPerformBatchUpdatesToObjects:(NSArray *)toObjects { +- (void)_beginPerformBatchUpdatesToObjects:(NSArray *)toObjects { self.pendingTransitionToObjects = toObjects; self.state = IGListBatchUpdateStateQueuedBatchUpdate; } -- (void)performBatchUpdatesItemBlockApplied { +- (void)_performBatchUpdatesItemBlockApplied { self.pendingTransitionToObjects = nil; } @@ -296,7 +351,7 @@ - (void)cleanStateBeforeUpdates { // destroy to/from transition items self.fromObjects = nil; - self.toObjects = nil; + self.toObjectsBlock = nil; // destroy reloadData state self.reloadUpdates = nil; @@ -304,17 +359,17 @@ - (void)cleanStateBeforeUpdates { // remove indexpath/item changes self.objectTransitionBlock = nil; - - // removes all object completion blocks. done before updates to start collecting completion blocks for coaslesced + + // removes all object completion blocks. done before updates to start collecting completion blocks for coalesced // or re-entrant object updates [self.completionBlocks removeAllObjects]; } -- (void)cleanStateAfterUpdates { +- (void)_cleanStateAfterUpdates { self.batchUpdates = [IGListBatchUpdates new]; } -- (void)queueUpdateWithCollectionView:(UICollectionView *)collectionView { +- (void)_queueUpdateWithCollectionView:(UICollectionView *)collectionView { IGAssertMainThread(); // callers may hold weak refs and lose the collection view by the time we requeue, bail if that's the case @@ -323,16 +378,19 @@ - (void)queueUpdateWithCollectionView:(UICollectionView *)collectionView { } __weak __typeof__(self) weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ + __weak __typeof__(collectionView) weakCollectionView = collectionView; + + // dispatch after a given amount of time to coalesce other updates and execute as one + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, self.coalescanceTime * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ if (weakSelf.state != IGListBatchUpdateStateIdle || ![weakSelf hasChanges]) { return; } if (weakSelf.hasQueuedReloadData) { - [weakSelf performReloadDataWithCollectionView:collectionView]; + [weakSelf performReloadDataWithCollectionView:weakCollectionView]; } else { - [weakSelf performBatchUpdatesWithCollectionView:collectionView]; + [weakSelf performBatchUpdatesWithCollectionView:weakCollectionView]; } }); } @@ -341,9 +399,10 @@ - (void)queueUpdateWithCollectionView:(UICollectionView *)collectionView { #pragma mark - IGListUpdatingDelegate static BOOL IGListIsEqual(const void *a, const void *b, NSUInteger (*size)(const void *item)) { - const id left = (__bridge id)a; - const id right = (__bridge id)b; - return [[left diffIdentifier] isEqual:[right diffIdentifier]]; + const id left = (__bridge id)a; + const id right = (__bridge id)b; + return [left class] == [right class] + && [[left diffIdentifier] isEqual:[right diffIdentifier]]; } // since the diffing algo used in this updater keys items based on their -diffIdentifier, we must use a map table that @@ -360,11 +419,11 @@ - (NSPointerFunctions *)objectLookupPointerFunctions { } - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView - fromObjects:(nullable NSArray *)fromObjects - toObjects:(nullable NSArray *)toObjects + fromObjects:(NSArray *)fromObjects + toObjectsBlock:(IGListToObjectBlock)toObjectsBlock animated:(BOOL)animated - objectTransitionBlock:(void (^)(NSArray *))objectTransitionBlock - completion:(nullable void (^)(BOOL))completion { + objectTransitionBlock:(IGListObjectTransitionBlock)objectTransitionBlock + completion:(IGListUpdatingCompletion)completion { IGAssertMainThread(); IGParameterAssert(collectionView != nil); IGParameterAssert(objectTransitionBlock != nil); @@ -375,19 +434,12 @@ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView // if performBatchUpdates: hasn't applied the update block, then data source hasn't transitioned its state. if an // update is queued in between then we must use the pending toObjects self.fromObjects = self.fromObjects ?: self.pendingTransitionToObjects ?: fromObjects; - self.toObjects = toObjects; + self.toObjectsBlock = toObjectsBlock; // disabled animations will always take priority // reset to YES in -cleanupState self.queuedUpdateIsAnimated = self.queuedUpdateIsAnimated && animated; -#ifdef DEBUG - for (id obj in toObjects) { - IGAssert([obj conformsToProtocol:@protocol(IGListDiffable)], - @"In order to use IGListAdapterUpdater, object %@ must conform to IGListDiffable", obj); - } -#endif - // always use the last update block, even though this should always do the exact same thing self.objectTransitionBlock = objectTransitionBlock; @@ -396,17 +448,17 @@ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView [self.completionBlocks addObject:localCompletion]; } - [self queueUpdateWithCollectionView:collectionView]; + [self _queueUpdateWithCollectionView:collectionView]; } - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView animated:(BOOL)animated - itemUpdates:(void (^)())itemUpdates + itemUpdates:(void (^)(void))itemUpdates completion:(void (^)(BOOL))completion { IGAssertMainThread(); IGParameterAssert(collectionView != nil); IGParameterAssert(itemUpdates != nil); - + IGListBatchUpdates *batchUpdates = self.batchUpdates; if (completion != nil) { [batchUpdates.itemCompletionBlocks addObject:completion]; @@ -418,12 +470,12 @@ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView itemUpdates(); } else { [batchUpdates.itemUpdateBlocks addObject:itemUpdates]; - + // disabled animations will always take priority // reset to YES in -cleanupState self.queuedUpdateIsAnimated = self.queuedUpdateIsAnimated && animated; - - [self queueUpdateWithCollectionView:collectionView]; + + [self _queueUpdateWithCollectionView:collectionView]; } } @@ -463,17 +515,56 @@ - (void)moveItemInCollectionView:(UICollectionView *)collectionView } } -- (void)reloadItemsInCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths { - IGAssertMainThread(); - IGParameterAssert(collectionView != nil); - IGParameterAssert(indexPaths != nil); +- (void)reloadItemInCollectionView:(UICollectionView *)collectionView + fromIndexPath:(NSIndexPath *)fromIndexPath + toIndexPath:(NSIndexPath *)toIndexPath { if (self.state == IGListBatchUpdateStateExecutingBatchUpdateBlock) { - [self.batchUpdates.itemReloads addObjectsFromArray:indexPaths]; + IGListReloadIndexPath *reload = [[IGListReloadIndexPath alloc] initWithFromIndexPath:fromIndexPath toIndexPath:toIndexPath]; + [self.batchUpdates.itemReloads addObject:reload]; } else { - [self.delegate listAdapterUpdater:self willReloadIndexPaths:indexPaths collectionView:collectionView]; - [collectionView reloadItemsAtIndexPaths:indexPaths]; + [collectionView reloadItemsAtIndexPaths:@[fromIndexPath]]; } } + +- (void)moveSectionInCollectionView:(UICollectionView *)collectionView + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex { + IGAssertMainThread(); + IGParameterAssert(collectionView != nil); + + // iOS expects interactive reordering to be movement of items not sections + // after moving a single-item section controller, + // you end up with two items in the section for the drop location, + // and zero items in the section originating at the drag location + // so, we have to reload data rather than doing a section move + + [collectionView reloadData]; + + // It seems that reloadData called during UICollectionView's moveItemAtIndexPath + // delegate call does not reload all cells as intended + // So, we further reload all visible sections to make sure none of our cells + // are left with data that's out of sync with our dataSource + + id delegate = self.delegate; + + NSMutableIndexSet *visibleSections = [NSMutableIndexSet new]; + NSArray *visibleIndexPaths = [collectionView indexPathsForVisibleItems]; + for (NSIndexPath *visibleIndexPath in visibleIndexPaths) { + [visibleSections addIndex:visibleIndexPath.section]; + } + + [delegate listAdapterUpdater:self willReloadSections:visibleSections collectionView:collectionView]; + + // prevent double-animation from reloadData + reloadSections + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + [collectionView performBatchUpdates:^{ + [collectionView reloadSections:visibleSections]; + } completion:^(BOOL finished) { + [CATransaction commit]; + }]; +} - (void)reloadDataWithCollectionView:(UICollectionView *)collectionView reloadUpdateBlock:(IGListReloadUpdateBlock)reloadUpdateBlock @@ -489,7 +580,7 @@ - (void)reloadDataWithCollectionView:(UICollectionView *)collectionView self.reloadUpdates = reloadUpdateBlock; self.queuedReloadData = YES; - [self queueUpdateWithCollectionView:collectionView]; + [self _queueUpdateWithCollectionView:collectionView]; } - (void)reloadCollectionView:(UICollectionView *)collectionView sections:(NSIndexSet *)sections { @@ -505,3 +596,4 @@ - (void)reloadCollectionView:(UICollectionView *)collectionView sections:(NSInde } @end + diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdaterDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdaterDelegate.h index 4acea98..bd88f72 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdaterDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListAdapterUpdaterDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -18,22 +16,23 @@ NS_ASSUME_NONNULL_BEGIN /** A protocol that receives events about `IGListAdapterUpdater` operations. */ +NS_SWIFT_NAME(ListAdapterUpdaterDelegate) @protocol IGListAdapterUpdaterDelegate /** Notifies the delegate that the updater will call `-[UICollectionView performBatchUpdates:completion:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param collectionView The collection view that will perform the batch updates. + @param collectionView The collection view that will perform the batch updates. */ - (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView; /** - Notifies the delegate that the updater succesfully finished `-[UICollectionView performBatchUpdates:completion:]`. + Notifies the delegate that the updater successfully finished `-[UICollectionView performBatchUpdates:completion:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param updates The batch updates that were applied to the collection view. - @param collectionView The collection view that performed the batch updates. + @param updates The batch updates that were applied to the collection view. + @param collectionView The collection view that performed the batch updates. @note This event is called in the completion block of the batch update. */ @@ -45,8 +44,8 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView insertItemsAtIndexPaths:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param indexPaths An array of index paths that will be inserted. - @param collectionView The collection view that will perform the insert. + @param indexPaths An array of index paths that will be inserted. + @param collectionView The collection view that will perform the insert. @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ @@ -58,8 +57,8 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView deleteItemsAtIndexPaths:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param indexPaths An array of index paths that will be deleted. - @param collectionView The collection view that will perform the delete. + @param indexPaths An array of index paths that will be deleted. + @param collectionView The collection view that will perform the delete. @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ @@ -71,9 +70,9 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView moveItemAtIndexPath:toIndexPath:]` @param listAdapterUpdater The adapter updater owning the transition. - @param fromIndexPath The index path of the item that will be moved. - @param toIndexPath The index path to move the item to. - @param collectionView The collection view that will perform the move. + @param fromIndexPath The index path of the item that will be moved. + @param toIndexPath The index path to move the item to. + @param collectionView The collection view that will perform the move. @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ @@ -86,8 +85,8 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView reloadItemsAtIndexPaths:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param indexPaths An array of index paths that will be reloaded. - @param collectionView The collection view that will perform the reload. + @param indexPaths An array of index paths that will be reloaded. + @param collectionView The collection view that will perform the reload. @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ @@ -99,8 +98,8 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView reloadSections:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param sections The sections that will be reloaded - @param collectionView The collection view that will perform the reload. + @param sections The sections that will be reloaded + @param collectionView The collection view that will perform the reload. @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ @@ -112,7 +111,7 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater will call `-[UICollectionView reloadData]`. @param listAdapterUpdater The adapter updater owning the transition. - @param collectionView The collection view that will be reloaded. + @param collectionView The collection view that will be reloaded. */ - (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater willReloadDataWithCollectionView:(UICollectionView *)collectionView; @@ -120,7 +119,7 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the updater successfully called `-[UICollectionView reloadData]`. @param listAdapterUpdater The adapter updater owning the transition. - @param collectionView The collection view that reloaded. + @param collectionView The collection view that reloaded. */ - (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater didReloadDataWithCollectionView:(UICollectionView *)collectionView; @@ -128,12 +127,14 @@ NS_ASSUME_NONNULL_BEGIN Notifies the delegate that the collection view threw an exception in `-[UICollectionView performBatchUpdates:completion:]`. @param listAdapterUpdater The adapter updater owning the transition. - @param exception The exception thrown by the collection view. - @param fromObjects The items transitioned from in the diff, if any. - @param toObjects The items transitioned to in the diff, if any. - @param updates The batch updates that were applied to the collection view. + @param collectionView The collection view being updated. + @param exception The exception thrown by the collection view. + @param fromObjects The items transitioned from in the diff, if any. + @param toObjects The items transitioned to in the diff, if any. + @param updates The batch updates that were applied to the collection view. */ - (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater + collectionView:(UICollectionView *)collectionView willCrashWithException:(NSException *)exception fromObjects:(nullable NSArray *)fromObjects toObjects:(nullable NSArray *)toObjects diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBatchContext.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListBatchContext.h new file mode 100644 index 0000000..4143dd8 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBatchContext.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class IGListSectionController; + + + +NS_ASSUME_NONNULL_BEGIN + +/** + Objects conforming to the IGListBatchContext protocol provide a way for section controllers to mutate their cells or + reload everything within the section. + */ +NS_SWIFT_NAME(ListBatchContext) +@protocol IGListBatchContext + +/** + Reloads cells in the section controller. + + @param sectionController The section controller who's cells need reloading. + @param indexes The indexes of items that need reloading. + */ +- (void)reloadInSectionController:(IGListSectionController *)sectionController + atIndexes:(NSIndexSet *)indexes; + +/** + Inserts cells in the list. + + @param sectionController The section controller who's cells need inserting. + @param indexes The indexes of items that need inserting. + */ +- (void)insertInSectionController:(IGListSectionController *)sectionController + atIndexes:(NSIndexSet *)indexes; + +/** + Deletes cells in the list. + + @param sectionController The section controller who's cells need deleted. + @param indexes The indexes of items that need deleting. + */ +- (void)deleteInSectionController:(IGListSectionController *)sectionController + atIndexes:(NSIndexSet *)indexes; + +/** + Moves a cell from one index to another within the section controller. + + @param sectionController The section controller who's cell needs moved. + @param fromIndex The index the cell is currently in. + @param toIndex The index the cell should move to. + */ +- (void)moveInSectionController:(IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex; + +/** + Reloads the entire section controller. + + @param sectionController The section controller who's cells need reloading. + */ +- (void)reloadSectionController:(IGListSectionController *)sectionController; + +/** + Moves a section controller from one index to another during interactive reordering. + + @param sectionController The section controller to move. + @param fromIndex The index where the section currently resides. + @param toIndex The index the section should move to. + */ +- (void)moveSectionControllerInteractive:(IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0); + +/** + Moves an object within a section controller from one index to another during interactive reordering. + + @param sectionController The section controller containing the object to move. + @param fromIndex The index where the object currently resides. + @param toIndex The index the object should move to. + */ +- (void)moveInSectionControllerInteractive:(IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0); + +/** + Reverts an move from one indexPath to another during interactive reordering. + + @param sourceIndexPath The indexPath the item was originally in. + @param destinationIndexPath The indexPath the item was moving to. + */ +- (void)revertInvalidInteractiveMoveFromIndexPath:(NSIndexPath *)sourceIndexPath + toIndexPath:(NSIndexPath *)destinationIndexPath NS_AVAILABLE_IOS(9_0); +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindable.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindable.h index 62b17db..0d1fbd2 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindable.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindable.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,12 +12,13 @@ NS_ASSUME_NONNULL_BEGIN /** A protocol for cells that configure themselves given a view model. */ +NS_SWIFT_NAME(ListBindable) @protocol IGListBindable /** Tells the cell to configure itself with the given view model. - @param viewModel The view model for the cel. + @param viewModel The view model for the cell. @note The view model can change many times throughout the lifetime of a cell as the model values change and the cell is reused. Implementations should use only this method to do their configuration. diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.h index 482fe34..d054f3c 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.h @@ -1,16 +1,14 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import #import -#import + #import #import #import @@ -47,7 +45,8 @@ NS_ASSUME_NONNULL_BEGIN Only when `-diffIdentifier`s match is object equality compared, so you can assume the class is the same, and the instance has already been checked. */ -@interface IGListBindingSectionController : IGListSectionController +NS_SWIFT_NAME(ListBindingSectionController) +@interface IGListBindingSectionController<__covariant ObjectType : id> : IGListSectionController /** A data source that transforms a top-level object into view models, and returns cells and sizes for given view models. @@ -59,6 +58,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, weak, nullable) id selectionDelegate; +/** + The object currently assigned to the section controller, if any. + */ +@property (nonatomic, strong, readonly, nullable) ObjectType object; + /** The array of view models created from the data source. Values are changed when the top-level object changes or by calling `-updateAnimated:completion:` manually. diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.m index aabf395..b769eb8 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionController.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListBindingSectionController.h" @@ -13,6 +11,9 @@ #import #import #import +#import + +#import "IGListArrayUtilsInternal.h" typedef NS_ENUM(NSInteger, IGListDiffingSectionState) { IGListDiffingSectionStateIdle = 0, @@ -48,14 +49,18 @@ - (void)updateAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { __block NSArray> *oldViewModels = nil; id collectionContext = self.collectionContext; - - [collectionContext performBatchAnimated:animated updates:^{ + [self.collectionContext performBatchAnimated:animated updates:^(id batchContext) { if (self.state != IGListDiffingSectionStateUpdateQueued) { return; } - + oldViewModels = self.viewModels; - self.viewModels = [self.dataSource sectionController:self viewModelsForObject:self.object]; + + id object = self.object; + IGAssert(object != nil, @"Expected IGListBindingSectionController object to be non-nil before updating."); + + NSArray *newViewModels = [self.dataSource sectionController:self viewModelsForObject:object]; + self.viewModels = objectsWithDuplicateIdentifiersRemoved(newViewModels); result = IGListDiff(oldViewModels, self.viewModels, IGListDiffEquality); [result.updates enumerateIndexesUsingBlock:^(NSUInteger oldUpdatedIndex, BOOL *stop) { @@ -67,26 +72,25 @@ - (void)updateAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { [cell bindViewModel:self.viewModels[indexAfterUpdate]]; } }]; - - - [collectionContext deleteInSectionController:self atIndexes:result.deletes]; - [collectionContext insertInSectionController:self atIndexes:result.inserts]; - + + + [batchContext deleteInSectionController:self atIndexes:result.deletes]; + [batchContext insertInSectionController:self atIndexes:result.inserts]; + for (IGListMoveIndex *move in result.moves) { - [collectionContext moveInSectionController:self fromIndex:move.from toIndex:move.to]; + [batchContext moveInSectionController:self fromIndex:move.from toIndex:move.to]; } - + self.state = IGListDiffingSectionStateUpdateApplied; } completion:^(BOOL finished) { self.state = IGListDiffingSectionStateIdle; - if (completion != nil) { completion(YES); } }]; } -#pragma mark - IGListSectionType +#pragma mark - IGListSectionController Overrides - (NSInteger)numberOfItems { return self.viewModels.count; @@ -108,7 +112,7 @@ - (void)didUpdateToObject:(id)object { self.object = object; if (oldObject == nil) { - self.viewModels = [self.dataSource sectionController:self viewModelsForObject:object]; + self.viewModels = [[self.dataSource sectionController:self viewModelsForObject:object] copy]; } else { IGAssert([oldObject isEqualToDiffableObject:object], @"Unequal objects %@ and %@ will cause IGListBindingSectionController to reload the entire section", @@ -121,4 +125,25 @@ - (void)didSelectItemAtIndex:(NSInteger)index { [self.selectionDelegate sectionController:self didSelectItemAtIndex:index viewModel:self.viewModels[index]]; } +- (void)didDeselectItemAtIndex:(NSInteger)index { + id selectionDelegate = self.selectionDelegate; + if ([selectionDelegate respondsToSelector:@selector(sectionController:didDeselectItemAtIndex:viewModel:)]) { + [selectionDelegate sectionController:self didDeselectItemAtIndex:index viewModel:self.viewModels[index]]; + } +} + +- (void)didHighlightItemAtIndex:(NSInteger)index { + id selectionDelegate = self.selectionDelegate; + if ([selectionDelegate respondsToSelector:@selector(sectionController:didHighlightItemAtIndex:viewModel:)]) { + [selectionDelegate sectionController:self didHighlightItemAtIndex:index viewModel:self.viewModels[index]]; + } +} + +- (void)didUnhighlightItemAtIndex:(NSInteger)index { + id selectionDelegate = self.selectionDelegate; + if ([selectionDelegate respondsToSelector:@selector(sectionController:didUnhighlightItemAtIndex:viewModel:)]) { + [selectionDelegate sectionController:self didUnhighlightItemAtIndex:index viewModel:self.viewModels[index]]; + } +} + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerDataSource.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerDataSource.h index 2319aa5..5a020a4 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerDataSource.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerDataSource.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -19,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN /** A protocol that returns data to power cells in an `IGListBindingSectionController`. */ +NS_SWIFT_NAME(ListBindingSectionControllerDataSource) @protocol IGListBindingSectionControllerDataSource /** @@ -26,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @param sectionController The section controller requesting view models. @param object The top-level object that powers the section controller. + @return A new array of view models. */ - (NSArray> *)sectionController:(IGListBindingSectionController *)sectionController @@ -37,6 +37,7 @@ NS_ASSUME_NONNULL_BEGIN @param sectionController The section controller requesting a cell. @param viewModel The view model for the cell. @param index The index of the view model. + @return A dequeued cell. @note The section controller will call `-bindViewModel:` with the provided view model after the cell is dequeued. You @@ -52,6 +53,7 @@ NS_ASSUME_NONNULL_BEGIN @param sectionController The section controller requesting a size. @param viewModel The view model for the cell. @param index The index of the view model. + @return A size for the view model. */ - (CGSize)sectionController:(IGListBindingSectionController *)sectionController diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerSelectionDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerSelectionDelegate.h index 6f6d9ab..a3c847f 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerSelectionDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListBindingSectionControllerSelectionDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -16,12 +14,13 @@ NS_ASSUME_NONNULL_BEGIN /** A protocol that handles cell selection events in an `IGListBindingSectionController`. */ +NS_SWIFT_NAME(ListBindingSectionControllerSelectionDelegate) @protocol IGListBindingSectionControllerSelectionDelegate /** Tells the delegate that a cell at a given index was selected. - @param sectionController The section controller the selection occured in. + @param sectionController The section controller the selection occurred in. @param index The index of the selected cell. @param viewModel The view model that was bound to the cell. */ @@ -29,6 +28,43 @@ NS_ASSUME_NONNULL_BEGIN didSelectItemAtIndex:(NSInteger)index viewModel:(id)viewModel; +@optional + +/** + Tells the delegate that a cell at a given index was deselected. + + @param sectionController The section controller the deselection occurred in. + @param index The index of the deselected cell. + @param viewModel The view model that was bound to the cell. + + @note Method is `@optional` until the 4.0.0 release where it will become required. + */ +- (void)sectionController:(IGListBindingSectionController *)sectionController + didDeselectItemAtIndex:(NSInteger)index + viewModel:(id)viewModel; + +/** + Tells the delegate that a cell at a given index was highlighted. + + @param sectionController The section controller the highlight occurred in. + @param index The index of the highlighted cell. + @param viewModel The view model that was bound to the cell. + */ +- (void)sectionController:(IGListBindingSectionController *)sectionController + didHighlightItemAtIndex:(NSInteger)index + viewModel:(id)viewModel; + +/** + Tells the delegate that a cell at a given index was unhighlighted. + + @param sectionController The section controller the unhighlight occurred in. + @param index The index of the unhighlighted cell. + @param viewModel The view model that was bound to the cell. + */ +- (void)sectionController:(IGListBindingSectionController *)sectionController +didUnhighlightItemAtIndex:(NSInteger)index + viewModel:(id)viewModel; + @end NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionContext.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionContext.h index 2b40809..a65b237 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionContext.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionContext.h @@ -1,30 +1,45 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import +#import + NS_ASSUME_NONNULL_BEGIN @class IGListSectionController; -@protocol IGListSectionType; /** The collection context provides limited access to the collection-related information that - section controllers need for operations like sizing, dequeing cells, insterting, deleting, reloading, etc. + section controllers need for operations like sizing, dequeuing cells, inserting, deleting, reloading, etc. */ +NS_SWIFT_NAME(ListCollectionContext) @protocol IGListCollectionContext /** - The size of the collection view. You may use this for sizing cells. + The size of the collection view. You can use this for sizing cells. */ @property (nonatomic, readonly) CGSize containerSize; +/** + The content insets of the collection view. You can use this for sizing cells. + */ +@property (nonatomic, readonly) UIEdgeInsets containerInset; + +/** + The adjusted content insets of the collection view. Equivalent to containerInset under iOS 11. + */ +@property (nonatomic, readonly) UIEdgeInsets adjustedContainerInset; + +/** + The size of the collection view with content insets applied. + */ +@property (nonatomic, readonly) CGSize insetContainerSize; + /** Returns size of the collection view relative to the section controller. @@ -32,23 +47,23 @@ NS_ASSUME_NONNULL_BEGIN @return The size of the collection view minus the given section controller's insets. */ -- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController; +- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController; /** Returns the index of the specified cell in the collection relative to the section controller. - @param cell An existing cell in the collection. + @param cell An existing cell in the collection. @param sectionController The section controller requesting this information. @return The index of the cell or `NSNotFound` if it does not exist in the collection. */ - (NSInteger)indexForCell:(UICollectionViewCell *)cell - sectionController:(IGListSectionController *)sectionController; + sectionController:(IGListSectionController *)sectionController; /** Returns the cell in the collection at the specified index for the section controller. - @param index The index of the desired cell. + @param index The index of the desired cell. @param sectionController The section controller requesting this information. @return The collection view cell, or `nil` if not found. @@ -56,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN @warning This method may return `nil` if the cell is offscreen. */ - (nullable __kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index - sectionController:(IGListSectionController *)sectionController; + sectionController:(IGListSectionController *)sectionController; /** Returns the visible cells for the given section controller. @@ -65,58 +80,80 @@ NS_ASSUME_NONNULL_BEGIN @return An array of visible cells, or an empty array if none are found. */ -- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController; +- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController; /** Returns the visible paths for the given section controller. @param sectionController The section controller requesting this information. + @return An array of visible index paths, or an empty array if none are found. */ -- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *) sectionController; +- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *) sectionController; /** Deselects a cell in the collection. - @param index The index of the item to deselect. + @param index The index of the item to deselect. @param sectionController The section controller requesting this information. - @param animated Pass `YES` to animate the change, `NO` otherwise. + @param animated Pass `YES` to animate the change, `NO` otherwise. */ - (void)deselectItemAtIndex:(NSInteger)index - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController animated:(BOOL)animated; /** - Returns the section index of an section controller. + Selects a cell in the collection. + + @param index The index of the item to select. + @param sectionController The section controller requesting this information. + @param animated Pass `YES` to animate the change, `NO` otherwise. + @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. + */ +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition; - @param sectionController An section controller object. +/** + Dequeues a cell from the collection view reuse pool. - @return The section index of the controller if found, otherwise `NSNotFound`. + @param cellClass The class of the cell you want to dequeue. + @param reuseIdentifier A reuse identifier for the specified cell. This parameter may be `nil`. + @param sectionController The section controller requesting this information. + @param index The index of the cell. + + @return A cell dequeued from the reuse pool or a newly created one. + + @note This method uses a string representation of the cell class as the identifier. */ -- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController; +- (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass + withReuseIdentifier:(nullable NSString *)reuseIdentifier + forSectionController:(IGListSectionController *)sectionController + atIndex:(NSInteger)index; /** Dequeues a cell from the collection view reuse pool. - @param cellClass The class of the cell you want to dequeue. + @param cellClass The class of the cell you want to dequeue. @param sectionController The section controller requesting this information. - @param index The index of the cell. + @param index The index of the cell. @return A cell dequeued from the reuse pool or a newly created one. @note This method uses a string representation of the cell class as the identifier. */ - (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; /** Dequeues a cell from the collection view reuse pool. - @param nibName The name of the nib file. - @param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle. + @param nibName The name of the nib file. + @param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle. @param sectionController The section controller requesting this information. - @param index The index of the cell. + @param index The index of the cell. @return A cell dequeued from the reuse pool or a newly created one. @@ -124,172 +161,129 @@ NS_ASSUME_NONNULL_BEGIN */ - (__kindof UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName bundle:(nullable NSBundle *)bundle - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; /** Dequeues a storyboard prototype cell from the collection view reuse pool. - @param identifier The identifier of the cell prototype in storyboard. + @param identifier The identifier of the cell prototype in storyboard. @param sectionController The section controller requesting this information. - @param index The index of the cell. + @param index The index of the cell. @return A cell dequeued from the reuse pool or a newly created one. */ - (__kindof UICollectionViewCell *)dequeueReusableCellFromStoryboardWithIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; /** Dequeues a supplementary view from the collection view reuse pool. - @param elementKind The kind of supplementary veiw. + @param elementKind The kind of supplementary view. @param sectionController The section controller requesting this information. - @param viewClass The class of the supplementary view. - @param index The index of the supplementary vew. + @param viewClass The class of the supplementary view. + @param index The index of the supplementary view. @return A supplementary view dequeued from the reuse pool or a newly created one. @note This method uses a string representation of the view class as the identifier. */ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController class:(Class)viewClass atIndex:(NSInteger)index; /** Dequeues a supplementary view from the collection view reuse pool. - @param elementKind The kind of supplementary veiw. - @param identifier The identifier of the supplementary view in storyboard. + @param elementKind The kind of supplementary view. + @param identifier The identifier of the supplementary view in storyboard. @param sectionController The section controller requesting this information. - @param index The index of the supplementary vew. + @param index The index of the supplementary view. @return A supplementary view dequeued from the reuse pool or a newly created one. */ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewFromStoryboardOfKind:(NSString *)elementKind withIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; /** Dequeues a supplementary view from the collection view reuse pool. - @param elementKind The kind of supplementary veiw. + @param elementKind The kind of supplementary view. @param sectionController The section controller requesting this information. - @param nibName The name of the nib file. - @param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle. - @param index The index of the supplementary vew. + @param nibName The name of the nib file. + @param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle. + @param index The index of the supplementary view. @return A supplementary view dequeued from the reuse pool or a newly created one. @note This method uses a string representation of the view class as the identifier. */ - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController nibName:(NSString *)nibName bundle:(nullable NSBundle *)bundle atIndex:(NSInteger)index; -/** - Reloads cells in the section controller. - - @param sectionController The section controller who's cells need reloading. - @param indexes The indexes of items that need reloading. - */ -- (void)reloadInSectionController:(IGListSectionController *)sectionController - atIndexes:(NSIndexSet *)indexes; - -/** - Inserts cells in the list. - - @param sectionController The section controller who's cells need inserting. - @param indexes The indexes of items that need inserting. - */ -- (void)insertInSectionController:(IGListSectionController *)sectionController - atIndexes:(NSIndexSet *)indexes; - -/** - Deletes cells in the list. - - @param sectionController The section controller who's cells need deleted. - @param indexes The indexes of items that need deleting. - */ -- (void)deleteInSectionController:(IGListSectionController *)sectionController - atIndexes:(NSIndexSet *)indexes; - -/** - Moves a cell from one index to another within the section controller. - - @param sectionController The section controller who's cell needs moved. - @param fromIndex The index the cell is currently in. - @param toIndex The index the cell should move to. - */ -- (void)moveInSectionController:(IGListSectionController *)sectionController - fromIndex:(NSInteger)fromIndex - toIndex:(NSInteger)toIndex; - -/** - Reloads the entire section controller. - - @param sectionController The section controller who's cells need reloading. - */ -- (void)reloadSectionController:(IGListSectionController *)sectionController; - /** Invalidate the backing `UICollectionViewLayout` for all items in the section controller. @param sectionController The section controller that needs invalidating. - @param completion An optional completion block to execute when the updates are finished. + @param completion An optional completion block to execute when the updates are finished. @note This method can be wrapped in `UIView` animation APIs to control the duration or perform without animations. This - will end up calling `-[UICollectionView performBatchUpdates:completion:] internally, so invalidated changes may not be + will end up calling `-[UICollectionView performBatchUpdates:completion:]` internally, so invalidated changes may not be reflected in the cells immediately. */ -- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController +- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController completion:(nullable void (^)(BOOL finished))completion; /** Batches and performs many cell-level updates in a single transaction. - @param animated A flag indicating if the transition should be animated. - @param updates A block containing all of the cell updates. + @param animated A flag indicating if the transition should be animated. + @param updates A block with a context parameter to make mutations. @param completion An optional completion block to execute when the updates are finished. - @note Use this method to batch cell updates (inserts, deletes, reloads) into a single transaction. This lets you - make many changes to your data store and perform all the transitions at once. + @note You should make state changes that impact the number of items in your section controller within the updates + block alongside changes on the context object. For example, inside your section controllers, you may want to delete *and* insert into the data source that backs your section controller. For example: ``` - [self.collectionContext performBatchItemUpdates:^{ - // perform data source changes inside the update block - [self.items addObject:newItem]; - [self.items removeObjectAtIndex:0]; + [self.collectionContext performBatchItemUpdates:^ (id batchContext>){ + // perform data source changes inside the update block + [self.items addObject:newItem]; + [self.items removeObjectAtIndex:0]; - NSIndexSet *inserts = [NSIndexSet indexSetWithIndex:[self.items count] - 1]; - [self.collectionContext insertInSectionController:self atIndexes:inserts]; + NSIndexSet *inserts = [NSIndexSet indexSetWithIndex:[self.items count] - 1]; + [batchContext insertInSectionController:self atIndexes:inserts]; - NSIndexSet *deletes = [NSIndexSet indexSetWithIndex:0]; - [self.collectionContext deleteInSectionController:self atIndexes:deletes]; + NSIndexSet *deletes = [NSIndexSet indexSetWithIndex:0]; + [batchContext deleteInSectionController:self atIndexes:deletes]; } completion:nil]; ``` @warning You **must** perform data modifications **inside** the update block. Updates will not be performed synchronously, so you should make sure that your data source changes only when necessary. */ -- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(nullable void (^)(BOOL finished))completion; +- (void)performBatchAnimated:(BOOL)animated + updates:(void (^)(id batchContext))updates + completion:(nullable void (^)(BOOL finished))completion; /** Scrolls to the specified section controller in the list. @param sectionController The section controller. - @param index The index of the item in the section controller to which to scroll. - @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. - @param animated A flag indicating if the scrolling should be animated. + @param index The index of the item in the section controller to which to scroll. + @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. + @param animated A flag indicating if the scrolling should be animated. */ -- (void)scrollToSectionController:(IGListSectionController *)sectionController +- (void)scrollToSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index scrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.h index 66b060c..f2bb458 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.h @@ -1,88 +1,47 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import -#import +@class IGListCollectionViewLayout; -/** - This class is never actually used by the `IGListKit` infrastructure. - It exists only to give compiler errors when editing - methods are called on the collection view returned by `-[IGListAdapter collectionView]`. - */ -IGLK_SUBCLASSING_RESTRICTED -@interface IGListCollectionView : UICollectionView - -/** - :nodoc: - */ -- (void)performBatchUpdates:(void (^)(void))updates - completion:(void (^)(BOOL))completion IGLK_UNAVAILABLE("Call -[IGListAdapter performUpdatesAnimated:completion:] instead"); - -/** - :nodoc: - */ -- (void)reloadData IGLK_UNAVAILABLE("Call -[IGListAdapter reloadDataWithCompletion:] instead"); - -/** - :nodoc: - */ -- (void)reloadSections:(NSIndexSet *)sections IGLK_UNAVAILABLE("Call -[IGListAdapter reloadObjects:] instead"); - -/** - :nodoc: - */ -- (void)insertSections:(NSIndexSet *)sections IGLK_UNAVAILABLE("Call -[IGListAdapter performUpdatesAnimated:completion:] instead"); - -/** - :nodoc: - */ -- (void)deleteSections:(NSIndexSet *)sections IGLK_UNAVAILABLE("Call -[IGListAdapter performUpdatesAnimated:completion:] instead"); - -/** - :nodoc: - */ -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection IGLK_UNAVAILABLE("Call -[IGListAdapter performUpdatesAnimated:completion:] instead"); +NS_ASSUME_NONNULL_BEGIN /** - :nodoc: - */ -- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths IGLK_UNAVAILABLE("Call -[ insertInSectionController:atIndexes:] instead"); + This `UICollectionView` subclass allows for partial layout invalidation using `IGListCollectionViewLayout`. -/** - :nodoc: + @note When updating a collection view (ex: calling `-insertSections`), `-invalidateLayoutWithContext` gets called on + the layout object. However, the invalidation context doesn't provide details on which index paths are being modified, + which typically forces a full layout re-calculation. `IGListCollectionView` gives `IGListCollectionViewLayout` the + missing information to re-calculate only the modified layout attributes. */ -- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths IGLK_UNAVAILABLE("Call -[ reloadInSectionController:atIndexes:] instead"); +NS_SWIFT_NAME(ListCollectionView) +@interface IGListCollectionView : UICollectionView /** - :nodoc: - */ -- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths IGLK_UNAVAILABLE("Call -[ deleteInSectionController:atIndexes:] instead"); + Create a new view with an `IGListcollectionViewLayout` class or subclass. -/** - :nodoc: - */ -- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath IGLK_UNAVAILABLE("Moving items currently unsupported"); + @param frame The frame to initialize with. + @param collectionViewLayout The layout to use with the collection view. -/** - :nodoc: + @note You can initialize a new view with a base layout by simply calling `-[IGListCollectionView initWithFrame:]`. */ -- (void)setDelegate:(id)delegate IGLK_UNAVAILABLE("IGListAdapter should be the delegate of the collection view"); +- (instancetype)initWithFrame:(CGRect)frame listCollectionViewLayout:(IGListCollectionViewLayout *)collectionViewLayout NS_DESIGNATED_INITIALIZER; /** :nodoc: */ -- (void)setDataSource:(id)dataSource IGLK_UNAVAILABLE("IGListAdapter should be the data source of the collection view"); +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)collectionViewLayout NS_UNAVAILABLE; /** :nodoc: */ -- (void)setBackgroundView:(UIView *)backgroundView IGLK_UNAVAILABLE("Return a view in -[IGListAdapterDataSource emptyViewForListAdapter:] instead"); +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.m index c167b61..1382bcc 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionView.m @@ -1,51 +1,104 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListCollectionView.h" +#import "IGListCollectionViewLayout.h" + @implementation IGListCollectionView -- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { - if (self = [super initWithFrame:frame collectionViewLayout:layout]) { - - UIColor *backgroundAppearanceColor = (UIColor *) [[[self class] appearance] backgroundColor]; - if (!backgroundAppearanceColor) { - self.backgroundColor = [UIColor whiteColor]; - } - - if ([self respondsToSelector:@selector(setPrefetchingEnabled:)]) { - self.prefetchingEnabled = NO; - } - - self.alwaysBounceVertical = YES; +#pragma mark - Init + +- (instancetype)initWithFrame:(CGRect)frame { + IGListCollectionViewLayout *layout = [[IGListCollectionViewLayout alloc] initWithStickyHeaders:NO topContentInset:0 stretchToEdge:YES]; + return [self initWithFrame:frame listCollectionViewLayout:layout]; +} + +- (instancetype)initWithFrame:(CGRect)frame listCollectionViewLayout:(IGListCollectionViewLayout *)collectionViewLayout { + return [super initWithFrame:frame collectionViewLayout:collectionViewLayout]; +} + +#pragma mark - IGListCollectionViewLayout + +- (IGListCollectionViewLayout *)_listLayout { + if ([self.collectionViewLayout isKindOfClass:[IGListCollectionViewLayout class]]) { + return (IGListCollectionViewLayout *)self.collectionViewLayout; } - return self; + + return nil; +} + +#pragma mark - Overides reloads + +- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths { + [self _didModifyIndexPaths:indexPaths]; + [super reloadItemsAtIndexPaths:indexPaths]; +} + +- (void)reloadSections:(NSIndexSet *)sections { + [self _didModifySections:sections]; + [super reloadSections:sections]; +} + +#pragma mark - Override deletes + +- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths { + [self _didModifyIndexPaths:indexPaths]; + [super deleteItemsAtIndexPaths:indexPaths]; +} + +- (void)deleteSections:(NSIndexSet *)sections { + [self _didModifySections:sections]; + [super deleteSections:sections]; } -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - if (self = [super initWithCoder:aDecoder]) { - if ([self respondsToSelector:@selector(setPrefetchingEnabled:)]) { - self.prefetchingEnabled = NO; - } +#pragma mark - Override inserts + +- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths { + [self _didModifyIndexPaths:indexPaths]; + [super insertItemsAtIndexPaths:indexPaths]; +} + +- (void)insertSections:(NSIndexSet *)sections { + [self _didModifySections:sections]; + [super insertSections:sections]; +} + +#pragma mark - Override moves + +- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { + [self _didModifyIndexPaths:@[indexPath, newIndexPath]]; + [super moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; +} + +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection { + [self _didModifySection:MIN(section, newSection)]; + [super moveSection:section toSection:newSection]; +} + +#pragma mark - Modify section + +- (void)_didModifySections:(NSIndexSet *)sections { + if (sections.count == 0) { + return; + } + [self _didModifySection:sections.firstIndex]; +} + +- (void)_didModifySection:(NSUInteger)section { + [self._listLayout didModifySection:section]; +} + +#pragma mark - Modified index path + +- (void)_didModifyIndexPaths:(NSArray *)indexPaths { + for (NSIndexPath *indexPath in indexPaths) { + [self _didModifySection:indexPath.section]; } - return self; -} - -- (void)layoutSubviews { - /** - UICollectionView will sometimes lay its cells out with an animation. This is especially noticeable on older devices - while scrolling quickly. The simplest fix is to just disable animations for -layoutSubviews, which is where cells - and other views inside the UICollectionView are laid out. - */ - [UIView performWithoutAnimation:^{ - [super layoutSubviews]; - }]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewDelegateLayout.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewDelegateLayout.h new file mode 100644 index 0000000..f224459 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewDelegateLayout.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +/** + Conform to `IGListCollectionViewDelegateLayout` to provide customized layout information for a collection view. + */ +@protocol IGListCollectionViewDelegateLayout + +/** + Asks the delegate to customize and return the starting layout information for an item being inserted into the collection view. + + @param collectionView The collection view to perform the transition on. + @param collectionViewLayout The layout to use with the collection view. + @param attributes The starting layout information for an item being inserted into the collection view. + @param indexPath The index path of the item being inserted. + */ +- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes atIndexPath:(NSIndexPath *)indexPath; + +/** + Asks the delegate to customize and return the final layout information for an item that is about to be removed from the collection view. + + @param collectionView The collection view to perform the transition on. + @param collectionViewLayout The layout to use with the collection view. + @param attributes The final layout information for an item that is about to be removed from the collection view. + @param indexPath The index path of the item being deleted. + */ +- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes atIndexPath:(NSIndexPath *)indexPath; + +@end + diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.h index d641ade..3d4e2b7 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,8 +12,8 @@ NS_ASSUME_NONNULL_BEGIN /** - This UICollectionViewLayout subclass is for vertically-scrolling lists of data with variable widths and heights. It - supports an infinite number of sections and items. All work is done on the main thread, and while extremely efficient, + This UICollectionViewLayout subclass is for vertically or horizontally scrolling lists of data with variable widths and + heights. It supports an infinite number of sections and items. All work is done on the main thread, and while extremely efficient, care must be taken not to stall the main thread in sizing delegate methods. This layout piggybacks on the mechanics of UICollectionViewFlowLayout in that: @@ -33,9 +31,9 @@ NS_ASSUME_NONNULL_BEGIN - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section; ``` - Sections and items are put into the same horizontal row until the max-x position of an item extends beyond the width - of the collection view. When that happens, the item is "newlined" to the next row. The y position of that row is - deteremined by the maximum height (including section insets) of the section/item of the previous row. + In a vertically scrolling layout, sections and items are put into the same horizontal row until the max-x position + of an item extends beyond the width of the collection view. When that happens, the item is "newlined" to the next row. + The y position of that row is determined by the maximum height (including section insets) of the section/item of the previous row. Ex. of a section (2,0) with a large width causing a newline. ``` @@ -64,32 +62,75 @@ NS_ASSUME_NONNULL_BEGIN Interitem spacing applies to items and sections within the same row. Line spacing only applies to items within the same section. + + In a horizontally scrolling layout, sections and items are flowed vertically until they need to be "newlined" to the + next column. Headers, if used, are stretched to the height of the collection view, minus the section insets. Please see the unit tests for more configuration examples and expected output. */ - +NS_SWIFT_NAME(ListCollectionViewLayout) @interface IGListCollectionViewLayout : UICollectionViewLayout /** - Set this to adjust the offset of the sticky headers. Can be used to change the sticky header position as UI like the - navigation bar is scrolled offscreen. Changing this to the height of the navigation bar will give the effect of the - headers sticking to the nav as it is collapsed. + Direction in which layout will be scrollable; items will be flowed in the perpendicular direction, "newlining" when they + run out of space along that axis or when a non-zero header is found. + */ +@property (nonatomic, readonly) UICollectionViewScrollDirection scrollDirection; - @discussion Changing the value on this method will invalidate the layout every time. +/** + Set this to adjust the offset of the sticky headers in the scrolling direction. Can be used to change the sticky + header position as UI like the navigation bar is scrolled offscreen. In a vertically scrolling layout, changing + this to the height of the navigation bar will give the effect of the headers sticking to the nav as it is collapsed. + + @note Changing the value on this method will invalidate the layout every time. */ -@property (nonatomic, assign) CGFloat stickyHeaderOriginYAdjustment; +@property (nonatomic, assign) CGFloat stickyHeaderYOffset; + +/** + Set this to `YES` to show sticky header when a section had no item. Default is `NO`. +*/ +@property (nonatomic, assign) BOOL showHeaderWhenEmpty; + +/** + Notify the layout that a specific section was modified before invalidation. Used to optimize layout re-calculation. + + @note When updating a collection view (ex: calling `-insertSections`), `-invalidateLayoutWithContext` gets called on + the layout object. However, the invalidation context doesn't provide details on which index paths are being modified, + which typically forces a full layout re-calculation. We can use this method to keep track of which section actually + needs to be updated on the following `-invalidateLayoutWithContext`. See `IGListCollectionView`. + + @param modifiedSection The section that was modified. + */ +- (void)didModifySection:(NSInteger)modifiedSection; /** Create and return a new collection view layout. - @param stickyHeaders Set to `YES` to stick section headers to the top of the bounds while scrolling. - @param topContentInset The top content inset used to offset the sticky headers. Ignored if stickyHeaders is `NO`. - @param stretchToEdge Specifies whether to stretch width of last item to right edge when distance from last item to right edge < epsilon(1) + + @param stickyHeaders Set to `YES` to stick section headers to the top of the bounds while scrolling. + @param scrollDirection Direction along which the collection view will be scrollable (if content size exceeds the frame size) + @param topContentInset The content inset (top or left, depending on scrolling direction) used to offset the sticky headers. Ignored if stickyHeaders is `NO`. + @param stretchToEdge Specifies whether to stretch width (in vertically scrolling layout) or height (horizontally scrolling) of last item to right/bottom edge when distance from last item to right/bottom edge < epsilon(1) + @return A new collection view layout. */ - (instancetype)initWithStickyHeaders:(BOOL)stickyHeaders + scrollDirection:(UICollectionViewScrollDirection)scrollDirection topContentInset:(CGFloat)topContentInset stretchToEdge:(BOOL)stretchToEdge NS_DESIGNATED_INITIALIZER; +/** + Create and return a new vertically scrolling collection view layout. + + @param stickyHeaders Set to `YES` to stick section headers to the top of the bounds while scrolling. + @param topContentInset The top content inset used to offset the sticky headers. Ignored if stickyHeaders is `NO`. + @param stretchToEdge Specifies whether to stretch width of last item to right edge when distance from last item to right edge < epsilon(1) + + @return A new collection view layout. + */ +- (instancetype)initWithStickyHeaders:(BOOL)stickyHeaders + topContentInset:(CGFloat)topContentInset + stretchToEdge:(BOOL)stretchToEdge; + /** :nodoc: */ diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.mm b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.mm index 1d67856..878efd5 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.mm +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListCollectionViewLayout.mm @@ -1,23 +1,84 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListCollectionViewLayout.h" #import "IGListCollectionViewLayoutInternal.h" +#import "UIScrollView+IGListKit.h" #import #import +#import -static NSIndexPath *headerIndexPathForSection(NSInteger section) { +static CGFloat UIEdgeInsetsLeadingInsetInDirection(UIEdgeInsets insets, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return insets.top; + case UICollectionViewScrollDirectionHorizontal: return insets.left; + } +} + +static CGFloat UIEdgeInsetsTrailingInsetInDirection(UIEdgeInsets insets, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return insets.bottom; + case UICollectionViewScrollDirectionHorizontal: return insets.right; + } +} + +static CGFloat CGPointGetCoordinateInDirection(CGPoint point, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return point.y; + case UICollectionViewScrollDirectionHorizontal: return point.x; + } +} + +static CGFloat CGRectGetLengthInDirection(CGRect rect, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return rect.size.height; + case UICollectionViewScrollDirectionHorizontal: return rect.size.width; + } +} + +static CGFloat CGRectGetMaxInDirection(CGRect rect, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return CGRectGetMaxY(rect); + case UICollectionViewScrollDirectionHorizontal: return CGRectGetMaxX(rect); + } +} + +static CGFloat CGRectGetMinInDirection(CGRect rect, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return CGRectGetMinY(rect); + case UICollectionViewScrollDirectionHorizontal: return CGRectGetMinX(rect); + } +} + +static CGFloat CGSizeGetLengthInDirection(CGSize size, UICollectionViewScrollDirection direction) { + switch (direction) { + case UICollectionViewScrollDirectionVertical: return size.height; + case UICollectionViewScrollDirectionHorizontal: return size.width; + } +} + +static NSIndexPath *indexPathForSection(NSInteger section) { return [NSIndexPath indexPathForItem:0 inSection:section]; } +static NSInteger IGListMergeMinimumInvalidatedSection(NSInteger section, NSInteger otherSection) { + if (section == NSNotFound && otherSection == NSNotFound) { + return NSNotFound; + } else if (section == NSNotFound) { + return otherSection; + } else if (otherSection == NSNotFound) { + return section; + } + + return MIN(section, otherSection); +} + struct IGListSectionEntry { /** Represents the minimum-bounding box of every element in the section. This includes all item frames as well as the @@ -32,9 +93,21 @@ // The RESTING frame of the header view (e.g. when the header is not sticking to the top of the scroll view). CGRect headerBounds; + // The RESTING frame of the footer view + CGRect footerBounds; + // An array of frames for each cell in the section. std::vector itemBounds; + // last item distance in scroll direction, used for partial invalidation + CGFloat lastItemCoordInScrollDirection; + + // last item distance in fixed direction, used for partial invalidation + CGFloat lastItemCoordInFixedDirection; + + // last next row distance in scroll direction, used for partial invalidation + CGFloat lastNextRowCoordInScrollDirection; + // Returns YES when the section has visible content (header and/or items). BOOL isValid() { return !CGSizeEqualToSize(bounds.size, CGSizeZero); @@ -54,8 +127,6 @@ static void adjustZIndexForAttributes(UICollectionViewLayoutAttributes *attribut attributes.zIndex = baseZIndex + attributes.indexPath.item; break; case UICollectionElementCategorySupplementaryView: - IGAssert([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader], - @"Only support for element kind header, not %@", attributes.representedElementKind); attributes.zIndex = baseZIndex + maxZIndexPerSection - 1; break; case UICollectionElementCategoryDecorationView: @@ -83,7 +154,9 @@ @interface IGListCollectionViewLayout () @implementation IGListCollectionViewLayout { std::vector _sectionData; NSMutableDictionary *_attributesCache; - BOOL _cachedLayoutInvalid; + + // invalidate starting at this section + NSInteger _minimumInvalidatedSection; /** The workflow for getting sticky headers working: @@ -95,19 +168,33 @@ @implementation IGListCollectionViewLayout { 6. Make sure -layoutAttributesForElementsInRect: always uses the attributes returned from -layoutAttributesForSupplementaryViewOfKind:atIndexPath:. */ - NSMutableDictionary *_headerAttributesCache; + NSMutableDictionary *> *_supplementaryAttributesCache; } - (instancetype)initWithStickyHeaders:(BOOL)stickyHeaders topContentInset:(CGFloat)topContentInset stretchToEdge:(BOOL)stretchToEdge { + return [self initWithStickyHeaders:stickyHeaders + scrollDirection:UICollectionViewScrollDirectionVertical + topContentInset:topContentInset + stretchToEdge:stretchToEdge]; +} + +- (instancetype)initWithStickyHeaders:(BOOL)stickyHeaders + scrollDirection:(UICollectionViewScrollDirection)scrollDirection + topContentInset:(CGFloat)topContentInset + stretchToEdge:(BOOL)stretchToEdge { if (self = [super init]) { + _scrollDirection = scrollDirection; _stickyHeaders = stickyHeaders; _topContentInset = topContentInset; _stretchToEdge = stretchToEdge; _attributesCache = [NSMutableDictionary new]; - _headerAttributesCache = [NSMutableDictionary new]; - _cachedLayoutInvalid = YES; + _supplementaryAttributesCache = [NSMutableDictionary dictionaryWithDictionary:@{ + UICollectionElementKindSectionHeader: [NSMutableDictionary new], + UICollectionElementKindSectionFooter: [NSMutableDictionary new], + }]; + _minimumInvalidatedSection = NSNotFound; } return self; } @@ -118,16 +205,36 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { #pragma mark - UICollectionViewLayout +- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath { + UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath]; + id delegate = (id)self.collectionView.delegate; + if ([delegate respondsToSelector:@selector(collectionView:layout:customizedInitialLayoutAttributes:atIndexPath:)]) { + return [delegate collectionView:self.collectionView + layout:self + customizedInitialLayoutAttributes:attributes + atIndexPath:itemIndexPath]; + } + return attributes; +} + +- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath{ + UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath]; + id delegate = (id)self.collectionView.delegate; + if ([delegate respondsToSelector:@selector(collectionView:layout:customizedFinalLayoutAttributes:atIndexPath:)]) { + return [delegate collectionView:self.collectionView + layout:self + customizedFinalLayoutAttributes:attributes + atIndexPath:itemIndexPath]; + } + return attributes; +} + - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { IGAssertMainThread(); NSMutableArray *result = [NSMutableArray new]; - // since we iterate through sections ascending, we may hit a section who is only partially visible - // in that case we short circuit building layout attributes - BOOL remainingCellsOutOfRect = NO; - - const NSRange range = [self rangeOfSectionsInRect:rect]; + const NSRange range = [self _rangeOfSectionsInRect:rect]; if (range.location == NSNotFound) { return nil; } @@ -136,15 +243,17 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { const NSInteger itemCount = _sectionData[section].itemBounds.size(); // do not add headers if there are no items - if (itemCount > 0) { - NSIndexPath *headerIndexPath = headerIndexPathForSection(section); - UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader - atIndexPath:headerIndexPath]; - // do not add zero height headers or headers that are outside the rect - const CGRect frame = attributes.frame; - const CGRect intersection = CGRectIntersection(frame, rect); - if (!CGRectIsEmpty(intersection) && CGRectGetHeight(frame) > 0.0) { - [result addObject:attributes]; + if (itemCount > 0 || self.showHeaderWhenEmpty) { + for (NSString *elementKind in _supplementaryAttributesCache.allKeys) { + NSIndexPath *indexPath = indexPathForSection(section); + UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:elementKind + atIndexPath:indexPath]; + // do not add zero height headers/footers or headers/footers that are outside the rect + const CGRect frame = attributes.frame; + const CGRect intersection = CGRectIntersection(frame, rect); + if (!CGRectIsEmpty(intersection) && CGRectGetLengthInDirection(frame, self.scrollDirection) > 0.0) { + [result addObject:attributes]; + } } } @@ -152,12 +261,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { for (NSInteger item = 0; item < itemCount; item++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section]; UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; - if (!CGRectIntersectsRect(attributes.frame, rect)) { - if (remainingCellsOutOfRect) { - return result; - } - } else { - remainingCellsOutOfRect = YES; + if (CGRectIntersectsRect(attributes.frame, rect)) { [result addObject:attributes]; } } @@ -175,7 +279,15 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde return attributes; } - attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; + // avoid OOB errors + const NSInteger section = indexPath.section; + const NSInteger item = indexPath.item; + if (section >= _sectionData.size() + || item >= _sectionData[section].itemBounds.size()) { + return nil; + } + + attributes = [[[self class] layoutAttributesClass] layoutAttributesForCellWithIndexPath:indexPath]; attributes.frame = _sectionData[indexPath.section].itemBounds[indexPath.item]; adjustZIndexForAttributes(attributes); _attributesCache[indexPath] = attributes; @@ -184,36 +296,55 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { IGAssertMainThread(); - IGParameterAssert([elementKind isEqualToString:UICollectionElementKindSectionHeader]); IGParameterAssert(indexPath != nil); - UICollectionViewLayoutAttributes *attributes = _headerAttributesCache[indexPath]; + UICollectionViewLayoutAttributes *attributes = _supplementaryAttributesCache[elementKind][indexPath]; if (attributes != nil) { return attributes; } - UICollectionView *collectionView = self.collectionView; + // avoid OOB errors const NSInteger section = indexPath.section; + if (section >= _sectionData.size()) { + return nil; + } + + UICollectionView *collectionView = self.collectionView; const IGListSectionEntry entry = _sectionData[section]; - const CGFloat minY = CGRectGetMinY(entry.bounds); + const CGFloat minOffset = CGRectGetMinInDirection(entry.bounds, self.scrollDirection); + + CGRect frame = CGRectZero; - CGRect frame = entry.headerBounds; + if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) { + frame = entry.headerBounds; - if (self.stickyHeaders) { - const CGFloat yOffset = collectionView.contentOffset.y + self.topContentInset + self.stickyHeaderOriginYAdjustment; + if (self.stickyHeaders) { + CGFloat offset = CGPointGetCoordinateInDirection(collectionView.contentOffset, self.scrollDirection) + self.topContentInset + self.stickyHeaderYOffset; - if (section + 1 == _sectionData.size()) { - frame.origin.y = MAX(minY, yOffset); - } else { - const CGFloat maxY = CGRectGetMinY(_sectionData[section + 1].bounds) - CGRectGetHeight(frame); - frame.origin.y = MIN(MAX(minY, yOffset), maxY); + if (section + 1 == _sectionData.size()) { + offset = MAX(minOffset, offset); + } else { + const CGFloat maxOffset = CGRectGetMinInDirection(_sectionData[section + 1].bounds, self.scrollDirection) - CGRectGetLengthInDirection(frame, self.scrollDirection); + offset = MIN(MAX(minOffset, offset), maxOffset); + } + switch (self.scrollDirection) { + case UICollectionViewScrollDirectionVertical: + frame.origin.y = offset; + break; + case UICollectionViewScrollDirectionHorizontal: + frame.origin.x = offset; + break; + } } + } else if ([elementKind isEqualToString:UICollectionElementKindSectionFooter]) { + frame = entry.footerBounds; } attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath]; attributes.frame = frame; adjustZIndexForAttributes(attributes); - _headerAttributesCache[indexPath] = attributes; + _supplementaryAttributesCache[elementKind][indexPath] = attributes; + return attributes; } @@ -227,11 +358,19 @@ - (CGSize)collectionViewContentSize { } const IGListSectionEntry section = _sectionData[sectionCount - 1]; - const CGFloat height = CGRectGetMaxY(section.bounds) + section.insets.bottom; - UICollectionView *collectionView = self.collectionView; - const UIEdgeInsets contentInset = collectionView.contentInset; - return CGSizeMake(CGRectGetWidth(collectionView.bounds) - contentInset.left - contentInset.right, height); + const UIEdgeInsets contentInset = collectionView.ig_contentInset; + switch (self.scrollDirection) { + case UICollectionViewScrollDirectionVertical: { + const CGFloat height = CGRectGetMaxY(section.bounds) + section.insets.bottom; + return CGSizeMake(CGRectGetWidth(collectionView.bounds) - contentInset.left - contentInset.right, height); + } + case UICollectionViewScrollDirectionHorizontal: { + const CGFloat width = CGRectGetMaxX(section.bounds) + section.insets.right; + return CGSizeMake(width, CGRectGetHeight(collectionView.bounds) - contentInset.top - contentInset.bottom); + } + } + } - (void)invalidateLayoutWithContext:(IGListCollectionViewLayoutInvalidationContext *)context { @@ -242,13 +381,16 @@ - (void)invalidateLayoutWithContext:(IGListCollectionViewLayoutInvalidationConte if (hasInvalidatedItemIndexPaths || [context invalidateEverything] - || [context invalidateDataSourceCounts] || context.ig_invalidateAllAttributes) { - _cachedLayoutInvalid = YES; + // invalidates all + _minimumInvalidatedSection = 0; + } else if ([context invalidateDataSourceCounts] && _minimumInvalidatedSection == NSNotFound) { + // invalidate all if count changed and we don't have information on the minimum invalidated section + _minimumInvalidatedSection = 0; } if (context.ig_invalidateSupplementaryAttributes) { - [_headerAttributesCache removeAllObjects]; + [self _resetSupplementaryAttributesCache]; } [super invalidateLayoutWithContext:context]; @@ -262,7 +404,7 @@ - (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChang const CGRect oldBounds = self.collectionView.bounds; IGListCollectionViewLayoutInvalidationContext *context = - (IGListCollectionViewLayoutInvalidationContext *)[super invalidationContextForBoundsChange:newBounds]; + (IGListCollectionViewLayoutInvalidationContext *)[super invalidationContextForBoundsChange:newBounds]; context.ig_invalidateSupplementaryAttributes = YES; if (!CGSizeEqualToSize(oldBounds.size, newBounds.size)) { context.ig_invalidateAllAttributes = YES; @@ -274,7 +416,7 @@ - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { const CGRect oldBounds = self.collectionView.bounds; // if the y origin has changed, only invalidate when using sticky headers - if (CGRectGetMinY(newBounds) != CGRectGetMinY(oldBounds)) { + if (CGRectGetMinInDirection(newBounds, self.scrollDirection) != CGRectGetMinInDirection(oldBounds, self.scrollDirection)) { return self.stickyHeaders; } @@ -283,20 +425,18 @@ - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { } - (void)prepareLayout { - if (_cachedLayoutInvalid) { - [self cacheLayout]; - } + [self _calculateLayoutIfNeeded]; } #pragma mark - Public API -- (void)setStickyHeaderOriginYAdjustment:(CGFloat)stickyHeaderOriginYAdjustment { +- (void)setStickyHeaderYOffset:(CGFloat)stickyHeaderYOffset { IGAssertMainThread(); - if (_stickyHeaderOriginYAdjustment != stickyHeaderOriginYAdjustment) { - _stickyHeaderOriginYAdjustment = stickyHeaderOriginYAdjustment; + if (_stickyHeaderYOffset != stickyHeaderYOffset) { + _stickyHeaderYOffset = stickyHeaderYOffset; - IGListCollectionViewLayoutInvalidationContext *invalidationContext = [[IGListCollectionViewLayoutInvalidationContext alloc] init]; + IGListCollectionViewLayoutInvalidationContext *invalidationContext = [IGListCollectionViewLayoutInvalidationContext new]; invalidationContext.ig_invalidateSupplementaryAttributes = YES; [self invalidateLayoutWithContext:invalidationContext]; } @@ -304,95 +444,130 @@ - (void)setStickyHeaderOriginYAdjustment:(CGFloat)stickyHeaderOriginYAdjustment #pragma mark - Private API -- (void)cacheLayout { - _cachedLayoutInvalid = NO; +- (void)_calculateLayoutIfNeeded { + if (_minimumInvalidatedSection == NSNotFound) { + return; + } // purge attribute caches so they are rebuilt [_attributesCache removeAllObjects]; - [_headerAttributesCache removeAllObjects]; + [self _resetSupplementaryAttributesCache]; UICollectionView *collectionView = self.collectionView; id dataSource = collectionView.dataSource; id delegate = (id)collectionView.delegate; const NSInteger sectionCount = [dataSource numberOfSectionsInCollectionView:collectionView]; - const UIEdgeInsets contentInset = collectionView.contentInset; - const CGFloat width = CGRectGetWidth(collectionView.bounds) - contentInset.left - contentInset.right; + const UIEdgeInsets contentInset = collectionView.ig_contentInset; + const CGRect contentInsetAdjustedCollectionViewBounds = UIEdgeInsetsInsetRect(collectionView.bounds, contentInset); - auto sectionData = std::vector(sectionCount); + _sectionData.resize(sectionCount); - CGFloat itemY = 0.0; - CGFloat itemX = 0.0; - CGFloat nextRowY = 0.0; + CGFloat itemCoordInScrollDirection = 0.0; + CGFloat itemCoordInFixedDirection = 0.0; + CGFloat nextRowCoordInScrollDirection = 0.0; // union item frames and optionally the header to find a bounding box of the entire section - CGRect rollingSectionBounds; + CGRect rollingSectionBounds = CGRectZero; + + // populate last valid section information + const NSInteger lastValidSection = _minimumInvalidatedSection - 1; + if (lastValidSection >= 0 && lastValidSection < sectionCount) { + itemCoordInScrollDirection = _sectionData[lastValidSection].lastItemCoordInScrollDirection; + itemCoordInFixedDirection = _sectionData[lastValidSection].lastItemCoordInFixedDirection; + nextRowCoordInScrollDirection = _sectionData[lastValidSection].lastNextRowCoordInScrollDirection; + rollingSectionBounds = _sectionData[lastValidSection].bounds; + } - for (NSInteger section = 0; section < sectionCount; section++) { + for (NSInteger section = _minimumInvalidatedSection; section < sectionCount; section++) { const NSInteger itemCount = [dataSource collectionView:collectionView numberOfItemsInSection:section]; - sectionData[section].itemBounds = std::vector(itemCount); + const BOOL itemsEmpty = itemCount == 0; + const BOOL hideHeaderWhenItemsEmpty = itemsEmpty && !self.showHeaderWhenEmpty; + _sectionData[section].itemBounds = std::vector(itemCount); const CGSize headerSize = [delegate collectionView:collectionView layout:self referenceSizeForHeaderInSection:section]; + const CGSize footerSize = [delegate collectionView:collectionView layout:self referenceSizeForFooterInSection:section]; const UIEdgeInsets insets = [delegate collectionView:collectionView layout:self insetForSectionAtIndex:section]; const CGFloat lineSpacing = [delegate collectionView:collectionView layout:self minimumLineSpacingForSectionAtIndex:section]; const CGFloat interitemSpacing = [delegate collectionView:collectionView layout:self minimumInteritemSpacingForSectionAtIndex:section]; - const CGFloat paddedWidth = width - insets.left - insets.right; - const BOOL headerExists = headerSize.height > 0; + const CGSize paddedCollectionViewSize = UIEdgeInsetsInsetRect(contentInsetAdjustedCollectionViewBounds, insets).size; + const UICollectionViewScrollDirection fixedDirection = self.scrollDirection == UICollectionViewScrollDirectionHorizontal ? UICollectionViewScrollDirectionVertical : UICollectionViewScrollDirectionHorizontal; + const CGFloat paddedLengthInFixedDirection = CGSizeGetLengthInDirection(paddedCollectionViewSize, fixedDirection); + const CGFloat headerLengthInScrollDirection = hideHeaderWhenItemsEmpty ? 0 : CGSizeGetLengthInDirection(headerSize, self.scrollDirection); + const CGFloat footerLengthInScrollDirection = hideHeaderWhenItemsEmpty ? 0 : CGSizeGetLengthInDirection(footerSize, self.scrollDirection); + const BOOL headerExists = headerLengthInScrollDirection > 0; + const BOOL footerExists = footerLengthInScrollDirection > 0; - // start the section y accounting for the header height - // header height is subtracted from the sectionBounds when calculating the header bounds after items are done - // this bumps the first row of items down enough to make room for the header - itemY += headerSize.height; - nextRowY += headerSize.height; + // start the section accounting for the header size + // header length in scroll direction is subtracted from the sectionBounds when calculating the header bounds after items are done + // this bumps the first row of items over enough to make room for the header + itemCoordInScrollDirection += headerLengthInScrollDirection; + nextRowCoordInScrollDirection += headerLengthInScrollDirection; + + // add the leading inset in fixed direction in case the section falls on the same row as the previous + // if the section is newlined then the coord in fixed direction is reset + itemCoordInFixedDirection += UIEdgeInsetsLeadingInsetInDirection(insets, fixedDirection); + + // the farthest in the fixed direction the frame of an item in this section can go + const CGFloat maxCoordinateInFixedDirection = CGRectGetLengthInDirection(contentInsetAdjustedCollectionViewBounds, fixedDirection) - UIEdgeInsetsTrailingInsetInDirection(insets, fixedDirection); - // add the left inset in case the section falls on the same row as the previous - // if the section is newlined then the x is reset - itemX += insets.left; - - // the farthest right the frame of an item in this section can go - const CGFloat maxX = width - insets.right; - for (NSInteger item = 0; item < itemCount; item++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section]; const CGSize size = [delegate collectionView:collectionView layout:self sizeForItemAtIndexPath:indexPath]; - IGAssert(size.width <= paddedWidth, @"Width of item %zi in section %zi must be less than container %.0f accounting for section insets %@", - item, section, width, NSStringFromUIEdgeInsets(insets)); - CGFloat itemWidth = MIN(size.width, paddedWidth); + IGAssert(CGSizeGetLengthInDirection(size, fixedDirection) <= paddedLengthInFixedDirection + || fabs(CGSizeGetLengthInDirection(size, fixedDirection) - paddedLengthInFixedDirection) < FLT_EPSILON, + @"%@ of item %li in section %li (%.0f pt) must be less than or equal to container (%.0f pt) accounting for section insets %@", + self.scrollDirection == UICollectionViewScrollDirectionVertical ? @"Width" : @"Height", + (long)item, + (long)section, + CGSizeGetLengthInDirection(size, fixedDirection), + CGRectGetLengthInDirection(contentInsetAdjustedCollectionViewBounds, fixedDirection), + NSStringFromUIEdgeInsets(insets)); + + CGFloat itemLengthInFixedDirection = MIN(CGSizeGetLengthInDirection(size, fixedDirection), paddedLengthInFixedDirection); - // if the x + width of the item busts the width of the container + // if the origin and length in fixed direction of the item busts the size of the container // or if this is the first item and the header has a non-zero size // newline to the next row and reset // define epsilon to avoid float overflow issue const CGFloat epsilon = 1.0; - if (itemX + itemWidth > maxX + epsilon + if (itemCoordInFixedDirection + itemLengthInFixedDirection > maxCoordinateInFixedDirection + epsilon || (item == 0 && headerExists)) { - itemY = nextRowY; - itemX = insets.left; + itemCoordInScrollDirection = nextRowCoordInScrollDirection; + itemCoordInFixedDirection = UIEdgeInsetsLeadingInsetInDirection(insets, fixedDirection); + // if newlining, always append line spacing unless its the very first item of the section if (item > 0) { - itemY += lineSpacing; + itemCoordInScrollDirection += lineSpacing; } } - - const CGFloat distanceToRighEdge = paddedWidth - (itemX + itemWidth); - if (self.stretchToEdge && distanceToRighEdge > 0 && distanceToRighEdge <= epsilon) { - itemWidth = paddedWidth - itemX; + + const CGFloat distanceToEdge = paddedLengthInFixedDirection - (itemCoordInFixedDirection + itemLengthInFixedDirection); + if (self.stretchToEdge && distanceToEdge > 0 && distanceToEdge <= epsilon) { + itemLengthInFixedDirection = paddedLengthInFixedDirection - itemCoordInFixedDirection; } - const CGRect frame = IGListRectIntegralScaled(CGRectMake(itemX, - itemY + insets.top, - itemWidth, - size.height)); - sectionData[section].itemBounds[item] = frame; + const CGRect rawFrame = (self.scrollDirection == UICollectionViewScrollDirectionVertical) ? + CGRectMake(itemCoordInFixedDirection, + itemCoordInScrollDirection + insets.top, + itemLengthInFixedDirection, + size.height) : + CGRectMake(itemCoordInScrollDirection + insets.left, + itemCoordInFixedDirection, + size.width, + itemLengthInFixedDirection); + const CGRect frame = IGListRectIntegralScaled(rawFrame); + + _sectionData[section].itemBounds[item] = frame; - // track the max size of the row to find the y of the next row, adjust for top inset while iterating items - nextRowY = MAX(CGRectGetMaxY(frame) - insets.top, nextRowY); + // track the max size of the row to find the coord of the next row, adjust for leading inset while iterating items + nextRowCoordInScrollDirection = MAX(CGRectGetMaxInDirection(frame, self.scrollDirection) - UIEdgeInsetsLeadingInsetInDirection(insets, self.scrollDirection), nextRowCoordInScrollDirection); - // increase the rolling x by the item width and add item spacing for all items on the same row - itemX += itemWidth + interitemSpacing; + // increase the rolling coord in fixed direction appropriately and add item spacing for all items on the same row + itemCoordInFixedDirection += itemLengthInFixedDirection + interitemSpacing; // union the rolling section bounds if (item == 0) { @@ -401,33 +576,63 @@ - (void)cacheLayout { rollingSectionBounds = CGRectUnion(rollingSectionBounds, frame); } } - - const CGRect headerBounds = CGRectMake(insets.left, - CGRectGetMinY(rollingSectionBounds) - headerSize.height, - paddedWidth, - headerSize.height); - sectionData[section].headerBounds = headerBounds; + + const CGRect headerBounds = self.scrollDirection == UICollectionViewScrollDirectionVertical ? + CGRectMake(insets.left, + itemsEmpty ? CGRectGetMaxY(rollingSectionBounds) : CGRectGetMinY(rollingSectionBounds) - headerSize.height, + paddedLengthInFixedDirection, + hideHeaderWhenItemsEmpty ? 0 : headerSize.height) : + CGRectMake(itemsEmpty ? CGRectGetMaxX(rollingSectionBounds) : CGRectGetMinX(rollingSectionBounds) - headerSize.width, + insets.top, + hideHeaderWhenItemsEmpty ? 0 : headerSize.width, + paddedLengthInFixedDirection); + + _sectionData[section].headerBounds = headerBounds; + + if (itemsEmpty) { + rollingSectionBounds = headerBounds; + } + + const CGRect footerBounds = (self.scrollDirection == UICollectionViewScrollDirectionVertical) ? + CGRectMake(insets.left, + CGRectGetMaxY(rollingSectionBounds), + paddedLengthInFixedDirection, + hideHeaderWhenItemsEmpty ? 0 : footerSize.height) : + CGRectMake(CGRectGetMaxX(rollingSectionBounds) + insets.right, + insets.top, + hideHeaderWhenItemsEmpty ? 0 : footerSize.width, + paddedLengthInFixedDirection); + + _sectionData[section].footerBounds = footerBounds; // union the header before setting the bounds of the section // only do this when the header has a size, otherwise the union stretches to box empty space if (headerExists) { rollingSectionBounds = CGRectUnion(rollingSectionBounds, headerBounds); } + if (footerExists) { + rollingSectionBounds = CGRectUnion(rollingSectionBounds, footerBounds); + } - sectionData[section].bounds = rollingSectionBounds; - sectionData[section].insets = insets; + _sectionData[section].bounds = rollingSectionBounds; + _sectionData[section].insets = insets; - // bump the x for the next section with the right insets - itemX += insets.right; + // bump the coord for the next section with the right insets + itemCoordInFixedDirection += UIEdgeInsetsTrailingInsetInDirection(insets, fixedDirection); - // find the lowest point in the section and add the bottom inset to find the next row's Y - nextRowY = MAX(nextRowY, CGRectGetMaxY(rollingSectionBounds) + insets.bottom); + // find the farthest point in the section and add the trailing inset to find the next row's coord + nextRowCoordInScrollDirection = MAX(nextRowCoordInScrollDirection, CGRectGetMaxInDirection(rollingSectionBounds, self.scrollDirection) + UIEdgeInsetsTrailingInsetInDirection(insets, self.scrollDirection)); + + // keep track of coordinates for partial invalidation + _sectionData[section].lastItemCoordInScrollDirection = itemCoordInScrollDirection; + _sectionData[section].lastItemCoordInFixedDirection = itemCoordInFixedDirection; + _sectionData[section].lastNextRowCoordInScrollDirection = nextRowCoordInScrollDirection; } - _sectionData = sectionData; + _minimumInvalidatedSection = NSNotFound; } -- (NSRange)rangeOfSectionsInRect:(CGRect)rect { +- (NSRange)_rangeOfSectionsInRect:(CGRect)rect { NSRange result = NSMakeRange(NSNotFound, 0); const NSInteger sectionCount = _sectionData.size(); @@ -442,8 +647,20 @@ - (NSRange)rangeOfSectionsInRect:(CGRect)rect { } } } - + return result; } +- (void)_resetSupplementaryAttributesCache { + [_supplementaryAttributesCache enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSMutableDictionary * _Nonnull attributesCache, BOOL * _Nonnull stop) { + [attributesCache removeAllObjects]; + }]; +} + +#pragma mark - Minimum Invalidated Section + +- (void)didModifySection:(NSInteger)modifiedSection { + _minimumInvalidatedSection = IGListMergeMinimumInvalidatedSection(_minimumInvalidatedSection, modifiedSection); +} + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListDisplayDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListDisplayDelegate.h index 00321da..c24663e 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListDisplayDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListDisplayDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,22 +10,23 @@ @class IGListAdapter; @class IGListSectionController; -@protocol IGListSectionType; + NS_ASSUME_NONNULL_BEGIN /** - Implement this protocol to receive display events for an section controller when it is on screen. + Implement this protocol to receive display events for a section controller when it is on screen. */ +NS_SWIFT_NAME(ListDisplayDelegate) @protocol IGListDisplayDelegate /** Tells the delegate that the specified section controller is about to be displayed. - @param listAdapter The list adapter for the section controller. + @param listAdapter The list adapter for the section controller. @param sectionController The section controller about to be displayed. */ -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController; /** Tells the delegate that the specified section controller is no longer being displayed. @@ -35,29 +34,29 @@ NS_ASSUME_NONNULL_BEGIN @param listAdapter The list adapter for the section controller. @param sectionController The section controller that is no longer displayed. */ -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController; /** Tells the delegate that a cell in the specified list is about to be displayed. - @param listAdapter The list adapter in which the cell will display. + @param listAdapter The list adapter in which the cell will display. @param sectionController The section controller that is displaying the cell. - @param cell The cell about to be displayed. - @param index The index of the cell in the section. + @param cell The cell about to be displayed. + @param index The index of the cell in the section. */ -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index; /** Tells the delegate that a cell in the specified list is no longer being displayed. - @param listAdapter The list adapter in which the cell was displayed. + @param listAdapter The list adapter in which the cell was displayed. @param sectionController The section controller that is no longer displaying the cell. - @param cell The cell that is no longer displayed. - @param index The index of the cell in the section. + @param cell The cell that is no longer displayed. + @param index The index of the cell in the section. */ -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.h new file mode 100644 index 0000000..f41be3d --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + This class adds a helper layer to `IGListSectionController` to automatically store a generic object in + `didUpdateToObject:`. + */ +NS_SWIFT_NAME(ListGenericSectionController) +@interface IGListGenericSectionController<__covariant ObjectType> : IGListSectionController + +/** + The object mapped to this section controller. Matches the object provided in + `[IGListAdapterDataSource listAdapter:sectionControllerForObject:]` when this section controller was created and + returned. + + @note This object is briefly `nil` between initialization and the first call to `didUpdateToObject:`. After that, it is + safe to assume that this is non-`nil`. + */ +@property (nonatomic, strong, nullable, readonly) ObjectType object; + +/** + Updates the section controller to a new object. + + @param object The object mapped to this section controller. + + @note This `IGListSectionController` subclass sets its object in this method, so any overrides **must call super**. + */ +- (void)didUpdateToObject:(id)object NS_REQUIRES_SUPER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.m new file mode 100644 index 0000000..78a9c4c --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListGenericSectionController.m @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListGenericSectionController.h" + +@implementation IGListGenericSectionController + +- (void)didUpdateToObject:(id)object { + _object = object; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListKit.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListKit.h index 9def504..19dc459 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListKit.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListKit.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -26,27 +24,32 @@ FOUNDATION_EXPORT const unsigned char IGListKitVersionString[]; #import #import #import +#import #import #import +#import +#import #import #import -#import #import -#import +#import #import #import +#import #import #import -#import -#import +#import +#import #import #import +#import #import #import #import +#import #import -#import #import +#import #endif diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.h index 342732a..d024057 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,13 +10,18 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** An `IGListReloadDataUpdater` is a concrete type that conforms to `IGListUpdatingDelegate`. - It is an out-of-box upater for `IGListAdapter` objects to use. + It is an out-of-box updater for `IGListAdapter` objects to use. @note This updater performs simple, synchronous updates using `-[UICollectionView reloadData]`. */ IGLK_SUBCLASSING_RESTRICTED +NS_SWIFT_NAME(ListReloadDataUpdater) @interface IGListReloadDataUpdater : NSObject @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.m index c508cb1..737455e 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListReloadDataUpdater.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -19,12 +17,15 @@ - (NSPointerFunctions *)objectLookupPointerFunctions { - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView fromObjects:(NSArray *)fromObjects - toObjects:(NSArray *)toObjects + toObjectsBlock:(IGListToObjectBlock)toObjectsBlock animated:(BOOL)animated objectTransitionBlock:(IGListObjectTransitionBlock)objectTransitionBlock completion:(IGListUpdatingCompletion)completion { - objectTransitionBlock(toObjects); - [self synchronousReloadDataWithCollectionView:collectionView]; + if (toObjectsBlock != nil) { + NSArray *toObjects = toObjectsBlock() ?: @[]; + objectTransitionBlock(toObjects); + } + [self _synchronousReloadDataWithCollectionView:collectionView]; if (completion) { completion(YES); } @@ -35,41 +36,49 @@ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView itemUpdates:(IGListItemUpdateBlock)itemUpdates completion:(IGListUpdatingCompletion)completion { itemUpdates(); - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; if (completion) { completion(YES); } } - (void)insertItemsIntoCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths { - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; } - (void)deleteItemsFromCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths { - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; } - (void)moveItemInCollectionView:(UICollectionView *)collectionView fromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; +} + +- (void)reloadItemInCollectionView:(UICollectionView *)collectionView fromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { + [self _synchronousReloadDataWithCollectionView:collectionView]; } -- (void)reloadItemsInCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths { - [self synchronousReloadDataWithCollectionView:collectionView]; +- (void)_reloadItemsInCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths { + [self _synchronousReloadDataWithCollectionView:collectionView]; +} + +- (void)moveSectionInCollectionView:(UICollectionView *)collectionView fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { + [self _synchronousReloadDataWithCollectionView:collectionView]; } - (void)reloadDataWithCollectionView:(UICollectionView *)collectionView reloadUpdateBlock:(IGListReloadUpdateBlock)reloadUpdateBlock completion:(IGListUpdatingCompletion)completion { reloadUpdateBlock(); - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; if (completion) { completion(YES); } } - (void)reloadCollectionView:(UICollectionView *)collectionView sections:(NSIndexSet *)sections { - [self synchronousReloadDataWithCollectionView:collectionView]; + [self _synchronousReloadDataWithCollectionView:collectionView]; } -- (void)synchronousReloadDataWithCollectionView:(UICollectionView *)collectionView { +- (void)_synchronousReloadDataWithCollectionView:(UICollectionView *)collectionView { [collectionView reloadData]; [collectionView layoutIfNeeded]; } diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListScrollDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListScrollDelegate.h index d13576f..843a105 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListScrollDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListScrollDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,35 +10,52 @@ @class IGListAdapter; @class IGListSectionController; -@protocol IGListSectionType; + + +NS_ASSUME_NONNULL_BEGIN /** - Implement this protocol to receive display events for an section controller when it is on screen. + Implement this protocol to receive display events for a section controller when it is on screen. */ +NS_SWIFT_NAME(ListScrollDelegate) @protocol IGListScrollDelegate /** Tells the delegate that the section controller was scrolled on screen. - @param listAdapter The list adapter whose collection view was scrolled. + @param listAdapter The list adapter whose collection view was scrolled. @param sectionController The visible section controller that was scrolled. */ -- (void)listAdapter:(IGListAdapter *)listAdapter didScrollSectionController:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter didScrollSectionController:(IGListSectionController *)sectionController; /** Tells the delegate that the section controller will be dragged on screen. - @param listAdapter The list adapter whose collection view will drag. + @param listAdapter The list adapter whose collection view will drag. @param sectionController The visible section controller that will drag. */ -- (void)listAdapter:(IGListAdapter *)listAdapter willBeginDraggingSectionController:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter willBeginDraggingSectionController:(IGListSectionController *)sectionController; /** Tells the delegate that the section controller did end dragging on screen. - @param listAdapter The list adapter whose collection view ended dragging. + @param listAdapter The list adapter whose collection view ended dragging. @param sectionController The visible section controller that ended dragging. */ -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDraggingSectionController:(IGListSectionController *)sectionController willDecelerate:(BOOL)decelerate; +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDraggingSectionController:(IGListSectionController *)sectionController willDecelerate:(BOOL)decelerate; + +@optional + +/** + Tells the delegate that the section controller did end decelerating on screen. + + @param listAdapter The list adapter whose collection view ended decelerating. + @param sectionController The visible section controller that ended decelerating. + + @note This method is `@optional` until the next breaking-change release. + */ +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDeceleratingSectionController:(IGListSectionController *)sectionController; @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.h index 99b9527..8946a8e 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,12 +12,121 @@ #import #import #import +#import + +NS_ASSUME_NONNULL_BEGIN /** The base class for section controllers used in a list. This class is intended to be subclassed. */ +NS_SWIFT_NAME(ListSectionController) @interface IGListSectionController : NSObject +/** + Returns the number of items in the section. + + @return A count of items in the list. + + @note The count returned is used to drive the number of cells displayed for this section controller. The default + implementation returns 1. **Calling super is not required.** + */ +- (NSInteger)numberOfItems; + +/** + The specific size for the item at the specified index. + + @param index The row index of the item. + + @return The size for the item at index. + + @note The returned size is not guaranteed to be used. The implementation may query sections for their + layout information at will, or use its own layout metrics. For example, consider a dynamic-text sized list versus a + fixed height-and-width grid. The former will ask each section for a size, and the latter will likely not. The default + implementation returns size zero. **Calling super is not required.** + */ +- (CGSize)sizeForItemAtIndex:(NSInteger)index; + +/** + Return a dequeued cell for a given index. + + @param index The index of the requested row. + + @return A configured `UICollectionViewCell` subclass. + + @note This is your opportunity to do any cell setup and configuration. The infrastructure requests a cell when it + will be used on screen. You should never allocate new cells in this method, instead use the provided adapter to call + one of the dequeue methods on the IGListCollectionContext. The default implementation will assert. **You must override + this method without calling super.** + */ +- (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index; + +/** + Updates the section controller to a new object. + + @param object The object mapped to this section controller. + + @note When this method is called, all available contexts and configurations have been set for the section + controller. This method will only be called when the object instance has changed, including from `nil` or a previous + object. **Calling super is not required.** + */ +- (void)didUpdateToObject:(id)object; + +/** + Tells the section controller that the cell at the specified index path was selected. + + @param index The index of the selected cell. + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (void)didSelectItemAtIndex:(NSInteger)index; + +/** + Tells the section controller that the cell at the specified index path was deselected. + + @param index The index of the deselected cell. + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (void)didDeselectItemAtIndex:(NSInteger)index; + +/** + Tells the section controller that the cell at the specified index path was highlighted. + + @param index The index of the highlighted cell. + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (void)didHighlightItemAtIndex:(NSInteger)index; + +/** + Tells the section controller that the cell at the specified index path was unhighlighted. + + @param index The index of the unhighlighted cell. + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (void)didUnhighlightItemAtIndex:(NSInteger)index; + +/** + Identifies whether an object can be moved through interactive reordering. + + @param index The index of the unhighlighted cell. + + @note Interactive reordering is supported both for items within a single section, as well as for reordering sections + themselves when sections contain only one item. The default implementation returns false. + */ +- (BOOL)canMoveItemAtIndex:(NSInteger)index; + +/** + Notifies the section that a list object should move within a section as the result of interactive reordering. + + @param sourceIndex The starting index of the object. + @param destinationIndex The ending index of the object. + + @note this method must be implemented if interactive reordering is enabled. + */ +- (void)moveObjectFromIndex:(NSInteger)sourceIndex toIndex:(NSInteger)destinationIndex NS_AVAILABLE_IOS(9_0); + /** The view controller housing the adapter that created this section controller. @@ -33,10 +140,18 @@ /** A context object for interacting with the collection. - Use this property for accessing the collection size, dequeing cells, reloading, inserting, deleting, etc. + Use this property for accessing the collection size, dequeuing cells, reloading, inserting, deleting, etc. */ @property (nonatomic, weak, nullable, readonly) id collectionContext; +/** + Returns the section within the list for this section controller. + + @note This value also relates to the section within a `UICollectionView` that this section controller's cells belong. + It also relates to the `-[NSIndexPath section]` value for individual cells within the collection view. + */ +@property (nonatomic, assign, readonly) NSInteger section; + /** Returns `YES` if the section controller is the first section in the list, `NO` otherwise. */ @@ -104,4 +219,15 @@ */ @property (nonatomic, weak, nullable) id scrollDelegate; +/** + An object that handles transition events for the section controller. Can be `nil`. + + @return An object that conforms to `IGListTransitionDelegat` or `nil`. + + @note You may wish to return `self` if your section controller implements this protocol. + */ +@property (nonatomic, weak, nullable) id transitionDelegate; + @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.m index 5e36b68..3f71644 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionController.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListSectionControllerInternal.h" @@ -62,8 +60,44 @@ - (instancetype)init { _minimumInteritemSpacing = 0.0; _minimumLineSpacing = 0.0; _inset = UIEdgeInsetsZero; + _section = NSNotFound; } return self; } +- (NSInteger)numberOfItems { + return 1; +} + +- (CGSize)sizeForItemAtIndex:(NSInteger)index { + return CGSizeZero; +} + +- (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { + IGFailAssert(@"Section controller %@ must override %s:", self, __PRETTY_FUNCTION__); + return nil; +} + +- (void)didUpdateToObject:(id)object {} + +- (void)didSelectItemAtIndex:(NSInteger)index {} + +- (void)didDeselectItemAtIndex:(NSInteger)index {} + +- (void)didHighlightItemAtIndex:(NSInteger)index {} + +- (void)didUnhighlightItemAtIndex:(NSInteger)index {} + +- (BOOL)canMoveItemAtIndex:(NSInteger)index { + return NO; +} + +- (BOOL)canMoveItemAtIndex:(NSInteger)sourceItemIndex toIndex:(NSInteger)destinationItemIndex { + return [self canMoveItemAtIndex:sourceItemIndex]; +} + +- (void)moveObjectFromIndex:(NSInteger)sourceIndex toIndex:(NSInteger)destinationIndex { + IGFailAssert(@"Section controller %@ must override %s if interactive reordering is enabled.", self, __PRETTY_FUNCTION__); +} + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionType.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionType.h deleted file mode 100644 index 72193df..0000000 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSectionType.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@protocol IGListSupplementaryViewSource; -@protocol IGListDisplayDelegate; -@protocol IGListWorkingRangeDelegate; - -NS_ASSUME_NONNULL_BEGIN - -/** - Implement this protocol in order to be used within the `IGListKit` data infrastructure and be registered for use in an - `IGListAdapter`. An `IGListSectionType` conforming object represents a single instance of an object in a collection of - objects. - - The infrastructure uses each `IGListSectionType` conforming object as a "view model" to populate and control cells as - part of a section in a `UICollectionView`. `IGListSectionType` objects should be architected without knowledge of - "global" state of the list in which they are contained. - - Index paths are used as a convenience for communicating the section index to each section object without allowing each - section to mutate its own position within a list. The row of an index path can be directly mapped to a cell within - an `IGListSectionType` conforming object. - */ -@protocol IGListSectionType - -/** - Returns the number of items in the section. - - @return A count of items in the list. - - @note The count returned is used to drive the number of cells displayed for this list. You are free to change - this value between data loading passes. - */ -- (NSInteger)numberOfItems; - -/** - The specific size for the item at the specified index. - - @param index The row index of the item. - - @return The size for the item at index. - - @note The returned size is not garaunteed to be used. The implementation may query sections for their - layout information at will, or use its own layout metrics. For example, consider a dynamic-text sized list versus a fixed - height-and-width grid. The former will ask each section for a size, and the latter will likely not. - */ -- (CGSize)sizeForItemAtIndex:(NSInteger)index; - -/** - Asks the section controller for a fully configured cell at the specified index. - - @param index The index of the requested row. - - @return A configured `UICollectionViewCell` subclass. - - @note This is your opportunity to do any cell setup and configuration. The infrastructure requests a cell when it - will be used on screen. You should never allocate new cells in this method, instead use the provided adapter to call - `-dequeCellClass:forIndexPath:` which either deques a cell from the collection view or creates a new one for you. - */ -- (__kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index; - -/** - Tells the section that the controller was updated to a new object. - - @param object The object mapped to this section controller. - - @note When this method is called, all available contexts and configurations have been set for the section - controller. Also, depending on the updating strategy used, your item models may have changed objects in memory, so you - can use this event to update the object stored on your section controller. - - This method will only be called when the object instance has changed, including from `nil` or a previous object. - */ -- (void)didUpdateToObject:(id)object; - -/** - Tells the section that the cell at the specified index path was selected. - - @param index The index of the selected cell. - */ -- (void)didSelectItemAtIndex:(NSInteger)index; - -@end - -NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.h index 7d7cf05..2d2dbf0 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.h @@ -1,16 +1,14 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import #import -#import + #import NS_ASSUME_NONNULL_BEGIN @@ -22,16 +20,18 @@ NS_ASSUME_NONNULL_BEGIN @param item The model with which to configure the cell. @param cell The cell to configure. */ +NS_SWIFT_NAME(ListSingleSectionCellConfigureBlock) typedef void (^IGListSingleSectionCellConfigureBlock)(id item, __kindof UICollectionViewCell *cell); /** A block that returns the size for the cell given the collection context. - @param item The model for the section. + @param item The model for the section. @param collectionContext The collection context for the section. - @return The for the cell. + @return The size for the cell. */ +NS_SWIFT_NAME(ListSingleSectionCellSizeBlock) typedef CGSize (^IGListSingleSectionCellSizeBlock)(id item, id _Nullable collectionContext); @class IGListSingleSectionController; @@ -39,32 +39,48 @@ typedef CGSize (^IGListSingleSectionCellSizeBlock)(id item, id /** Tells the delegate that the section controller was selected. @param sectionController The section controller that was selected. - @param object The model for the given section. + @param object The model for the given section. */ - (void)didSelectSectionController:(IGListSingleSectionController *)sectionController withObject:(id)object; +@optional + +/** + Tells the delegate that the section controller was deselected. + + @param sectionController The section controller that was deselected. + @param object The model for the given section. + + @note Method is `@optional` until the 4.0.0 release where it will become required. + */ +- (void)didDeselectSectionController:(IGListSingleSectionController *)sectionController + withObject:(id)object; + @end /** This section controller is meant to make building simple, single-cell lists easier. By providing the type of cell, a block - to configure the cell, and a block to return the size of a cell, you can use an IGListAdapter-powered list simpler architecture. + to configure the cell, and a block to return the size of a cell, you can use an `IGListAdapter`-powered list with a + simpler architecture. */ IGLK_SUBCLASSING_RESTRICTED -@interface IGListSingleSectionController : IGListSectionController +NS_SWIFT_NAME(ListSingleSectionController) +@interface IGListSingleSectionController : IGListSectionController /** Creates a new section controller for a given cell type that will always have only one cell when present in a list. - @param cellClass The `UICollectionViewCell` subclass for the single cell. + @param cellClass The `UICollectionViewCell` subclass for the single cell. @param configureBlock A block that configures the cell with the item given to the section controller. - @param sizeBlock A block that returns the size for the cell given the collection context. + @param sizeBlock A block that returns the size for the cell given the collection context. @return A new section controller. @@ -78,10 +94,10 @@ IGLK_SUBCLASSING_RESTRICTED /** Creates a new section controller for a given nib name and bundle that will always have only one cell when present in a list. - @param nibName The name of the nib file for the single cell. - @param bundle The bundle in which to search for the nib file. If nil, this method looks for the file in the main bundle. + @param nibName The name of the nib file for the single cell. + @param bundle The bundle in which to search for the nib file. If `nil`, this method looks for the file in the main bundle. @param configureBlock A block that configures the cell with the item given to the section controller. - @param sizeBlock A block that returns the size for the cell given the collection context. + @param sizeBlock A block that returns the size for the cell given the collection context. @return A new section controller. @@ -96,9 +112,9 @@ IGLK_SUBCLASSING_RESTRICTED /** Creates a new section controller for a given storyboard cell identifier that will always have only one cell when present in a list. - @param identifier The identifier of the cell prototype in storyboard. + @param identifier The identifier of the cell prototype in storyboard. @param configureBlock A block that configures the cell with the item given to the section controller. - @param sizeBlock A block that returns the size for the cell given the collection context. + @param sizeBlock A block that returns the size for the cell given the collection context. @return A new section controller. diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.m index a57b224..c517022 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListSingleSectionController.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListSingleSectionController.h" @@ -71,7 +69,7 @@ - (instancetype)initWithStoryboardCellIdentifier:(NSString *)identifier } -#pragma mark - IGListSectionType +#pragma mark - IGListSectionController Overrides - (NSInteger)numberOfItems { return 1; @@ -109,4 +107,10 @@ - (void)didSelectItemAtIndex:(NSInteger)index { [self.selectionDelegate didSelectSectionController:self withObject:self.item]; } +- (void)didDeselectItemAtIndex:(NSInteger)index { + if ([self.selectionDelegate respondsToSelector:@selector(didDeselectSectionController:withObject:)]) { + [self.selectionDelegate didDeselectSectionController:self withObject:self.item]; + } +} + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.h index f8cc318..2b7f90e 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.h @@ -1,28 +1,29 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import -#import + #import +NS_ASSUME_NONNULL_BEGIN + /** - An instance of `IGListStackedSectionController` is a clustered section controller, - composed of many child section controllers. It constructs and routes item-level - indexes to the appropriate child section controller with a local index. This lets you build section controllers made up - of individual units that can be shared and reused with other section controllers. + An instance of `IGListStackedSectionController` is a clustered section controller, composed of many child section + controllers. It constructs and routes item-level indexes to the appropriate child section controller with a local + index. This lets you build section controllers made up of individual units that can be shared and reused with other + section controllers. For example, you can create a "Comments" section controller that displays lists of text that is used alongside photo, video, or slideshow section controllers. You then have four small and manageable section controllers instead of one huge class. */ IGLK_SUBCLASSING_RESTRICTED -@interface IGListStackedSectionController : IGListSectionController +NS_SWIFT_NAME(ListStackedSectionController) +@interface IGListStackedSectionController : IGListSectionController /** Creates a new stacked section controller. @@ -33,7 +34,7 @@ IGLK_SUBCLASSING_RESTRICTED @warning The first section controller that is the supplementary source decides which supplementary views get displayed. */ -- (instancetype)initWithSectionControllers:(NSArray *> *)sectionControllers NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithSectionControllers:(NSArray *)sectionControllers NS_DESIGNATED_INITIALIZER; /** :nodoc: @@ -46,3 +47,5 @@ IGLK_SUBCLASSING_RESTRICTED + (instancetype)new NS_UNAVAILABLE; @end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.m b/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.m index f6666d4..411ea55 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListStackedSectionController.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListStackedSectionControllerInternal.h" @@ -44,14 +42,14 @@ - (NSInteger)ig_stackedSectionControllerIndex { @implementation IGListStackedSectionController -- (instancetype)initWithSectionControllers:(NSArray *> *)sectionControllers { +- (instancetype)initWithSectionControllers:(NSArray *)sectionControllers { if (self = [super init]) { - for (IGListSectionController *sectionController in sectionControllers) { + for (IGListSectionController *sectionController in sectionControllers) { sectionController.collectionContext = self; sectionController.viewController = self.viewController; } - _visibleSectionControllers = [[NSCountedSet alloc] init]; + _visibleSectionControllers = [NSCountedSet new]; _sectionControllers = [NSOrderedSet orderedSetWithArray:sectionControllers]; self.displayDelegate = self; @@ -65,11 +63,11 @@ - (instancetype)initWithSectionControllers:(NSArray *sectionController in self.sectionControllers) { + for (IGListSectionController *sectionController in self.sectionControllers) { [offsets addObject:@(numberOfItems)]; const NSInteger items = [sectionController numberOfItems]; @@ -88,30 +86,30 @@ - (void)reloadData { IGAssert(self.sectionControllersForItems.count == self.flattenedNumberOfItems, @"Controller map does not equal total number of items"); } -- (IGListSectionController *)sectionControllerForObjectIndex:(NSInteger)itemIndex { +- (IGListSectionController *)sectionControllerForObjectIndex:(NSInteger)itemIndex { return self.sectionControllersForItems[itemIndex]; } -- (NSInteger)offsetForSectionController:(IGListSectionController *)sectionController { +- (NSInteger)offsetForSectionController:(IGListSectionController *)sectionController { const NSInteger index = [self.sectionControllers indexOfObject:sectionController]; IGAssert(index != NSNotFound, @"Querying offset for an undocumented section controller"); return [self.sectionControllerOffsets[index] integerValue]; } -- (NSInteger)localIndexForSectionController:(IGListSectionController *)sectionController index:(NSInteger)index { +- (NSInteger)_localIndexForSectionController:(IGListSectionController *)sectionController index:(NSInteger)index { const NSInteger offset = [self offsetForSectionController:sectionController]; IGAssert(offset <= index, @"Section controller offset must be less than or equal to the item index"); return index - offset; } -- (NSInteger)relativeIndexForSectionController:(IGListSectionController *)sectionController fromLocalIndex:(NSInteger)index { +- (NSInteger)_relativeIndexForSectionController:(IGListSectionController *)sectionController fromLocalIndex:(NSInteger)index { const NSInteger offset = [self offsetForSectionController:sectionController]; return index + offset; } -- (NSIndexSet *)itemIndexesForSectionController:(IGListSectionController *)sectionController indexes:(NSIndexSet *)indexes { +- (NSIndexSet *)_itemIndexesForSectionController:(IGListSectionController *)sectionController indexes:(NSIndexSet *)indexes { const NSInteger offset = [self offsetForSectionController:sectionController]; - NSMutableIndexSet *itemIndexes = [[NSMutableIndexSet alloc] init]; + NSMutableIndexSet *itemIndexes = [NSMutableIndexSet new]; [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { [itemIndexes addIndex:(idx + offset)]; }]; @@ -128,59 +126,136 @@ - (NSIndexSet *)itemIndexesForSectionController:(IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; - const NSInteger localIndex = [self localIndexForSectionController:sectionController index:index]; + // during interactive reordering, its possible for an item to be moved into a section beyond the last section + // in that case, just return the size of the current last item in the section + const NSInteger maxIndex = [self numberOfItems]-1; + const NSInteger effectiveIndex = MAX(MIN(index, maxIndex), 0); + + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:effectiveIndex]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; return [sectionController sizeForItemAtIndex:localIndex]; } - (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index { - IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; - const NSInteger localIndex = [self localIndexForSectionController:sectionController index:index]; + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; return [sectionController cellForItemAtIndex:localIndex]; } - (void)didUpdateToObject:(id)object { - for (IGListSectionController *sectionController in self.sectionControllers) { + for (IGListSectionController *sectionController in self.sectionControllers) { + sectionController.section = self.section; [sectionController didUpdateToObject:object]; } [self reloadData]; } - (void)didSelectItemAtIndex:(NSInteger)index { - IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; - const NSInteger localIndex = [self localIndexForSectionController:sectionController index:index]; + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; [sectionController didSelectItemAtIndex:localIndex]; } +- (void)didDeselectItemAtIndex:(NSInteger)index { + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; + [sectionController didDeselectItemAtIndex:localIndex]; +} + +- (void)didHighlightItemAtIndex:(NSInteger)index { + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; + [sectionController didHighlightItemAtIndex:localIndex]; +} + +- (void)didUnhighlightItemAtIndex:(NSInteger)index { + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; + [sectionController didUnhighlightItemAtIndex:localIndex]; +} + +- (BOOL)canMoveItemAtIndex:(NSInteger)index { + IGListSectionController *sectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:sectionController index:index]; + return [sectionController canMoveItemAtIndex:localIndex]; +} + +- (BOOL)canMoveItemAtIndex:(NSInteger)sourceItemIndex toIndex:(NSInteger)destinationItemIndex { + IGListSectionController *sourceSectionController = [self sectionControllerForObjectIndex:sourceItemIndex]; + IGListSectionController *destinationSectionController = [self sectionControllerForObjectIndex:destinationItemIndex]; + + BOOL isSameSection = (sourceSectionController == destinationSectionController); + + BOOL allSectionsAreSingleItem = YES; + for (IGListSectionController *section in self.sectionControllers) { + if ([section numberOfItems] != 1) { + allSectionsAreSingleItem = NO; + break; + } + } + + return isSameSection || allSectionsAreSingleItem; +} + +- (void)moveObjectFromIndex:(NSInteger)sourceIndex toIndex:(NSInteger)destinationIndex { + IGListSectionController *sourceSection = [self sectionControllerForObjectIndex:sourceIndex]; + IGListSectionController *destinationSection = [self sectionControllerForObjectIndex:destinationIndex]; + + __weak __typeof__(self) weakSelf = self; + [self performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + if (sourceSection == destinationSection) { + // this is a move within a sub-section + [weakSelf moveInSectionControllerInteractive:sourceSection fromIndex:sourceIndex toIndex:destinationIndex]; + } + else { + // this is a reordering of sub-sections themselves + // canMoveItemAtIndex:toIndex: ensures that all sub-sections have only 1 item + [weakSelf moveSectionControllerInteractive:sourceSection fromIndex:sourceIndex toIndex:destinationIndex]; + } + } completion:nil]; +} + #pragma mark - IGListCollectionContext - (CGSize)containerSize { return [self.collectionContext containerSize]; } -- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController { +- (UIEdgeInsets)containerInset { + return [self.collectionContext containerInset]; +} + +- (UIEdgeInsets)adjustedContainerInset { + return [self.collectionContext adjustedContainerInset]; +} + +- (CGSize)insetContainerSize { + return [self.collectionContext insetContainerSize]; +} + +- (CGSize)containerSizeForSectionController:(IGListSectionController *)sectionController { const UIEdgeInsets inset = sectionController.inset; return CGSizeMake(self.containerSize.width - inset.left - inset.right, self.containerSize.height - inset.top - inset.bottom); } -- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(IGListSectionController *)sectionController { +- (NSInteger)indexForCell:(UICollectionViewCell *)cell sectionController:(IGListSectionController *)sectionController { const NSInteger index = [self.collectionContext indexForCell:cell sectionController:self]; - return [self localIndexForSectionController:sectionController index:index]; + return [self _localIndexForSectionController:sectionController index:index]; } -- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index sectionController:(IGListSectionController *)sectionController { - return [self.collectionContext cellForItemAtIndex: [self relativeIndexForSectionController:sectionController fromLocalIndex:index] sectionController:self]; +- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index sectionController:(IGListSectionController *)sectionController { + return [self.collectionContext cellForItemAtIndex: [self _relativeIndexForSectionController:sectionController fromLocalIndex:index] sectionController:self]; } -- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController { +- (NSArray *)visibleCellsForSectionController:(IGListSectionController *)sectionController { NSMutableArray *cells = [NSMutableArray new]; id collectionContext = self.collectionContext; NSArray *visibleCells = [collectionContext visibleCellsForSectionController:self]; @@ -193,7 +268,7 @@ - (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index sectionController: return cells; } -- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *)sectionController { +- (NSArray *)visibleIndexPathsForSectionController:(IGListSectionController *)sectionController { NSMutableArray *paths = [NSMutableArray new]; id collectionContext = self.collectionContext; NSArray *visiblePaths = [collectionContext visibleIndexPathsForSectionController:self]; @@ -205,29 +280,41 @@ - (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index sectionController: return paths; } -- (void)deselectItemAtIndex:(NSInteger)index sectionController:(IGListSectionController *)sectionController animated:(BOOL)animated { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; +- (void)deselectItemAtIndex:(NSInteger)index sectionController:(IGListSectionController *)sectionController animated:(BOOL)animated { + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; [self.collectionContext deselectItemAtIndex:offsetIndex sectionController:self animated:animated]; } -- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController { - return [self.collectionContext sectionForSectionController:self]; +- (void)selectItemAtIndex:(NSInteger)index + sectionController:(IGListSectionController *)sectionController + animated:(BOOL)animated + scrollPosition:(UICollectionViewScrollPosition)scrollPosition { + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; + [self.collectionContext selectItemAtIndex:offsetIndex sectionController:self animated:animated scrollPosition:scrollPosition]; } - (UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass - forSectionController:(IGListSectionController *)sectionController + withReuseIdentifier:(NSString *)reuseIdentifier + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableCellOfClass:cellClass + withReuseIdentifier:reuseIdentifier forSectionController:self atIndex:offsetIndex]; } +- (UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass + forSectionController:(IGListSectionController *)sectionController + atIndex:(NSInteger)index { + return [self dequeueReusableCellOfClass:cellClass withReuseIdentifier:nil forSectionController:sectionController atIndex:index]; +} + - (UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableCellWithNibName:nibName bundle:bundle forSectionController:self @@ -235,19 +322,19 @@ - (UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName } - (UICollectionViewCell *)dequeueReusableCellFromStoryboardWithIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableCellFromStoryboardWithIdentifier:identifier forSectionController:self atIndex:offsetIndex]; } - (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController class:(Class)viewClass atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableSupplementaryViewOfKind:elementKind forSectionController:self class:viewClass @@ -256,9 +343,9 @@ - (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString * - (UICollectionReusableView *)dequeueReusableSupplementaryViewFromStoryboardOfKind:(NSString *)elementKind withIdentifier:(NSString *)identifier - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableSupplementaryViewFromStoryboardOfKind:elementKind withIdentifier:identifier forSectionController:self @@ -266,11 +353,11 @@ - (UICollectionReusableView *)dequeueReusableSupplementaryViewFromStoryboardOfKi } - (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind - forSectionController:(IGListSectionController *)sectionController + forSectionController:(IGListSectionController *)sectionController nibName:(NSString *)nibName bundle:(NSBundle *)bundle atIndex:(NSInteger)index { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; return (UICollectionViewCell *_Nonnull)[self.collectionContext dequeueReusableSupplementaryViewOfKind:elementKind forSectionController:self nibName:nibName @@ -278,66 +365,103 @@ - (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString * atIndex:offsetIndex]; } -- (void)reloadInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { - NSIndexSet *itemIndexes = [self itemIndexesForSectionController:sectionController indexes:indexes]; - [self.collectionContext reloadInSectionController:self atIndexes:itemIndexes]; -} - -- (void)insertInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { - [self reloadData]; - NSIndexSet *itemIndexes = [self itemIndexesForSectionController:sectionController indexes:indexes]; - [self.collectionContext insertInSectionController:self atIndexes:itemIndexes]; -} - -- (void)deleteInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { - [self reloadData]; - NSIndexSet *itemIndexes = [self itemIndexesForSectionController:sectionController indexes:indexes]; - [self.collectionContext deleteInSectionController:self atIndexes:itemIndexes]; -} - -- (void)moveInSectionController:(IGListSectionController *)sectionController fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { - [self reloadData]; - const NSInteger fromRelativeIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:fromIndex]; - const NSInteger toRelativeIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:toIndex]; - [self.collectionContext moveInSectionController:self fromIndex:fromRelativeIndex toIndex:toRelativeIndex]; -} - -- (void)reloadSectionController:(IGListSectionController *)sectionController { - [self reloadData]; - [self.collectionContext reloadSectionController:self]; -} - -- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion { - [self.collectionContext performBatchAnimated:animated updates:^{ - updates(); +- (void)performBatchAnimated:(BOOL)animated updates:(void (^)(id))updates completion:(void (^)(BOOL))completion { + __weak __typeof__(self) weakSelf = self; + [self.collectionContext performBatchAnimated:animated updates:^ (id batchContext) { + weakSelf.forwardingBatchContext = batchContext; + updates(weakSelf); + weakSelf.forwardingBatchContext = nil; } completion:^(BOOL finished) { - [self reloadData]; + [weakSelf reloadData]; if (completion) { completion(finished); } }]; } -- (void)scrollToSectionController:(IGListSectionController *)sectionController +- (void)scrollToSectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index scrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated { - const NSInteger offsetIndex = [self relativeIndexForSectionController:sectionController fromLocalIndex:index]; + const NSInteger offsetIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:index]; [self.collectionContext scrollToSectionController:self atIndex:offsetIndex scrollPosition:scrollPosition animated:animated]; } -- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController completion:(void (^)(BOOL))completion { +- (void)invalidateLayoutForSectionController:(IGListSectionController *)sectionController completion:(void (^)(BOOL))completion { [self.collectionContext invalidateLayoutForSectionController:self completion:completion]; } +#pragma mark - IGListBatchContext + +- (void)reloadInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { + NSIndexSet *itemIndexes = [self _itemIndexesForSectionController:sectionController indexes:indexes]; + [self.forwardingBatchContext reloadInSectionController:self atIndexes:itemIndexes]; +} + +- (void)insertInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { + [self reloadData]; + NSIndexSet *itemIndexes = [self _itemIndexesForSectionController:sectionController indexes:indexes]; + [self.forwardingBatchContext insertInSectionController:self atIndexes:itemIndexes]; +} + +- (void)deleteInSectionController:(IGListSectionController *)sectionController atIndexes:(NSIndexSet *)indexes { + [self reloadData]; + NSIndexSet *itemIndexes = [self _itemIndexesForSectionController:sectionController indexes:indexes]; + [self.forwardingBatchContext deleteInSectionController:self atIndexes:itemIndexes]; +} + +- (void)moveInSectionController:(IGListSectionController *)sectionController fromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { + [self reloadData]; + const NSInteger fromRelativeIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:fromIndex]; + const NSInteger toRelativeIndex = [self _relativeIndexForSectionController:sectionController fromLocalIndex:toIndex]; + [self.forwardingBatchContext moveInSectionController:self fromIndex:fromRelativeIndex toIndex:toRelativeIndex]; +} + +- (void)reloadSectionController:(IGListSectionController *)sectionController { + [self reloadData]; + [self.forwardingBatchContext reloadSectionController:self]; +} + +- (void)moveSectionControllerInteractive:(nonnull IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0) { + + NSMutableArray<__kindof IGListSectionController *> *mutSections = [[self.sectionControllers array] mutableCopy]; + IGListSectionController *section = [mutSections objectAtIndex:fromIndex]; + [mutSections removeObjectAtIndex:fromIndex]; + [mutSections insertObject:section atIndex:toIndex]; + _sectionControllers = [NSOrderedSet orderedSetWithArray:[mutSections copy]]; + + [self reloadData]; +} + +- (void)moveInSectionControllerInteractive:(nonnull IGListSectionController *)sectionController + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex NS_AVAILABLE_IOS(9_0) { + + const NSInteger localFromIndex = [self _localIndexForSectionController:sectionController index:fromIndex]; + const NSInteger localToIndex = [self _localIndexForSectionController:sectionController index:toIndex]; + + [self.forwardingBatchContext moveInSectionControllerInteractive:sectionController + fromIndex:localFromIndex + toIndex:localToIndex]; +} + +- (void)revertInvalidInteractiveMoveFromIndexPath:(nonnull NSIndexPath *)sourceIndexPath + toIndexPath:(nonnull NSIndexPath *)destinationIndexPath NS_AVAILABLE_IOS(9_0) { + IGFailAssert(@"Invalid interactive movement shouldn't be possible within IGListStackedSectionController. \ + It is handled in IGListAdapter. %s:", + __PRETTY_FUNCTION__); +} + #pragma mark - IGListDisplayDelegate -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { - IGListSectionController *childSectionController = [self sectionControllerForObjectIndex:index]; - const NSInteger localIndex = [self localIndexForSectionController:childSectionController index:index]; +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { + IGListSectionController *childSectionController = [self sectionControllerForObjectIndex:index]; + const NSInteger localIndex = [self _localIndexForSectionController:childSectionController index:index]; // update the assoc objects for use in didEndDisplay [cell ig_setStackedSectionController:childSectionController]; @@ -354,9 +478,9 @@ - (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(I [visibleSectionControllers addObject:childSectionController]; } -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { const NSInteger localIndex = [cell ig_stackedSectionControllerIndex]; - IGListSectionController *childSectionController = [cell ig_stackedSectionController]; + IGListSectionController *childSectionController = [cell ig_stackedSectionController]; NSCountedSet *visibleSectionControllers = self.visibleSectionControllers; id displayDelegate = [childSectionController displayDelegate]; @@ -369,39 +493,48 @@ - (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionControll } } -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController {} -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController {} +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController {} +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController {} #pragma mark - IGListScrollDelegate -- (void)listAdapter:(IGListAdapter *)listAdapter didScrollSectionController:(IGListSectionController *)sectionController { - for (IGListSectionController *childSectionController in self.sectionControllers) { +- (void)listAdapter:(IGListAdapter *)listAdapter didScrollSectionController:(IGListSectionController *)sectionController { + for (IGListSectionController *childSectionController in self.sectionControllers) { [[childSectionController scrollDelegate] listAdapter:listAdapter didScrollSectionController:childSectionController]; } } -- (void)listAdapter:(IGListAdapter *)listAdapter willBeginDraggingSectionController:(IGListSectionController *)sectionController { - for (IGListSectionController *childSectionController in self.sectionControllers) { +- (void)listAdapter:(IGListAdapter *)listAdapter willBeginDraggingSectionController:(IGListSectionController *)sectionController { + for (IGListSectionController *childSectionController in self.sectionControllers) { [[childSectionController scrollDelegate] listAdapter:listAdapter willBeginDraggingSectionController:childSectionController]; } } -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDraggingSectionController:(IGListSectionController *)sectionController willDecelerate:(BOOL)decelerate { - for (IGListSectionController *childSectionController in self.sectionControllers) { +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDraggingSectionController:(IGListSectionController *)sectionController willDecelerate:(BOOL)decelerate { + for (IGListSectionController *childSectionController in self.sectionControllers) { [[childSectionController scrollDelegate] listAdapter:listAdapter didEndDraggingSectionController:childSectionController willDecelerate:decelerate]; } } +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDeceleratingSectionController:(IGListSectionController *)sectionController { + for (IGListSectionController *childSectionController in self.sectionControllers) { + id scrollDelegate = [childSectionController scrollDelegate]; + if ([scrollDelegate respondsToSelector:@selector(listAdapter:didEndDeceleratingSectionController:)]) { + [scrollDelegate listAdapter:listAdapter didEndDeceleratingSectionController:childSectionController]; + } + } +} + #pragma mark - IGListWorkingRangeDelegate -- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerWillEnterWorkingRange:(IGListSectionController *)sectionController { - for (IGListSectionController *childSectionController in self.sectionControllers) { +- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerWillEnterWorkingRange:(IGListSectionController *)sectionController { + for (IGListSectionController *childSectionController in self.sectionControllers) { [[childSectionController workingRangeDelegate] listAdapter:listAdapter sectionControllerWillEnterWorkingRange:childSectionController]; } } -- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerDidExitWorkingRange:(IGListSectionController *)sectionController { - for (IGListSectionController *childSectionController in self.sectionControllers) { +- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerDidExitWorkingRange:(IGListSectionController *)sectionController { + for (IGListSectionController *childSectionController in self.sectionControllers) { [[childSectionController workingRangeDelegate] listAdapter:listAdapter sectionControllerDidExitWorkingRange:childSectionController]; } } diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListSupplementaryViewSource.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListSupplementaryViewSource.h index c79718b..044c330 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListSupplementaryViewSource.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListSupplementaryViewSource.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -16,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN `IGListAdapter` which then configures and maintains a `UICollectionView`. The supplementary API reflects that in `UICollectionView`, `UICollectionViewLayout`, and `UICollectionViewDataSource`. */ +NS_SWIFT_NAME(ListSupplementaryViewSource) @protocol IGListSupplementaryViewSource /** @@ -29,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN Asks the SupplementaryViewSource for a configured supplementary view for the specified kind and index. @param elementKind The kind of supplementary view being requested - @param index The index for the supplementary veiw being requested. + @param index The index for the supplementary veiw being requested. @note This is your opportunity to do any supplementary view setup and configuration. @@ -42,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN Asks the SupplementaryViewSource for the size of a supplementary view for the given kind and index path. @param elementKind The kind of supplementary view. - @param index The index of the requested view. + @param index The index of the requested view. @return The size for the supplementary view. */ diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListTransitionDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListTransitionDelegate.h new file mode 100644 index 0000000..d9e9a26 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListTransitionDelegate.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + Conform to `IGListTransitionDelegate` to provide customized layout information for a collection view. + */ +@protocol IGListTransitionDelegate + +/** + Asks the delegate to customize and return the starting layout information for an item being inserted into the collection view. + + @param listAdapter The adapter controlling the list. + @param attributes The starting layout information for an item being inserted into the collection view. + @param sectionController The section controller to perform the transition on. + @param index The index of the item being inserted. + */ +- (UICollectionViewLayoutAttributes *)listAdapter:(IGListAdapter *)listAdapter customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes sectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; + +/** + Asks the delegate to customize and return the final layout information for an item that is about to be removed from the collection view. + + @param listAdapter The adapter controlling the list. + @param attributes The final layout information for an item that is about to be removed from the collection view. + @param sectionController The section controller to perform the transition on. + @param index The index of the item being deleted. + */ +- (UICollectionViewLayoutAttributes *)listAdapter:(IGListAdapter *)listAdapter customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes sectionController:(IGListSectionController *)sectionController atIndex:(NSInteger)index; + +@end + diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListUpdatingDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListUpdatingDelegate.h index 30ddc4e..47a6946 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListUpdatingDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListUpdatingDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -18,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @param finished Specifies whether or not the update finished. */ +NS_SWIFT_NAME(ListUpdatingCompletion) typedef void (^IGListUpdatingCompletion)(BOOL finished); /** @@ -25,18 +24,26 @@ typedef void (^IGListUpdatingCompletion)(BOOL finished); @param toObjects The new objects in the collection. */ +NS_SWIFT_NAME(ListObjectTransitionBlock) typedef void (^IGListObjectTransitionBlock)(NSArray *toObjects); /// A block that contains all of the updates. -typedef void (^IGListItemUpdateBlock)(); +NS_SWIFT_NAME(ListItemUpdateBlock) +typedef void (^IGListItemUpdateBlock)(void); /// A block to be called when an adapter reloads the collection view. -typedef void (^IGListReloadUpdateBlock)(); +NS_SWIFT_NAME(ListReloadUpdateBlock) +typedef void (^IGListReloadUpdateBlock)(void); + +/// A block that returns an array of objects to transition to. +NS_SWIFT_NAME(ListToObjectBlock) +typedef NSArray * _Nullable (^IGListToObjectBlock)(void); /** Implement this protocol in order to handle both section and row based update events. Implementation should forward or coalesce these events to a backing store or collection. */ +NS_SWIFT_NAME(ListUpdatingDelegate) @protocol IGListUpdatingDelegate /** @@ -56,12 +63,12 @@ typedef void (^IGListReloadUpdateBlock)(); /** Tells the delegate to perform a section transition from an old array of objects to a new one. - @param collectionView The collection view to perform the transition on. - @param fromObjects The previous objects in the collection view. Objects must conform to `IGListDiffable`. - @param toObjects The new objects in collection view. Objects must conform to `IGListDiffable`. - @param animated A flag indicating if the transition should be animated. + @param collectionView The collection view to perform the transition on. + @param fromObjects The previous objects in the collection view. Objects must conform to `IGListDiffable`. + @param toObjectsBlock A block returning the new objects in the collection view. Objects must conform to `IGListDiffable`. + @param animated A flag indicating if the transition should be animated. @param objectTransitionBlock A block that must be called when the adapter applies changes to the collection view. - @param completion A completion block to execute when the update is finished. + @param completion A completion block to execute when the update is finished. @note Implementations determine how to transition between objects. You can perform a diff on the objects, reload each section, or simply call `-reloadData` on the collection view. In the end, the collection view must be setup with a @@ -72,7 +79,7 @@ typedef void (^IGListReloadUpdateBlock)(); */ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView fromObjects:(nullable NSArray> *)fromObjects - toObjects:(nullable NSArray> *)toObjects + toObjectsBlock:(nullable IGListToObjectBlock)toObjectsBlock animated:(BOOL)animated objectTransitionBlock:(IGListObjectTransitionBlock)objectTransitionBlock completion:(nullable IGListUpdatingCompletion)completion; @@ -81,7 +88,7 @@ typedef void (^IGListReloadUpdateBlock)(); Tells the delegate to perform item inserts at the given index paths. @param collectionView The collection view on which to perform the transition. - @param indexPaths The index paths to insert items into. + @param indexPaths The index paths to insert items into. */ - (void)insertItemsIntoCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths; @@ -89,7 +96,7 @@ typedef void (^IGListReloadUpdateBlock)(); Tells the delegate to perform item deletes at the given index paths. @param collectionView The collection view on which to perform the transition. - @param indexPaths The index paths to delete items from. + @param indexPaths The index paths to delete items from. */ - (void)deleteItemsFromCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths; @@ -97,27 +104,45 @@ typedef void (^IGListReloadUpdateBlock)(); Tells the delegate to move an item from and to given index paths. @param collectionView The collection view on which to perform the transition. - @param fromIndexPath The source index path of the item to move. - @param toIndexPath The destination index path of the item to move. + @param fromIndexPath The source index path of the item to move. + @param toIndexPath The destination index path of the item to move. */ - (void)moveItemInCollectionView:(UICollectionView *)collectionView fromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath; /** - Tells the delegate to perform item reloads at the given index paths. + Tells the delegate to reload an item from and to given index paths. @param collectionView The collection view on which to perform the transition. - @param indexPaths The index paths of items to reload. + @param fromIndexPath The source index path of the item to reload. + @param toIndexPath The destination index path of the item to reload. + + @note Since UICollectionView is unable to handle calling -[UICollectionView reloadItemsAtIndexPaths:] safely while also + executing insert and delete operations in the same batch updates, the updater must know about the origin and + destination of the reload to perform a safe transition. */ -- (void)reloadItemsInCollectionView:(UICollectionView *)collectionView indexPaths:(NSArray *)indexPaths; +- (void)reloadItemInCollectionView:(UICollectionView *)collectionView + fromIndexPath:(NSIndexPath *)fromIndexPath + toIndexPath:(NSIndexPath *)toIndexPath; +/** + Tells the delegate to move a section from and to given indexes. + + @param collectionView The collection view on which to perform the transition. + @param fromIndex The source index of the section to move. + @param toIndex The destination index of the section to move. + */ +- (void)moveSectionInCollectionView:(UICollectionView *)collectionView + fromIndex:(NSInteger)fromIndex + toIndex:(NSInteger)toIndex; + /** Completely reload data in the collection. - @param collectionView The collection view to reload. + @param collectionView The collection view to reload. @param reloadUpdateBlock A block that must be called when the adapter reloads the collection view. - @param completion A completion block to execute when the reload is finished. + @param completion A completion block to execute when the reload is finished. */ - (void)reloadDataWithCollectionView:(UICollectionView *)collectionView reloadUpdateBlock:(IGListReloadUpdateBlock)reloadUpdateBlock @@ -127,7 +152,7 @@ typedef void (^IGListReloadUpdateBlock)(); Completely reload each section in the collection view. @param collectionView The collection view to reload. - @param sections The sections to reload. + @param sections The sections to reload. */ - (void)reloadCollectionView:(UICollectionView *)collectionView sections:(NSIndexSet *)sections; @@ -135,9 +160,9 @@ typedef void (^IGListReloadUpdateBlock)(); Perform an item update block in the collection view. @param collectionView The collection view to update. - @param animated A flag indicating if the transition should be animated. - @param itemUpdates A block containing all of the updates. - @param completion A completion block to execute when the update is finished. + @param animated A flag indicating if the transition should be animated. + @param itemUpdates A block containing all of the updates. + @param completion A completion block to execute when the update is finished. */ - (void)performUpdateWithCollectionView:(UICollectionView *)collectionView animated:(BOOL)animated diff --git a/ZaloMessageUI/Pods/IGListKit/Source/IGListWorkingRangeDelegate.h b/ZaloMessageUI/Pods/IGListKit/Source/IGListWorkingRangeDelegate.h index df050bb..e69acad 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/IGListWorkingRangeDelegate.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/IGListWorkingRangeDelegate.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,7 +10,7 @@ @class IGListAdapter; @class IGListSectionController; -@protocol IGListSectionType; + NS_ASSUME_NONNULL_BEGIN @@ -22,23 +20,24 @@ NS_ASSUME_NONNULL_BEGIN The working range is a range *near* the viewport in which you can begin preparing content for display. For example, you could begin decoding images, or warming text caches. */ +NS_SWIFT_NAME(ListWorkingRangeDelegate) @protocol IGListWorkingRangeDelegate /** Notifies the delegate that an section controller will enter the working range. - @param listAdapter The adapter controlling the list. + @param listAdapter The adapter controlling the list. @param sectionController The section controller entering the range. */ -- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerWillEnterWorkingRange:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerWillEnterWorkingRange:(IGListSectionController *)sectionController; /** Notifies the delegate that an section controller exited the working range. - @param listAdapter The adapter controlling the list. + @param listAdapter The adapter controlling the list. @param sectionController The section controller that exited the range. */ -- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerDidExitWorkingRange:(IGListSectionController *)sectionController; +- (void)listAdapter:(IGListAdapter *)listAdapter sectionControllerDidExitWorkingRange:(IGListSectionController *)sectionController; @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.h new file mode 100644 index 0000000..3163fea --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface IGListAdapter (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.m new file mode 100644 index 0000000..26cf347 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+DebugDescription.m @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListAdapter+DebugDescription.h" + +#import "IGListAdapterInternal.h" +#import "IGListSectionMap+DebugDescription.h" +#import "IGListAdapterUpdater+DebugDescription.h" +#import "UICollectionView+DebugDescription.h" +#import "IGListDebuggingUtilities.h" + +@implementation IGListAdapter (DebugDescription) + +- (NSString *)debugDescription { + NSMutableArray *lines = [NSMutableArray arrayWithObject:[NSString stringWithFormat:@"IGListAdapter %p:", self]]; + [lines addObjectsFromArray:IGListDebugIndentedLines([self debugDescriptionLines])]; + return [lines componentsJoinedByString:@"\n"]; +} + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Updater type: %@", NSStringFromClass(self.updater.class)]]; + [debug addObject:[NSString stringWithFormat:@"Data source: %@", self.dataSource]]; + [debug addObject:[NSString stringWithFormat:@"Collection view delegate: %@", self.collectionViewDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Scroll view delegate: %@", self.scrollViewDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Is in update block: %@", IGListDebugBOOL(self.isInUpdateBlock)]]; + [debug addObject:[NSString stringWithFormat:@"View controller: %@", self.viewController]]; + if (@available(iOS 10.0, tvOS 10, *)) { + [debug addObject:[NSString stringWithFormat:@"Is prefetching enabled: %@", IGListDebugBOOL(self.collectionView.isPrefetchingEnabled)]]; + } + + if (self.registeredCellClasses.count > 0) { + [debug addObject:@"Registered cell classes:"]; + [debug addObject:[self.registeredCellClasses description]]; + } + + if (self.registeredNibNames.count > 0) { + [debug addObject:@"Registered nib names:"]; + [debug addObject:[self.registeredNibNames description]]; + } + + if (self.registeredSupplementaryViewIdentifiers.count > 0) { + [debug addObject:@"Registered supplementary view identifiers:"]; + [debug addObject:[self.registeredSupplementaryViewIdentifiers description]]; + } + + if (self.registeredSupplementaryViewNibNames.count > 0) { + [debug addObject:@"Registered supplementary view nib names:"]; + [debug addObject:self.registeredSupplementaryViewNibNames]; + } + + if ([self.updater isKindOfClass:[IGListAdapterUpdater class]]) { + [debug addObject:[NSString stringWithFormat:@"IGListAdapterUpdater instance %p:", self.updater]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([(IGListAdapterUpdater *)self.updater debugDescriptionLines])]; + } + + [debug addObject:[NSString stringWithFormat:@"Section map details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.sectionMap debugDescriptionLines])]; + + if (self.previousSectionMap != nil) { + [debug addObject:[NSString stringWithFormat:@"Previous section map details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.previousSectionMap debugDescriptionLines])]; + } + + [debug addObject:[NSString stringWithFormat:@"Collection view details:"]]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.collectionView debugDescriptionLines])]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.h new file mode 100644 index 0000000..269b834 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import + +@interface IGListAdapter (UICollectionView) +< +UICollectionViewDataSource, +IGListCollectionViewDelegateLayout +> +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.m new file mode 100644 index 0000000..61becb3 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapter+UICollectionView.m @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListAdapter+UICollectionView.h" + +#import +#import +#import +#import +#import + +@implementation IGListAdapter (UICollectionView) + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return self.sectionMap.objects.count; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + IGListSectionController * sectionController = [self sectionControllerForSection:section]; + IGAssert(sectionController != nil, @"Nil section controller for section %li for item %@. Check your -diffIdentifier and -isEqual: implementations.", + (long)section, [self.sectionMap objectForSection:section]); + const NSInteger numberOfItems = [sectionController numberOfItems]; + IGAssert(numberOfItems >= 0, @"Cannot return negative number of items %li for section controller %@.", (long)numberOfItems, sectionController); + return numberOfItems; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; + + // flag that a cell is being dequeued in case it tries to access a cell in the process + _isDequeuingCell = YES; + UICollectionViewCell *cell = [sectionController cellForItemAtIndex:indexPath.item]; + _isDequeuingCell = NO; + + IGAssert(cell != nil, @"Returned a nil cell at indexPath <%@> from section controller: <%@>", indexPath, sectionController); + + // associate the section controller with the cell so that we know which section controller is using it + [self mapView:cell toSectionController:sectionController]; + + return cell; +} + +- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; + id supplementarySource = [sectionController supplementaryViewSource]; + UICollectionReusableView *view = [supplementarySource viewForSupplementaryElementOfKind:kind atIndex:indexPath.item]; + IGAssert(view != nil, @"Returned a nil supplementary view at indexPath <%@> from section controller: <%@>, supplementary source: <%@>", indexPath, sectionController, supplementarySource); + + // associate the section controller with the cell so that we know which section controller is using it + [self mapView:view toSectionController:sectionController]; + + return view; +} + +- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath { + const NSInteger sectionIndex = indexPath.section; + const NSInteger itemIndex = indexPath.item; + + IGListSectionController *sectionController = [self sectionControllerForSection:sectionIndex]; + return [sectionController canMoveItemAtIndex:itemIndex]; +} + +- (void)collectionView:(UICollectionView *)collectionView + moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath + toIndexPath:(NSIndexPath *)destinationIndexPath { + + if (@available(iOS 9.0, *)) { + const NSInteger sourceSectionIndex = sourceIndexPath.section; + const NSInteger destinationSectionIndex = destinationIndexPath.section; + const NSInteger sourceItemIndex = sourceIndexPath.item; + const NSInteger destinationItemIndex = destinationIndexPath.item; + + IGListSectionController *sourceSectionController = [self sectionControllerForSection:sourceSectionIndex]; + IGListSectionController *destinationSectionController = [self sectionControllerForSection:destinationSectionIndex]; + + // this is a move within a section + if (sourceSectionController == destinationSectionController) { + + if ([sourceSectionController canMoveItemAtIndex:sourceItemIndex toIndex:destinationItemIndex]) { + [self moveInSectionControllerInteractive:sourceSectionController + fromIndex:sourceItemIndex + toIndex:destinationItemIndex]; + } else { + // otherwise this is a move of an _item_ from one section to another section + // we need to revert the change as it's too late to cancel + [self revertInvalidInteractiveMoveFromIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; + } + return; + } + + // this is a reordering of sections themselves + if ([sourceSectionController numberOfItems] == 1 && [destinationSectionController numberOfItems] == 1) { + + // perform view changes in the collection view + [self moveSectionControllerInteractive:sourceSectionController + fromIndex:sourceSectionIndex + toIndex:destinationSectionIndex]; + return; + } + + // otherwise this is a move of an _item_ from one section to another section + // this is not currently supported, so we need to revert the change as it's too late to cancel + [self revertInvalidInteractiveMoveFromIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; + } +} + +#pragma mark - UICollectionViewDelegate + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didSelectItemAtIndexPath:indexPath]; + } + + IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; + [sectionController didSelectItemAtIndex:indexPath.item]; +} + +- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didDeselectItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didDeselectItemAtIndexPath:indexPath]; + } + + IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; + [sectionController didDeselectItemAtIndex:indexPath.item]; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:willDisplayCell:forItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView willDisplayCell:cell forItemAtIndexPath:indexPath]; + } + + IGListSectionController *sectionController = [self sectionControllerForView:cell]; + // if the section controller relationship was destroyed, reconnect it + // this happens with iOS 10 UICollectionView display range changes + if (sectionController == nil) { + sectionController = [self sectionControllerForSection:indexPath.section]; + [self mapView:cell toSectionController:sectionController]; + } + + id object = [self.sectionMap objectForSection:indexPath.section]; + [self.displayHandler willDisplayCell:cell forListAdapter:self sectionController:sectionController object:object indexPath:indexPath]; + + _isSendingWorkingRangeDisplayUpdates = YES; + [self.workingRangeHandler willDisplayItemAtIndexPath:indexPath forListAdapter:self]; + _isSendingWorkingRangeDisplayUpdates = NO; +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didEndDisplayingCell:cell forItemAtIndexPath:indexPath]; + } + + IGListSectionController *sectionController = [self sectionControllerForView:cell]; + [self.displayHandler didEndDisplayingCell:cell forListAdapter:self sectionController:sectionController indexPath:indexPath]; + [self.workingRangeHandler didEndDisplayingItemAtIndexPath:indexPath forListAdapter:self]; + + // break the association between the cell and the section controller + [self removeMapForView:cell]; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:willDisplaySupplementaryView:forElementKind:atIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView willDisplaySupplementaryView:view forElementKind:elementKind atIndexPath:indexPath]; + } + + IGListSectionController *sectionController = [self sectionControllerForView:view]; + // if the section controller relationship was destroyed, reconnect it + // this happens with iOS 10 UICollectionView display range changes + if (sectionController == nil) { + sectionController = [self.sectionMap sectionControllerForSection:indexPath.section]; + [self mapView:view toSectionController:sectionController]; + } + + id object = [self.sectionMap objectForSection:indexPath.section]; + [self.displayHandler willDisplaySupplementaryView:view forListAdapter:self sectionController:sectionController object:object indexPath:indexPath]; +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didEndDisplayingSupplementaryView:forElementOfKind:atIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didEndDisplayingSupplementaryView:view forElementOfKind:elementKind atIndexPath:indexPath]; + } + + IGListSectionController *sectionController = [self sectionControllerForView:view]; + [self.displayHandler didEndDisplayingSupplementaryView:view forListAdapter:self sectionController:sectionController indexPath:indexPath]; + + [self removeMapForView:view]; +} + +- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didHighlightItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didHighlightItemAtIndexPath:indexPath]; + } + + IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; + [sectionController didHighlightItemAtIndex:indexPath.item]; +} + +- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath { + // forward this method to the delegate b/c this implementation will steal the message from the proxy + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:didUnhighlightItemAtIndexPath:)]) { + [collectionViewDelegate collectionView:collectionView didUnhighlightItemAtIndexPath:indexPath]; + } + + IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; + [sectionController didUnhighlightItemAtIndex:indexPath.item]; +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + + CGSize size = [self sizeForItemAtIndexPath:indexPath]; + IGAssert(!isnan(size.height), @"IGListAdapter returned NaN height = %f for item at indexPath <%@>", size.height, indexPath); + IGAssert(!isnan(size.width), @"IGListAdapter returned NaN width = %f for item at indexPath <%@>", size.width, indexPath); + + return size; +} + +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + return [[self sectionControllerForSection:section] inset]; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + return [[self sectionControllerForSection:section] minimumLineSpacing]; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + return [[self sectionControllerForSection:section] minimumInteritemSpacing]; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section]; + return [self sizeForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { + IGAssert(![self.collectionViewDelegate respondsToSelector:_cmd], @"IGListAdapter is consuming method also implemented by the collectionViewDelegate: %@", NSStringFromSelector(_cmd)); + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:section]; + return [self sizeForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:indexPath]; +} + +#pragma mark - IGListCollectionViewDelegateLayout + +- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout*)collectionViewLayout + customizedInitialLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes + atIndexPath:(NSIndexPath *)indexPath { + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; + if (sectionController.transitionDelegate) { + return [sectionController.transitionDelegate listAdapter:self + customizedInitialLayoutAttributes:attributes + sectionController:sectionController + atIndex:indexPath.item]; + } + return attributes; +} + +- (UICollectionViewLayoutAttributes *)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout*)collectionViewLayout + customizedFinalLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes + atIndexPath:(NSIndexPath *)indexPath { + IGListSectionController *sectionController = [self sectionControllerForSection:indexPath.section]; + if (sectionController.transitionDelegate) { + return [sectionController.transitionDelegate listAdapter:self + customizedFinalLayoutAttributes:attributes + sectionController:sectionController + atIndex:indexPath.item]; + } + return attributes; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterInternal.h index a8dac24..ff8c519 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterInternal.h @@ -1,35 +1,36 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import #import +#import #import "IGListAdapterProxy.h" #import "IGListDisplayHandler.h" #import "IGListSectionMap.h" #import "IGListWorkingRangeHandler.h" +#import "IGListAdapter+UICollectionView.h" NS_ASSUME_NONNULL_BEGIN /// Generate a string representation of a reusable view class when registering with a UICollectionView. -NS_INLINE NSString *IGListReusableViewIdentifier(Class viewClass, NSString * _Nullable nibName, NSString * _Nullable kind) { - return [NSString stringWithFormat:@"%@%@%@", kind ?: @"", nibName ?: @"", NSStringFromClass(viewClass)]; +NS_INLINE NSString *IGListReusableViewIdentifier(Class viewClass, NSString * _Nullable nibName, NSString * _Nullable kind, NSString * _Nullable givenReuseIdentifier) { + return [NSString stringWithFormat:@"%@%@%@%@", kind ?: @"", nibName ?: @"", givenReuseIdentifier ?: @"", NSStringFromClass(viewClass)]; } @interface IGListAdapter () < -UICollectionViewDataSource, -UICollectionViewDelegateFlowLayout, -IGListCollectionContext +IGListCollectionContext, +IGListBatchContext > { __weak UICollectionView *_collectionView; + BOOL _isDequeuingCell; + BOOL _isSendingWorkingRangeDisplayUpdates; } @property (nonatomic, strong) id updater; @@ -42,6 +43,9 @@ IGListCollectionContext @property (nonatomic, strong, nullable) UIView *emptyBackgroundView; +// we need to special case interactive section moves that are moved to the last position +@property (nonatomic) BOOL isLastInteractiveMoveToLastSectionIndex; + /** When making object updates inside a batch update block, delete operations must use the section /before/ any moves take place. This includes when other objects are deleted or inserted ahead of the section controller making the mutations. @@ -59,7 +63,11 @@ IGListCollectionContext @property (nonatomic, strong) NSMutableSet *registeredSupplementaryViewIdentifiers; @property (nonatomic, strong) NSMutableSet *registeredSupplementaryViewNibNames; -- (NSArray *)indexPathsFromSectionController:(IGListSectionController *)sectionController +- (void)mapView:(__kindof UIView *)view toSectionController:(IGListSectionController *)sectionController; +- (nullable IGListSectionController *)sectionControllerForView:(__kindof UIView *)view; +- (void)removeMapForView:(__kindof UIView *)view; + +- (NSArray *)indexPathsFromSectionController:(IGListSectionController *)sectionController indexes:(NSIndexSet *)indexes usePreviousIfInUpdateBlock:(BOOL)usePreviousIfInUpdateBlock; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.h index b1af43b..151ae31 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -25,9 +23,9 @@ IGLK_SUBCLASSING_RESTRICTED /** Create a new proxy object with targets and interceptor. - @param collectionViewTarget A UICollectionViewDelegate conforming object that receives unintercepted messages. - @param scrollViewTarget A UIScrollViewDelegate conforming object that receives unintercepted messages. - @param interceptor An IGListAdapter object that intercepts a set of messages. + @param collectionViewTarget A UICollectionViewDelegate conforming object that receives non-intercepted messages. + @param scrollViewTarget A UIScrollViewDelegate conforming object that receives non-intercepted messages. + @param interceptor An IGListAdapter object that intercepts a set of messages. @return A new IGListAdapterProxy object. */ @@ -35,6 +33,16 @@ IGLK_SUBCLASSING_RESTRICTED scrollViewTarget:(nullable id)scrollViewTarget interceptor:(IGListAdapter *)interceptor; +/** + :nodoc: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + :nodoc: + */ ++ (instancetype)new NS_UNAVAILABLE; + @end NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.m index 6d7297e..590b880 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterProxy.m @@ -1,15 +1,14 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListAdapterProxy.h" #import +#import "IGListCollectionViewDelegateLayout.h" /** Define messages that you want the IGListAdapter object to intercept. Pattern copied from @@ -17,10 +16,18 @@ */ static BOOL isInterceptedSelector(SEL sel) { return ( + // UIScrollViewDelegate + sel == @selector(scrollViewDidScroll:) || + sel == @selector(scrollViewWillBeginDragging:) || + sel == @selector(scrollViewDidEndDragging:willDecelerate:) || + sel == @selector(scrollViewDidEndDecelerating:) || // UICollectionViewDelegate - sel == @selector(collectionView:didSelectItemAtIndexPath:) || sel == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) || sel == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) || + sel == @selector(collectionView:didSelectItemAtIndexPath:) || + sel == @selector(collectionView:didDeselectItemAtIndexPath:) || + sel == @selector(collectionView:didHighlightItemAtIndexPath:) || + sel == @selector(collectionView:didUnhighlightItemAtIndexPath:) || // UICollectionViewDelegateFlowLayout sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) || sel == @selector(collectionView:layout:insetForSectionAtIndex:) || @@ -28,10 +35,15 @@ static BOOL isInterceptedSelector(SEL sel) { sel == @selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:) || sel == @selector(collectionView:layout:referenceSizeForFooterInSection:) || sel == @selector(collectionView:layout:referenceSizeForHeaderInSection:) || + sel == @selector(collectionView:layout:referenceSizeForHeaderInSection:) || // UIScrollViewDelegate sel == @selector(scrollViewDidScroll:) || sel == @selector(scrollViewWillBeginDragging:) || - sel == @selector(scrollViewDidEndDragging:willDecelerate:) + sel == @selector(scrollViewDidEndDragging:willDecelerate:) || + sel == @selector(scrollViewDidEndDecelerating:) || + // IGListCollectionViewDelegateLayout + sel == @selector(collectionView:layout:customizedInitialLayoutAttributes:atIndexPath:) || + sel == @selector(collectionView:layout:customizedFinalLayoutAttributes:atIndexPath:) ); } diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.h new file mode 100644 index 0000000..eee18e2 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface IGListAdapterUpdater (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.m new file mode 100644 index 0000000..f7e72aa --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdater+DebugDescription.m @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListAdapterUpdater+DebugDescription.h" + +#import "IGListAdapterUpdaterInternal.h" +#import "IGListBatchUpdateData+DebugDescription.h" +#import "IGListDebuggingUtilities.h" + +#if IGLK_DEBUG_DESCRIPTION_ENABLED +static NSMutableArray *linesFromObjects(NSArray *objects) { + NSMutableArray *lines = [NSMutableArray new]; + for (id object in objects) { + [lines addObject:[NSString stringWithFormat:@"Object %p of type %@ with identifier %@", + object, NSStringFromClass([object class]), [object diffIdentifier]]]; + } + return lines; +} +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + +@implementation IGListAdapterUpdater (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Moves as deletes+inserts: %@", IGListDebugBOOL(self.movesAsDeletesInserts)]]; + [debug addObject:[NSString stringWithFormat:@"Allows background reloading: %@", IGListDebugBOOL(self.allowsBackgroundReloading)]]; + [debug addObject:[NSString stringWithFormat:@"Has queued reload data: %@", IGListDebugBOOL(self.hasQueuedReloadData)]]; + [debug addObject:[NSString stringWithFormat:@"Queued update is animated: %@", IGListDebugBOOL(self.queuedUpdateIsAnimated)]]; + + NSString *stateString; + switch (self.state) { + case IGListBatchUpdateStateIdle: + stateString = @"Idle"; + break; + case IGListBatchUpdateStateQueuedBatchUpdate: + stateString = @"Queued batch update"; + break; + case IGListBatchUpdateStateExecutedBatchUpdateBlock: + stateString = @"Executed batch update block"; + break; + case IGListBatchUpdateStateExecutingBatchUpdateBlock: + stateString = @"Executing batch update block"; + break; + } + [debug addObject:[NSString stringWithFormat:@"State: %@", stateString]]; + + if (self.applyingUpdateData != nil) { + [debug addObject:@"Batch update data:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines([self.applyingUpdateData debugDescriptionLines])]; + } + + if (self.fromObjects != nil) { + [debug addObject:@"From objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.fromObjects))]; + } + + if (self.toObjectsBlock != nil) { + [debug addObject:@"To objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.toObjectsBlock()))]; + } + + if (self.pendingTransitionToObjects != nil) { + [debug addObject:@"Pending objects:"]; + [debug addObjectsFromArray:IGListDebugIndentedLines(linesFromObjects(self.pendingTransitionToObjects))]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdaterInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdaterInternal.h index 9de3726..efc9b84 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdaterInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListAdapterUpdaterInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -27,7 +25,7 @@ FOUNDATION_EXTERN void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, @interface IGListAdapterUpdater () @property (nonatomic, copy, nullable) NSArray *fromObjects; -@property (nonatomic, copy, nullable) NSArray *toObjects; +@property (nonatomic, copy, nullable) IGListToObjectBlock toObjectsBlock; @property (nonatomic, copy, nullable) NSArray *pendingTransitionToObjects; @property (nonatomic, strong) NSMutableArray *completionBlocks; @@ -41,6 +39,7 @@ FOUNDATION_EXTERN void convertReloadToDeleteInsert(NSMutableIndexSet *reloads, @property (nonatomic, assign, getter=hasQueuedReloadData) BOOL queuedReloadData; @property (nonatomic, assign) IGListBatchUpdateState state; +@property (nonatomic, strong, nullable) IGListBatchUpdateData *applyingUpdateData; - (void)performReloadDataWithCollectionView:(UICollectionView *)collectionView; - (void)performBatchUpdatesWithCollectionView:(UICollectionView *)collectionView; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.h new file mode 100644 index 0000000..69bc73c --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface IGListBatchUpdateData (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.m new file mode 100644 index 0000000..041f8d9 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateData+DebugDescription.m @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListBatchUpdateData+DebugDescription.h" + +@implementation IGListBatchUpdateData (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Insert sections: %@", self.insertSections]]; + [debug addObject:[NSString stringWithFormat:@"Delete sections: %@", self.deleteSections]]; + + for (IGListMoveIndex *move in self.moveSections) { + [debug addObject:[NSString stringWithFormat:@"Move from section %li to %li", (long)move.from, (long)move.to]]; + } + + for (NSIndexPath *path in self.deleteIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Delete section %li item %li", (long)path.section, (long)path.item]]; + } + + for (NSIndexPath *path in self.insertIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Insert section %li item %li", (long)path.section, (long)path.item]]; + } + + for (IGListMoveIndexPath *move in self.moveIndexPaths) { + [debug addObject:[NSString stringWithFormat:@"Move from section %li item %li to section %li item %li", + (long)move.from.section, (long)move.from.item, (long)move.to.section, (long)move.to.item]]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateState.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateState.h index 5b00ed2..149de75 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateState.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdateState.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.h index c695541..df1494c 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,17 +10,18 @@ #import @class IGListMoveIndexPath; +@class IGListReloadIndexPath; IGLK_SUBCLASSING_RESTRICTED @interface IGListBatchUpdates : NSObject @property (nonatomic, strong, readonly) NSMutableIndexSet *sectionReloads; -@property (nonatomic, strong, readonly) NSMutableSet *itemInserts; -@property (nonatomic, strong, readonly) NSMutableSet *itemDeletes; -@property (nonatomic, strong, readonly) NSMutableSet *itemReloads; -@property (nonatomic, strong, readonly) NSMutableSet *itemMoves; +@property (nonatomic, strong, readonly) NSMutableArray *itemInserts; +@property (nonatomic, strong, readonly) NSMutableArray *itemDeletes; +@property (nonatomic, strong, readonly) NSMutableArray *itemReloads; +@property (nonatomic, strong, readonly) NSMutableArray *itemMoves; -@property (nonatomic, strong, readonly) NSMutableArray *itemUpdateBlocks; +@property (nonatomic, strong, readonly) NSMutableArray *itemUpdateBlocks; @property (nonatomic, strong, readonly) NSMutableArray *itemCompletionBlocks; - (BOOL)hasChanges; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.m index 3a91eb7..b6f7962 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBatchUpdates.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListBatchUpdates.h" @@ -14,10 +12,10 @@ @implementation IGListBatchUpdates - (instancetype)init { if (self = [super init]) { _sectionReloads = [NSMutableIndexSet new]; - _itemInserts = [NSMutableSet new]; - _itemMoves = [NSMutableSet new]; - _itemReloads = [NSMutableSet new]; - _itemDeletes = [NSMutableSet new]; + _itemInserts = [NSMutableArray new]; + _itemMoves = [NSMutableArray new]; + _itemDeletes = [NSMutableArray new]; + _itemReloads = [NSMutableArray new]; _itemUpdateBlocks = [NSMutableArray new]; _itemCompletionBlocks = [NSMutableArray new]; } diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.h new file mode 100644 index 0000000..abbd858 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface IGListBindingSectionController (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.m new file mode 100644 index 0000000..9aad0f6 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListBindingSectionController+DebugDescription.m @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListBindingSectionController+DebugDescription.h" + +#import "IGListDebuggingUtilities.h" + +@implementation IGListBindingSectionController (DebugDescription) + +- (NSString *)debugDescription { + NSMutableArray *lines = [NSMutableArray arrayWithObject:[NSString stringWithFormat:@"IGListBindingSectionController %p:", self]]; + [lines addObjectsFromArray:IGListDebugIndentedLines([self debugDescriptionLines])]; + return [lines componentsJoinedByString:@"\n"]; +} + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Data source: %@", self.dataSource]]; + [debug addObject:[NSString stringWithFormat:@"Selection delegate: %@", self.selectionDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Object: %@", self.object]]; + [debug addObject:@"View models:"]; + for (id viewModel in self.viewModels) { + [debug addObject:[NSString stringWithFormat:@"%@: %@", viewModel, viewModel.diffIdentifier]]; + } + [debug addObject:[NSString stringWithFormat:@"Number of items: %ld", (long)self.numberOfItems]]; + [debug addObject:[NSString stringWithFormat:@"View controller: %@", self.viewController]]; + [debug addObject:[NSString stringWithFormat:@"Collection context: %@", self.collectionContext]]; + [debug addObject:[NSString stringWithFormat:@"Section: %ld", (long)self.section]]; + [debug addObject:[NSString stringWithFormat:@"Is first section: %@", IGListDebugBOOL(self.isFirstSection)]]; + [debug addObject:[NSString stringWithFormat:@"Is last section: %@", IGListDebugBOOL(self.isLastSection)]]; + [debug addObject:[NSString stringWithFormat:@"Supplementary view source: %@", self.supplementaryViewSource]]; + [debug addObject:[NSString stringWithFormat:@"Display delegate: %@", self.displayDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Working range delegate: %@", self.workingRangeDelegate]]; + [debug addObject:[NSString stringWithFormat:@"Scroll delegate: %@", self.scrollDelegate]]; + +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end + diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListCollectionViewLayoutInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListCollectionViewLayoutInternal.h index 99372a7..c78867f 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListCollectionViewLayoutInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListCollectionViewLayoutInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ static CGRect IGListRectIntegralScaled(CGRect rect) { diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.h new file mode 100644 index 0000000..523d677 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +@class IGListAdapter; + +IGLK_SUBCLASSING_RESTRICTED +@interface IGListDebugger : NSObject + ++ (void)trackAdapter:(IGListAdapter *)adapter; + ++ (NSArray *)adapterDescriptions; + ++ (void)clear; + ++ (NSString *)dump; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.m new file mode 100644 index 0000000..4bb63de --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebugger.m @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListDebugger.h" + +#import "IGListDebuggingUtilities.h" +#import "IGListAdapter+DebugDescription.h" + +@implementation IGListDebugger + +static NSHashTable *livingAdaptersTable = nil; + ++ (void)trackAdapter:(IGListAdapter *)adapter { +#if IGLK_DEBUG_DESCRIPTION_ENABLED + if (livingAdaptersTable == nil) { + livingAdaptersTable = [NSHashTable weakObjectsHashTable]; + } + [livingAdaptersTable addObject:adapter]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED +} + ++ (NSArray *)adapterDescriptions { + NSMutableArray *descriptions = [NSMutableArray new]; + for (IGListAdapter *adapter in livingAdaptersTable) { + [descriptions addObject:[adapter debugDescription]]; + } + return descriptions; +} + ++ (void)clear { + [livingAdaptersTable removeAllObjects]; +} + ++ (NSString *)dump { + return [[self adapterDescriptions] componentsJoinedByString:@"\n"]; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.h new file mode 100644 index 0000000..aab440e --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class IGListAdapter; + +extern NSString *IGListDebugBOOL(BOOL b); + +extern NSArray *IGListDebugIndentedLines(NSArray *lines); diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.m new file mode 100644 index 0000000..aa627a3 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDebuggingUtilities.m @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListDebuggingUtilities.h" + +NSString *IGListDebugBOOL(BOOL b) { + return b ? @"Yes" : @"No"; +} + +NSArray *IGListDebugIndentedLines(NSArray *lines) { + NSMutableArray *newLines = [NSMutableArray new]; + for (NSString *line in lines) { + [newLines addObject:[NSString stringWithFormat:@" %@", line]]; + } + return newLines; +} diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.h index 3f43d57..3066d8e 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -14,54 +12,59 @@ @class IGListAdapter; @class IGListSectionController; -@protocol IGListSectionType; + NS_ASSUME_NONNULL_BEGIN IGLK_SUBCLASSING_RESTRICTED @interface IGListDisplayHandler : NSObject +/** + Counted set of the currently visible section controllers. + */ +@property (nonatomic, strong, readonly) NSCountedSet *visibleListSections; + /** Tells the handler that a cell will be displayed in the IGListAdapter. - @param cell A cell that will be displayed. - @param listAdapter The adapter the cell will display in. + @param cell A cell that will be displayed. + @param listAdapter The adapter the cell will display in. @param sectionController The section controller that manages the cell. - @param object The object that powers the section controller. - @param indexPath The index path of the cell in the UICollectionView. + @param object The object that powers the section controller. + @param indexPath The index path of the cell in the UICollectionView. */ - (void)willDisplayCell:(UICollectionViewCell *)cell forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath; /** Tells the handler that a cell did end display in the IGListAdapter. - @param cell A cell that will be displayed. - @param listAdapter The adapter the cell will display in. + @param cell A cell that will be displayed. + @param listAdapter The adapter the cell will display in. @param sectionController The section controller that manages the cell. - @param indexPath The index path of the cell in the UICollectionView. + @param indexPath The index path of the cell in the UICollectionView. */ - (void)didEndDisplayingCell:(UICollectionViewCell *)cell forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController indexPath:(NSIndexPath *)indexPath; /** Tells the handler that a supplementary view will be displayed in the IGListAdapter. - @param view A supplementary view that will be displayed. - @param listAdapter The adapter the supplementary view will display in. + @param view A supplementary view that will be displayed. + @param listAdapter The adapter the supplementary view will display in. @param sectionController The section controller that manages the supplementary view. - @param object The object that powers the section controller. - @param indexPath The index path of the supplementary view in the UICollectionView. + @param object The object that powers the section controller. + @param indexPath The index path of the supplementary view in the UICollectionView. */ - (void)willDisplaySupplementaryView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath; @@ -69,14 +72,14 @@ IGLK_SUBCLASSING_RESTRICTED /** Tells the handler that a supplementary view did end display in the IGListAdapter. - @param view A supplementary view that will be displayed. - @param listAdapter The adapter the supplementary view will display in. + @param view A supplementary view that will be displayed. + @param listAdapter The adapter the supplementary view will display in. @param sectionController The section controller that manages the supplementary view. - @param indexPath The index path of the supplementary view in the UICollectionView. + @param indexPath The index path of the supplementary view in the UICollectionView. */ - (void)didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController indexPath:(NSIndexPath *)indexPath; @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.m index 5dd7564..c96b038 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListDisplayHandler.m @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListDisplayHandler.h" @@ -16,7 +14,6 @@ @interface IGListDisplayHandler () -@property (nonatomic, strong) NSCountedSet *visibleListSections; @property (nonatomic, strong) NSMapTable *visibleViewObjectMap; @end @@ -25,22 +22,22 @@ @implementation IGListDisplayHandler - (instancetype)init { if (self = [super init]) { - _visibleListSections = [[NSCountedSet alloc] init]; + _visibleListSections = [NSCountedSet new]; _visibleViewObjectMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory capacity:0]; } return self; } -- (id)pluckObjectForView:(UICollectionReusableView *)view { +- (id)_pluckObjectForView:(UICollectionReusableView *)view { NSMapTable *viewObjectMap = self.visibleViewObjectMap; id object = [viewObjectMap objectForKey:view]; [viewObjectMap removeObjectForKey:view]; return object; } -- (void)willDisplayReusableView:(UICollectionReusableView *)view +- (void)_willDisplayReusableView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath { IGParameterAssert(view != nil); @@ -57,9 +54,9 @@ - (void)willDisplayReusableView:(UICollectionReusableView *)view [visibleListSections addObject:sectionController]; } -- (void)didEndDisplayingReusableView:(UICollectionReusableView *)view +- (void)_didEndDisplayingReusableView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath { IGParameterAssert(view != nil); @@ -83,43 +80,43 @@ - (void)didEndDisplayingReusableView:(UICollectionReusableView *)view - (void)willDisplaySupplementaryView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath { - [self willDisplayReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; + [self _willDisplayReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; } - (void)didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController indexPath:(NSIndexPath *)indexPath { // if cell display events break, don't send display events when the object has disappeared - id object = [self pluckObjectForView:view]; - [self didEndDisplayingReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; + id object = [self _pluckObjectForView:view]; + [self _didEndDisplayingReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; } - (void)willDisplayCell:(UICollectionViewCell *)cell forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController object:(id)object indexPath:(NSIndexPath *)indexPath { id displayDelegate = [sectionController displayDelegate]; [displayDelegate listAdapter:listAdapter willDisplaySectionController:sectionController cell:cell atIndex:indexPath.item]; - [self willDisplayReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; + [self _willDisplayReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; } - (void)didEndDisplayingCell:(UICollectionViewCell *)cell forListAdapter:(IGListAdapter *)listAdapter - sectionController:(IGListSectionController *)sectionController + sectionController:(IGListSectionController *)sectionController indexPath:(NSIndexPath *)indexPath { // if cell display events break, don't send cell events to the displayDelegate when the object has disappeared - id object = [self pluckObjectForView:cell]; + id object = [self _pluckObjectForView:cell]; if (object == nil) { return; } [sectionController.displayDelegate listAdapter:listAdapter didEndDisplayingSectionController:sectionController cell:cell atIndex:indexPath.item]; - [self didEndDisplayingReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; + [self _didEndDisplayingReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath]; } @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.h new file mode 100644 index 0000000..0913428 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + An object with index path information for reloading an item during a batch update. + */ +IGLK_SUBCLASSING_RESTRICTED +@interface IGListReloadIndexPath : NSObject + +/** + The index path of the item before batch updates are applied. + */ +@property (nonatomic, strong, readonly) NSIndexPath *fromIndexPath; + +/** + The index path of the item after batch updates are applied. + */ +@property (nonatomic, strong, readonly) NSIndexPath *toIndexPath; + +/** + Creates a new reload object. + + @param fromIndexPath The index path of the item before batch updates. + @param toIndexPath The index path of the item after batch updates. + @return A new reload object. + */ +- (instancetype)initWithFromIndexPath:(NSIndexPath *)fromIndexPath + toIndexPath:(NSIndexPath *)toIndexPath NS_DESIGNATED_INITIALIZER; + +/** + :nodoc: + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + :nodoc: + */ ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.m new file mode 100644 index 0000000..8f2e50b --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListReloadIndexPath.m @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListReloadIndexPath.h" + +@implementation IGListReloadIndexPath + +- (instancetype)initWithFromIndexPath:(NSIndexPath *)fromIndexPath + toIndexPath:(NSIndexPath *)toIndexPath { + if (self = [super init]) { + _fromIndexPath = fromIndexPath; + _toIndexPath = toIndexPath; + } + return self; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionControllerInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionControllerInternal.h index 73c9cb6..a56f3cb 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionControllerInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionControllerInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListSectionController.h" @@ -19,8 +17,15 @@ FOUNDATION_EXTERN void IGListSectionControllerPopThread(void); @property (nonatomic, weak, readwrite) UIViewController *viewController; +@property (nonatomic, assign, readwrite) NSInteger section; + @property (nonatomic, assign, readwrite) BOOL isFirstSection; @property (nonatomic, assign, readwrite) BOOL isLastSection; +/* + Provides a way for specialized section controllers (like the stacked section controller) to reject invalid moves + */ +- (BOOL)canMoveItemAtIndex:(NSInteger)sourceItemIndex toIndex:(NSInteger)destinationItemIndex; + @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.h new file mode 100644 index 0000000..8d7e33b --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import "IGListSectionMap.h" + +@interface IGListSectionMap (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.m new file mode 100644 index 0000000..4bf71c1 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap+DebugDescription.m @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "IGListSectionMap+DebugDescription.h" +#import "IGListBindingSectionController.h" + +@implementation IGListSectionMap (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [self enumerateUsingBlock:^(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop) { + if ([sectionController isKindOfClass:[IGListBindingSectionController class]]) { + [debug addObject:[sectionController debugDescription]]; + } else { + [debug addObject:[NSString stringWithFormat:@"Object and section controller at section: %li:", (long)section]]; + [debug addObject:[NSString stringWithFormat:@" %@", object]]; + [debug addObject:[NSString stringWithFormat:@" %@", sectionController]]; + } + }]; +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.h index 9fe8ba7..6d84edc 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -12,7 +10,7 @@ #import @class IGListSectionController; -@protocol IGListSectionType; + NS_ASSUME_NONNULL_BEGIN @@ -20,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN The IGListSectionMap provides a way to map a collection of objects to a collection of section controllers and achieve constant-time lookups O(1). - IGListSectionMap is a mutable object and does not garauntee thread safety. + IGListSectionMap is a mutable object and does not guarantee thread safety. */ IGLK_SUBCLASSING_RESTRICTED @interface IGListSectionMap : NSObject @@ -35,10 +33,10 @@ IGLK_SUBCLASSING_RESTRICTED /** Update the map with objects and the section controller counterparts. - @param objects The objects in the collection. + @param objects The objects in the collection. @param sectionControllers The section controllers that map to each object. */ -- (void)updateWithObjects:(NSArray > *)objects sectionControllers:(NSArray > *)sectionControllers; +- (void)updateWithObjects:(NSArray > *)objects sectionControllers:(NSArray *)sectionControllers; /** Fetch a section controller given a section. @@ -47,7 +45,7 @@ IGLK_SUBCLASSING_RESTRICTED @return A section controller. */ -- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section; +- (nullable IGListSectionController *)sectionControllerForSection:(NSInteger)section; /** Fetch the object for a section @@ -100,13 +98,18 @@ IGLK_SUBCLASSING_RESTRICTED @param block A block object to operate on entries in the section controller map. */ -- (void)enumerateUsingBlock:(void (^)(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop))block; +- (void)enumerateUsingBlock:(void (^)(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop))block; /** :nodoc: */ - (instancetype)init NS_UNAVAILABLE; +/** + :nodoc: + */ ++ (instancetype)new NS_UNAVAILABLE; + @end NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.m index 8a5ecb4..b039c40 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListSectionMap.m @@ -1,21 +1,21 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListSectionMap.h" #import +#import "IGListSectionControllerInternal.h" + @interface IGListSectionMap () // both of these maps allow fast lookups of objects, list objects, and indexes -@property (nonatomic, strong, readonly, nonnull) NSMapTable *> *objectToSectionControllerMap; -@property (nonatomic, strong, readonly, nonnull) NSMapTable *, NSNumber *> *sectionControllerToSectionMap; +@property (nonatomic, strong, readonly, nonnull) NSMapTable *objectToSectionControllerMap; +@property (nonatomic, strong, readonly, nonnull) NSMapTable *sectionControllerToSectionMap; @property (nonatomic, strong, nonnull) NSMutableArray *mObjects; @@ -45,34 +45,41 @@ - (NSArray *)objects { return [self.mObjects copy]; } -- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController { +- (NSInteger)sectionForSectionController:(IGListSectionController *)sectionController { IGParameterAssert(sectionController != nil); NSNumber *index = [self.sectionControllerToSectionMap objectForKey:sectionController]; return index != nil ? [index integerValue] : NSNotFound; } -- (IGListSectionController *)sectionControllerForSection:(NSInteger)section { +- (IGListSectionController *)sectionControllerForSection:(NSInteger)section { return [self.objectToSectionControllerMap objectForKey:[self objectForSection:section]]; } - (void)updateWithObjects:(NSArray *)objects sectionControllers:(NSArray *)sectionControllers { IGParameterAssert(objects.count == sectionControllers.count); + [self reset]; + self.mObjects = [objects mutableCopy]; - [self reset]; + id firstObject = objects.firstObject; + id lastObject = objects.lastObject; [objects enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) { - IGListSectionController *sectionController = sectionControllers[idx]; + IGListSectionController *sectionController = sectionControllers[idx]; // set the index of the list for easy reverse lookup [self.sectionControllerToSectionMap setObject:@(idx) forKey:sectionController]; [self.objectToSectionControllerMap setObject:sectionController forKey:object]; + + sectionController.isFirstSection = (object == firstObject); + sectionController.isLastSection = (object == lastObject); + sectionController.section = (NSInteger)idx; }]; } -- (nullable IGListSectionController *)sectionControllerForObject:(id)object { +- (nullable IGListSectionController *)sectionControllerForObject:(id)object { IGParameterAssert(object != nil); return [self.objectToSectionControllerMap objectForKey:object]; @@ -99,6 +106,12 @@ - (NSInteger)sectionForObject:(id)object { } - (void)reset { + [self enumerateUsingBlock:^(id _Nonnull object, IGListSectionController * _Nonnull sectionController, NSInteger section, BOOL * _Nonnull stop) { + sectionController.section = NSNotFound; + sectionController.isFirstSection = NO; + sectionController.isLastSection = NO; + }]; + [self.sectionControllerToSectionMap removeAllObjects]; [self.objectToSectionControllerMap removeAllObjects]; } @@ -112,14 +125,14 @@ - (void)updateObject:(id)object { self.mObjects[section] = object; } -- (void)enumerateUsingBlock:(void (^)(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop))block { +- (void)enumerateUsingBlock:(void (^)(id object, IGListSectionController *sectionController, NSInteger section, BOOL *stop))block { IGParameterAssert(block != nil); BOOL stop = NO; NSArray *objects = self.objects; for (NSInteger section = 0; section < objects.count; section++) { id object = objects[section]; - IGListSectionController *sectionController = [self sectionControllerForObject:object]; + IGListSectionController *sectionController = [self sectionControllerForObject:object]; block(object, sectionController, section, &stop); if (stop) { break; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListStackedSectionControllerInternal.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListStackedSectionControllerInternal.h index a2ff41c..83237b0 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListStackedSectionControllerInternal.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListStackedSectionControllerInternal.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @@ -13,16 +11,17 @@ @interface IGListStackedSectionController () < +IGListBatchContext, IGListCollectionContext, IGListDisplayDelegate, IGListScrollDelegate, IGListWorkingRangeDelegate > -@property (nonatomic, strong, readonly) NSOrderedSet<__kindof IGListSectionController *> *sectionControllers; +@property (nonatomic, strong, readonly) NSOrderedSet<__kindof IGListSectionController *> *sectionControllers; /// An array the length of the total number of items in the stack, pointing to a section controller for the item index. -@property (nonatomic, copy) NSArray *> *sectionControllersForItems; +@property (nonatomic, copy) NSArray *sectionControllersForItems; /// An array of index offsets for each item in the flattened stack. @property (nonatomic, copy) NSArray *sectionControllerOffsets; @@ -33,8 +32,11 @@ IGListWorkingRangeDelegate /// A counted set of the visible section controllers, used to forward granular display events to child section controllers @property (nonatomic, strong, readonly) NSCountedSet *visibleSectionControllers; -- (IGListSectionController *)sectionControllerForObjectIndex:(NSInteger)itemIndex; -- (NSInteger)offsetForSectionController:(IGListSectionController *)sectionController; +/// Temporary batch context so the stack controller can transform child indices within the stack before updating. +@property (nonatomic, strong) id forwardingBatchContext; + +- (IGListSectionController *)sectionControllerForObjectIndex:(NSInteger)itemIndex; +- (NSInteger)offsetForSectionController:(IGListSectionController *)sectionController; - (void)reloadData; @end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.h index ba02519..5df27e7 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.h @@ -1,17 +1,15 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import @class IGListAdapter; -@protocol IGListSectionType; + @interface IGListWorkingRangeHandler : NSObject @@ -26,7 +24,7 @@ /** Tells the handler that a cell will be displayed in the IGListKit infra. - @param indexPath The index path of the cell in the UICollectionView. + @param indexPath The index path of the cell in the UICollectionView. @param listAdapter The adapter managing the infra. */ - (void)willDisplayItemAtIndexPath:(NSIndexPath *)indexPath @@ -35,7 +33,7 @@ /** Tells the handler that a cell did end display in the IGListKit infra. - @param indexPath The index path of the cell in the UICollectionView. + @param indexPath The index path of the cell in the UICollectionView. @param listAdapter The adapter managing the infra. */ - (void)didEndDisplayingItemAtIndexPath:(NSIndexPath *)indexPath diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.mm b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.mm index 31257f8..61bd36d 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.mm +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/IGListWorkingRangeHandler.mm @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "IGListWorkingRangeHandler.h" @@ -31,7 +29,7 @@ }; struct _IGListWorkingRangeHandlerSectionControllerWrapper { - IGListSectionController *sectionController; + IGListSectionController *sectionController; bool operator==(const _IGListWorkingRangeHandlerSectionControllerWrapper &other) const { return (sectionController == other.sectionController); @@ -82,7 +80,7 @@ - (void)willDisplayItemAtIndexPath:(NSIndexPath *)indexPath .hash = indexPath.hash }); - [self updateWorkingRangesWithListAdapter:listAdapter]; + [self _updateWorkingRangesWithListAdapter:listAdapter]; } - (void)didEndDisplayingItemAtIndexPath:(NSIndexPath *)indexPath @@ -96,12 +94,12 @@ - (void)didEndDisplayingItemAtIndexPath:(NSIndexPath *)indexPath .hash = indexPath.hash }); - [self updateWorkingRangesWithListAdapter:listAdapter]; + [self _updateWorkingRangesWithListAdapter:listAdapter]; } #pragma mark - Working Ranges -- (void)updateWorkingRangesWithListAdapter:(IGListAdapter *)listAdapter { +- (void)_updateWorkingRangesWithListAdapter:(IGListAdapter *)listAdapter { IGAssertMainThread(); // This method is optimized C++ to improve straight-line speed of these operations. Change at your peril. @@ -126,7 +124,7 @@ - (void)updateWorkingRangesWithListAdapter:(IGListAdapter *)listAdapter { _IGListWorkingRangeSectionControllerSet workingRangeSectionControllers (visibleSectionSet.size()); for (NSInteger idx = start; idx < end; idx++) { id item = [listAdapter objectAtSection:idx]; - id sectionController = [listAdapter sectionControllerForObject:item]; + IGListSectionController *sectionController = [listAdapter sectionControllerForObject:item]; workingRangeSectionControllers.insert({sectionController}); } diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.h new file mode 100644 index 0000000..9c5a94b --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface UICollectionView (DebugDescription) + +- (NSArray *)debugDescriptionLines; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.m new file mode 100644 index 0000000..4a65782 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+DebugDescription.m @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "UICollectionView+DebugDescription.h" + +#import + +@implementation UICollectionView (DebugDescription) + +- (NSArray *)debugDescriptionLines { + NSMutableArray *debug = [NSMutableArray new]; +#if IGLK_DEBUG_DESCRIPTION_ENABLED + [debug addObject:[NSString stringWithFormat:@"Class: %@, instance: %p", NSStringFromClass(self.class), self]]; + [debug addObject:[NSString stringWithFormat:@"Data source: %@", self.dataSource]]; + [debug addObject:[NSString stringWithFormat:@"Delegate: %@", self.delegate]]; + [debug addObject:[NSString stringWithFormat:@"Layout: %@", self.collectionViewLayout]]; + [debug addObject:[NSString stringWithFormat:@"Frame: %@, bounds: %@", + NSStringFromCGRect(self.frame), NSStringFromCGRect(self.bounds)]]; + + const NSInteger sections = [self numberOfSections]; + [debug addObject:[NSString stringWithFormat:@"Number of sections: %lld", (long long)sections]]; + + for (NSInteger section = 0; section < sections; section++) { + [debug addObject:[NSString stringWithFormat:@" %lld items in section %lld", + (long long)[self numberOfItemsInSection:section], (long long)section]]; + } + + [debug addObject:@"Visible cell details:"]; + NSArray *visibleIndexPaths = [[self indexPathsForVisibleItems] sortedArrayUsingSelector:@selector(compare:)]; + for (NSIndexPath *path in visibleIndexPaths) { + [debug addObject:[NSString stringWithFormat:@" Visible cell at section %lld, item %lld:", + (long long)path.section, (long long)path.item]]; + [debug addObject:[NSString stringWithFormat:@" %@", [[self cellForItemAtIndexPath:path] description] ?: @""]]; + } +#endif // #if IGLK_DEBUG_DESCRIPTION_ENABLED + return debug; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.h index 36af9bf..cda2aca 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.h +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.h @@ -1,10 +1,8 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.m index ba7f35a..c99749a 100644 --- a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.m +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionView+IGListBatchUpdateData.m @@ -1,22 +1,19 @@ /** * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. */ #import "UICollectionView+IGListBatchUpdateData.h" -#import "IGListBatchUpdateData.h" +#import @implementation UICollectionView (IGListBatchUpdateData) - (void)ig_applyBatchUpdateData:(IGListBatchUpdateData *)updateData { - [self deleteItemsAtIndexPaths:[updateData.deleteIndexPaths allObjects]]; - [self insertItemsAtIndexPaths:[updateData.insertIndexPaths allObjects]]; - [self reloadItemsAtIndexPaths:[updateData.reloadIndexPaths allObjects]]; + [self deleteItemsAtIndexPaths:updateData.deleteIndexPaths]; + [self insertItemsAtIndexPaths:updateData.insertIndexPaths]; for (IGListMoveIndexPath *move in updateData.moveIndexPaths) { [self moveItemAtIndexPath:move.from toIndexPath:move.to]; diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.h new file mode 100644 index 0000000..1daef20 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UICollectionViewLayout (InteractiveReordering) + +- (void)ig_hijackLayoutInteractiveReorderingMethodForAdapter:(IGListAdapter *)adapter; + +- (nullable NSIndexPath *)updatedTargetForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath + toIndexPath:(NSIndexPath *)originalTarget + adapter:(IGListAdapter *)adapter; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.m new file mode 100644 index 0000000..cf978ee --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UICollectionViewLayout+InteractiveReordering.m @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "UICollectionViewLayout+InteractiveReordering.h" + +#import +#import +#import +#import + +#import + +@implementation UICollectionViewLayout (InteractiveReordering) + +static void * kIGListAdapterKey = &kIGListAdapterKey; + ++ (void)load +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // interactive reordering does not exist prior to iOS 9 + if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0) { + return; + } + + Class layoutClass = [self class]; + + // override implementation for targetIndexPathForInteractivelyMovingItem:withPosition: + SEL userMoveSelector = @selector(targetIndexPathForInteractivelyMovingItem:withPosition:); + SEL overrideSelector = @selector(ig_targetIndexPathForInteractivelyMovingItem:withPosition:); + Method userLayoutMethod = class_getInstanceMethod(layoutClass, userMoveSelector); + Method overrideLayoutMethod = class_getInstanceMethod(layoutClass, overrideSelector); + method_exchangeImplementations(userLayoutMethod, overrideLayoutMethod); + + // override implementation for + // invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition: + SEL userInvalidationSelector = + @selector(invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition:); + SEL overrideInvalidationSelector = + @selector(ig_invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition:); + Method userInvalidationMethod = class_getInstanceMethod(layoutClass, userInvalidationSelector); + Method overrideInvalidationMethod = class_getInstanceMethod(layoutClass, overrideInvalidationSelector); + method_exchangeImplementations(userInvalidationMethod, overrideInvalidationMethod); + + // override implementation for + // invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition: + SEL userEndInvalidationSelector = + @selector(invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:previousIndexPaths:movementCancelled:); + SEL overrideEndInvalidationSelector = + @selector(ig_invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:previousIndexPaths:movementCancelled:); + Method userEndInvalidationMethod = class_getInstanceMethod(layoutClass, userEndInvalidationSelector); + Method overrideEndInvalidationMethod = class_getInstanceMethod(layoutClass, overrideEndInvalidationSelector); + method_exchangeImplementations(userEndInvalidationMethod, overrideEndInvalidationMethod); + }); +} + +- (void)ig_hijackLayoutInteractiveReorderingMethodForAdapter:(IGListAdapter *)adapter { + objc_setAssociatedObject(self, kIGListAdapterKey, adapter, OBJC_ASSOCIATION_ASSIGN); +} + +- (NSIndexPath *)ig_targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath + withPosition:(CGPoint)position NS_AVAILABLE_IOS(9_0) { + // call looks recursive, but through swizzling is calling the original implementation for + // targetIndexPathForInteractivelyMovingItem:withPosition: + NSIndexPath *originalTarget = [self ig_targetIndexPathForInteractivelyMovingItem:previousIndexPath + withPosition:position]; + + IGListAdapter *adapter = (IGListAdapter *)objc_getAssociatedObject(self, kIGListAdapterKey); + if (adapter == nil) { + return originalTarget; + } + + NSIndexPath *updatedTarget = [self updatedTargetForInteractivelyMovingItem:previousIndexPath + toIndexPath:originalTarget + adapter:adapter]; + if (updatedTarget) { + return updatedTarget; + } + return originalTarget; +} + +- (nullable NSIndexPath *)updatedTargetForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath + toIndexPath:(NSIndexPath *)originalTarget + adapter:(IGListAdapter *)adapter { + const NSInteger sourceSectionIndex = previousIndexPath.section; + NSInteger destinationSectionIndex = originalTarget.section; + NSInteger destinationItemIndex = originalTarget.item; + + IGListSectionController *sourceSectionController = [adapter sectionControllerForSection:sourceSectionIndex]; + IGListSectionController *destinationSectionController = [adapter sectionControllerForSection:destinationSectionIndex]; + + // this is a reordering of sections themselves + if ([sourceSectionController numberOfItems] == 1 + && [destinationSectionController numberOfItems] == 1) { + + if (destinationItemIndex == 1) { + // the "item" representing our section was dropped + // into the end of a destination section rather than the beginning + // so it really belongs one section after the section where it landed + if (destinationSectionIndex < [[adapter objects] count] - 1) { + destinationSectionIndex += 1; + destinationItemIndex = 0; + } + else { + // if we're moving an item to the last spot, our index would exceed the number of sections available + // so we have to special case this scenario. iOS doesnt allow an item move to "create" a new section + adapter.isLastInteractiveMoveToLastSectionIndex = YES; + } + NSIndexPath *updatedTarget = [NSIndexPath indexPathForItem:destinationItemIndex + inSection:destinationSectionIndex]; + return updatedTarget; + } + } + + return nil; +} + +- (UICollectionViewLayoutInvalidationContext *)ig_invalidationContextForInteractivelyMovingItems:(NSArray *)targetIndexPaths withTargetPosition:(CGPoint)targetPosition previousIndexPaths:(NSArray *)previousIndexPaths previousPosition:(CGPoint)previousPosition { + + // call looks recursive, but through swizzling is calling the original implementation for + // invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition: + UICollectionViewLayoutInvalidationContext *originalContext = + [self ig_invalidationContextForInteractivelyMovingItems:targetIndexPaths withTargetPosition:targetPosition previousIndexPaths:previousIndexPaths previousPosition:previousPosition]; + + return [self ig_cleanupInvalidationContext:originalContext]; +} + +- (UICollectionViewLayoutInvalidationContext *)ig_invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:(NSArray *)indexPaths previousIndexPaths:(NSArray *)previousIndexPaths movementCancelled:(BOOL)movementCancelled { + + // call looks recursive, but through swizzling is calling the original implementation for + // invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:previousIndexPaths:movementCancelled: + UICollectionViewLayoutInvalidationContext *originalContext = + [self ig_invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:indexPaths previousIndexPaths:previousIndexPaths movementCancelled:movementCancelled]; + + return [self ig_cleanupInvalidationContext:originalContext]; +} + +- (UICollectionViewLayoutInvalidationContext *)ig_cleanupInvalidationContext:(UICollectionViewLayoutInvalidationContext *)originalContext { + IGListAdapter *adapter = (IGListAdapter *)objc_getAssociatedObject(self, kIGListAdapterKey); + if (adapter == nil || !self.collectionView) { + return originalContext; + } + + const NSInteger numSections = [adapter numberOfSectionsInCollectionView:(UICollectionView * _Nonnull)self.collectionView]; + + // protect against invalidating an index path that no longer exists + // (like item 1 in the last section after interactively reordering an item to the end of a list of 1 item sections) + if ([originalContext.invalidatedItemIndexPaths count] > 0) { + NSUInteger indexToRemove = NSNotFound; + + indexToRemove = [originalContext.invalidatedItemIndexPaths indexOfObjectPassingTest: + ^BOOL(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (obj.section == numSections-1) { + IGListSectionController *section = [adapter sectionControllerForSection:obj.section]; + return obj.item > [section numberOfItems] - 1; + } + return NO; + }]; + + if (indexToRemove != NSNotFound) { + NSMutableArray *invalidatedItemIndexPaths = [originalContext.invalidatedItemIndexPaths mutableCopy]; + [invalidatedItemIndexPaths removeObjectAtIndex:indexToRemove]; + + UICollectionViewLayoutInvalidationContext *modifiedContext; + if ([originalContext isKindOfClass:[UICollectionViewFlowLayoutInvalidationContext class]]) { + // UICollectionViewFlowLayout has a special invalidation context subclass + UICollectionViewFlowLayoutInvalidationContext *flowModifiedContext = + [[self.class invalidationContextClass] new]; + + flowModifiedContext.invalidateFlowLayoutDelegateMetrics = + [(UICollectionViewFlowLayoutInvalidationContext *)originalContext invalidateFlowLayoutDelegateMetrics]; + flowModifiedContext.invalidateFlowLayoutAttributes = + [(UICollectionViewFlowLayoutInvalidationContext *)originalContext invalidateFlowLayoutAttributes]; + modifiedContext = flowModifiedContext; + } + else { + modifiedContext = [[self.class invalidationContextClass] new]; + } + + [modifiedContext invalidateItemsAtIndexPaths:invalidatedItemIndexPaths]; + [originalContext.invalidatedSupplementaryIndexPaths enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) { + [modifiedContext invalidateSupplementaryElementsOfKind:key atIndexPaths:obj]; + }]; + [originalContext.invalidatedDecorationIndexPaths enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSArray * _Nonnull obj, BOOL * _Nonnull stop) { + [modifiedContext invalidateDecorationElementsOfKind:key atIndexPaths:obj]; + }]; + modifiedContext.contentOffsetAdjustment = originalContext.contentOffsetAdjustment; + modifiedContext.contentSizeAdjustment = originalContext.contentSizeAdjustment; + + return modifiedContext; + } + } + return originalContext; +} + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.h b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.h new file mode 100644 index 0000000..62639ae --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface UIScrollView (IGListKit) + +- (UIEdgeInsets) ig_contentInset; + +@end diff --git a/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.m b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.m new file mode 100644 index 0000000..6a0a846 --- /dev/null +++ b/ZaloMessageUI/Pods/IGListKit/Source/Internal/UIScrollView+IGListKit.m @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2016-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "UIScrollView+IGListKit.h" + +@implementation UIScrollView (IGListKit) + +- (UIEdgeInsets) ig_contentInset +{ +#ifdef __IPHONE_11_0 + if (@available(iOS 11.0, tvOS 11.0, *)) { + return self.adjustedContentInset; + } else { + return self.contentInset; + } +#else + return self.contentInset; +#endif +} + +@end diff --git a/ZaloMessageUI/Pods/Local Podspecs/IGListKit.podspec.json b/ZaloMessageUI/Pods/Local Podspecs/IGListKit.podspec.json index 789499c..5c777e8 100644 --- a/ZaloMessageUI/Pods/Local Podspecs/IGListKit.podspec.json +++ b/ZaloMessageUI/Pods/Local Podspecs/IGListKit.podspec.json @@ -1,18 +1,18 @@ { "name": "IGListKit", - "version": "2.1.0", + "version": "3.4.0", "summary": "A data-driven UICollectionView framework.", "homepage": "https://github.com/Instagram/IGListKit", "documentation_url": "https://instagram.github.io/IGListKit", "description": "A data-driven UICollectionView framework for building fast and flexible lists.", "license": { - "type": "BSD" + "type": "MIT" }, "authors": "Instagram", "social_media_url": "https://twitter.com/fbOpenSource", "source": { "git": "https://github.com/Instagram/IGListKit.git", - "tag": "2.1.0", + "tag": "3.4.0", "branch": "stable" }, "default_subspecs": "Default", @@ -20,7 +20,7 @@ "platforms": { "ios": "8.0", "tvos": "9.0", - "osx": "10.10" + "osx": "10.11" }, "ios": { "frameworks": "UIKit" diff --git a/ZaloMessageUI/Pods/Manifest.lock b/ZaloMessageUI/Pods/Manifest.lock index fcd97b6..7c54228 100644 --- a/ZaloMessageUI/Pods/Manifest.lock +++ b/ZaloMessageUI/Pods/Manifest.lock @@ -1,9 +1,9 @@ PODS: - - IGListKit (2.1.0): - - IGListKit/Default (= 2.1.0) - - IGListKit/Default (2.1.0): + - IGListKit (3.4.0): + - IGListKit/Default (= 3.4.0) + - IGListKit/Default (3.4.0): - IGListKit/Diffing - - IGListKit/Diffing (2.1.0) + - IGListKit/Diffing (3.4.0) DEPENDENCIES: - IGListKit (from `https://github.com/Instagram/IGListKit.git`, branch `master`) @@ -15,12 +15,12 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: IGListKit: - :commit: 24308a9881f54fc190070c858ec520d93074d95d + :commit: cce5a462bb8e4e3cf5b4d0aeebfedb318e52cf09 :git: https://github.com/Instagram/IGListKit.git SPEC CHECKSUMS: - IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e + IGListKit: 7a5d788e9fb746bcd402baa8e8b24bc3bd2a5a07 -PODFILE CHECKSUM: 0582a7790dd44dbac3df902d378fdbbf2f2cc6ba +PODFILE CHECKSUM: 639ede2e3c835232264f72146840d6924fe954d8 -COCOAPODS: 1.2.0 +COCOAPODS: 1.4.0 diff --git a/ZaloMessageUI/Pods/Pods.xcodeproj/project.pbxproj b/ZaloMessageUI/Pods/Pods.xcodeproj/project.pbxproj index b94aaa9..ed2ec3c 100644 --- a/ZaloMessageUI/Pods/Pods.xcodeproj/project.pbxproj +++ b/ZaloMessageUI/Pods/Pods.xcodeproj/project.pbxproj @@ -7,89 +7,120 @@ objects = { /* Begin PBXBuildFile section */ - 06DE5F187AC9D88E421DCFC5FD4D83A2 /* IGListMoveIndexPath.m in Sources */ = {isa = PBXBuildFile; fileRef = F82561F9D2F8C802108AE86C0E2EEB1B /* IGListMoveIndexPath.m */; }; - 0F2603368FC49EB8CB29B08FECCC399F /* IGListMoveIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = B11D4CA08332D8FCBA79D03D0319F5ED /* IGListMoveIndex.m */; }; - 103E241708D29F06C36C7836D066A0A3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */; }; - 1369E38745E60F250DB553327A90E220 /* IGListIndexPathResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCAA7A7AC06A491C7C589E23C23921E8 /* IGListIndexPathResultInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 13FEA770FD412AA781189394183D0140 /* IGListDisplayHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 55E1C761261B4FC3324D3D29CADEB7C5 /* IGListDisplayHandler.m */; }; - 1986C8B4075AC9610DE1987639B3CB51 /* IGListSectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2001DD06082463F4E1B1A1DAAE19199B /* IGListSectionMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1E7B647A4A49BA7685B2B97EB8901241 /* IGListWorkingRangeDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 73254ED54EC807B3FB25FEE911048301 /* IGListWorkingRangeDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 280840F0B69F12FDD6D7DE1219F56A65 /* IGListSingleSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 885816AA0E2310FF4F2A5FB62E351603 /* IGListSingleSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 29A6583505AE31C7E14E436F0D87D3BC /* IGListIndexSetResult.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7F603F1CAF57E05D90C8358D67C7FA /* IGListIndexSetResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3789823B840F701270CF3C89F41DAA7B /* IGListBindable.h in Headers */ = {isa = PBXBuildFile; fileRef = 47AD689F7E36931512210195B51DC939 /* IGListBindable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3D2EB85CD5357639074CA5DD2D4E7551 /* IGListAdapterDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E7BE22886808C98EFAF7994EE6568DA /* IGListAdapterDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 3F1999B4074112AEBE5DF30D82FCF951 /* IGListDisplayDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 010584FD1C9A0536B2855DFA61D29811 /* IGListDisplayDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 48DCC2400FD1C6404EC6D9F6B22E72CC /* IGListWorkingRangeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 51C149BC9621A6A6DFC34F2FB9F1425C /* IGListWorkingRangeHandler.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4A3EFF59399B8E6AE643F4C42F3FAD98 /* IGListAdapterInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4174531EE7E4CB451191AECA50819F5F /* IGListAdapterInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 4B7A48A14982ABE52BBB7EA773D77966 /* IGListSectionType.h in Headers */ = {isa = PBXBuildFile; fileRef = 76749C313DA571984B78AA95DB51E102 /* IGListSectionType.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 50B4C742F6EF24F4D7E3EEF36A3B9284 /* IGListSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 368EB3EF4F72EC88B1850E7B6569BAF9 /* IGListSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 52A42A4E819F52AFF627C48EB43DA670 /* IGListStackedSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 91EFBC2BA2D7A79B94746CAA05414C48 /* IGListStackedSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5A567DA80629D19A882903C3207F5EE7 /* IGListBatchUpdateState.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E8415EE9C0C02894DE9D7105F85C835 /* IGListBatchUpdateState.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 5C0E1A07063CCEF3EAD5F170D71885E7 /* IGListExperiments.h in Headers */ = {isa = PBXBuildFile; fileRef = 54B57271641DC0C7CA17035FE9C3A8B5 /* IGListExperiments.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5DE604DA2C97FBBA405A690F3D35CD6D /* IGListBindingSectionControllerSelectionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AB39E5DE2E20926EA6D4984EBCFE59 /* IGListBindingSectionControllerSelectionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5E0FE48D39AEEB037830382CAE198F29 /* IGListWorkingRangeHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1FD976B91AF21538CF7C4DBE0DDC722F /* IGListWorkingRangeHandler.mm */; }; - 5FC66EF7C5CD106B195DCC47830C6504 /* IGListSectionMap.m in Sources */ = {isa = PBXBuildFile; fileRef = D023E1E57BE8AF38FC013F1CFE43EB23 /* IGListSectionMap.m */; }; - 609B3D3030F4D00163F09224F4D07BB8 /* IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D5A31C01478666EFFAED2069D102019 /* IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 620AEB58639B7F0B4109DE8640810C3B /* IGListReloadDataUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 430BC698E899473DBA4C089E811ED2E9 /* IGListReloadDataUpdater.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 64B25DE39737CB258CB4A78A73A60105 /* IGListAdapterProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A09086C7AB0DC46E91CB1099F1C6200 /* IGListAdapterProxy.m */; }; - 6616011B818AD909AF2C4057E6BC6B60 /* IGListIndexPathResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 20EF09DA25084EF36543E9D42914E471 /* IGListIndexPathResult.m */; }; - 697271424EB167F7C0C58ED12EAACD84 /* IGListMoveIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D71A4799B19EE1D916324FB5E1D5461 /* IGListMoveIndexPath.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6AA1240DEC5184C2CF88B062E428BFF0 /* IGListScrollDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F8FC0AEA108EE633AA29B103554AFDC /* IGListScrollDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6AFCC7263232A3DB96FEC0AC62E183AD /* IGListKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F2E303D7701BA73D012E6B1B4B8A4C0A /* IGListKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6BEEAC62E01CF7CF63952056D94C3382 /* IGListBindingSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 82756399D6433AFBC13A0410E0179623 /* IGListBindingSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6FC811837A5F75FDD32BCAEF32F3EF44 /* NSNumber+IGListDiffable.m in Sources */ = {isa = PBXBuildFile; fileRef = 73161ADDD6004C7DB5AFB67922643DFD /* NSNumber+IGListDiffable.m */; }; - 75533C15807CA2947ACE53A052172EEB /* IGListMoveIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E3AC1DFACCEEA11A38A2401A4D2B4AC /* IGListMoveIndex.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 774D86036F65420A16E2BD9418857BBA /* IGListStackedSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = BA169A6945D36F0B13E400449585DEAB /* IGListStackedSectionController.m */; }; - 77EABC38894B691882ECCBB6E7A6F529 /* IGListAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 01C0B92FD99AEE2D5EC215E5F1BC1BB0 /* IGListAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 78C5E274B0720D3093224F0CBC267303 /* IGListUpdatingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 3079C3EA36555E2AD7E80A08D4E3143D /* IGListUpdatingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7C576B84FB485A137BCB47747C15D889 /* IGListDisplayHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C985162A550067251A36CEBB5D1F21A /* IGListDisplayHandler.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7C964EAF8C7F67F73AA3AF3C1A1D233A /* NSString+IGListDiffable.m in Sources */ = {isa = PBXBuildFile; fileRef = E22A432F99D8C7B036F29A07B5288629 /* NSString+IGListDiffable.m */; }; - 7CB59DC42F5DEEF8423B99B9EF15F680 /* IGListAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = B1D9DBDD98FA8E96ED56870368BA3993 /* IGListAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 807A30B1A51217D4F8D06557763B3306 /* UICollectionView+IGListBatchUpdateData.h in Headers */ = {isa = PBXBuildFile; fileRef = 25F28D195CA2FF2460A4C1136FD105B3 /* UICollectionView+IGListBatchUpdateData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 814E8604B46678A6E240642692187209 /* IGListAdapterProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = B483E6CAF66FCDEFAD191E281BE8C924 /* IGListAdapterProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 83C88E2D20A21A6E74C411A0D02F07AB /* IGListStackedSectionControllerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7362F257F9D7C07018084F3A7A18DC09 /* IGListStackedSectionControllerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 859D316248F143EEE011F9F813EAA47E /* IGListCollectionViewLayoutInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = B05EE17648F226B8FD6DEA8CDD553B87 /* IGListCollectionViewLayoutInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8B025CF4F63CD4E38D9281D59E583DB3 /* IGListSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 779DF4A841B6C9CE47E40C67E7D83D62 /* IGListSectionController.m */; }; - 8C0162174342AC9AD6BF1DD254F2D4B0 /* IGListCollectionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = F171DC4805CABE00914128DA4EE6223A /* IGListCollectionContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8D00CE2E5C811366ABA222D254528190 /* UICollectionView+IGListBatchUpdateData.m in Sources */ = {isa = PBXBuildFile; fileRef = 48E529B73159621366115FE581A1C7FA /* UICollectionView+IGListBatchUpdateData.m */; }; - 8E7B30B1EA0D83A5089D5FCB93B81163 /* IGListMoveIndexInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FBE926B7E64281B80C7BC38803AF4D6D /* IGListMoveIndexInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 92B3A5660013C02DCA2C7214BD7310AB /* IGListIndexSetResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1046470BDD719AFB20C97992FE4E6EF8 /* IGListIndexSetResultInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 978A1812F44351CCFAB84DB993479537 /* IGListAdapterUpdaterInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AE2FD6DC4BDF404C3B20D1EE0920A449 /* IGListAdapterUpdaterInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 98FED758909CCCB91BA8A46021BA066F /* Pods-ZaloMessageUI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9EBEF6CD72FB4E0A3F923D1BA6E6CB /* Pods-ZaloMessageUI-dummy.m */; }; - 991FDBFCF84830061021BA41412B23D3 /* IGListIndexPathResult.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD3F5A948A44666E6CAFA58C5F1DDDA /* IGListIndexPathResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 9B5B59C7D4FAA46BA8D86BD94576B085 /* IGListCollectionViewLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2B3A48B8D6446CBE6A307AF598C92B4 /* IGListCollectionViewLayout.mm */; }; - 9ED092EA0B8FD6C9914926F61DD7974C /* IGListBatchUpdates.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD4D98D644A32BDDADDD3BB554B53C6 /* IGListBatchUpdates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A1F6C98344934E2F14285FAF23FED437 /* IGListBatchUpdates.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C949040285E9D68D76CBCF5808AA3DE /* IGListBatchUpdates.m */; }; - A460B450702AF73290B119803B5459F0 /* IGListDiff.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3763862FB70563C77923F76394243E /* IGListDiff.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A63613377875A83C1AC0645C00FBC524 /* IGListAdapterUpdaterDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 257562CD4FD5E868C0A72DEFAD5DE5E4 /* IGListAdapterUpdaterDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A7049C2854D9E9693F2C79BB4D37595B /* IGListDiffKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F9615EFEA89C09AA6B27C4FFC7AA9A50 /* IGListDiffKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA0C09DF4610E5752965A774F5C255CF /* IGListCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 97454DD8E599E4B00183E3A285DB9C22 /* IGListCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B3F8B6690891C6DD25452DD4A20B2DA3 /* IGListIndexSetResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 996AD1693136E561660FDEC81D1BD614 /* IGListIndexSetResult.m */; }; - B3FAF94584AFACCA7CDCD30E83FA019A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */; }; - B6362766042314B04067F91511E8570D /* IGListSingleSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = D3E7C76FA815DF001AF4DC02D68EBFBE /* IGListSingleSectionController.m */; }; - B69F465B5C554886119DCB41B7E0C463 /* IGListMoveIndexPathInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F82250AA9AA427031C8A47D8F1144B /* IGListMoveIndexPathInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - B6F02397FFA625CBA70AC844396AD104 /* NSString+IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = D6D2A8989F37FF0BD6AF5CF60F05CFF0 /* NSString+IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - BC5744F76AEED9E1B86966F420BCD839 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */; }; - BF924715ED330F1EBFB93C0DE9FB75F1 /* IGListSectionControllerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BFF7D6EF49DB458D59B8A56A68F4DA6E /* IGListSectionControllerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C3DBA70EFC22978AAA471095896D6197 /* IGListCollectionViewLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = D6D3213014B1E504187FAB80A4C19DB3 /* IGListCollectionViewLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C46FD4B178066D467A76D5C064CBD11A /* NSNumber+IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D9B3A11994AABDA0DA3D09FB0D695BB /* NSNumber+IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C93529C81BA22193C43F0A56013650B0 /* IGListBindingSectionControllerDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 120D206999D71756EA8DF788A441EA71 /* IGListBindingSectionControllerDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D3A94B9A8260D31F78BF66E221BA5693 /* IGListAdapterUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CC1021D9A9AE103C42417C0430800FC /* IGListAdapterUpdater.m */; }; - D41D845251DF6C645D0FC7BE96675800 /* IGListCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 711343872265842BB56759CA607E0EA7 /* IGListCollectionView.m */; }; - D4395F27CF226BDFCBE9E3894A5D589A /* IGListAdapterUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E1F19085938A1D0F4E97D89760E6FF4 /* IGListAdapterUpdater.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DA1B3D45BF018B620290019D6931A5B8 /* IGListAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 808CAE702E0FF8F6EE6BBFF562D6B05D /* IGListAdapter.m */; }; - DA5F89C380774C1EDED0E593CC8D71FA /* IGListKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1949E563D6CC13ABFA8D3CFA3E42C27B /* IGListKit-dummy.m */; }; - E0705CAE840D25826F78F7755FB9B8B1 /* IGListDiff.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C804130A0610F5FEB0118D5DEBB0520 /* IGListDiff.mm */; }; - E2C87FAC44A49E254239D3BA72A2C602 /* IGListBatchUpdateData.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EC6367CA5091DC825F156D4CC222F79 /* IGListBatchUpdateData.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E2D4A2D234373AF4D01358DE2B964D71 /* IGListReloadDataUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = FC9464E8FDCAA0D9DE053CEB658D2B3C /* IGListReloadDataUpdater.m */; }; - E3C61169F814ED56C9476DF5AF4434A6 /* IGListBatchUpdateData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41DB6F6AE476EBDF2FBBD47C2E8208CC /* IGListBatchUpdateData.mm */; }; - E63AF54F71D8795A31E7C4AA97E961BC /* Pods-ZaloMessageUI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = EC2FA4D3D829C0D349DE4D1A1D70C2C5 /* Pods-ZaloMessageUI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E8924336590F81446EC1FA6BEA897D7D /* IGListCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = FC0CCC63453F0DE9ECBDD889B3788469 /* IGListCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EB11684EDF70986D2C74A975BBFCED12 /* IGListSupplementaryViewSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E51AD1DE4B35C479661A831CAAD915A /* IGListSupplementaryViewSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F7D0FF68D1C3603A4687F723A06EC5F2 /* IGListMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C923E3559F037E7FCC2494A7B67B01D /* IGListMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F81C53F494B5F089471ECFBDEDC94C77 /* IGListBindingSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DA237241A8B6D8FB5781051C8A23C66 /* IGListBindingSectionController.m */; }; - F8D3E13C31FC83AFC640BE3C7AE8CC5D /* IGListKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7436B092709EECAE742549ED4CA674 /* IGListKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FAACFDF402F6458A7D4419E47AD783EF /* IGListAdapterDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FDD11DC6D1B49C93AD32646572440B6 /* IGListAdapterDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00FD3A151D6607256D58A29F93EDCE72 /* IGListBindingSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0177AF4A40D41CEE1CB36108C24A7022 /* IGListBindingSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 02E1A2C249B9A41A23B1DFEBBEDD38FE /* UICollectionView+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC32F955A10354B7CE981F906933837 /* UICollectionView+DebugDescription.m */; }; + 0669ADE79B91179ED76A9CEC38DFAF7D /* IGListBatchUpdates.h in Headers */ = {isa = PBXBuildFile; fileRef = 047EB4A6E4010DC4E5133F0DC5F9C230 /* IGListBatchUpdates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0980D8E2EE9F48CAA78073361C6C60F8 /* IGListAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 63349022EA306D2F76C266669BC30859 /* IGListAdapter.m */; }; + 0A77E1DC9CC439CEBF7AADF7E3CCA9BC /* UICollectionView+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F921E777F84D02B8779A979C3996470 /* UICollectionView+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0E1DCDA4EA4637E16205F53AF1AC621B /* IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = D41497FAB210714ACAED2B33357E47D3 /* IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1328A35B5C0B138A38015B82619BE0A3 /* IGListMoveIndexPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 68DD4547A9A52D5784CA694D1DE4DB9B /* IGListMoveIndexPath.m */; }; + 1349CEA76F20C96C9873AF312DD3B7AB /* IGListBindingSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 492DDCEE6074F2D47556F1A08FD3EC24 /* IGListBindingSectionController.m */; }; + 1626618941AA3D0DFE92D24F1FABB835 /* IGListDisplayHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D7F95C292A0B7DC1D8516840C716BC5E /* IGListDisplayHandler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 16A4511E933A5CB0A89CD07ECC517FA6 /* IGListDebugger.m in Sources */ = {isa = PBXBuildFile; fileRef = 13624E6C15B892DEDBFE0E1C40F45131 /* IGListDebugger.m */; }; + 19AF6C688FF10545F8B30FDD6AF26947 /* IGListSingleSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53526A36E61F13210FE618FB67F501E9 /* IGListSingleSectionController.m */; }; + 1DF000BCB90932296A057352B0B7C57E /* IGListAdapter+UICollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 322AC6642D589AA3CCA4578B9CED512A /* IGListAdapter+UICollectionView.m */; }; + 1F6193099593C9752F0980A5E0111D58 /* IGListWorkingRangeDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = C0C83B1ADDB3EBC0C2A7F187C3135519 /* IGListWorkingRangeDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 24D3BCA28A1E3AD37403EEC95D37F56D /* IGListBindingSectionController+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E091C4C041B8839D4DD117441AF962 /* IGListBindingSectionController+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 282A689A8C14C853022E1DC70AC350B9 /* IGListSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = B42E50CA17C278BA568FCAE8E1430ACC /* IGListSectionController.m */; }; + 2BE748A34797FD31CFC4F41DACFDB3B7 /* IGListSectionMap+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 8637DD702D29A68A5D099D27027363EB /* IGListSectionMap+DebugDescription.m */; }; + 2E0B60B0B7E8F1402B3AF014632F530B /* IGListDebuggingUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B5D1B00158A99A6CD9E597EB32A0873 /* IGListDebuggingUtilities.m */; }; + 2E561BA63103FEC30C0B7D6587B2C247 /* IGListDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = A99A44A60992AB3E7F6A5BDE3764D1D8 /* IGListDebugger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2EE97D54664FD7FE22E7332FA8A26ED9 /* IGListAdapterUpdaterInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA7DB8B7222CE0CCFE2D80419410445 /* IGListAdapterUpdaterInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 307E641EF37FCB5C01EAA5EC1ADA978D /* IGListBindingSectionController+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 95A01125FE4C75073CF52AA00009099D /* IGListBindingSectionController+DebugDescription.m */; }; + 30906853093014EA2911504C2B86DF87 /* IGListStackedSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 407C2D74BB448428273E5DAD218280D0 /* IGListStackedSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 320AF651B4C821C526F0151F65ED9733 /* IGListSupplementaryViewSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A95307CCB218CF625E58C886EF0DDDD1 /* IGListSupplementaryViewSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 33E27E1D5F91ED769DAB566B0807AA02 /* IGListStackedSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 643A51D5E237E6B3FDE21FCA4B2E0A44 /* IGListStackedSectionController.m */; }; + 35B549886D7FBC153C20F4F15D9CA2BD /* IGListIndexSetResult.h in Headers */ = {isa = PBXBuildFile; fileRef = E3ED5A8D5654A9255F283E6D32ACB60B /* IGListIndexSetResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 35EB94DA10091201052F12313B3ED081 /* IGListAdapterProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 529D578276A85FB7C02DE97B03034027 /* IGListAdapterProxy.m */; }; + 39366ABAFB8818F7987108BE3831504E /* UICollectionView+IGListBatchUpdateData.h in Headers */ = {isa = PBXBuildFile; fileRef = 88E34C67EC78CCBE88CEBBE49B76FEA5 /* UICollectionView+IGListBatchUpdateData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3BB3DB028BF1E38FB951C875B60889DA /* IGListAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EDEDAB37563E1B63250F6410EFDD8E /* IGListAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3E4041948DDE685508234016E27DED88 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */; }; + 3FF0ECE458B1DAF6E9D08C277821052B /* IGListDisplayDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F32E8F5DEFF6857693CFEBA263E1C0B /* IGListDisplayDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 40926B29323FC063B2CF8DCA456498D6 /* IGListAdapter+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = E4FAA77B888E031451935CDD7720FE18 /* IGListAdapter+DebugDescription.m */; }; + 477AA365124DE42E6E176C77AB789903 /* IGListReloadIndexPath.m in Sources */ = {isa = PBXBuildFile; fileRef = D729F30E164B54B3350CD6B968FCDD39 /* IGListReloadIndexPath.m */; }; + 47D826D320AFAC50434CC6C85D250E33 /* IGListArrayUtilsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E696FBAE2AC98C82D0A73C9E39E59439 /* IGListArrayUtilsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4915AD1938B56C8B7D46314273941D84 /* IGListAdapterDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = CD81C2D20EA665176B5A89B06377EAB4 /* IGListAdapterDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 494EFB53CCCDE4730B79F3B2A861BE58 /* UICollectionViewLayout+InteractiveReordering.h in Headers */ = {isa = PBXBuildFile; fileRef = A5D91E3F7CBECC8CD1D49D2FD63432B4 /* UICollectionViewLayout+InteractiveReordering.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4A2AE37A36522FE3B2398A083F1274D1 /* IGListBindingSectionControllerDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61BAA609182BF4EC549C921692E196 /* IGListBindingSectionControllerDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C274051160C465F00282E80FFB3A935 /* IGListSectionControllerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = B2B249761F9D8D235776AE3ABCF8F46E /* IGListSectionControllerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4E6CCE94042A6DC407AF0CAE3733C1F7 /* NSNumber+IGListDiffable.m in Sources */ = {isa = PBXBuildFile; fileRef = 54CAC4FBB82E56D2D0E54194FE0E74D8 /* NSNumber+IGListDiffable.m */; }; + 53D096CFC5829F685034B1C7CBD9E0FC /* IGListStackedSectionControllerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A44F7EDFF037081042B4287A294DEA78 /* IGListStackedSectionControllerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5417C871D765FF92FB6FE20B4F93B486 /* IGListWorkingRangeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F811605A36E3C3E5B7E5BE196DB222 /* IGListWorkingRangeHandler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 56E1A6ED190CD271F2012D193FD02193 /* IGListDebuggingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 163CEC950A97BC177C84803F42934B12 /* IGListDebuggingUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5C66620892D0161E3B4F190E018E2507 /* IGListMoveIndexInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = E8C7CCBFE4B4142A3B87B06995956D3D /* IGListMoveIndexInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5EB6C8BB152EE9635A0D1705D4F8EB00 /* IGListBatchUpdateState.h in Headers */ = {isa = PBXBuildFile; fileRef = 36FFE505227F681FDF8F9F5C447F5CC8 /* IGListBatchUpdateState.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5FECBDC6E10A5865BAF8BD0FBA40DE27 /* IGListAdapter+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = E6268C042C954A1A283BE06B6499FD58 /* IGListAdapter+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 603A4D113E86EFCCAF1745C56728D042 /* IGListAdapter+UICollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 763F24D6D009FDEBCC03F2B0EB665861 /* IGListAdapter+UICollectionView.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 65928B50FFA02AAC792E3456BC248AD0 /* IGListAdapterInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EE42A909C94E4233DBE55E748120961 /* IGListAdapterInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 689F08E0B8F69052078C2B45B26ABD69 /* UICollectionView+IGListBatchUpdateData.m in Sources */ = {isa = PBXBuildFile; fileRef = 0024CEFA348D3F6B1119DA5D366865B4 /* UICollectionView+IGListBatchUpdateData.m */; }; + 6B2175DA5949FF3838BD6664D0B19FEB /* IGListIndexPathResult.h in Headers */ = {isa = PBXBuildFile; fileRef = B56457B4D4255F65F321DC0979F5A67E /* IGListIndexPathResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DBB61EEEC19BC07A49CAD420FC05F7B /* NSNumber+IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = 065B975ECA01D0791C823F77E71BFE28 /* NSNumber+IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E10F6760B6A61ED34AD12E94AE75BF1 /* IGListAdapterUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = DADCF46067894FAE4F695ABBFB7A8AA9 /* IGListAdapterUpdater.m */; }; + 6E16E0456D9EB61AAF505678035B7623 /* IGListAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = CBEB63A10F7782FFE59A8B539044F49F /* IGListAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6EF2EA280BC1EE19DAF9C88DD31E9D5D /* IGListCollectionViewLayoutInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 775016B5F9D61893B64A0943E1BC0627 /* IGListCollectionViewLayoutInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 71EA424E166C3069FDCD8F6F34EF9FC7 /* IGListAdapterDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 75D3D286D2AC63292FF406A4F4A3FA29 /* IGListAdapterDataSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 726628D43E59E125EE6C84A24DB02789 /* IGListGenericSectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D63C79BCB0E794E34C7C820EB84606 /* IGListGenericSectionController.m */; }; + 735A02C29E5CB736E46DA33E53F7DDC5 /* IGListBatchUpdateData+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC47AE8E7F1B2829CA388EC9633C121 /* IGListBatchUpdateData+DebugDescription.m */; }; + 73AC9CD9697A503CBB2B35EBE86D1761 /* IGListAdapterProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = C8E654FC50F012E92B396CEA2C071441 /* IGListAdapterProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 82B2A3B8E767FB47A730D5C496BF0B05 /* IGListBatchUpdateData.h in Headers */ = {isa = PBXBuildFile; fileRef = 23BD8ED568FE0C89ACEF6334F1A75E87 /* IGListBatchUpdateData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8494F6BE88E480A18C4193A6E0379AEC /* IGListDiffKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B3AB9B73F507D06A27DB0DD8672C1F1 /* IGListDiffKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84DF44F178F591848CC36133C39623D4 /* IGListAdapterUpdaterDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B11A0867617137D39BA82FCE425C900C /* IGListAdapterUpdaterDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8B800F0610802E277372F3F29AE28D88 /* UIScrollView+IGListKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D64EA5E1D59919444CB30762B945D58D /* UIScrollView+IGListKit.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8D0EFF2BA871A37FDC618B734DDFBF58 /* UIScrollView+IGListKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BA8780B9F2F90290DC94CC2FF934653 /* UIScrollView+IGListKit.m */; }; + 8D9D44190E2941464E6CC60E35548571 /* IGListCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = FB92E0EF5AACFD94DDAC6A85190308E7 /* IGListCollectionView.m */; }; + 8EFD8AD1A68194A1426D827638902667 /* IGListBatchUpdateData+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 24736BC9E24CAFD23751927854F26186 /* IGListBatchUpdateData+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9034C03B1A71744248001AFA227CFC55 /* IGListCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 05D721ACEF7DACEF9927C83A73DF4DBA /* IGListCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 91592C1BF05299E4FA15807729C72E07 /* IGListBatchUpdates.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C96CB39F29243D0088DEB8B9323C3F /* IGListBatchUpdates.m */; }; + 95EBCFA1300EBE827CBF6DABEEED2F33 /* IGListBindable.h in Headers */ = {isa = PBXBuildFile; fileRef = E54D40951FCADB7DF461F8119322DDA0 /* IGListBindable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 98FED758909CCCB91BA8A46021BA066F /* Pods-ZaloMessageUI-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F6E146EC37AC1A581154B4BF6D7ACDB5 /* Pods-ZaloMessageUI-dummy.m */; }; + 99FBC326DBD70A4DFE8DB401C00C143E /* IGListAdapterMoveDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = A218FC42EA9C8362A6EC35960FF9D261 /* IGListAdapterMoveDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9EBB5545372E8DA3090E966A6ABF3FE0 /* IGListExperiments.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FD646349EBECA7157CBA588BE444607 /* IGListExperiments.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1B6562DB58C36470DD8E46E21DB745C /* IGListMoveIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C4B12BF7E1D767A7B4C24EC5CBED240 /* IGListMoveIndexPath.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A37E889EDAA908A05225D6E4A49451C7 /* IGListIndexSetResult.m in Sources */ = {isa = PBXBuildFile; fileRef = D66B2D1BE3BD8AB81C1E13E490BFCD89 /* IGListIndexSetResult.m */; }; + A3DA55704C4C3C68E6BC71A21D783D2F /* IGListAdapterUpdateListener.h in Headers */ = {isa = PBXBuildFile; fileRef = D4751CF6F8DE938C99786954388D4D4D /* IGListAdapterUpdateListener.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A412AAFAB580539D9684EB594F77F995 /* IGListAdapterUpdater+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D0A8CF3C29032B8791A46D349893DA3 /* IGListAdapterUpdater+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A421E945E1C00D6D4B5356E756D963ED /* IGListUpdatingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 03CBE19D1FA7D3B67A32FB55FC895070 /* IGListUpdatingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A49BECCC811AA42FE2FDF71F52BCFF00 /* IGListDiff.h in Headers */ = {isa = PBXBuildFile; fileRef = 74BA69709A51C6D7F5B40365EA9C6014 /* IGListDiff.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A582474CB493B54DC2EDF92E082303BE /* IGListBindingSectionControllerSelectionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E5EDA2855BEC4AC45F1F24DEAC63C43 /* IGListBindingSectionControllerSelectionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A7ECEF478A0C350BA7EDB3C0BFDD6A53 /* IGListIndexPathResult.m in Sources */ = {isa = PBXBuildFile; fileRef = FF4CDD01E4D6FCD4744A0628E458EC6C /* IGListIndexPathResult.m */; }; + A849E060A19C9E5E70C8365880727688 /* IGListMoveIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = E2340871863ACFE8A65F0F9A1FA4E596 /* IGListMoveIndex.m */; }; + A881B1AA711AE18417CAE0FF05E37912 /* IGListKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 65EC38859FAA58F02398F4A98ADCDD1E /* IGListKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ABE63502883410507829B29E3696C9DE /* IGListScrollDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ABC701FFD27091D59C1A387DEF7373E /* IGListScrollDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AF2E5CD9F501E601F23CEECB09F8B2E8 /* IGListSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 79F0BE17BA22601D674C972E9ACE9080 /* IGListSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2BAA2FA23FE34F42ED75E425776039D /* IGListCollectionViewDelegateLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 463E7F1407D752F7D9455C654DEF9BBE /* IGListCollectionViewDelegateLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3948123A4470290154C74F986803DEA /* IGListSectionMap+DebugDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = CEA8E08FC68D6DBB093E3C6733B1CFB9 /* IGListSectionMap+DebugDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B6981F2DF44D70105C72235BF79CA484 /* IGListWorkingRangeHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = A0FA949EAE4F162DD90DAA5F43B4DD43 /* IGListWorkingRangeHandler.mm */; }; + BB0AF9BEF206B0F0E77F5CF648FBEAA8 /* IGListSectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CA49A3657430FE67EFBDEA004EA2A71 /* IGListSectionMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BCA5AFA2132091C48DE68859301D3BE2 /* IGListMoveIndexPathInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = C3BEBE7FC46FDD9304EEC6CCCD0EFD71 /* IGListMoveIndexPathInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BE4EE27767A15480990BB0317811CEBB /* IGListDisplayHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 80EEB16402C06EEF42C9C9C11E99249F /* IGListDisplayHandler.m */; }; + C076D04DC7D61BB4A699D5C6B2A837DB /* NSString+IGListDiffable.m in Sources */ = {isa = PBXBuildFile; fileRef = 15D0F4EB026D6786436D2A8F3E7978D7 /* NSString+IGListDiffable.m */; }; + C1C5243A9A03E62B783ED7E054B18876 /* IGListAdapterUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 8093EA48163FB7088AF188D16976534A /* IGListAdapterUpdater.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C3A17C5AB199F6C695B03A37FD667AD2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */; }; + C3CD5AFA1934403AB14BC99320DBC48D /* IGListIndexPathResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A116F0C825FF33DB907E23477B7608B /* IGListIndexPathResultInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C46CEB2DC7D5195A816DEDDB38BA86C8 /* IGListCollectionViewLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A4A694DCA7D32D60D9D9EA75CF04303 /* IGListCollectionViewLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C4D0C27B3A4D3ACB3145CE7BF52BB6A9 /* IGListMoveIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 63D3306C4FCADADA24BB3E4848498009 /* IGListMoveIndex.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C77F65C025CE9AE7FD1FDBE0AE8B1D8A /* IGListSectionMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 3887683279880249AB7E08138E3A1534 /* IGListSectionMap.m */; }; + C7EA68DDDD768AC5C80BEDEB896E5263 /* UICollectionViewLayout+InteractiveReordering.m in Sources */ = {isa = PBXBuildFile; fileRef = A5C333A721D1B946EC8F88323ADD78BA /* UICollectionViewLayout+InteractiveReordering.m */; }; + C83DDF8BA60AF512ADF75B5AEB1A8855 /* IGListCollectionViewLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = EFD3B4911FD0F697A60277CB4369D39E /* IGListCollectionViewLayout.mm */; }; + CD42CB63D39C6263FA1FF718E29E2EE3 /* IGListCollectionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 59DCDB9312101DF7F5D5B57AFB181047 /* IGListCollectionContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CD82ABAECC16FD36D8CC1A6C4CC3E658 /* IGListReloadDataUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = D12A98E0133749857364C75428D71896 /* IGListReloadDataUpdater.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D42BA228E55F0DB2C8CBF20DF82E2221 /* IGListBatchContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DA9398198500956878EE35FCF91BE07 /* IGListBatchContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D5BB97F5973CC5AE48D9376CFE395360 /* IGListBatchUpdateData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70509C5764B55CAAC4E64733E0F8026F /* IGListBatchUpdateData.mm */; }; + D6169AF781DC7A6CCC248CB3DFF1B668 /* IGListSingleSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = EE8F295FB7875CBC524D1495C1D1D10C /* IGListSingleSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DAD48C3715C347CF23C4F542AE5C7466 /* IGListGenericSectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 643933F60E2287B88A5F72DC8FD229B1 /* IGListGenericSectionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DEB9619E034323E4C37948DE9850F88A /* IGListReloadDataUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = A80A9DAEFE4C1F36E5973C29696039B9 /* IGListReloadDataUpdater.m */; }; + DFD9C059ECA61A503605754D689ADD2B /* NSString+IGListDiffable.h in Headers */ = {isa = PBXBuildFile; fileRef = B047D5CE3ED32253ECFDD6F39CF29AEF /* NSString+IGListDiffable.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E0B99A9E6BBF5165A3C99ED2EFAA520F /* IGListDiff.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2FB53570D9FA612AC525EC662BDA3B24 /* IGListDiff.mm */; }; + E63AF54F71D8795A31E7C4AA97E961BC /* Pods-ZaloMessageUI-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FCC1E666B0971D28ADF5D8079C0EC3E /* Pods-ZaloMessageUI-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECC17D3441A9A361193C2EC863357615 /* IGListIndexSetResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = F24A0ECF3CE912E0AD22DE4ABD1A989F /* IGListIndexSetResultInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EF2A525A4C3A13D8568E29019E821FD1 /* IGListKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = FC2C2E953A1E025EFD2540C8DD328458 /* IGListKit-dummy.m */; }; + EF6D5B957916E714B3EAA2A64179F460 /* IGListKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9659EC0975BDEBCE76E13AF059695499 /* IGListKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F291303229C7596334D830421C00454C /* IGListAdapterUpdater+DebugDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 831631C94FBCE24B06164C85E36714C7 /* IGListAdapterUpdater+DebugDescription.m */; }; + F31E7058342A01FD094E905A52EDAEAE /* IGListCompatibility.h in Headers */ = {isa = PBXBuildFile; fileRef = A19101BD44E4673AEBB1CE71424BEC98 /* IGListCompatibility.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F7DD77F2526E0BEA90904F21B2E25553 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */; }; + FA6C0CCA4193F7A9FCF3CB97DAF1AEA1 /* IGListTransitionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B004396B6CFFB8A9DC2638F32AF182C1 /* IGListTransitionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FEB6AB97493672FBC1CB54DC3317BBE1 /* IGListReloadIndexPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 5EC9F595D2BF0435A78F4BFCB482ACB6 /* IGListReloadIndexPath.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FEC5F821A80D6BE85BE021732ADC9B98 /* IGListMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 095A2EA0AB34AB6D1A64EFDEE28B1B99 /* IGListMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -97,109 +128,140 @@ isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 7E8FA01AD073C38BEBF299EE44B91444; + remoteGlobalIDString = BC17A8B6E847EB854B5E4439B9001E21; remoteInfo = IGListKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 010584FD1C9A0536B2855DFA61D29811 /* IGListDisplayDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDisplayDelegate.h; path = Source/IGListDisplayDelegate.h; sourceTree = ""; }; - 01C0B92FD99AEE2D5EC215E5F1BC1BB0 /* IGListAdapter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapter.h; path = Source/IGListAdapter.h; sourceTree = ""; }; - 0A9EBEF6CD72FB4E0A3F923D1BA6E6CB /* Pods-ZaloMessageUI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ZaloMessageUI-dummy.m"; sourceTree = ""; }; - 0C949040285E9D68D76CBCF5808AA3DE /* IGListBatchUpdates.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListBatchUpdates.m; path = Source/Internal/IGListBatchUpdates.m; sourceTree = ""; }; - 1046470BDD719AFB20C97992FE4E6EF8 /* IGListIndexSetResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexSetResultInternal.h; path = Source/Common/Internal/IGListIndexSetResultInternal.h; sourceTree = ""; }; - 120D206999D71756EA8DF788A441EA71 /* IGListBindingSectionControllerDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionControllerDataSource.h; path = Source/IGListBindingSectionControllerDataSource.h; sourceTree = ""; }; - 1949E563D6CC13ABFA8D3CFA3E42C27B /* IGListKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "IGListKit-dummy.m"; sourceTree = ""; }; - 1C804130A0610F5FEB0118D5DEBB0520 /* IGListDiff.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListDiff.mm; path = Source/Common/IGListDiff.mm; sourceTree = ""; }; - 1DA237241A8B6D8FB5781051C8A23C66 /* IGListBindingSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListBindingSectionController.m; path = Source/IGListBindingSectionController.m; sourceTree = ""; }; - 1FD976B91AF21538CF7C4DBE0DDC722F /* IGListWorkingRangeHandler.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListWorkingRangeHandler.mm; path = Source/Internal/IGListWorkingRangeHandler.mm; sourceTree = ""; }; - 2001DD06082463F4E1B1A1DAAE19199B /* IGListSectionMap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionMap.h; path = Source/Internal/IGListSectionMap.h; sourceTree = ""; }; - 20EF09DA25084EF36543E9D42914E471 /* IGListIndexPathResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListIndexPathResult.m; path = Source/Common/IGListIndexPathResult.m; sourceTree = ""; }; - 228DE7AE291679DAAE4BE93A069CAB95 /* Pods-ZaloMessageUI-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ZaloMessageUI-acknowledgements.markdown"; sourceTree = ""; }; - 257562CD4FD5E868C0A72DEFAD5DE5E4 /* IGListAdapterUpdaterDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdaterDelegate.h; path = Source/IGListAdapterUpdaterDelegate.h; sourceTree = ""; }; - 25F28D195CA2FF2460A4C1136FD105B3 /* UICollectionView+IGListBatchUpdateData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionView+IGListBatchUpdateData.h"; path = "Source/Internal/UICollectionView+IGListBatchUpdateData.h"; sourceTree = ""; }; + 0024CEFA348D3F6B1119DA5D366865B4 /* UICollectionView+IGListBatchUpdateData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionView+IGListBatchUpdateData.m"; path = "Source/Internal/UICollectionView+IGListBatchUpdateData.m"; sourceTree = ""; }; + 003FAECEA0B36DB072907AC26440676B /* Pods-ZaloMessageUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ZaloMessageUI.release.xcconfig"; sourceTree = ""; }; + 00D12847F06BED1EACCB9D124C2277D9 /* IGListKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = IGListKit.xcconfig; sourceTree = ""; }; + 0177AF4A40D41CEE1CB36108C24A7022 /* IGListBindingSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionController.h; path = Source/IGListBindingSectionController.h; sourceTree = ""; }; + 03CBE19D1FA7D3B67A32FB55FC895070 /* IGListUpdatingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListUpdatingDelegate.h; path = Source/IGListUpdatingDelegate.h; sourceTree = ""; }; + 047EB4A6E4010DC4E5133F0DC5F9C230 /* IGListBatchUpdates.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdates.h; path = Source/Internal/IGListBatchUpdates.h; sourceTree = ""; }; + 05D721ACEF7DACEF9927C83A73DF4DBA /* IGListCollectionView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionView.h; path = Source/IGListCollectionView.h; sourceTree = ""; }; + 065B975ECA01D0791C823F77E71BFE28 /* NSNumber+IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNumber+IGListDiffable.h"; path = "Source/Common/NSNumber+IGListDiffable.h"; sourceTree = ""; }; + 095A2EA0AB34AB6D1A64EFDEE28B1B99 /* IGListMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMacros.h; path = Source/Common/IGListMacros.h; sourceTree = ""; }; + 0CC47AE8E7F1B2829CA388EC9633C121 /* IGListBatchUpdateData+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListBatchUpdateData+DebugDescription.m"; path = "Source/Internal/IGListBatchUpdateData+DebugDescription.m"; sourceTree = ""; }; + 0E5EDA2855BEC4AC45F1F24DEAC63C43 /* IGListBindingSectionControllerSelectionDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionControllerSelectionDelegate.h; path = Source/IGListBindingSectionControllerSelectionDelegate.h; sourceTree = ""; }; + 0EE42A909C94E4233DBE55E748120961 /* IGListAdapterInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterInternal.h; path = Source/Internal/IGListAdapterInternal.h; sourceTree = ""; }; + 0F9F2F29026CC7459B43396FF0238DA5 /* Pods-ZaloMessageUI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-ZaloMessageUI.modulemap"; sourceTree = ""; }; + 13624E6C15B892DEDBFE0E1C40F45131 /* IGListDebugger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListDebugger.m; path = Source/Internal/IGListDebugger.m; sourceTree = ""; }; + 15D0F4EB026D6786436D2A8F3E7978D7 /* NSString+IGListDiffable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+IGListDiffable.m"; path = "Source/Common/NSString+IGListDiffable.m"; sourceTree = ""; }; + 163CEC950A97BC177C84803F42934B12 /* IGListDebuggingUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDebuggingUtilities.h; path = Source/Internal/IGListDebuggingUtilities.h; sourceTree = ""; }; + 1DA9398198500956878EE35FCF91BE07 /* IGListBatchContext.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchContext.h; path = Source/IGListBatchContext.h; sourceTree = ""; }; + 1F32E8F5DEFF6857693CFEBA263E1C0B /* IGListDisplayDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDisplayDelegate.h; path = Source/IGListDisplayDelegate.h; sourceTree = ""; }; + 23BD8ED568FE0C89ACEF6334F1A75E87 /* IGListBatchUpdateData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdateData.h; path = Source/Common/IGListBatchUpdateData.h; sourceTree = ""; }; + 24736BC9E24CAFD23751927854F26186 /* IGListBatchUpdateData+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListBatchUpdateData+DebugDescription.h"; path = "Source/Internal/IGListBatchUpdateData+DebugDescription.h"; sourceTree = ""; }; 2656E6F1699FAC24AC8D26A24776B7B0 /* Pods_ZaloMessageUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_ZaloMessageUI.framework; path = "Pods-ZaloMessageUI.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 2FDD11DC6D1B49C93AD32646572440B6 /* IGListAdapterDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterDataSource.h; path = Source/IGListAdapterDataSource.h; sourceTree = ""; }; - 3079C3EA36555E2AD7E80A08D4E3143D /* IGListUpdatingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListUpdatingDelegate.h; path = Source/IGListUpdatingDelegate.h; sourceTree = ""; }; - 368EB3EF4F72EC88B1850E7B6569BAF9 /* IGListSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionController.h; path = Source/IGListSectionController.h; sourceTree = ""; }; - 3E1F19085938A1D0F4E97D89760E6FF4 /* IGListAdapterUpdater.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdater.h; path = Source/IGListAdapterUpdater.h; sourceTree = ""; }; - 3E8415EE9C0C02894DE9D7105F85C835 /* IGListBatchUpdateState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdateState.h; path = Source/Internal/IGListBatchUpdateState.h; sourceTree = ""; }; - 4174531EE7E4CB451191AECA50819F5F /* IGListAdapterInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterInternal.h; path = Source/Internal/IGListAdapterInternal.h; sourceTree = ""; }; - 41DB6F6AE476EBDF2FBBD47C2E8208CC /* IGListBatchUpdateData.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListBatchUpdateData.mm; path = Source/Common/IGListBatchUpdateData.mm; sourceTree = ""; }; - 430BC698E899473DBA4C089E811ED2E9 /* IGListReloadDataUpdater.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListReloadDataUpdater.h; path = Source/IGListReloadDataUpdater.h; sourceTree = ""; }; - 47AD689F7E36931512210195B51DC939 /* IGListBindable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindable.h; path = Source/IGListBindable.h; sourceTree = ""; }; - 48E529B73159621366115FE581A1C7FA /* UICollectionView+IGListBatchUpdateData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionView+IGListBatchUpdateData.m"; path = "Source/Internal/UICollectionView+IGListBatchUpdateData.m"; sourceTree = ""; }; - 49344776B1D965DC389EE3F5B2692911 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 4C7436B092709EECAE742549ED4CA674 /* IGListKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IGListKit-umbrella.h"; sourceTree = ""; }; - 4C923E3559F037E7FCC2494A7B67B01D /* IGListMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMacros.h; path = Source/Common/IGListMacros.h; sourceTree = ""; }; - 4E7BE22886808C98EFAF7994EE6568DA /* IGListAdapterDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterDelegate.h; path = Source/IGListAdapterDelegate.h; sourceTree = ""; }; - 4EC6367CA5091DC825F156D4CC222F79 /* IGListBatchUpdateData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdateData.h; path = Source/Common/IGListBatchUpdateData.h; sourceTree = ""; }; - 51C149BC9621A6A6DFC34F2FB9F1425C /* IGListWorkingRangeHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListWorkingRangeHandler.h; path = Source/Internal/IGListWorkingRangeHandler.h; sourceTree = ""; }; - 52AB39E5DE2E20926EA6D4984EBCFE59 /* IGListBindingSectionControllerSelectionDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionControllerSelectionDelegate.h; path = Source/IGListBindingSectionControllerSelectionDelegate.h; sourceTree = ""; }; - 5381841AC8F1E3165C7483C0D2FEA35D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 54B57271641DC0C7CA17035FE9C3A8B5 /* IGListExperiments.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListExperiments.h; path = Source/Common/IGListExperiments.h; sourceTree = ""; }; - 55E1C761261B4FC3324D3D29CADEB7C5 /* IGListDisplayHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListDisplayHandler.m; path = Source/Internal/IGListDisplayHandler.m; sourceTree = ""; }; - 5CC1021D9A9AE103C42417C0430800FC /* IGListAdapterUpdater.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapterUpdater.m; path = Source/IGListAdapterUpdater.m; sourceTree = ""; }; - 5E3AC1DFACCEEA11A38A2401A4D2B4AC /* IGListMoveIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndex.h; path = Source/Common/IGListMoveIndex.h; sourceTree = ""; }; - 603200A8CD1CEFFD00AA1D336FDC3E12 /* Pods-ZaloMessageUI-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ZaloMessageUI-resources.sh"; sourceTree = ""; }; - 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 6E51AD1DE4B35C479661A831CAAD915A /* IGListSupplementaryViewSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSupplementaryViewSource.h; path = Source/IGListSupplementaryViewSource.h; sourceTree = ""; }; - 6F8F78AD7CBD5561CE29BA948CF90580 /* IGListKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = IGListKit.xcconfig; sourceTree = ""; }; - 6F8FC0AEA108EE633AA29B103554AFDC /* IGListScrollDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListScrollDelegate.h; path = Source/IGListScrollDelegate.h; sourceTree = ""; }; - 711343872265842BB56759CA607E0EA7 /* IGListCollectionView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListCollectionView.m; path = Source/IGListCollectionView.m; sourceTree = ""; }; - 73161ADDD6004C7DB5AFB67922643DFD /* NSNumber+IGListDiffable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+IGListDiffable.m"; path = "Source/Common/NSNumber+IGListDiffable.m"; sourceTree = ""; }; - 73254ED54EC807B3FB25FEE911048301 /* IGListWorkingRangeDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListWorkingRangeDelegate.h; path = Source/IGListWorkingRangeDelegate.h; sourceTree = ""; }; - 7362F257F9D7C07018084F3A7A18DC09 /* IGListStackedSectionControllerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListStackedSectionControllerInternal.h; path = Source/Internal/IGListStackedSectionControllerInternal.h; sourceTree = ""; }; - 76749C313DA571984B78AA95DB51E102 /* IGListSectionType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionType.h; path = Source/IGListSectionType.h; sourceTree = ""; }; - 779DF4A841B6C9CE47E40C67E7D83D62 /* IGListSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSectionController.m; path = Source/IGListSectionController.m; sourceTree = ""; }; - 7D9B3A11994AABDA0DA3D09FB0D695BB /* NSNumber+IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNumber+IGListDiffable.h"; path = "Source/Common/NSNumber+IGListDiffable.h"; sourceTree = ""; }; - 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 808CAE702E0FF8F6EE6BBFF562D6B05D /* IGListAdapter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapter.m; path = Source/IGListAdapter.m; sourceTree = ""; }; - 82756399D6433AFBC13A0410E0179623 /* IGListBindingSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionController.h; path = Source/IGListBindingSectionController.h; sourceTree = ""; }; - 85B53583128FAAECA97E82ACD9564809 /* Pods-ZaloMessageUI.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ZaloMessageUI.debug.xcconfig"; sourceTree = ""; }; - 885816AA0E2310FF4F2A5FB62E351603 /* IGListSingleSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSingleSectionController.h; path = Source/IGListSingleSectionController.h; sourceTree = ""; }; - 8A09086C7AB0DC46E91CB1099F1C6200 /* IGListAdapterProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapterProxy.m; path = Source/Internal/IGListAdapterProxy.m; sourceTree = ""; }; - 8C985162A550067251A36CEBB5D1F21A /* IGListDisplayHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDisplayHandler.h; path = Source/Internal/IGListDisplayHandler.h; sourceTree = ""; }; - 8D5A31C01478666EFFAED2069D102019 /* IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiffable.h; path = Source/Common/IGListDiffable.h; sourceTree = ""; }; - 8D71A4799B19EE1D916324FB5E1D5461 /* IGListMoveIndexPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexPath.h; path = Source/Common/IGListMoveIndexPath.h; sourceTree = ""; }; - 91EFBC2BA2D7A79B94746CAA05414C48 /* IGListStackedSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListStackedSectionController.h; path = Source/IGListStackedSectionController.h; sourceTree = ""; }; + 2ABC701FFD27091D59C1A387DEF7373E /* IGListScrollDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListScrollDelegate.h; path = Source/IGListScrollDelegate.h; sourceTree = ""; }; + 2CA49A3657430FE67EFBDEA004EA2A71 /* IGListSectionMap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionMap.h; path = Source/Internal/IGListSectionMap.h; sourceTree = ""; }; + 2EF1CB5ADA8B96E8726D2FEE42143B9F /* IGListKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = IGListKit.modulemap; sourceTree = ""; }; + 2FB53570D9FA612AC525EC662BDA3B24 /* IGListDiff.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListDiff.mm; path = Source/Common/IGListDiff.mm; sourceTree = ""; }; + 2FCC1E666B0971D28ADF5D8079C0EC3E /* Pods-ZaloMessageUI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ZaloMessageUI-umbrella.h"; sourceTree = ""; }; + 322AC6642D589AA3CCA4578B9CED512A /* IGListAdapter+UICollectionView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListAdapter+UICollectionView.m"; path = "Source/Internal/IGListAdapter+UICollectionView.m"; sourceTree = ""; }; + 36FFE505227F681FDF8F9F5C447F5CC8 /* IGListBatchUpdateState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdateState.h; path = Source/Internal/IGListBatchUpdateState.h; sourceTree = ""; }; + 3887683279880249AB7E08138E3A1534 /* IGListSectionMap.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSectionMap.m; path = Source/Internal/IGListSectionMap.m; sourceTree = ""; }; + 3B5D1B00158A99A6CD9E597EB32A0873 /* IGListDebuggingUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListDebuggingUtilities.m; path = Source/Internal/IGListDebuggingUtilities.m; sourceTree = ""; }; + 407C2D74BB448428273E5DAD218280D0 /* IGListStackedSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListStackedSectionController.h; path = Source/IGListStackedSectionController.h; sourceTree = ""; }; + 441085A09A6C9EDD683E9719356F0825 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 44E4E9C14FABF864E53FB18F54F924A3 /* Pods-ZaloMessageUI-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ZaloMessageUI-acknowledgements.markdown"; sourceTree = ""; }; + 463E7F1407D752F7D9455C654DEF9BBE /* IGListCollectionViewDelegateLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionViewDelegateLayout.h; path = Source/IGListCollectionViewDelegateLayout.h; sourceTree = ""; }; + 492DDCEE6074F2D47556F1A08FD3EC24 /* IGListBindingSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListBindingSectionController.m; path = Source/IGListBindingSectionController.m; sourceTree = ""; }; + 4D0A8CF3C29032B8791A46D349893DA3 /* IGListAdapterUpdater+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListAdapterUpdater+DebugDescription.h"; path = "Source/Internal/IGListAdapterUpdater+DebugDescription.h"; sourceTree = ""; }; + 4F921E777F84D02B8779A979C3996470 /* UICollectionView+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionView+DebugDescription.h"; path = "Source/Internal/UICollectionView+DebugDescription.h"; sourceTree = ""; }; + 529D578276A85FB7C02DE97B03034027 /* IGListAdapterProxy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapterProxy.m; path = Source/Internal/IGListAdapterProxy.m; sourceTree = ""; }; + 53526A36E61F13210FE618FB67F501E9 /* IGListSingleSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSingleSectionController.m; path = Source/IGListSingleSectionController.m; sourceTree = ""; }; + 54CAC4FBB82E56D2D0E54194FE0E74D8 /* NSNumber+IGListDiffable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+IGListDiffable.m"; path = "Source/Common/NSNumber+IGListDiffable.m"; sourceTree = ""; }; + 5596781CAF7C6DECBC9DD6704FC3DEA1 /* Pods-ZaloMessageUI.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ZaloMessageUI.debug.xcconfig"; sourceTree = ""; }; + 59DCDB9312101DF7F5D5B57AFB181047 /* IGListCollectionContext.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionContext.h; path = Source/IGListCollectionContext.h; sourceTree = ""; }; + 5A4A694DCA7D32D60D9D9EA75CF04303 /* IGListCollectionViewLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionViewLayout.h; path = Source/IGListCollectionViewLayout.h; sourceTree = ""; }; + 5B3AB9B73F507D06A27DB0DD8672C1F1 /* IGListDiffKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiffKit.h; path = Source/Common/IGListDiffKit.h; sourceTree = ""; }; + 5BA8780B9F2F90290DC94CC2FF934653 /* UIScrollView+IGListKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIScrollView+IGListKit.m"; path = "Source/Internal/UIScrollView+IGListKit.m"; sourceTree = ""; }; + 5D61BAA609182BF4EC549C921692E196 /* IGListBindingSectionControllerDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindingSectionControllerDataSource.h; path = Source/IGListBindingSectionControllerDataSource.h; sourceTree = ""; }; + 5DA7DB8B7222CE0CCFE2D80419410445 /* IGListAdapterUpdaterInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdaterInternal.h; path = Source/Internal/IGListAdapterUpdaterInternal.h; sourceTree = ""; }; + 5EC9F595D2BF0435A78F4BFCB482ACB6 /* IGListReloadIndexPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListReloadIndexPath.h; path = Source/Internal/IGListReloadIndexPath.h; sourceTree = ""; }; + 63349022EA306D2F76C266669BC30859 /* IGListAdapter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapter.m; path = Source/IGListAdapter.m; sourceTree = ""; }; + 63D3306C4FCADADA24BB3E4848498009 /* IGListMoveIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndex.h; path = Source/Common/IGListMoveIndex.h; sourceTree = ""; }; + 643933F60E2287B88A5F72DC8FD229B1 /* IGListGenericSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListGenericSectionController.h; path = Source/IGListGenericSectionController.h; sourceTree = ""; }; + 643A51D5E237E6B3FDE21FCA4B2E0A44 /* IGListStackedSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListStackedSectionController.m; path = Source/IGListStackedSectionController.m; sourceTree = ""; }; + 65EC38859FAA58F02398F4A98ADCDD1E /* IGListKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListKit.h; path = Source/IGListKit.h; sourceTree = ""; }; + 68DD4547A9A52D5784CA694D1DE4DB9B /* IGListMoveIndexPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListMoveIndexPath.m; path = Source/Common/IGListMoveIndexPath.m; sourceTree = ""; }; + 69F811605A36E3C3E5B7E5BE196DB222 /* IGListWorkingRangeHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListWorkingRangeHandler.h; path = Source/Internal/IGListWorkingRangeHandler.h; sourceTree = ""; }; + 6FD646349EBECA7157CBA588BE444607 /* IGListExperiments.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListExperiments.h; path = Source/Common/IGListExperiments.h; sourceTree = ""; }; + 70509C5764B55CAAC4E64733E0F8026F /* IGListBatchUpdateData.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListBatchUpdateData.mm; path = Source/Common/IGListBatchUpdateData.mm; sourceTree = ""; }; + 71F763FF750E60EE92446171A0C09F64 /* IGListKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IGListKit-prefix.pch"; sourceTree = ""; }; + 72C96CB39F29243D0088DEB8B9323C3F /* IGListBatchUpdates.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListBatchUpdates.m; path = Source/Internal/IGListBatchUpdates.m; sourceTree = ""; }; + 74BA69709A51C6D7F5B40365EA9C6014 /* IGListDiff.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiff.h; path = Source/Common/IGListDiff.h; sourceTree = ""; }; + 753EFA7012906B5B73F05065E1D6263E /* Pods-ZaloMessageUI-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ZaloMessageUI-frameworks.sh"; sourceTree = ""; }; + 75D3D286D2AC63292FF406A4F4A3FA29 /* IGListAdapterDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterDataSource.h; path = Source/IGListAdapterDataSource.h; sourceTree = ""; }; + 763F24D6D009FDEBCC03F2B0EB665861 /* IGListAdapter+UICollectionView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListAdapter+UICollectionView.h"; path = "Source/Internal/IGListAdapter+UICollectionView.h"; sourceTree = ""; }; + 775016B5F9D61893B64A0943E1BC0627 /* IGListCollectionViewLayoutInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionViewLayoutInternal.h; path = Source/Internal/IGListCollectionViewLayoutInternal.h; sourceTree = ""; }; + 79EDEDAB37563E1B63250F6410EFDD8E /* IGListAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAssert.h; path = Source/Common/IGListAssert.h; sourceTree = ""; }; + 79F0BE17BA22601D674C972E9ACE9080 /* IGListSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionController.h; path = Source/IGListSectionController.h; sourceTree = ""; }; + 7A116F0C825FF33DB907E23477B7608B /* IGListIndexPathResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexPathResultInternal.h; path = Source/Common/Internal/IGListIndexPathResultInternal.h; sourceTree = ""; }; + 7A5B7EC8DD8E024D351457A163F9890F /* Pods-ZaloMessageUI-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ZaloMessageUI-resources.sh"; sourceTree = ""; }; + 8093EA48163FB7088AF188D16976534A /* IGListAdapterUpdater.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdater.h; path = Source/IGListAdapterUpdater.h; sourceTree = ""; }; + 80EEB16402C06EEF42C9C9C11E99249F /* IGListDisplayHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListDisplayHandler.m; path = Source/Internal/IGListDisplayHandler.m; sourceTree = ""; }; + 831631C94FBCE24B06164C85E36714C7 /* IGListAdapterUpdater+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListAdapterUpdater+DebugDescription.m"; path = "Source/Internal/IGListAdapterUpdater+DebugDescription.m"; sourceTree = ""; }; + 845452A9142BB1D17C43CB3A4283DEAE /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8637DD702D29A68A5D099D27027363EB /* IGListSectionMap+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListSectionMap+DebugDescription.m"; path = "Source/Internal/IGListSectionMap+DebugDescription.m"; sourceTree = ""; }; + 88E34C67EC78CCBE88CEBBE49B76FEA5 /* UICollectionView+IGListBatchUpdateData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionView+IGListBatchUpdateData.h"; path = "Source/Internal/UICollectionView+IGListBatchUpdateData.h"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 97454DD8E599E4B00183E3A285DB9C22 /* IGListCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCompatibility.h; path = Source/Common/IGListCompatibility.h; sourceTree = ""; }; - 996AD1693136E561660FDEC81D1BD614 /* IGListIndexSetResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListIndexSetResult.m; path = Source/Common/IGListIndexSetResult.m; sourceTree = ""; }; - 9BD4D98D644A32BDDADDD3BB554B53C6 /* IGListBatchUpdates.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBatchUpdates.h; path = Source/Internal/IGListBatchUpdates.h; sourceTree = ""; }; - A9F82250AA9AA427031C8A47D8F1144B /* IGListMoveIndexPathInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexPathInternal.h; path = Source/Common/Internal/IGListMoveIndexPathInternal.h; sourceTree = ""; }; - AE2FD6DC4BDF404C3B20D1EE0920A449 /* IGListAdapterUpdaterInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdaterInternal.h; path = Source/Internal/IGListAdapterUpdaterInternal.h; sourceTree = ""; }; - AEAA5ACCAF93345858954D0120C75BBD /* IGListKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IGListKit-prefix.pch"; sourceTree = ""; }; - B05EE17648F226B8FD6DEA8CDD553B87 /* IGListCollectionViewLayoutInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionViewLayoutInternal.h; path = Source/Internal/IGListCollectionViewLayoutInternal.h; sourceTree = ""; }; - B11D4CA08332D8FCBA79D03D0319F5ED /* IGListMoveIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListMoveIndex.m; path = Source/Common/IGListMoveIndex.m; sourceTree = ""; }; - B1D9DBDD98FA8E96ED56870368BA3993 /* IGListAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAssert.h; path = Source/Common/IGListAssert.h; sourceTree = ""; }; - B483E6CAF66FCDEFAD191E281BE8C924 /* IGListAdapterProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterProxy.h; path = Source/Internal/IGListAdapterProxy.h; sourceTree = ""; }; - B63DB6A8D07E5BC14D8CECEBA47E1521 /* Pods-ZaloMessageUI-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ZaloMessageUI-frameworks.sh"; sourceTree = ""; }; - BA169A6945D36F0B13E400449585DEAB /* IGListStackedSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListStackedSectionController.m; path = Source/IGListStackedSectionController.m; sourceTree = ""; }; - BCAA7A7AC06A491C7C589E23C23921E8 /* IGListIndexPathResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexPathResultInternal.h; path = Source/Common/Internal/IGListIndexPathResultInternal.h; sourceTree = ""; }; - BEE505FE7B2586E24B685F6E9E88C897 /* Pods-ZaloMessageUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ZaloMessageUI.release.xcconfig"; sourceTree = ""; }; - BFF7D6EF49DB458D59B8A56A68F4DA6E /* IGListSectionControllerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionControllerInternal.h; path = Source/Internal/IGListSectionControllerInternal.h; sourceTree = ""; }; - C2B3A48B8D6446CBE6A307AF598C92B4 /* IGListCollectionViewLayout.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListCollectionViewLayout.mm; path = Source/IGListCollectionViewLayout.mm; sourceTree = ""; }; - D023E1E57BE8AF38FC013F1CFE43EB23 /* IGListSectionMap.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSectionMap.m; path = Source/Internal/IGListSectionMap.m; sourceTree = ""; }; + 95A01125FE4C75073CF52AA00009099D /* IGListBindingSectionController+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListBindingSectionController+DebugDescription.m"; path = "Source/Internal/IGListBindingSectionController+DebugDescription.m"; sourceTree = ""; }; + 9659EC0975BDEBCE76E13AF059695499 /* IGListKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "IGListKit-umbrella.h"; sourceTree = ""; }; + 9C4B12BF7E1D767A7B4C24EC5CBED240 /* IGListMoveIndexPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexPath.h; path = Source/Common/IGListMoveIndexPath.h; sourceTree = ""; }; + A0FA949EAE4F162DD90DAA5F43B4DD43 /* IGListWorkingRangeHandler.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListWorkingRangeHandler.mm; path = Source/Internal/IGListWorkingRangeHandler.mm; sourceTree = ""; }; + A19101BD44E4673AEBB1CE71424BEC98 /* IGListCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCompatibility.h; path = Source/Common/IGListCompatibility.h; sourceTree = ""; }; + A1E091C4C041B8839D4DD117441AF962 /* IGListBindingSectionController+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListBindingSectionController+DebugDescription.h"; path = "Source/Internal/IGListBindingSectionController+DebugDescription.h"; sourceTree = ""; }; + A218FC42EA9C8362A6EC35960FF9D261 /* IGListAdapterMoveDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterMoveDelegate.h; path = Source/IGListAdapterMoveDelegate.h; sourceTree = ""; }; + A44F7EDFF037081042B4287A294DEA78 /* IGListStackedSectionControllerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListStackedSectionControllerInternal.h; path = Source/Internal/IGListStackedSectionControllerInternal.h; sourceTree = ""; }; + A5C333A721D1B946EC8F88323ADD78BA /* UICollectionViewLayout+InteractiveReordering.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionViewLayout+InteractiveReordering.m"; path = "Source/Internal/UICollectionViewLayout+InteractiveReordering.m"; sourceTree = ""; }; + A5D91E3F7CBECC8CD1D49D2FD63432B4 /* UICollectionViewLayout+InteractiveReordering.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UICollectionViewLayout+InteractiveReordering.h"; path = "Source/Internal/UICollectionViewLayout+InteractiveReordering.h"; sourceTree = ""; }; + A80A9DAEFE4C1F36E5973C29696039B9 /* IGListReloadDataUpdater.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListReloadDataUpdater.m; path = Source/IGListReloadDataUpdater.m; sourceTree = ""; }; + A95307CCB218CF625E58C886EF0DDDD1 /* IGListSupplementaryViewSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSupplementaryViewSource.h; path = Source/IGListSupplementaryViewSource.h; sourceTree = ""; }; + A99A44A60992AB3E7F6A5BDE3764D1D8 /* IGListDebugger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDebugger.h; path = Source/Internal/IGListDebugger.h; sourceTree = ""; }; + B004396B6CFFB8A9DC2638F32AF182C1 /* IGListTransitionDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListTransitionDelegate.h; path = Source/IGListTransitionDelegate.h; sourceTree = ""; }; + B047D5CE3ED32253ECFDD6F39CF29AEF /* NSString+IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+IGListDiffable.h"; path = "Source/Common/NSString+IGListDiffable.h"; sourceTree = ""; }; + B11A0867617137D39BA82FCE425C900C /* IGListAdapterUpdaterDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdaterDelegate.h; path = Source/IGListAdapterUpdaterDelegate.h; sourceTree = ""; }; + B2B249761F9D8D235776AE3ABCF8F46E /* IGListSectionControllerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSectionControllerInternal.h; path = Source/Internal/IGListSectionControllerInternal.h; sourceTree = ""; }; + B42E50CA17C278BA568FCAE8E1430ACC /* IGListSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSectionController.m; path = Source/IGListSectionController.m; sourceTree = ""; }; + B4D63C79BCB0E794E34C7C820EB84606 /* IGListGenericSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListGenericSectionController.m; path = Source/IGListGenericSectionController.m; sourceTree = ""; }; + B56457B4D4255F65F321DC0979F5A67E /* IGListIndexPathResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexPathResult.h; path = Source/Common/IGListIndexPathResult.h; sourceTree = ""; }; + B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + C0C83B1ADDB3EBC0C2A7F187C3135519 /* IGListWorkingRangeDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListWorkingRangeDelegate.h; path = Source/IGListWorkingRangeDelegate.h; sourceTree = ""; }; + C3BEBE7FC46FDD9304EEC6CCCD0EFD71 /* IGListMoveIndexPathInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexPathInternal.h; path = Source/Common/Internal/IGListMoveIndexPathInternal.h; sourceTree = ""; }; + C8E654FC50F012E92B396CEA2C071441 /* IGListAdapterProxy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterProxy.h; path = Source/Internal/IGListAdapterProxy.h; sourceTree = ""; }; + CBEB63A10F7782FFE59A8B539044F49F /* IGListAdapter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapter.h; path = Source/IGListAdapter.h; sourceTree = ""; }; + CC3A19B2D6176DB16013243F2414CF27 /* Pods-ZaloMessageUI-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ZaloMessageUI-acknowledgements.plist"; sourceTree = ""; }; + CD81C2D20EA665176B5A89B06377EAB4 /* IGListAdapterDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterDelegate.h; path = Source/IGListAdapterDelegate.h; sourceTree = ""; }; + CEA8E08FC68D6DBB093E3C6733B1CFB9 /* IGListSectionMap+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListSectionMap+DebugDescription.h"; path = "Source/Internal/IGListSectionMap+DebugDescription.h"; sourceTree = ""; }; D06E8626F69EE46B76BD3FB0CB23461C /* IGListKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = IGListKit.framework; path = IGListKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D3E7C76FA815DF001AF4DC02D68EBFBE /* IGListSingleSectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListSingleSectionController.m; path = Source/IGListSingleSectionController.m; sourceTree = ""; }; - D6D2A8989F37FF0BD6AF5CF60F05CFF0 /* NSString+IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+IGListDiffable.h"; path = "Source/Common/NSString+IGListDiffable.h"; sourceTree = ""; }; - D6D3213014B1E504187FAB80A4C19DB3 /* IGListCollectionViewLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionViewLayout.h; path = Source/IGListCollectionViewLayout.h; sourceTree = ""; }; - DA7F603F1CAF57E05D90C8358D67C7FA /* IGListIndexSetResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexSetResult.h; path = Source/Common/IGListIndexSetResult.h; sourceTree = ""; }; - DAD69A8143754FC3FB53E6F2E0CE8D43 /* IGListKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = IGListKit.modulemap; sourceTree = ""; }; - DCD3F5A948A44666E6CAFA58C5F1DDDA /* IGListIndexPathResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexPathResult.h; path = Source/Common/IGListIndexPathResult.h; sourceTree = ""; }; - E22A432F99D8C7B036F29A07B5288629 /* NSString+IGListDiffable.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+IGListDiffable.m"; path = "Source/Common/NSString+IGListDiffable.m"; sourceTree = ""; }; - E9642E09DD663EE6592275E41031574D /* Pods-ZaloMessageUI.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-ZaloMessageUI.modulemap"; sourceTree = ""; }; - EB3763862FB70563C77923F76394243E /* IGListDiff.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiff.h; path = Source/Common/IGListDiff.h; sourceTree = ""; }; - EC2FA4D3D829C0D349DE4D1A1D70C2C5 /* Pods-ZaloMessageUI-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ZaloMessageUI-umbrella.h"; sourceTree = ""; }; - F171DC4805CABE00914128DA4EE6223A /* IGListCollectionContext.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionContext.h; path = Source/IGListCollectionContext.h; sourceTree = ""; }; - F2E303D7701BA73D012E6B1B4B8A4C0A /* IGListKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListKit.h; path = Source/IGListKit.h; sourceTree = ""; }; - F82561F9D2F8C802108AE86C0E2EEB1B /* IGListMoveIndexPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListMoveIndexPath.m; path = Source/Common/IGListMoveIndexPath.m; sourceTree = ""; }; - F9615EFEA89C09AA6B27C4FFC7AA9A50 /* IGListDiffKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiffKit.h; path = Source/Common/IGListDiffKit.h; sourceTree = ""; }; - FBAF13AF15ABD80300ED35BC61B5D2D0 /* Pods-ZaloMessageUI-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ZaloMessageUI-acknowledgements.plist"; sourceTree = ""; }; - FBE926B7E64281B80C7BC38803AF4D6D /* IGListMoveIndexInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexInternal.h; path = Source/Common/Internal/IGListMoveIndexInternal.h; sourceTree = ""; }; - FC0CCC63453F0DE9ECBDD889B3788469 /* IGListCollectionView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListCollectionView.h; path = Source/IGListCollectionView.h; sourceTree = ""; }; - FC9464E8FDCAA0D9DE053CEB658D2B3C /* IGListReloadDataUpdater.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListReloadDataUpdater.m; path = Source/IGListReloadDataUpdater.m; sourceTree = ""; }; + D12A98E0133749857364C75428D71896 /* IGListReloadDataUpdater.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListReloadDataUpdater.h; path = Source/IGListReloadDataUpdater.h; sourceTree = ""; }; + D41497FAB210714ACAED2B33357E47D3 /* IGListDiffable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDiffable.h; path = Source/Common/IGListDiffable.h; sourceTree = ""; }; + D4751CF6F8DE938C99786954388D4D4D /* IGListAdapterUpdateListener.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListAdapterUpdateListener.h; path = Source/IGListAdapterUpdateListener.h; sourceTree = ""; }; + D64EA5E1D59919444CB30762B945D58D /* UIScrollView+IGListKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIScrollView+IGListKit.h"; path = "Source/Internal/UIScrollView+IGListKit.h"; sourceTree = ""; }; + D66B2D1BE3BD8AB81C1E13E490BFCD89 /* IGListIndexSetResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListIndexSetResult.m; path = Source/Common/IGListIndexSetResult.m; sourceTree = ""; }; + D729F30E164B54B3350CD6B968FCDD39 /* IGListReloadIndexPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListReloadIndexPath.m; path = Source/Internal/IGListReloadIndexPath.m; sourceTree = ""; }; + D7F95C292A0B7DC1D8516840C716BC5E /* IGListDisplayHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListDisplayHandler.h; path = Source/Internal/IGListDisplayHandler.h; sourceTree = ""; }; + D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + DADCF46067894FAE4F695ABBFB7A8AA9 /* IGListAdapterUpdater.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListAdapterUpdater.m; path = Source/IGListAdapterUpdater.m; sourceTree = ""; }; + E2340871863ACFE8A65F0F9A1FA4E596 /* IGListMoveIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListMoveIndex.m; path = Source/Common/IGListMoveIndex.m; sourceTree = ""; }; + E3ED5A8D5654A9255F283E6D32ACB60B /* IGListIndexSetResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexSetResult.h; path = Source/Common/IGListIndexSetResult.h; sourceTree = ""; }; + E4FAA77B888E031451935CDD7720FE18 /* IGListAdapter+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "IGListAdapter+DebugDescription.m"; path = "Source/Internal/IGListAdapter+DebugDescription.m"; sourceTree = ""; }; + E54D40951FCADB7DF461F8119322DDA0 /* IGListBindable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListBindable.h; path = Source/IGListBindable.h; sourceTree = ""; }; + E6268C042C954A1A283BE06B6499FD58 /* IGListAdapter+DebugDescription.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "IGListAdapter+DebugDescription.h"; path = "Source/Internal/IGListAdapter+DebugDescription.h"; sourceTree = ""; }; + E696FBAE2AC98C82D0A73C9E39E59439 /* IGListArrayUtilsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListArrayUtilsInternal.h; path = Source/Common/Internal/IGListArrayUtilsInternal.h; sourceTree = ""; }; + E8C7CCBFE4B4142A3B87B06995956D3D /* IGListMoveIndexInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListMoveIndexInternal.h; path = Source/Common/Internal/IGListMoveIndexInternal.h; sourceTree = ""; }; + EE8F295FB7875CBC524D1495C1D1D10C /* IGListSingleSectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListSingleSectionController.h; path = Source/IGListSingleSectionController.h; sourceTree = ""; }; + EEC32F955A10354B7CE981F906933837 /* UICollectionView+DebugDescription.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UICollectionView+DebugDescription.m"; path = "Source/Internal/UICollectionView+DebugDescription.m"; sourceTree = ""; }; + EFD3B4911FD0F697A60277CB4369D39E /* IGListCollectionViewLayout.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = IGListCollectionViewLayout.mm; path = Source/IGListCollectionViewLayout.mm; sourceTree = ""; }; + F24A0ECF3CE912E0AD22DE4ABD1A989F /* IGListIndexSetResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = IGListIndexSetResultInternal.h; path = Source/Common/Internal/IGListIndexSetResultInternal.h; sourceTree = ""; }; + F6E146EC37AC1A581154B4BF6D7ACDB5 /* Pods-ZaloMessageUI-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ZaloMessageUI-dummy.m"; sourceTree = ""; }; + FB92E0EF5AACFD94DDAC6A85190308E7 /* IGListCollectionView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListCollectionView.m; path = Source/IGListCollectionView.m; sourceTree = ""; }; + FC2C2E953A1E025EFD2540C8DD328458 /* IGListKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "IGListKit-dummy.m"; sourceTree = ""; }; + FF4CDD01E4D6FCD4744A0628E458EC6C /* IGListIndexPathResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = IGListIndexPathResult.m; path = Source/Common/IGListIndexPathResult.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -207,204 +269,235 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 103E241708D29F06C36C7836D066A0A3 /* Foundation.framework in Frameworks */, + F7DD77F2526E0BEA90904F21B2E25553 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - CAFF474EE43E51A9AB3AF6DA4B083DAE /* Frameworks */ = { + CCF93949C7ECDB87A881BAA80DE18CB5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B3FAF94584AFACCA7CDCD30E83FA019A /* Foundation.framework in Frameworks */, - BC5744F76AEED9E1B86966F420BCD839 /* UIKit.framework in Frameworks */, + 3E4041948DDE685508234016E27DED88 /* Foundation.framework in Frameworks */, + C3A17C5AB199F6C695B03A37FD667AD2 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 258C1DDB52B2BD6F6AE21648E1BEA28A /* Default */ = { + 201BD335AE7A23F1DB44C6E07FE1A5C3 /* Support Files */ = { isa = PBXGroup; children = ( - 01C0B92FD99AEE2D5EC215E5F1BC1BB0 /* IGListAdapter.h */, - 808CAE702E0FF8F6EE6BBFF562D6B05D /* IGListAdapter.m */, - 2FDD11DC6D1B49C93AD32646572440B6 /* IGListAdapterDataSource.h */, - 4E7BE22886808C98EFAF7994EE6568DA /* IGListAdapterDelegate.h */, - 4174531EE7E4CB451191AECA50819F5F /* IGListAdapterInternal.h */, - B483E6CAF66FCDEFAD191E281BE8C924 /* IGListAdapterProxy.h */, - 8A09086C7AB0DC46E91CB1099F1C6200 /* IGListAdapterProxy.m */, - 3E1F19085938A1D0F4E97D89760E6FF4 /* IGListAdapterUpdater.h */, - 5CC1021D9A9AE103C42417C0430800FC /* IGListAdapterUpdater.m */, - 257562CD4FD5E868C0A72DEFAD5DE5E4 /* IGListAdapterUpdaterDelegate.h */, - AE2FD6DC4BDF404C3B20D1EE0920A449 /* IGListAdapterUpdaterInternal.h */, - B1D9DBDD98FA8E96ED56870368BA3993 /* IGListAssert.h */, - 4EC6367CA5091DC825F156D4CC222F79 /* IGListBatchUpdateData.h */, - 41DB6F6AE476EBDF2FBBD47C2E8208CC /* IGListBatchUpdateData.mm */, - 9BD4D98D644A32BDDADDD3BB554B53C6 /* IGListBatchUpdates.h */, - 0C949040285E9D68D76CBCF5808AA3DE /* IGListBatchUpdates.m */, - 3E8415EE9C0C02894DE9D7105F85C835 /* IGListBatchUpdateState.h */, - 47AD689F7E36931512210195B51DC939 /* IGListBindable.h */, - 82756399D6433AFBC13A0410E0179623 /* IGListBindingSectionController.h */, - 1DA237241A8B6D8FB5781051C8A23C66 /* IGListBindingSectionController.m */, - 120D206999D71756EA8DF788A441EA71 /* IGListBindingSectionControllerDataSource.h */, - 52AB39E5DE2E20926EA6D4984EBCFE59 /* IGListBindingSectionControllerSelectionDelegate.h */, - F171DC4805CABE00914128DA4EE6223A /* IGListCollectionContext.h */, - FC0CCC63453F0DE9ECBDD889B3788469 /* IGListCollectionView.h */, - 711343872265842BB56759CA607E0EA7 /* IGListCollectionView.m */, - D6D3213014B1E504187FAB80A4C19DB3 /* IGListCollectionViewLayout.h */, - C2B3A48B8D6446CBE6A307AF598C92B4 /* IGListCollectionViewLayout.mm */, - B05EE17648F226B8FD6DEA8CDD553B87 /* IGListCollectionViewLayoutInternal.h */, - 97454DD8E599E4B00183E3A285DB9C22 /* IGListCompatibility.h */, - EB3763862FB70563C77923F76394243E /* IGListDiff.h */, - 1C804130A0610F5FEB0118D5DEBB0520 /* IGListDiff.mm */, - 8D5A31C01478666EFFAED2069D102019 /* IGListDiffable.h */, - F9615EFEA89C09AA6B27C4FFC7AA9A50 /* IGListDiffKit.h */, - 010584FD1C9A0536B2855DFA61D29811 /* IGListDisplayDelegate.h */, - 8C985162A550067251A36CEBB5D1F21A /* IGListDisplayHandler.h */, - 55E1C761261B4FC3324D3D29CADEB7C5 /* IGListDisplayHandler.m */, - 54B57271641DC0C7CA17035FE9C3A8B5 /* IGListExperiments.h */, - DCD3F5A948A44666E6CAFA58C5F1DDDA /* IGListIndexPathResult.h */, - 20EF09DA25084EF36543E9D42914E471 /* IGListIndexPathResult.m */, - BCAA7A7AC06A491C7C589E23C23921E8 /* IGListIndexPathResultInternal.h */, - DA7F603F1CAF57E05D90C8358D67C7FA /* IGListIndexSetResult.h */, - 996AD1693136E561660FDEC81D1BD614 /* IGListIndexSetResult.m */, - 1046470BDD719AFB20C97992FE4E6EF8 /* IGListIndexSetResultInternal.h */, - F2E303D7701BA73D012E6B1B4B8A4C0A /* IGListKit.h */, - 4C923E3559F037E7FCC2494A7B67B01D /* IGListMacros.h */, - 5E3AC1DFACCEEA11A38A2401A4D2B4AC /* IGListMoveIndex.h */, - B11D4CA08332D8FCBA79D03D0319F5ED /* IGListMoveIndex.m */, - FBE926B7E64281B80C7BC38803AF4D6D /* IGListMoveIndexInternal.h */, - 8D71A4799B19EE1D916324FB5E1D5461 /* IGListMoveIndexPath.h */, - F82561F9D2F8C802108AE86C0E2EEB1B /* IGListMoveIndexPath.m */, - A9F82250AA9AA427031C8A47D8F1144B /* IGListMoveIndexPathInternal.h */, - 430BC698E899473DBA4C089E811ED2E9 /* IGListReloadDataUpdater.h */, - FC9464E8FDCAA0D9DE053CEB658D2B3C /* IGListReloadDataUpdater.m */, - 6F8FC0AEA108EE633AA29B103554AFDC /* IGListScrollDelegate.h */, - 368EB3EF4F72EC88B1850E7B6569BAF9 /* IGListSectionController.h */, - 779DF4A841B6C9CE47E40C67E7D83D62 /* IGListSectionController.m */, - BFF7D6EF49DB458D59B8A56A68F4DA6E /* IGListSectionControllerInternal.h */, - 2001DD06082463F4E1B1A1DAAE19199B /* IGListSectionMap.h */, - D023E1E57BE8AF38FC013F1CFE43EB23 /* IGListSectionMap.m */, - 76749C313DA571984B78AA95DB51E102 /* IGListSectionType.h */, - 885816AA0E2310FF4F2A5FB62E351603 /* IGListSingleSectionController.h */, - D3E7C76FA815DF001AF4DC02D68EBFBE /* IGListSingleSectionController.m */, - 91EFBC2BA2D7A79B94746CAA05414C48 /* IGListStackedSectionController.h */, - BA169A6945D36F0B13E400449585DEAB /* IGListStackedSectionController.m */, - 7362F257F9D7C07018084F3A7A18DC09 /* IGListStackedSectionControllerInternal.h */, - 6E51AD1DE4B35C479661A831CAAD915A /* IGListSupplementaryViewSource.h */, - 3079C3EA36555E2AD7E80A08D4E3143D /* IGListUpdatingDelegate.h */, - 73254ED54EC807B3FB25FEE911048301 /* IGListWorkingRangeDelegate.h */, - 51C149BC9621A6A6DFC34F2FB9F1425C /* IGListWorkingRangeHandler.h */, - 1FD976B91AF21538CF7C4DBE0DDC722F /* IGListWorkingRangeHandler.mm */, - 7D9B3A11994AABDA0DA3D09FB0D695BB /* NSNumber+IGListDiffable.h */, - 73161ADDD6004C7DB5AFB67922643DFD /* NSNumber+IGListDiffable.m */, - D6D2A8989F37FF0BD6AF5CF60F05CFF0 /* NSString+IGListDiffable.h */, - E22A432F99D8C7B036F29A07B5288629 /* NSString+IGListDiffable.m */, - 25F28D195CA2FF2460A4C1136FD105B3 /* UICollectionView+IGListBatchUpdateData.h */, - 48E529B73159621366115FE581A1C7FA /* UICollectionView+IGListBatchUpdateData.m */, + 2EF1CB5ADA8B96E8726D2FEE42143B9F /* IGListKit.modulemap */, + 00D12847F06BED1EACCB9D124C2277D9 /* IGListKit.xcconfig */, + FC2C2E953A1E025EFD2540C8DD328458 /* IGListKit-dummy.m */, + 71F763FF750E60EE92446171A0C09F64 /* IGListKit-prefix.pch */, + 9659EC0975BDEBCE76E13AF059695499 /* IGListKit-umbrella.h */, + 845452A9142BB1D17C43CB3A4283DEAE /* Info.plist */, ); - name = Default; + name = "Support Files"; + path = "../Target Support Files/IGListKit"; sourceTree = ""; }; 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { isa = PBXGroup; children = ( - E6EE98446B568159EE277B68FD442AF0 /* iOS */, + 438B396F6B4147076630CAEFE34282C1 /* iOS */, ); name = Frameworks; sourceTree = ""; }; - 6C301443E286BB5F41C8A832C084AB3B /* Pods */ = { + 438B396F6B4147076630CAEFE34282C1 /* iOS */ = { isa = PBXGroup; children = ( - A19EF018D78555D042CFEB14DBC75EA7 /* IGListKit */, + D88AAE1F92055A60CC2FC970D7D34634 /* Foundation.framework */, + B63C6A64CF66340668996F78DA6BB482 /* UIKit.framework */, ); - name = Pods; + name = iOS; sourceTree = ""; }; - 7DB346D0F39D3F0E887471402A8071AB = { + 50855FDE1480F5F6689BE7CC35BC5302 /* Pods-ZaloMessageUI */ = { isa = PBXGroup; children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, - 6C301443E286BB5F41C8A832C084AB3B /* Pods */, - 996F08FD9E3AAD82C8014BAEF89125E1 /* Products */, - F5503F083F0F6F1A4E48DEAC6858F672 /* Targets Support Files */, + 441085A09A6C9EDD683E9719356F0825 /* Info.plist */, + 0F9F2F29026CC7459B43396FF0238DA5 /* Pods-ZaloMessageUI.modulemap */, + 44E4E9C14FABF864E53FB18F54F924A3 /* Pods-ZaloMessageUI-acknowledgements.markdown */, + CC3A19B2D6176DB16013243F2414CF27 /* Pods-ZaloMessageUI-acknowledgements.plist */, + F6E146EC37AC1A581154B4BF6D7ACDB5 /* Pods-ZaloMessageUI-dummy.m */, + 753EFA7012906B5B73F05065E1D6263E /* Pods-ZaloMessageUI-frameworks.sh */, + 7A5B7EC8DD8E024D351457A163F9890F /* Pods-ZaloMessageUI-resources.sh */, + 2FCC1E666B0971D28ADF5D8079C0EC3E /* Pods-ZaloMessageUI-umbrella.h */, + 5596781CAF7C6DECBC9DD6704FC3DEA1 /* Pods-ZaloMessageUI.debug.xcconfig */, + 003FAECEA0B36DB072907AC26440676B /* Pods-ZaloMessageUI.release.xcconfig */, ); + name = "Pods-ZaloMessageUI"; + path = "Target Support Files/Pods-ZaloMessageUI"; sourceTree = ""; }; - 996F08FD9E3AAD82C8014BAEF89125E1 /* Products */ = { + 5A3E4C8ACF8459CED8274B350233E198 /* IGListKit */ = { isa = PBXGroup; children = ( - D06E8626F69EE46B76BD3FB0CB23461C /* IGListKit.framework */, - 2656E6F1699FAC24AC8D26A24776B7B0 /* Pods_ZaloMessageUI.framework */, + 94DD89928336A981D6378F2D842D879C /* Default */, + B231E43B992AFA174C321B899FFF0461 /* Diffing */, + 201BD335AE7A23F1DB44C6E07FE1A5C3 /* Support Files */, ); - name = Products; + name = IGListKit; + path = IGListKit; sourceTree = ""; }; - A19EF018D78555D042CFEB14DBC75EA7 /* IGListKit */ = { + 6C301443E286BB5F41C8A832C084AB3B /* Pods */ = { isa = PBXGroup; children = ( - 258C1DDB52B2BD6F6AE21648E1BEA28A /* Default */, - AB23AF4DF6B1AF3D62A331E04D374ADC /* Diffing */, - EE4EF4117B89944D0EEBE678AE16DBAD /* Support Files */, + 5A3E4C8ACF8459CED8274B350233E198 /* IGListKit */, ); - name = IGListKit; - path = IGListKit; + name = Pods; sourceTree = ""; }; - AB23AF4DF6B1AF3D62A331E04D374ADC /* Diffing */ = { + 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, + 6C301443E286BB5F41C8A832C084AB3B /* Pods */, + 996F08FD9E3AAD82C8014BAEF89125E1 /* Products */, + F5503F083F0F6F1A4E48DEAC6858F672 /* Targets Support Files */, ); - name = Diffing; sourceTree = ""; }; - D7426B161A53BF2167AED526A4574492 /* Pods-ZaloMessageUI */ = { + 94DD89928336A981D6378F2D842D879C /* Default */ = { isa = PBXGroup; children = ( - 5381841AC8F1E3165C7483C0D2FEA35D /* Info.plist */, - E9642E09DD663EE6592275E41031574D /* Pods-ZaloMessageUI.modulemap */, - 228DE7AE291679DAAE4BE93A069CAB95 /* Pods-ZaloMessageUI-acknowledgements.markdown */, - FBAF13AF15ABD80300ED35BC61B5D2D0 /* Pods-ZaloMessageUI-acknowledgements.plist */, - 0A9EBEF6CD72FB4E0A3F923D1BA6E6CB /* Pods-ZaloMessageUI-dummy.m */, - B63DB6A8D07E5BC14D8CECEBA47E1521 /* Pods-ZaloMessageUI-frameworks.sh */, - 603200A8CD1CEFFD00AA1D336FDC3E12 /* Pods-ZaloMessageUI-resources.sh */, - EC2FA4D3D829C0D349DE4D1A1D70C2C5 /* Pods-ZaloMessageUI-umbrella.h */, - 85B53583128FAAECA97E82ACD9564809 /* Pods-ZaloMessageUI.debug.xcconfig */, - BEE505FE7B2586E24B685F6E9E88C897 /* Pods-ZaloMessageUI.release.xcconfig */, + CBEB63A10F7782FFE59A8B539044F49F /* IGListAdapter.h */, + 63349022EA306D2F76C266669BC30859 /* IGListAdapter.m */, + E6268C042C954A1A283BE06B6499FD58 /* IGListAdapter+DebugDescription.h */, + E4FAA77B888E031451935CDD7720FE18 /* IGListAdapter+DebugDescription.m */, + 763F24D6D009FDEBCC03F2B0EB665861 /* IGListAdapter+UICollectionView.h */, + 322AC6642D589AA3CCA4578B9CED512A /* IGListAdapter+UICollectionView.m */, + 75D3D286D2AC63292FF406A4F4A3FA29 /* IGListAdapterDataSource.h */, + CD81C2D20EA665176B5A89B06377EAB4 /* IGListAdapterDelegate.h */, + 0EE42A909C94E4233DBE55E748120961 /* IGListAdapterInternal.h */, + A218FC42EA9C8362A6EC35960FF9D261 /* IGListAdapterMoveDelegate.h */, + C8E654FC50F012E92B396CEA2C071441 /* IGListAdapterProxy.h */, + 529D578276A85FB7C02DE97B03034027 /* IGListAdapterProxy.m */, + D4751CF6F8DE938C99786954388D4D4D /* IGListAdapterUpdateListener.h */, + 8093EA48163FB7088AF188D16976534A /* IGListAdapterUpdater.h */, + DADCF46067894FAE4F695ABBFB7A8AA9 /* IGListAdapterUpdater.m */, + 4D0A8CF3C29032B8791A46D349893DA3 /* IGListAdapterUpdater+DebugDescription.h */, + 831631C94FBCE24B06164C85E36714C7 /* IGListAdapterUpdater+DebugDescription.m */, + B11A0867617137D39BA82FCE425C900C /* IGListAdapterUpdaterDelegate.h */, + 5DA7DB8B7222CE0CCFE2D80419410445 /* IGListAdapterUpdaterInternal.h */, + E696FBAE2AC98C82D0A73C9E39E59439 /* IGListArrayUtilsInternal.h */, + 79EDEDAB37563E1B63250F6410EFDD8E /* IGListAssert.h */, + 1DA9398198500956878EE35FCF91BE07 /* IGListBatchContext.h */, + 23BD8ED568FE0C89ACEF6334F1A75E87 /* IGListBatchUpdateData.h */, + 70509C5764B55CAAC4E64733E0F8026F /* IGListBatchUpdateData.mm */, + 24736BC9E24CAFD23751927854F26186 /* IGListBatchUpdateData+DebugDescription.h */, + 0CC47AE8E7F1B2829CA388EC9633C121 /* IGListBatchUpdateData+DebugDescription.m */, + 047EB4A6E4010DC4E5133F0DC5F9C230 /* IGListBatchUpdates.h */, + 72C96CB39F29243D0088DEB8B9323C3F /* IGListBatchUpdates.m */, + 36FFE505227F681FDF8F9F5C447F5CC8 /* IGListBatchUpdateState.h */, + E54D40951FCADB7DF461F8119322DDA0 /* IGListBindable.h */, + 0177AF4A40D41CEE1CB36108C24A7022 /* IGListBindingSectionController.h */, + 492DDCEE6074F2D47556F1A08FD3EC24 /* IGListBindingSectionController.m */, + A1E091C4C041B8839D4DD117441AF962 /* IGListBindingSectionController+DebugDescription.h */, + 95A01125FE4C75073CF52AA00009099D /* IGListBindingSectionController+DebugDescription.m */, + 5D61BAA609182BF4EC549C921692E196 /* IGListBindingSectionControllerDataSource.h */, + 0E5EDA2855BEC4AC45F1F24DEAC63C43 /* IGListBindingSectionControllerSelectionDelegate.h */, + 59DCDB9312101DF7F5D5B57AFB181047 /* IGListCollectionContext.h */, + 05D721ACEF7DACEF9927C83A73DF4DBA /* IGListCollectionView.h */, + FB92E0EF5AACFD94DDAC6A85190308E7 /* IGListCollectionView.m */, + 463E7F1407D752F7D9455C654DEF9BBE /* IGListCollectionViewDelegateLayout.h */, + 5A4A694DCA7D32D60D9D9EA75CF04303 /* IGListCollectionViewLayout.h */, + EFD3B4911FD0F697A60277CB4369D39E /* IGListCollectionViewLayout.mm */, + 775016B5F9D61893B64A0943E1BC0627 /* IGListCollectionViewLayoutInternal.h */, + A19101BD44E4673AEBB1CE71424BEC98 /* IGListCompatibility.h */, + A99A44A60992AB3E7F6A5BDE3764D1D8 /* IGListDebugger.h */, + 13624E6C15B892DEDBFE0E1C40F45131 /* IGListDebugger.m */, + 163CEC950A97BC177C84803F42934B12 /* IGListDebuggingUtilities.h */, + 3B5D1B00158A99A6CD9E597EB32A0873 /* IGListDebuggingUtilities.m */, + 74BA69709A51C6D7F5B40365EA9C6014 /* IGListDiff.h */, + 2FB53570D9FA612AC525EC662BDA3B24 /* IGListDiff.mm */, + D41497FAB210714ACAED2B33357E47D3 /* IGListDiffable.h */, + 5B3AB9B73F507D06A27DB0DD8672C1F1 /* IGListDiffKit.h */, + 1F32E8F5DEFF6857693CFEBA263E1C0B /* IGListDisplayDelegate.h */, + D7F95C292A0B7DC1D8516840C716BC5E /* IGListDisplayHandler.h */, + 80EEB16402C06EEF42C9C9C11E99249F /* IGListDisplayHandler.m */, + 6FD646349EBECA7157CBA588BE444607 /* IGListExperiments.h */, + 643933F60E2287B88A5F72DC8FD229B1 /* IGListGenericSectionController.h */, + B4D63C79BCB0E794E34C7C820EB84606 /* IGListGenericSectionController.m */, + B56457B4D4255F65F321DC0979F5A67E /* IGListIndexPathResult.h */, + FF4CDD01E4D6FCD4744A0628E458EC6C /* IGListIndexPathResult.m */, + 7A116F0C825FF33DB907E23477B7608B /* IGListIndexPathResultInternal.h */, + E3ED5A8D5654A9255F283E6D32ACB60B /* IGListIndexSetResult.h */, + D66B2D1BE3BD8AB81C1E13E490BFCD89 /* IGListIndexSetResult.m */, + F24A0ECF3CE912E0AD22DE4ABD1A989F /* IGListIndexSetResultInternal.h */, + 65EC38859FAA58F02398F4A98ADCDD1E /* IGListKit.h */, + 095A2EA0AB34AB6D1A64EFDEE28B1B99 /* IGListMacros.h */, + 63D3306C4FCADADA24BB3E4848498009 /* IGListMoveIndex.h */, + E2340871863ACFE8A65F0F9A1FA4E596 /* IGListMoveIndex.m */, + E8C7CCBFE4B4142A3B87B06995956D3D /* IGListMoveIndexInternal.h */, + 9C4B12BF7E1D767A7B4C24EC5CBED240 /* IGListMoveIndexPath.h */, + 68DD4547A9A52D5784CA694D1DE4DB9B /* IGListMoveIndexPath.m */, + C3BEBE7FC46FDD9304EEC6CCCD0EFD71 /* IGListMoveIndexPathInternal.h */, + D12A98E0133749857364C75428D71896 /* IGListReloadDataUpdater.h */, + A80A9DAEFE4C1F36E5973C29696039B9 /* IGListReloadDataUpdater.m */, + 5EC9F595D2BF0435A78F4BFCB482ACB6 /* IGListReloadIndexPath.h */, + D729F30E164B54B3350CD6B968FCDD39 /* IGListReloadIndexPath.m */, + 2ABC701FFD27091D59C1A387DEF7373E /* IGListScrollDelegate.h */, + 79F0BE17BA22601D674C972E9ACE9080 /* IGListSectionController.h */, + B42E50CA17C278BA568FCAE8E1430ACC /* IGListSectionController.m */, + B2B249761F9D8D235776AE3ABCF8F46E /* IGListSectionControllerInternal.h */, + 2CA49A3657430FE67EFBDEA004EA2A71 /* IGListSectionMap.h */, + 3887683279880249AB7E08138E3A1534 /* IGListSectionMap.m */, + CEA8E08FC68D6DBB093E3C6733B1CFB9 /* IGListSectionMap+DebugDescription.h */, + 8637DD702D29A68A5D099D27027363EB /* IGListSectionMap+DebugDescription.m */, + EE8F295FB7875CBC524D1495C1D1D10C /* IGListSingleSectionController.h */, + 53526A36E61F13210FE618FB67F501E9 /* IGListSingleSectionController.m */, + 407C2D74BB448428273E5DAD218280D0 /* IGListStackedSectionController.h */, + 643A51D5E237E6B3FDE21FCA4B2E0A44 /* IGListStackedSectionController.m */, + A44F7EDFF037081042B4287A294DEA78 /* IGListStackedSectionControllerInternal.h */, + A95307CCB218CF625E58C886EF0DDDD1 /* IGListSupplementaryViewSource.h */, + B004396B6CFFB8A9DC2638F32AF182C1 /* IGListTransitionDelegate.h */, + 03CBE19D1FA7D3B67A32FB55FC895070 /* IGListUpdatingDelegate.h */, + C0C83B1ADDB3EBC0C2A7F187C3135519 /* IGListWorkingRangeDelegate.h */, + 69F811605A36E3C3E5B7E5BE196DB222 /* IGListWorkingRangeHandler.h */, + A0FA949EAE4F162DD90DAA5F43B4DD43 /* IGListWorkingRangeHandler.mm */, + 065B975ECA01D0791C823F77E71BFE28 /* NSNumber+IGListDiffable.h */, + 54CAC4FBB82E56D2D0E54194FE0E74D8 /* NSNumber+IGListDiffable.m */, + B047D5CE3ED32253ECFDD6F39CF29AEF /* NSString+IGListDiffable.h */, + 15D0F4EB026D6786436D2A8F3E7978D7 /* NSString+IGListDiffable.m */, + 4F921E777F84D02B8779A979C3996470 /* UICollectionView+DebugDescription.h */, + EEC32F955A10354B7CE981F906933837 /* UICollectionView+DebugDescription.m */, + 88E34C67EC78CCBE88CEBBE49B76FEA5 /* UICollectionView+IGListBatchUpdateData.h */, + 0024CEFA348D3F6B1119DA5D366865B4 /* UICollectionView+IGListBatchUpdateData.m */, + A5D91E3F7CBECC8CD1D49D2FD63432B4 /* UICollectionViewLayout+InteractiveReordering.h */, + A5C333A721D1B946EC8F88323ADD78BA /* UICollectionViewLayout+InteractiveReordering.m */, + D64EA5E1D59919444CB30762B945D58D /* UIScrollView+IGListKit.h */, + 5BA8780B9F2F90290DC94CC2FF934653 /* UIScrollView+IGListKit.m */, ); - name = "Pods-ZaloMessageUI"; - path = "Target Support Files/Pods-ZaloMessageUI"; + name = Default; sourceTree = ""; }; - E6EE98446B568159EE277B68FD442AF0 /* iOS */ = { + 996F08FD9E3AAD82C8014BAEF89125E1 /* Products */ = { isa = PBXGroup; children = ( - 616BEB51ECCAD129BDBCB7A956B56CC6 /* Foundation.framework */, - 7EC994CDC2D681BA26389F78A7E4B325 /* UIKit.framework */, + D06E8626F69EE46B76BD3FB0CB23461C /* IGListKit.framework */, + 2656E6F1699FAC24AC8D26A24776B7B0 /* Pods_ZaloMessageUI.framework */, ); - name = iOS; + name = Products; sourceTree = ""; }; - EE4EF4117B89944D0EEBE678AE16DBAD /* Support Files */ = { + B231E43B992AFA174C321B899FFF0461 /* Diffing */ = { isa = PBXGroup; children = ( - DAD69A8143754FC3FB53E6F2E0CE8D43 /* IGListKit.modulemap */, - 6F8F78AD7CBD5561CE29BA948CF90580 /* IGListKit.xcconfig */, - 1949E563D6CC13ABFA8D3CFA3E42C27B /* IGListKit-dummy.m */, - AEAA5ACCAF93345858954D0120C75BBD /* IGListKit-prefix.pch */, - 4C7436B092709EECAE742549ED4CA674 /* IGListKit-umbrella.h */, - 49344776B1D965DC389EE3F5B2692911 /* Info.plist */, ); - name = "Support Files"; - path = "../Target Support Files/IGListKit"; + name = Diffing; sourceTree = ""; }; F5503F083F0F6F1A4E48DEAC6858F672 /* Targets Support Files */ = { isa = PBXGroup; children = ( - D7426B161A53BF2167AED526A4574492 /* Pods-ZaloMessageUI */, + 50855FDE1480F5F6689BE7CC35BC5302 /* Pods-ZaloMessageUI */, ); name = "Targets Support Files"; sourceTree = ""; @@ -420,64 +513,82 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 62F65EA4FC0AAD94B67512EFF23DD7A9 /* Headers */ = { + E84FA3D9834E10A655DD735141BE8760 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 77EABC38894B691882ECCBB6E7A6F529 /* IGListAdapter.h in Headers */, - FAACFDF402F6458A7D4419E47AD783EF /* IGListAdapterDataSource.h in Headers */, - 3D2EB85CD5357639074CA5DD2D4E7551 /* IGListAdapterDelegate.h in Headers */, - 4A3EFF59399B8E6AE643F4C42F3FAD98 /* IGListAdapterInternal.h in Headers */, - 814E8604B46678A6E240642692187209 /* IGListAdapterProxy.h in Headers */, - D4395F27CF226BDFCBE9E3894A5D589A /* IGListAdapterUpdater.h in Headers */, - A63613377875A83C1AC0645C00FBC524 /* IGListAdapterUpdaterDelegate.h in Headers */, - 978A1812F44351CCFAB84DB993479537 /* IGListAdapterUpdaterInternal.h in Headers */, - 7CB59DC42F5DEEF8423B99B9EF15F680 /* IGListAssert.h in Headers */, - E2C87FAC44A49E254239D3BA72A2C602 /* IGListBatchUpdateData.h in Headers */, - 9ED092EA0B8FD6C9914926F61DD7974C /* IGListBatchUpdates.h in Headers */, - 5A567DA80629D19A882903C3207F5EE7 /* IGListBatchUpdateState.h in Headers */, - 3789823B840F701270CF3C89F41DAA7B /* IGListBindable.h in Headers */, - 6BEEAC62E01CF7CF63952056D94C3382 /* IGListBindingSectionController.h in Headers */, - C93529C81BA22193C43F0A56013650B0 /* IGListBindingSectionControllerDataSource.h in Headers */, - 5DE604DA2C97FBBA405A690F3D35CD6D /* IGListBindingSectionControllerSelectionDelegate.h in Headers */, - 8C0162174342AC9AD6BF1DD254F2D4B0 /* IGListCollectionContext.h in Headers */, - E8924336590F81446EC1FA6BEA897D7D /* IGListCollectionView.h in Headers */, - C3DBA70EFC22978AAA471095896D6197 /* IGListCollectionViewLayout.h in Headers */, - 859D316248F143EEE011F9F813EAA47E /* IGListCollectionViewLayoutInternal.h in Headers */, - AA0C09DF4610E5752965A774F5C255CF /* IGListCompatibility.h in Headers */, - A460B450702AF73290B119803B5459F0 /* IGListDiff.h in Headers */, - 609B3D3030F4D00163F09224F4D07BB8 /* IGListDiffable.h in Headers */, - A7049C2854D9E9693F2C79BB4D37595B /* IGListDiffKit.h in Headers */, - 3F1999B4074112AEBE5DF30D82FCF951 /* IGListDisplayDelegate.h in Headers */, - 7C576B84FB485A137BCB47747C15D889 /* IGListDisplayHandler.h in Headers */, - 5C0E1A07063CCEF3EAD5F170D71885E7 /* IGListExperiments.h in Headers */, - 991FDBFCF84830061021BA41412B23D3 /* IGListIndexPathResult.h in Headers */, - 1369E38745E60F250DB553327A90E220 /* IGListIndexPathResultInternal.h in Headers */, - 29A6583505AE31C7E14E436F0D87D3BC /* IGListIndexSetResult.h in Headers */, - 92B3A5660013C02DCA2C7214BD7310AB /* IGListIndexSetResultInternal.h in Headers */, - F8D3E13C31FC83AFC640BE3C7AE8CC5D /* IGListKit-umbrella.h in Headers */, - 6AFCC7263232A3DB96FEC0AC62E183AD /* IGListKit.h in Headers */, - F7D0FF68D1C3603A4687F723A06EC5F2 /* IGListMacros.h in Headers */, - 75533C15807CA2947ACE53A052172EEB /* IGListMoveIndex.h in Headers */, - 8E7B30B1EA0D83A5089D5FCB93B81163 /* IGListMoveIndexInternal.h in Headers */, - 697271424EB167F7C0C58ED12EAACD84 /* IGListMoveIndexPath.h in Headers */, - B69F465B5C554886119DCB41B7E0C463 /* IGListMoveIndexPathInternal.h in Headers */, - 620AEB58639B7F0B4109DE8640810C3B /* IGListReloadDataUpdater.h in Headers */, - 6AA1240DEC5184C2CF88B062E428BFF0 /* IGListScrollDelegate.h in Headers */, - 50B4C742F6EF24F4D7E3EEF36A3B9284 /* IGListSectionController.h in Headers */, - BF924715ED330F1EBFB93C0DE9FB75F1 /* IGListSectionControllerInternal.h in Headers */, - 1986C8B4075AC9610DE1987639B3CB51 /* IGListSectionMap.h in Headers */, - 4B7A48A14982ABE52BBB7EA773D77966 /* IGListSectionType.h in Headers */, - 280840F0B69F12FDD6D7DE1219F56A65 /* IGListSingleSectionController.h in Headers */, - 52A42A4E819F52AFF627C48EB43DA670 /* IGListStackedSectionController.h in Headers */, - 83C88E2D20A21A6E74C411A0D02F07AB /* IGListStackedSectionControllerInternal.h in Headers */, - EB11684EDF70986D2C74A975BBFCED12 /* IGListSupplementaryViewSource.h in Headers */, - 78C5E274B0720D3093224F0CBC267303 /* IGListUpdatingDelegate.h in Headers */, - 1E7B647A4A49BA7685B2B97EB8901241 /* IGListWorkingRangeDelegate.h in Headers */, - 48DCC2400FD1C6404EC6D9F6B22E72CC /* IGListWorkingRangeHandler.h in Headers */, - C46FD4B178066D467A76D5C064CBD11A /* NSNumber+IGListDiffable.h in Headers */, - B6F02397FFA625CBA70AC844396AD104 /* NSString+IGListDiffable.h in Headers */, - 807A30B1A51217D4F8D06557763B3306 /* UICollectionView+IGListBatchUpdateData.h in Headers */, + 5FECBDC6E10A5865BAF8BD0FBA40DE27 /* IGListAdapter+DebugDescription.h in Headers */, + 603A4D113E86EFCCAF1745C56728D042 /* IGListAdapter+UICollectionView.h in Headers */, + 6E16E0456D9EB61AAF505678035B7623 /* IGListAdapter.h in Headers */, + 71EA424E166C3069FDCD8F6F34EF9FC7 /* IGListAdapterDataSource.h in Headers */, + 4915AD1938B56C8B7D46314273941D84 /* IGListAdapterDelegate.h in Headers */, + 65928B50FFA02AAC792E3456BC248AD0 /* IGListAdapterInternal.h in Headers */, + 99FBC326DBD70A4DFE8DB401C00C143E /* IGListAdapterMoveDelegate.h in Headers */, + 73AC9CD9697A503CBB2B35EBE86D1761 /* IGListAdapterProxy.h in Headers */, + A3DA55704C4C3C68E6BC71A21D783D2F /* IGListAdapterUpdateListener.h in Headers */, + A412AAFAB580539D9684EB594F77F995 /* IGListAdapterUpdater+DebugDescription.h in Headers */, + C1C5243A9A03E62B783ED7E054B18876 /* IGListAdapterUpdater.h in Headers */, + 84DF44F178F591848CC36133C39623D4 /* IGListAdapterUpdaterDelegate.h in Headers */, + 2EE97D54664FD7FE22E7332FA8A26ED9 /* IGListAdapterUpdaterInternal.h in Headers */, + 47D826D320AFAC50434CC6C85D250E33 /* IGListArrayUtilsInternal.h in Headers */, + 3BB3DB028BF1E38FB951C875B60889DA /* IGListAssert.h in Headers */, + D42BA228E55F0DB2C8CBF20DF82E2221 /* IGListBatchContext.h in Headers */, + 8EFD8AD1A68194A1426D827638902667 /* IGListBatchUpdateData+DebugDescription.h in Headers */, + 82B2A3B8E767FB47A730D5C496BF0B05 /* IGListBatchUpdateData.h in Headers */, + 0669ADE79B91179ED76A9CEC38DFAF7D /* IGListBatchUpdates.h in Headers */, + 5EB6C8BB152EE9635A0D1705D4F8EB00 /* IGListBatchUpdateState.h in Headers */, + 95EBCFA1300EBE827CBF6DABEEED2F33 /* IGListBindable.h in Headers */, + 24D3BCA28A1E3AD37403EEC95D37F56D /* IGListBindingSectionController+DebugDescription.h in Headers */, + 00FD3A151D6607256D58A29F93EDCE72 /* IGListBindingSectionController.h in Headers */, + 4A2AE37A36522FE3B2398A083F1274D1 /* IGListBindingSectionControllerDataSource.h in Headers */, + A582474CB493B54DC2EDF92E082303BE /* IGListBindingSectionControllerSelectionDelegate.h in Headers */, + CD42CB63D39C6263FA1FF718E29E2EE3 /* IGListCollectionContext.h in Headers */, + 9034C03B1A71744248001AFA227CFC55 /* IGListCollectionView.h in Headers */, + B2BAA2FA23FE34F42ED75E425776039D /* IGListCollectionViewDelegateLayout.h in Headers */, + C46CEB2DC7D5195A816DEDDB38BA86C8 /* IGListCollectionViewLayout.h in Headers */, + 6EF2EA280BC1EE19DAF9C88DD31E9D5D /* IGListCollectionViewLayoutInternal.h in Headers */, + F31E7058342A01FD094E905A52EDAEAE /* IGListCompatibility.h in Headers */, + 2E561BA63103FEC30C0B7D6587B2C247 /* IGListDebugger.h in Headers */, + 56E1A6ED190CD271F2012D193FD02193 /* IGListDebuggingUtilities.h in Headers */, + A49BECCC811AA42FE2FDF71F52BCFF00 /* IGListDiff.h in Headers */, + 0E1DCDA4EA4637E16205F53AF1AC621B /* IGListDiffable.h in Headers */, + 8494F6BE88E480A18C4193A6E0379AEC /* IGListDiffKit.h in Headers */, + 3FF0ECE458B1DAF6E9D08C277821052B /* IGListDisplayDelegate.h in Headers */, + 1626618941AA3D0DFE92D24F1FABB835 /* IGListDisplayHandler.h in Headers */, + 9EBB5545372E8DA3090E966A6ABF3FE0 /* IGListExperiments.h in Headers */, + DAD48C3715C347CF23C4F542AE5C7466 /* IGListGenericSectionController.h in Headers */, + 6B2175DA5949FF3838BD6664D0B19FEB /* IGListIndexPathResult.h in Headers */, + C3CD5AFA1934403AB14BC99320DBC48D /* IGListIndexPathResultInternal.h in Headers */, + 35B549886D7FBC153C20F4F15D9CA2BD /* IGListIndexSetResult.h in Headers */, + ECC17D3441A9A361193C2EC863357615 /* IGListIndexSetResultInternal.h in Headers */, + EF6D5B957916E714B3EAA2A64179F460 /* IGListKit-umbrella.h in Headers */, + A881B1AA711AE18417CAE0FF05E37912 /* IGListKit.h in Headers */, + FEC5F821A80D6BE85BE021732ADC9B98 /* IGListMacros.h in Headers */, + C4D0C27B3A4D3ACB3145CE7BF52BB6A9 /* IGListMoveIndex.h in Headers */, + 5C66620892D0161E3B4F190E018E2507 /* IGListMoveIndexInternal.h in Headers */, + A1B6562DB58C36470DD8E46E21DB745C /* IGListMoveIndexPath.h in Headers */, + BCA5AFA2132091C48DE68859301D3BE2 /* IGListMoveIndexPathInternal.h in Headers */, + CD82ABAECC16FD36D8CC1A6C4CC3E658 /* IGListReloadDataUpdater.h in Headers */, + FEB6AB97493672FBC1CB54DC3317BBE1 /* IGListReloadIndexPath.h in Headers */, + ABE63502883410507829B29E3696C9DE /* IGListScrollDelegate.h in Headers */, + AF2E5CD9F501E601F23CEECB09F8B2E8 /* IGListSectionController.h in Headers */, + 4C274051160C465F00282E80FFB3A935 /* IGListSectionControllerInternal.h in Headers */, + B3948123A4470290154C74F986803DEA /* IGListSectionMap+DebugDescription.h in Headers */, + BB0AF9BEF206B0F0E77F5CF648FBEAA8 /* IGListSectionMap.h in Headers */, + D6169AF781DC7A6CCC248CB3DFF1B668 /* IGListSingleSectionController.h in Headers */, + 30906853093014EA2911504C2B86DF87 /* IGListStackedSectionController.h in Headers */, + 53D096CFC5829F685034B1C7CBD9E0FC /* IGListStackedSectionControllerInternal.h in Headers */, + 320AF651B4C821C526F0151F65ED9733 /* IGListSupplementaryViewSource.h in Headers */, + FA6C0CCA4193F7A9FCF3CB97DAF1AEA1 /* IGListTransitionDelegate.h in Headers */, + A421E945E1C00D6D4B5356E756D963ED /* IGListUpdatingDelegate.h in Headers */, + 1F6193099593C9752F0980A5E0111D58 /* IGListWorkingRangeDelegate.h in Headers */, + 5417C871D765FF92FB6FE20B4F93B486 /* IGListWorkingRangeHandler.h in Headers */, + 6DBB61EEEC19BC07A49CAD420FC05F7B /* NSNumber+IGListDiffable.h in Headers */, + DFD9C059ECA61A503605754D689ADD2B /* NSString+IGListDiffable.h in Headers */, + 0A77E1DC9CC439CEBF7AADF7E3CCA9BC /* UICollectionView+DebugDescription.h in Headers */, + 39366ABAFB8818F7987108BE3831504E /* UICollectionView+IGListBatchUpdateData.h in Headers */, + 494EFB53CCCDE4730B79F3B2A861BE58 /* UICollectionViewLayout+InteractiveReordering.h in Headers */, + 8B800F0610802E277372F3F29AE28D88 /* UIScrollView+IGListKit.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -502,13 +613,13 @@ productReference = 2656E6F1699FAC24AC8D26A24776B7B0 /* Pods_ZaloMessageUI.framework */; productType = "com.apple.product-type.framework"; }; - 7E8FA01AD073C38BEBF299EE44B91444 /* IGListKit */ = { + BC17A8B6E847EB854B5E4439B9001E21 /* IGListKit */ = { isa = PBXNativeTarget; - buildConfigurationList = AE53E7E0AFBB00E1C9C2C8ADFB7C7387 /* Build configuration list for PBXNativeTarget "IGListKit" */; + buildConfigurationList = CC2139648BACCBA67DED9BD9D6B9B0BA /* Build configuration list for PBXNativeTarget "IGListKit" */; buildPhases = ( - 9735BED377FEBE43132CD1E727045B4D /* Sources */, - CAFF474EE43E51A9AB3AF6DA4B083DAE /* Frameworks */, - 62F65EA4FC0AAD94B67512EFF23DD7A9 /* Headers */, + 45C96F938A430E17C8598B25DCE3C452 /* Sources */, + CCF93949C7ECDB87A881BAA80DE18CB5 /* Frameworks */, + E84FA3D9834E10A655DD735141BE8760 /* Headers */, ); buildRules = ( ); @@ -525,8 +636,8 @@ D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -540,41 +651,54 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 7E8FA01AD073C38BEBF299EE44B91444 /* IGListKit */, + BC17A8B6E847EB854B5E4439B9001E21 /* IGListKit */, 0AF38B37B1321D189B6774C262E5C00F /* Pods-ZaloMessageUI */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - 9735BED377FEBE43132CD1E727045B4D /* Sources */ = { + 45C96F938A430E17C8598B25DCE3C452 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DA1B3D45BF018B620290019D6931A5B8 /* IGListAdapter.m in Sources */, - 64B25DE39737CB258CB4A78A73A60105 /* IGListAdapterProxy.m in Sources */, - D3A94B9A8260D31F78BF66E221BA5693 /* IGListAdapterUpdater.m in Sources */, - E3C61169F814ED56C9476DF5AF4434A6 /* IGListBatchUpdateData.mm in Sources */, - A1F6C98344934E2F14285FAF23FED437 /* IGListBatchUpdates.m in Sources */, - F81C53F494B5F089471ECFBDEDC94C77 /* IGListBindingSectionController.m in Sources */, - D41D845251DF6C645D0FC7BE96675800 /* IGListCollectionView.m in Sources */, - 9B5B59C7D4FAA46BA8D86BD94576B085 /* IGListCollectionViewLayout.mm in Sources */, - E0705CAE840D25826F78F7755FB9B8B1 /* IGListDiff.mm in Sources */, - 13FEA770FD412AA781189394183D0140 /* IGListDisplayHandler.m in Sources */, - 6616011B818AD909AF2C4057E6BC6B60 /* IGListIndexPathResult.m in Sources */, - B3F8B6690891C6DD25452DD4A20B2DA3 /* IGListIndexSetResult.m in Sources */, - DA5F89C380774C1EDED0E593CC8D71FA /* IGListKit-dummy.m in Sources */, - 0F2603368FC49EB8CB29B08FECCC399F /* IGListMoveIndex.m in Sources */, - 06DE5F187AC9D88E421DCFC5FD4D83A2 /* IGListMoveIndexPath.m in Sources */, - E2D4A2D234373AF4D01358DE2B964D71 /* IGListReloadDataUpdater.m in Sources */, - 8B025CF4F63CD4E38D9281D59E583DB3 /* IGListSectionController.m in Sources */, - 5FC66EF7C5CD106B195DCC47830C6504 /* IGListSectionMap.m in Sources */, - B6362766042314B04067F91511E8570D /* IGListSingleSectionController.m in Sources */, - 774D86036F65420A16E2BD9418857BBA /* IGListStackedSectionController.m in Sources */, - 5E0FE48D39AEEB037830382CAE198F29 /* IGListWorkingRangeHandler.mm in Sources */, - 6FC811837A5F75FDD32BCAEF32F3EF44 /* NSNumber+IGListDiffable.m in Sources */, - 7C964EAF8C7F67F73AA3AF3C1A1D233A /* NSString+IGListDiffable.m in Sources */, - 8D00CE2E5C811366ABA222D254528190 /* UICollectionView+IGListBatchUpdateData.m in Sources */, + 40926B29323FC063B2CF8DCA456498D6 /* IGListAdapter+DebugDescription.m in Sources */, + 1DF000BCB90932296A057352B0B7C57E /* IGListAdapter+UICollectionView.m in Sources */, + 0980D8E2EE9F48CAA78073361C6C60F8 /* IGListAdapter.m in Sources */, + 35EB94DA10091201052F12313B3ED081 /* IGListAdapterProxy.m in Sources */, + F291303229C7596334D830421C00454C /* IGListAdapterUpdater+DebugDescription.m in Sources */, + 6E10F6760B6A61ED34AD12E94AE75BF1 /* IGListAdapterUpdater.m in Sources */, + 735A02C29E5CB736E46DA33E53F7DDC5 /* IGListBatchUpdateData+DebugDescription.m in Sources */, + D5BB97F5973CC5AE48D9376CFE395360 /* IGListBatchUpdateData.mm in Sources */, + 91592C1BF05299E4FA15807729C72E07 /* IGListBatchUpdates.m in Sources */, + 307E641EF37FCB5C01EAA5EC1ADA978D /* IGListBindingSectionController+DebugDescription.m in Sources */, + 1349CEA76F20C96C9873AF312DD3B7AB /* IGListBindingSectionController.m in Sources */, + 8D9D44190E2941464E6CC60E35548571 /* IGListCollectionView.m in Sources */, + C83DDF8BA60AF512ADF75B5AEB1A8855 /* IGListCollectionViewLayout.mm in Sources */, + 16A4511E933A5CB0A89CD07ECC517FA6 /* IGListDebugger.m in Sources */, + 2E0B60B0B7E8F1402B3AF014632F530B /* IGListDebuggingUtilities.m in Sources */, + E0B99A9E6BBF5165A3C99ED2EFAA520F /* IGListDiff.mm in Sources */, + BE4EE27767A15480990BB0317811CEBB /* IGListDisplayHandler.m in Sources */, + 726628D43E59E125EE6C84A24DB02789 /* IGListGenericSectionController.m in Sources */, + A7ECEF478A0C350BA7EDB3C0BFDD6A53 /* IGListIndexPathResult.m in Sources */, + A37E889EDAA908A05225D6E4A49451C7 /* IGListIndexSetResult.m in Sources */, + EF2A525A4C3A13D8568E29019E821FD1 /* IGListKit-dummy.m in Sources */, + A849E060A19C9E5E70C8365880727688 /* IGListMoveIndex.m in Sources */, + 1328A35B5C0B138A38015B82619BE0A3 /* IGListMoveIndexPath.m in Sources */, + DEB9619E034323E4C37948DE9850F88A /* IGListReloadDataUpdater.m in Sources */, + 477AA365124DE42E6E176C77AB789903 /* IGListReloadIndexPath.m in Sources */, + 282A689A8C14C853022E1DC70AC350B9 /* IGListSectionController.m in Sources */, + 2BE748A34797FD31CFC4F41DACFDB3B7 /* IGListSectionMap+DebugDescription.m in Sources */, + C77F65C025CE9AE7FD1FDBE0AE8B1D8A /* IGListSectionMap.m in Sources */, + 19AF6C688FF10545F8B30FDD6AF26947 /* IGListSingleSectionController.m in Sources */, + 33E27E1D5F91ED769DAB566B0807AA02 /* IGListStackedSectionController.m in Sources */, + B6981F2DF44D70105C72235BF79CA484 /* IGListWorkingRangeHandler.mm in Sources */, + 4E6CCE94042A6DC407AF0CAE3733C1F7 /* NSNumber+IGListDiffable.m in Sources */, + C076D04DC7D61BB4A699D5C6B2A837DB /* NSString+IGListDiffable.m in Sources */, + 02E1A2C249B9A41A23B1DFEBBEDD38FE /* UICollectionView+DebugDescription.m in Sources */, + 689F08E0B8F69052078C2B45B26ABD69 /* UICollectionView+IGListBatchUpdateData.m in Sources */, + C7EA68DDDD768AC5C80BEDEB896E5263 /* UICollectionViewLayout+InteractiveReordering.m in Sources */, + 8D0EFF2BA871A37FDC618B734DDFBF58 /* UIScrollView+IGListKit.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -592,109 +716,119 @@ 1BD068347D2D20E5B0E1AA44DFCD82DB /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = IGListKit; - target = 7E8FA01AD073C38BEBF299EE44B91444 /* IGListKit */; + target = BC17A8B6E847EB854B5E4439B9001E21 /* IGListKit */; targetProxy = 76203A6802D536C9EE4782073217DFE1 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 649DDDE2FDD67D6646745BE10B0B05D4 /* Release */ = { + 0B893F5A8FA1C1120D6237BA7D3B6E66 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BEE505FE7B2586E24B685F6E9E88C897 /* Pods-ZaloMessageUI.release.xcconfig */; + baseConfigurationReference = 00D12847F06BED1EACCB9D124C2277D9 /* IGListKit.xcconfig */; buildSettings = { + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ZaloMessageUI/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/IGListKit/IGListKit-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/IGListKit/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ZaloMessageUI; + MODULEMAP_FILE = "Target Support Files/IGListKit/IGListKit.modulemap"; + PRODUCT_NAME = IGListKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 673254EEAF0B5BF4596080C749645884 /* Release */ = { + 26F954BA177A9A46FFFD4E23ED11D67A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; }; name = Release; }; - 93C96884632808D9233E45ACF5E0978C /* Debug */ = { + 43E9B72984C5334182A8DFC740DD20DD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 85B53583128FAAECA97E82ACD9564809 /* Pods-ZaloMessageUI.debug.xcconfig */; + baseConfigurationReference = 003FAECEA0B36DB072907AC26440676B /* Pods-ZaloMessageUI.release.xcconfig */; buildSettings = { + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "Target Support Files/Pods-ZaloMessageUI/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -703,125 +837,144 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - CA2B65C826B829C8C5C2FBA65B1B2EEF /* Release */ = { + C2C8FA512FA756A685900854FA366568 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6F8F78AD7CBD5561CE29BA948CF90580 /* IGListKit.xcconfig */; + baseConfigurationReference = 00D12847F06BED1EACCB9D124C2277D9 /* IGListKit.xcconfig */; buildSettings = { + CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/IGListKit/IGListKit-prefix.pch"; INFOPLIST_FILE = "Target Support Files/IGListKit/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/IGListKit/IGListKit.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = IGListKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; + }; + DE57B331A1F6584335C6729A7C95B6CA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5596781CAF7C6DECBC9DD6704FC3DEA1 /* Pods-ZaloMessageUI.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ZaloMessageUI/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_ZaloMessageUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; }; - E4F26E6EB105713A6A7E7E2E283AC2DF /* Debug */ = { + E2BF6D6731C31DE69900B7B24E6F0445 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.2; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; - E8AE6D846F9FA68FF61AA21F03B54487 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6F8F78AD7CBD5561CE29BA948CF90580 /* IGListKit.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/IGListKit/IGListKit-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/IGListKit/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/IGListKit/IGListKit.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = IGListKit; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - E4F26E6EB105713A6A7E7E2E283AC2DF /* Debug */, - 673254EEAF0B5BF4596080C749645884 /* Release */, + E2BF6D6731C31DE69900B7B24E6F0445 /* Debug */, + 26F954BA177A9A46FFFD4E23ED11D67A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -829,17 +982,17 @@ 9E265DF67BA04206EAA8C2EF93A22CF0 /* Build configuration list for PBXNativeTarget "Pods-ZaloMessageUI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 93C96884632808D9233E45ACF5E0978C /* Debug */, - 649DDDE2FDD67D6646745BE10B0B05D4 /* Release */, + DE57B331A1F6584335C6729A7C95B6CA /* Debug */, + 43E9B72984C5334182A8DFC740DD20DD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - AE53E7E0AFBB00E1C9C2C8ADFB7C7387 /* Build configuration list for PBXNativeTarget "IGListKit" */ = { + CC2139648BACCBA67DED9BD9D6B9B0BA /* Build configuration list for PBXNativeTarget "IGListKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - E8AE6D846F9FA68FF61AA21F03B54487 /* Debug */, - CA2B65C826B829C8C5C2FBA65B1B2EEF /* Release */, + C2C8FA512FA756A685900854FA366568 /* Debug */, + 0B893F5A8FA1C1120D6237BA7D3B6E66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/IGListKit.xcscheme b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/IGListKit.xcscheme new file mode 100644 index 0000000..bf6e028 --- /dev/null +++ b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/IGListKit.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/Pods-ZaloMessageUI.xcscheme b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/Pods-ZaloMessageUI.xcscheme new file mode 100644 index 0000000..b23cdd2 --- /dev/null +++ b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/Pods-ZaloMessageUI.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..089cd99 --- /dev/null +++ b/ZaloMessageUI/Pods/Pods.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,25 @@ + + + + + SchemeUserState + + IGListKit.xcscheme + + isShown + + orderHint + 0 + + Pods-ZaloMessageUI.xcscheme + + isShown + + orderHint + 1 + + + SuppressBuildableAutocreation + + + diff --git a/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit-umbrella.h b/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit-umbrella.h index 49c423e..1a30b82 100644 --- a/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit-umbrella.h +++ b/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit-umbrella.h @@ -27,24 +27,29 @@ #import "IGListAdapter.h" #import "IGListAdapterDataSource.h" #import "IGListAdapterDelegate.h" +#import "IGListAdapterMoveDelegate.h" +#import "IGListAdapterUpdateListener.h" #import "IGListAdapterUpdater.h" #import "IGListAdapterUpdaterDelegate.h" +#import "IGListBatchContext.h" #import "IGListBindable.h" #import "IGListBindingSectionController.h" #import "IGListBindingSectionControllerDataSource.h" #import "IGListBindingSectionControllerSelectionDelegate.h" #import "IGListCollectionContext.h" #import "IGListCollectionView.h" +#import "IGListCollectionViewDelegateLayout.h" #import "IGListCollectionViewLayout.h" #import "IGListDisplayDelegate.h" +#import "IGListGenericSectionController.h" #import "IGListKit.h" #import "IGListReloadDataUpdater.h" #import "IGListScrollDelegate.h" #import "IGListSectionController.h" -#import "IGListSectionType.h" #import "IGListSingleSectionController.h" #import "IGListStackedSectionController.h" #import "IGListSupplementaryViewSource.h" +#import "IGListTransitionDelegate.h" #import "IGListUpdatingDelegate.h" #import "IGListWorkingRangeDelegate.h" #import "IGListAssert.h" diff --git a/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit.xcconfig b/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit.xcconfig index 56c7908..2e42b3f 100644 --- a/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit.xcconfig +++ b/ZaloMessageUI/Pods/Target Support Files/IGListKit/IGListKit.xcconfig @@ -1,11 +1,11 @@ CLANG_CXX_LANGUAGE_STANDARD = c++11 CLANG_CXX_LIBRARY = libc++ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/IGListKit +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/IGListKit GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -l"c++" -framework "UIKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/IGListKit PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/ZaloMessageUI/Pods/Target Support Files/IGListKit/Info.plist b/ZaloMessageUI/Pods/Target Support Files/IGListKit/Info.plist index 7f71fff..ebdce25 100644 --- a/ZaloMessageUI/Pods/Target Support Files/IGListKit/Info.plist +++ b/ZaloMessageUI/Pods/Target Support Files/IGListKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.1.0 + 3.4.0 CFBundleSignature ???? CFBundleVersion diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.markdown b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.markdown index 2c79cad..48ef95c 100644 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.markdown +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.markdown @@ -3,35 +3,26 @@ This application makes use of the following third party libraries: ## IGListKit -BSD License - -For `IGListKit` software - -Copyright (c) 2016, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +MIT License + +Copyright (c) 2016-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. Generated by CocoaPods - https://cocoapods.org diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.plist b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.plist index cf1beb3..0591572 100644 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.plist +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-acknowledgements.plist @@ -14,39 +14,30 @@ FooterText - BSD License + MIT License -For `IGListKit` software +Copyright (c) 2016-present, Facebook, Inc. -Copyright (c) 2016, Facebook, Inc. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. License - BSD + MIT Title IGListKit Type diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-frameworks.sh b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-frameworks.sh index 345a523..b4f70c6 100755 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-frameworks.sh +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-frameworks.sh @@ -6,6 +6,14 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then @@ -23,9 +31,9 @@ install_framework() source="$(readlink "${source}")" fi - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" @@ -54,6 +62,34 @@ install_framework() fi } +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then @@ -72,11 +108,19 @@ code_sign_if_enabled() { # Strip invalid architectures strip_invalid_archs() { binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi stripped="" - for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" @@ -85,14 +129,15 @@ strip_invalid_archs() { if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi + STRIP_BINARY_RETVAL=1 } if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/IGListKit/IGListKit.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/IGListKit/IGListKit.framework" + install_framework "${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-resources.sh b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-resources.sh index 4602c68..a7df440 100755 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-resources.sh +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-resources.sh @@ -8,6 +8,10 @@ RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt XCASSET_FILES=() +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" @@ -21,6 +25,9 @@ case "${TARGETED_DEVICE_FAMILY}" in 3) TARGET_DEVICE_ARGS="--target-device tv" ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; *) TARGET_DEVICE_ARGS="--target-device mac" ;; @@ -41,29 +48,29 @@ EOM fi case $RESOURCE_PATH in *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) @@ -71,7 +78,7 @@ EOM XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) - echo "$RESOURCE_PATH" + echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.debug.xcconfig b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.debug.xcconfig index 39a8e31..7edc256 100644 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.debug.xcconfig +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.debug.xcconfig @@ -1,8 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/IGListKit" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/IGListKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/IGListKit/IGListKit.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IGListKit/IGListKit.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "IGListKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.release.xcconfig b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.release.xcconfig index 39a8e31..7edc256 100644 --- a/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.release.xcconfig +++ b/ZaloMessageUI/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI.release.xcconfig @@ -1,8 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/IGListKit" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/IGListKit" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/IGListKit/IGListKit.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/IGListKit/IGListKit.framework/Headers" OTHER_LDFLAGS = $(inherited) -framework "IGListKit" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/ZaloMessageUI/ZaloMessageUI.xcodeproj/project.pbxproj b/ZaloMessageUI/ZaloMessageUI.xcodeproj/project.pbxproj index 18c9437..227d8d1 100644 --- a/ZaloMessageUI/ZaloMessageUI.xcodeproj/project.pbxproj +++ b/ZaloMessageUI/ZaloMessageUI.xcodeproj/project.pbxproj @@ -581,9 +581,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ZaloMessageUI/Pods-ZaloMessageUI-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IGListKit.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -611,13 +614,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ZaloMessageUI-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/ZaloMessageUI/ZaloMessageUI.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist b/ZaloMessageUI/ZaloMessageUI.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c3cddea --- /dev/null +++ b/ZaloMessageUI/ZaloMessageUI.xcodeproj/xcuserdata/grant.zhou.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + ZaloMessageUI.xcscheme + + orderHint + 2 + + + + diff --git a/ZaloMessageUI/ZaloMessageUI.xcworkspace/xcuserdata/grant.zhou.xcuserdatad/UserInterfaceState.xcuserstate b/ZaloMessageUI/ZaloMessageUI.xcworkspace/xcuserdata/grant.zhou.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..9f7baa7d7aa8d7e2ca0d9a7f5fc0821654791a77 GIT binary patch literal 46268 zcmeFa33wF6_6OQky-o*`$-XC(JtUcAX0o$php>bt2|I*IG9iI%OcM5`3lT(A6crUj zAt1;iD2jp#f`E!3va8?%C?bN23%H>2PEBW$4B_7Yeeb)Md%y2t4C(ILPMu$!I;T!` z*D0;9u4-sB7)~&V!3@iA49^HoS|``x;gc=ahN`;S;o)_q6D(zo4I{$M*0Rbfcw7|T zSXb}Hp!qAexU$n3k&zg8#)I)>BA7@fiiu{rFfmLllfa}fsZ1J^&J1J*F@u>QOd(Um z6f;AaVa#x*mZ@XvnMsV5X7Z zYGNDA2gu0_1s3*!qStu9fq26c!Dn=vF7-U8kRD~v>T2zPX z(PT6Y%|r?!=t1-lT8th>kDwLk8T2e#iB_RCXam}aUPP~>H_)4CC)$PHLI=?M=mT^d zoj@O>&(Rm?EA&130bNCZpd08Bfj9`qVLgt=3D|&*I1^{#Y@CC0aUSlC z2jBu+gp2VQJQi2tD%^k@@oYQ?EBJoA2tRt$pW`p^S$qY5hrh=^;H&sY{1g5e-(&?=WS!VfY-iS$bz?)>FgBcxU?bTmHl6Lt zc4ND}+-ptFVNf%ihDzWAA0> zvkTb!*oEx<>>~C7_CfX`b}{=f`v|*)eUyESeVkp&KEXc8KE*C$m$Of^E7(^^os`wsgq`yP9cJ}hKuFmI6W87C2$7L$eFlAt{c~#>%nDny}3Tz5U!9b;)=PU+!(H$vv3vM zc&?Uf;%0IR_a1kM`+z&j9pg@MA8}{6Pr0+)Iqm}YHTNxdnfrme%KgG!<9_G<;Qr=r z@+{Bs60hMq^Uk~*@6LPkK70Tl$cONud?X*m$MSK!fj9EWd z@&)`rzK}2Chw~%&G5lD*lrQ7Q^ObxxU&Bx0t^7RxUVc8mfWMDl$luQ|;ve82o0#ec+q%%A1Y z@#pzp_-p)i{#X7t{&)Tl{)WH`oWKj-f{)-U_zC_(fDkAI36VmS5G`~Sx(VHd9zsu{ zmyjW33i(1`p`XxS7$6h~0|m2CDwGN3f<>qh#tW4~y)a3z3Jt=&!hB(YaG$VHxL;T# zJRm$KJT5F1o)^{&8-$I*CgBBPv#>>YP1r8%5Dp55gb#$n!iT~U;izy-I4+zJP70@l zkAyFTv%)#yXWh=Zg1;^Td0_2gQfP z#o{WlSzIly5uX#+itEJZ#r5J#;#Tox@fC5K_^SAxctCt#JSZL#KM)U#ABrD|AB&%e zm&GgMcjEWr58_qvNAV}|5AlZhr{pZTNLtBNa+BO856M#sl!ByS$tanmL@7y1mQtit zDNRb3x=LA6wv;0cm4->fr4iCdX_Pct8Y7LBDx~pJr8HfdA)5r zNLnF1BRwmvlvYX2(rRgqv`KnF+AQss_DF9_d!>ESe(4?QUFkjPh;&psCLNbfNMB1A zrEjE5(znuO>5BB7^u2Ul`c?W(BWs*Aoiv>_&KehuR^zJi)%a=rHF{0FCP8D+7&RtM zq9#exUDHF;Q!_|2STjUZs43DEYldouX-YKXG-geMrcu+RnXH+jnW~wlnXZ|uxkock zvsCkh=1I*{nq`{hnx{1@G|y?)YSw9XXkOR6p?OoYQ?pC+mS(qRkLGR7Ud=(xA2`Cjvb=BkWkR_0`07GzPDWR2`9yUFfygd8bH$i)MRKt`R30V|mq*AWf5J zP#8baGOb}G{B6;gL&M9e%?%CBOlQVf!3x{VXc64OD4EoIE^hAAbwlOg)J1sjc*$yz*1GCyi?u}ClNPae)iEtM$CPf&$xPBG znliKXNrv=veO6|=L7$hCo|&F)$j&k*8;&t?0EV84r%;pwy+=l-XXt1MIED@(L)?YrE9f;K!gH90Fa z)0C$-<>aL3lhTdp`b?uCO`o2Zm6V)h%1TPfHI`^Sp{#vCw6XEHi`Lc6)90TIM|Tex z9-W%KykRi7D_+O_{9OYAg8=4&!oo7E#ZuefJgu&&vA8%tr?AmlRXZNYbWAF&nr@*3 zOmTu?oSU4RZc53^)92--CF;{m$wqyyF(px-lVZ$EHsxhzCgvuOnqf4h8R95&W*rL+ z3y&D7ibgGrjN$5~rD3dNBhBHF!wU)r+Kf+1V|14w+X$v@CS@gNr=;ZqTT)X~^~r{m zWPMtS!Keq8=jCLj~j%QQ=QW{c7OX?9L-Uhh8nef#wvP%v=N;30)WiiZvxK4Rn; zJ7u;$!ni4_YNVp=3PV>VS)CLtR!GZlfJ%oJ6c*>_=KwnS4Fk+owIy0@L1A8%wV@Gm z*4Nd-I3HC|m`&%t0-NY-TdPvJ-T=vkjnk?v1I!H*OSJCxhFXO`Kc|&n1x+=j7OR33 zRuMD`)+mg^DWcXz;oTTExCGW7t}ye3f!v#5wJ{jh7IT>S%nDdDe8T+5{03_QCs+-5 z!aBeg1)w0LL!qb($^lD%6xjMDXg*qkoCQL?_Xj(C z5FUaj;(PFYU~@0StMF>Dy4T@-_&mOdf5E@98nB}cY#Q62En-Kp_=eLo?&eNVWj?LMz#EH`NN)7IvrySj1jt&csoe}$Obeu(pj2L z(5oR^5|a$5(7RTdku?8wP}x;TS0;xEU(a-7x-&hPo=h($gUMvFm~1-KVS1pW(@XJI zd=%gHOfD#s-b^1RpXtl=1JyD>@dK5zR9Qh#EJ5)ErGtdVD)nPvX38zE0!@->wSWTA z!hK<7-IN0J1$I?(WzSg1M(X{fmvUWOE5~?f>AnTb84X{Es*EXshYEVb8 zoqHpgGRnP?0O4q63^SG~Va73Lrd07)0+c`{NC{SSN{AAwgso@F84K`l0Q^)j6PSsN zP6<~sfPb;@)1W+{JP6nIBdcwbZxPJH(0D5!2h^2YN#*CnZ`^9y7Cr-Nu33$#5i_wRGqcT-d$*^yV6sOlt?Xj79L<8g!Ud{7Bdes zk1$J^N0|XI3hnx~e_ff4MPu{Jp?FnAmBl*9+z1LCa@4?-*!Gy(NH8N#9av#6+m@!J zDbY$dB}$1c(IyNp117}-Q0g!TQu7-vHEMP7turHNom=(`4Pclz2 z%b4ZN(@GabuNag>C0R*5&OFPkgdD42ysaMD)@HGd8YKn>UEDt~OVqh%Ewipf8vyjQ z@lG`dY!wVLS6Q2x=b7aHBafYo4a`PnwGyu+C~>3P8$tH;EzFCMZd6Q4Trm~O1}(NH zZKFL_y`(UOX)YD?FIgoNS-kdcI1b9GgM9ma-) zx_V2k%`8u-s%uDyDb7!bq29E~Kz>5ul&X3Q9dER=;64L!%C=NjCpdKAmb=@Th-w!O zFz3?4{3FDZSXJUcNEK`Aeall zaW|8>U+DqT)Kg*9QF@A5v5J`ma-6CXb(%R-qK$$^T8FiR25_7=nwd{2P5)|kwS~`_ zFG{pw|3VAR%voCdzmnBH=bvZ3V!~H3Un-famJ;?G;>NF4GFW zRkBwxSCky3zKB{;_SCD)FO1u2uw8y)epYgoJf-()<{FIfUzI*E!Y9$CV;6_!Y%8@w zP_4D&ZI`WvpiO~!I_9;|!DuN5Th-xtZ%bW`rO`S~#p^GM*WXG$okeU*T!fH@315dW zViAXUBp?w%6et6gLFp)FB%r4f(__Dfcm^M3PqY5CeuDaZ| z8P`;|Em5EBZs#w)J3qVbxfoKpKjE0~> z#iCRwJ~MrYDK$RX{WO6kJ@P|`=fT+spS!>u<4@-9rcle=CSJ-zmC&>4sagq zWWY|}Y8CXWYK&KhlYJb=4}we$O$}|B97mJDO=V?fqDE#P^#GKb8!WKainm&-!CaYa zfl0YeNmm&=1x+o6h1`(-&1edftUjBLX4sZv_SHq}l5#bgPWi5Ka~4bwXtrWiQXQAP zhQw4@@*2};&9dV^7cF4I*PwgQJajLbuQV!6%4B8A8gw68$ZSN5l&Q*Wun6u~>WBBY zRJ2(7)UDBKZMIsgBh|T;nzJK@RE@8+Wwtj1D>&NBqv$d8I9jSqQ>H63l$mSj3I#0# zJDV;_W>M=JR?bA?7JV&DBlR+V^uzwF!Wwys!*3Js6V?iMHZ( zR$iTeEFo+i89dtpg>1)+%#Wq30Ea(&h>ZzP0Dn_-jxL zZbDm{(F3ci&{p&^dPSM5+@s7}jb3GRXuEPRbalQmZVXh{HvNsJ zcWsV4E!@&B3^0$ct!iv4x3nS>sq5Zao?o%6T14JD~2hkx|zPF4a zo87e<9aJqZRht|}M`+(aR2G4C3fR!T!+M~huG#`>qS0cdFx#6yiB2)$D_1J@_6MJ! zGqm(+<)KyRQ)Tf#1y-Fk=>o#T@39 zCza)`#9|3|y0t;vnbBbvcVZjIvsJU-^t6e}V!i({&DWld6qD4B}gt zC?IYBAWI&2lR*RigH#*yU`Q0U$X{#KCECD$P$a*h0R*^ZgkTd+2e&v*#7Q_Ar{Gka zrmRt(Q`Rc$l;@T8YjIcH4R>dPaZe^#*`VxE-i8_CJ@|!AQFnXp)OuKGTgq)BNSCkF zm)+v>9s=f*3bCC!b*UZ#Ss)D-gZAlJ9m$}}b8G2*1O270iPpY2G?HbhsI#_=eJG(; zN!MP5*#oG;Z)&);HhWk5;J%F8Dx9xuT!s57o9yFHozOBHXifI41My%Oc6gBT!YVvO z*$i$PhsB6J+fY1$32$b$;o-36f)P0qE?!i&DD{KvIZ7}%JytVY@NirTOSUb_ORI4? z+*BxA;pTOvepH(~x)qZNxE2cGiOdG5?`2pCZdr}%pwMvT6(|JNgVUgGtwg6Lx?Zw3 z*@UOj(!=o-JQXr;Q(mPvGobVqpl8Y7sRS8-wzqYKd2AJ8hTx?$(!S|}Q z-Gk>r;qA%}S{tQ>QevYeq@_N(V^LRIWHo~|Nw1*77SF{Pha7f7AH`Yn`I;HvAeSFx!-*Rd~Cyzb)YnyptwuQH-nb zF6EuJggtmKP1vBsufqG3ciR%)#Rq7@DkWx>jfr+OfIq+=wo-LOInYMcaeRVluQ2dO z_%w`Y{4xGSIj9_J#%J)S$_L7)bjbNmYO+|T4KmX$D$qL(Z3A~qg-sKIR|lTk7iah! z{+c3l9)F3y!WWdo%7@Ak<>(sl1Al`r;ct~=%5mj{a*|f<)#6Hn5o0qTvMcNAz>5IW z9yrDubIlFYit6$~_f~^#yH{M@gMLK&P@Cl{(FSEwyYAoUA5y!*eWfuSZhYq z&`PqwNE}%U3{VZ7k+x(TG0JJ>lms^8C(4-R(iS<=JSH4ir zD(67GoL|cXvjO18(y_tJi=a-v1aFozL4NQD#zP>T&cWUsSX(_UAAFSHXl=C5CbckO zc|*EQ^Qn^!h^=j@2lDKllhwObZ`fv^+D6r{OLu1Nbq;B&rL$93bzRv+C}c}&G?z`x zuB)LVkuHX9TA@XF*=W`POM12o8^gx3ajc$=XA_jKlnct&%0=ZH<&yI4I%WWCViVaU za9hI<7;2Z5E6R6ZcF-T_Qk$O$^gg9X)njy4Qw<R`!kvQigqe{&NI#X^;& zA(jf@L~WS`_LWo|Y$ff=Rqb|*FBE!32ZJqxgZeDdn&5dK^JI%EP}SAb?CB1)WViT= zTWB)=qe9t(id*TwrA&mKfXr&}e3wt7+^@~6vldvU3^F%0fDF<8j!vyGmn9i1%F>Og zurCdsS~d%9S*a{kuXEW+TePuk9^0Gk!{)Pn*?zEfG=ME&2eO0M!R!#W5H^yE*`e$( zb~rnN9SNICquDX+Shj>6$C}wvwhT6zENlfko~>l7*a_@JwwkSBYuP%sUin`6LAk2@ zsQje-to))}Q?4t&D!(beD}N|Als}cfl)sgm1Th4`8*P{%mLPZ`fhR~HNF+!iNJEfJ zkP|_j2x5j zNK7-fzqO5S$iRxx`+s!v9Bs$ zQrmaS(8eKSMUo-8v>jE@X+t}pfXKFXDR;|Y7r$MPl7S_yx5)-`YHLFj#(_&cCplvCo@p*cX}bjqGzU`>$i4XV@Yq6&QI+y2Kt##I0R{`qg3!Q`Pv%GBrDw}BA%Ws)4JItjGbUi~0 zHDpaw_sLx00X4qqt10Es2=#@~S5sP_^|sbE)x$%FjI?aavzFRG2hlwg^}QfN_4#Q#)u(sYZY%F$LaluuY!_+D)H_*bi0`6r-ZOlKrrm!fS`;C=1qK zGkc6ZPEZ^{`ew>v%1g>fPaB<71NXO>CtAww$})KPkk*tI1)FEBt7+YyuvdPD{fr4$ zSMKcR1SPaA-Pv^`cj zIr@hw$##Y&aj6uuWG;oE-URh&=F+%yg7OI(NqJ##aH}|06W?Y+S*&(K|6hBi8Jp*i z>&az+0C9j{-&Gvo*B=&oZBA=0k2Q|x-ovNQo_e1pM^vw?aWEepWuo2tduCn(n zpBn&6ZmuuakLyp+0D=k#8n~J(;0AJo2!j6y6Ep%g*{0Xk)eN`Rfqe$1Fj&=D1wF%G?buW1P!NqnPAs(V`+K`Hx7PE z2`VJ0$o7A+k{Z_Qs!eW~F!c|^guQiS_2S)drxvZGMaQXyZG~D&+pDfq(``BI_0lZ% z^vU*g$YD>1)(h?Fv)DB*Fp5<0@tGH%vH9^3UF$6*5 z&`KFW7J|kTR7KE4f@%l?BqtHnKu{AwQwW+y&DvjEe|>pS=pY*lPZy*BIo{xiF7dP6CAvISxt?NuzTykz0)dTrT=;E zITBV#Uvz6|R1xmzF?A&J3zbOFYY+eTxOY46sUw+Rsbp4^Xy@NiGV^=WH!oT|#BDxQ zN8&E2#KFs5cbYi6`R(Azjdu`_?^WU^lxSz&QO*_TQ?np8)8Cy@Qr*EKbfDxPvxia(+Pq-yHx}=69kUqH3U6J(AstUOnw$Wo1eogJmKdOw2q+X z30hCk27)#cw27b>=>EjN@#BQseh={<{jwsw?FD^xXXXFH_aIs?ZE9GCR^3R@I%(6i zoSoTA_{VMESn!W2qY2vFjF$0FDBxw^qKv!c`wCa#2YaEXdDsS6$FJa@;h*JK@~ik} z9#DCSpsfVGOwcO?Z6oMaf?k7nfcTm8YZrb!{BBfY0VDdk3xW5{;h!CM(SdiIwBB~U zzRK@V!Prj0c%6dr1_k4dj$r6A?1gso?@=)J@Ne^b`F;F;{v95+D0ULGi=ej%+D*_N zg5D-*FMt7GGyoX%hyM^>$cnXndIWz7g4Zwa3d(ppPe0*5Re?A|f!I%h_?!aqPDdcn za(kgKdH67I9sd=7f&ZGn$bZ9M;=d*6J%SDp^gclc2|7g32Lv5<1mY)0AU?bc1jvM) zr+@M{RUrPRKpX)e1Vn*2+7Sqs>n()@L4a2b)(N5@2^v8boP5N*)KSvm;Dsf>fuUc2Xv}kdHexoj(@H;{9 zhSm*&{v_xxg8nAxrsJe_kHe$|AB5di&4f#H~*Wx^7ev@q@n1xm03 z@r3X!1>#BJDPftgTzFboAv{AcM=(#YK(I)#M6iZn*%64fjzBow1)`nycu{y+1!5}& zq7wyT8wH|sM5bSHa@FUp&E*x~FQKy{}mZ59W24l6u?5zG+IHTfon&J~c z@%fD66W9?SuM74<=Y?-6K3@u72^WN~g^R*B!X<)(3DyxDLU1U-VFZU09N{P^KROCZ zapY_u%_)zc^LYVlSrE(VDqHXuYD1;W(s@QGX8B6bj>!~_aL zwAe+A5o5(TQ7;15lL$^GIECO;g3}02C%7v}1DyR~I{}0lAkuS(N?R}hxVqhyhBj#s zGsJ8age(d|cPb6JR2q78lm;AV2coYygaXk|>@N-w3&erqAaO9ky$H@AIFsNkg0l(E zAvo7zS`tS%PD^=rfoKOrnOLC$VWB|ura)9uAo_F!0=d|Ms1che5Vc~RST9Zztzv`N zNN`_*`w`rq-~j{|5Im6JK{g=x*+MdPOo=lo5H>IFCEFDqd>4v#P|Oz>s!-fVp%_A; zSVW;H>5j>pW5d@DUc+@)aDRG&& z9R6J)J|nIm7}^*^@HpFrncz}_%@mIR-><~AT03tyh%cysY@&dS1x+Dtf%P7SbBbn+yWUt{h@hytZc5#RJy7-3prnpnwMQ}O67J@4X9#3#3!BqrLaGbH; zah$Ox-W8K}Vsb=0uA*{`qEb!87#q$)1GvcS>XX5AL7vfp*9Km%2 z*AqO6U@O551j8KG1VD&i*Wtg#_PE z@FD<0is8mdaZ(&yB~XcYfPPhkAB6wu-9vZ505G&3T2DJ~yGcD&KzdL>7E?enC?F4a z1SHY!CX{j|_*`wBlqdC;`bhawU#Xu2w$u`WA0_xPf*&V%DZ!xIpQL~cq*IhM5Ppj& z1W(zVw(tk8m)(Vf!XewiD3MB4Fw7K;Ct6o{875F02ETRQ^b!rLWciv&kEt&?7qUXr#-FH5gT+oV?seudy|1jEH^1aBvJ z2f?qeleSAcBshCndK0eRB=`-2;orCD+_c+vx0|AIcb!pVXYB#$kc!7aipNecq@=^t zklNJ|4{m!{MnKCt!`)u~qy(oAtdmYjA4wlepGc>rGt#F7zfJI7g7*=;pWt^0ewX0) zY%;=?NayHsT>6U22>mn}AFy5F_wPyx)f^f-Uw@E(QgQi_;&PD6$uCq+4t2yu`pjPF zcMYOo{2|?t{*?Zb{+4cP7=jNI{2{?d2tG>iF@ld1e8OSE(nyXImhGglf8+M@o!=Y( zcgS}OPc?2DPa6;#4+_L707BzUf%xb)KwPmG3ebcD5Sl(3Bjic zK0`1_$Y%t9PVg6wK+t!m+TNbRXYa~Ho956YYt(a_HE?b-!RIItT`3UfI|6}y>_GI= z^rk>$XficfnruyuCRdY3@K*$1Aoy#7FB1F>!LYwX&lPKXjZIVF2*l;PK(qs5xMq|p z5hE!OS11r;C=lOu1VV_j15v7(K!GUJlxr-S3e9*;r3QRYKM;JC;2#P8iQu0J{)OOc z00ci%*w1XFFL!DtQ7y3!c3tTqMD*=WeElvK?XZ}knXO_mi(>IB#X_N2{B|2GM%b~q zSMwmnV!md9=043r&Hb81ngl#dnytcq%`2L%aP=BtI}x@seHVdsrWf?qnroWtnqM`)5jKdh z!GzTjHiWRDgbgEXxC0O};|N5=T_D+=2~rJ&wY>^L-L`BJ z{7b?3cUb3leogUjTo7r??3|64jVc@l3I}~3L{5a&H=EcI4*a!ty1iJs+zpPImb(%* zWtH5Wu&L@Xdj)V_vU=dL<58dXVwp0W%l^EaC1=Yya;}^w_m=y}`Gid;EL7EvuuxSG z!uBL=FT!R#FZY8(^n&FAd7wN<9?XEqWx^4=plz}Un@!jp!sf#LxDjxa_jpTVVNSo1 zRSmh-RpZqttX}Hl9LwaYGE08Luquf60mtjY5q0eo>@lO@Xh-$2E$&VuoCgl!#9AM! zmE@Ugs;c2YUeERw*go>6VQt`W>-Nv{>9N@mIh3CB>t0n~2`4Z&RMj*=$dNj$(HNfy zkzLCtHXa>(5Y!D zB`HZms|L}!N2q_&Mx7p+k}_bf)caH@OaNc}}jE zC&^a1L2e{$Kf(?n>`=mvAnfSY!y)AvOy7+q1MF=))i+pK?FZLl#j{qov|HNLXlYQeqEpxrg-vB;77Ls~a@-XHVte`0U_Q4*mu~j(R5*oi_V$5@&wh$0 z#Q)5LL;WEqe3o8kJsB7jtdm1%uw6)@5qqKCio9y`_y!tJsWoa1B+|JoEF)4y#C4e# z!UKznFPt+OUzi8sVBr{dJse&zdD<~Kx=Re4O{q52Rz*ANeH0C)IL?r?S|6W4BLpj* zRvS%;iW+;`8{`S-E24xJ=NHp3eyxRVfrn@UrM2BtoxMPw1p;AMEpUi0JvY6fT^6lc zV^%ecZCjR-?rixo-?8hmR^oIyhh>~RSpy{Op6fR2%uiuxBo z^047>M(nMOZyr%_o2QU_)aaJc&^)T(F0meZMKw1+70k5%*BHP0(1CtH$thKD-uLPf{tePNCtnOV?R8W|o1BWW-XJuFu>Q~rf(9*+1dgM7Q;cUpNvSq;OW?hGS- zQ&w+nWEgNE!s(n-8tdtGAGr3ISTrOXu17PB)TyN`JZ6G>TWT%Vsxlo!ot>uZZ3dO0 zGsT;9gRFJ*cmkT`-}_%pbrYqV{ud0tof;+<_JhCiK>xgQa}K>ugX^tj=G?-T>u)Dl z4K0A{42Hp>^^I9W;JPndmo`l-&V+0DmI!aEu;vxRbx*kdxU#7ay-s2n)@yoY(J;6U zg6qDur3C}wx+`2)mNjILgzIRyZmzWCQ=EWj?E6)X`9*LI?Xllm>xR($F$}|XFSq36 zs?WKKiFN%b4e;I+_e#U$Li*fB^YqGWN+-0%otj|oI|!~}65@WbRQIO&p&s6^zHtz( z6Ylw(+Uf$@ZU$U0wKUlJ3-|n~#>yg!nTcV9&_-(!Eeo^>5Dz0SAFlJ@dTOP$4}A{( z6?WBE+r}C2MEKL%G=%mY`Y7gEYKtik>9|nL*4*B34ZITHWQHO$V`1u;Quw!wsb$WA zvDN@ld?(wk#zVm08u--#1#$4(8*mGT(@t<1mnoW46@Ox(m>N`E0(1p(c7MPw>`7B+SYU0w@a<9P6ApjP}bi2_WZK*cn|Qa5o)f6 z9@e(-rva$>6X>4UQo4GW5LviUyXB%c}Jv2|d8W3x1myX#?TP-xT27W2B78|a;fgUs9(E!|T zf^kYq>tV#SQF-f#g4*7l`KAw}JN3Zs1B`BycE@|Iz0;lKwvRsE>D`$XwGaE%*N$ICJ7+p0=MeZYIcLCCm~*Ie ze`jw$ zp8EEZVG+6tQ9`Z|WvkoPJ0VBtBjhnU!APIO$JBk{I-TaC!ID7VFxhqW)2uYUr7n|3 z@6y2`I`MHjlfekujoM5!55xRC*k%hMuR~=`*2(HKj{f1{OmY{-gYgBe8V1^054}od zx`EEj1sh->Q^bsbAoXQ{W({y`3WRbZ%zS1M#5jK(LWn=htYOwOo0+Z5Ys{O>9_Ag0 zE`0=Ip`QVLa)G(bTxG5^HxNQ1>WtixFT}@7I%VBg@F)YFaf9GOxzC_;W2nTo`k34 zdH5mxByPr=@T+(aK8R1^v-mQ;1|g`NAo5ZOL@P>Tvmsp0NC<*sWoNVZvrE}#h`{kW z`!0K&JatA(_p76C&lSW zrx%^xb2{hrdndO}F`cqIjqcRc>7h>RI_>WCNvEGXckUe7IivH)&W)WP>b$=5-p-$Q z{>|ClIo>(nx!ie<^K$1`osT(x@1k*uaLIHT>oVPCsmseQAG%!8YP6BsY^_;4Tf1Dl zL;I2Tnyb63(RH9}jq3xh8(a^#e&Z&(MY`p>mAlPzTkW>j?MrvoJ&|^Wn zf-VKS2louF3Vtm3t>ABUp1Mq3weCsXKHb%jfRH{RO(Cm74u{+bjS4Leog2C(^s_KI zEG?`e?6I)7!>)!0hYtv!8NM<6bc7}%Euu2wiHLV2evOQZ92U7C^0mlsqI{zAqozk~ zjQTXXb9ArhNzu*GC%On-(z;CSvZBk87#x!vQyH^7=EGPVn-W_UyCU{z93Ph+R~y$H z_mRGnK2twgzfpfK-YdR;{M`80;=fM_PZ*i-NW!}be;bkw)u7$Z7~PD0jdP8!8-Fsz zn95AcO(zmNC*~#2N!*_JV^VCACFz-@kCWY#2P7{@emnWEl++Y!%I1_yso|;PQlC!! zD9s~nP}&1&@1^tUS?P1q-%S6#Yf9I~u3NkQ&`sZMVz&+5zUdy--O_zc_b+>d_AvKY z)#GeWUC(hnSN1&HE2NjXS97oP8DSaa8EZ2xW_HP(khv-I`z%A2HEUbeui0I*XJzls zVRL%t+@Ete*Dbd=cUkV|d7*jZ^ET#P?Va3vM(^Ey_&)vmJksZ*{J{LO{Pp=)`=<7t z)puXNPW=k|E$er_e@uUC|JMiL0euHNI^ffSh=SUJ*9I~J^9MdU@UuZtgC-4nW3VuI z(BS2RzaC;7GIPkgh3^jUEEas_E49hqlc~^`s=WqVM~Uc9iA|J z*6@QP{6l8$Dowd8jG6>E5PulY35HKKZvPL#Mnv)pcs^)I-x^ zrY)RyaeChL=Vov-%4WPhGh`;2d2UwbtW~qo?9$n9&k36|Z_Wj!xAHuZ$wczOT*KTY zbAP#K*gdb$3!JCS`|{r2_imi;Jl{J1qXpd-JbNE^U)6nw7bY%zYT@7am*4;XBEzDk zi~f9|?1A?mG(Py`gEt?lctKlSiae=e(Bc5->v@-0sXJiYMgUssf`IQC4& zGn=0ce0I^Zf2^!p`SGgWt6pu6Y+kxrSUq|5*K3BZdH1=r=hm>a-M#J<7%4)5=`|Gjte-r4(Z=DTmb*W;!_`gH2R~nAD4gp%_r5L{CIlu=^JMhFyin3O#9i=&jUVh{-VnlTh6AO z-FYtO+@bS@=g)ju_T}ZT8ov7T!o06Lf4%f#@Wu7tn7(=QQr@K_-;VnB!sYtQH?GY8 z&h@*ezmNX@l^-&GICORR)eApbf4uqA13&xzyzZBzU*5hp=-TJkYp&n;_5R;{e|!G- zwBO(TW7r=TZ%p}9{PW4by8QL}-~Imn^k&V?n@S+Kei|Cbv^U}{P^-5M0^HFclFbUZp1@ah>vQlL78F7( zKR7+vT2=`m$E`>2nO9`3t7}vcczawKKd?(wt7H^dZI#R=2d0~^9HjM!bZQt9A-WN3*-`5AAcbMX^<1xA1){aMWSr5J9?u6usn*;P&6Ek zMq|MODMjUI4uk^Vjt-(D=omVIPNC1xS#%zKg)V~iaT$Gwop1yMHtvGsaXQYz1Mv_% z3Xg+`v<(ndR>4d0GW;yw3V}@DgFvGvAcW|7{4M^Kyj&BLyC7*1~ zsh0etE!dd+DYIe&(#oI9U&v?WbMkrlORkrELH=5)CF}&kRudL3>In<b zRY`4kG`)P;c4Q+v@qhGWU-_y^U(NpzeeI9Dl&`7uLFB7D9f0HZ$Az~)Bvk%GC2rFH z;CY-5blz0ygdNR09UtLeI5)H{1eg=2(%E$9!M^=z&h1B{lSUzyAZ_LT+ONIJr5w7u$mA*~|c6*bInel3~8?C8omi8BTl<$B5-(l{itXfpZ2L z#VO)6ai#d0xKBJP9v4rFABms9SG}K!--=hn@5QU)PvS4)by#GFNj+hKT_r7&4oUER zMCT_uKh?Rp^9!9{?Yyt^!Oq7zpXvN*=g&I-0S+=h=K$v*XB{}j!kr_XqrqVo=iCci zX4%fU&b^)cIuCFjwU``V-0&s-VTPOi?bT30t$4_7Z&A6LC=1}wTuU1z&0u5(@I zxz2aJ&-HcJy{?B{kGLLlJ>h!F^<&r5t`}W@a{bNq57$3k|910q3v%n>mgQ!4t97e) zv${395x0lj9(G&e_L$o;x2N6KyKQuP!EKA%PPg~n4!Iq6JL2}a+eNn@+fMxo>da4a@j5?q7MhczAg9@)+(h(qpv8SdVcYRUXwIwI1~z(>zvtJnwPL z=R;_Vmp3%m$OD#&f#oEYCTfb3NyI&i7p8`K0Hwo~t}pdp_s6$#b*k zi=JCOU-3Na`J0#4%hxNwE67XdrT6OY)zd4(E6Xd#E6=NsS6{CYUZcFmc$IjWy~?~S zUgN#0ye50i^;+TelGg`bm%V=V)_8k)M|ekhckzz()_W&-8@&^~v%GV>^St|b_x0}Y zUEn>)dx-Zm?g`M&*p2l$Tk9ql{Tcbspn?+o8rzH@wu?=!xKeb4xQ>HCB4 zkG?=aNrhue?lz<)qy#g`=vIBAh1_lfd7#~mzE|u8>pSVI4E#PV0mCo;Pk**fpY@q2F?qdAGkR1vB0H)PX;avTo<@G z@WsHbfv*I<5x6t(t-w9t$k`Y8LE!1YbAew5UI@Gx_mF2c-pd4H^?PBWPLB=AgqtXM(;7`ZnlF(Dy-CgMJG7B^U*> z!F;e7tO<4s?i}nA92uM(+&g$;@Uq|?!S4hg2tF8mIQU5LvEZ+Qe+>R5_k4#(bVGDSx}myKU7c>SZmMp&Zl>-Y z-MzX6x`nz$x|O;Ybg$@M)os_kuG^#AtJ|-8S9d`7vF>}_jSw8dg$N;1h)alTh8$vdPYzuiUWJkyw zAv;6f3OOEfDU=Hh42=oZhbDxYLX$#MLbF5jLi>dF3mp(TFm!ZiNvJurJhURTGPEgl zYUuRPS)p@6N$5kNkAyxNx-|63&}E_PLN|nN0teVjp)ZH-4&58NKlHuO_d^ebeiC{* z^i1eyq2Gr75c*^2&!NAC{t^0T=-**}VbNj9VLih#!m`40!t%lfh7ArY3@Z*B7B(Wx z8um!oimyi0i3@FC%&!pDV|hL?v| zgwF_{7yfkks_-4*N5fBre-Xh%@DY&_Q4vWInGx9$xe>i1@+10142T#RF*;&w#JGsk z2usBHh^mN%5vwD1MtmIcb0ib#66qT09_bnB9qAkC9~l@K7a1REh%`keMW#fiMRtws z9yvbp!N|>#??m2+N{AX3RUTCnRU1_wH7)8`)QPB5Q6ER0j`}p}^Qf~?=cB%g`a0^H zsBfdLM13E1HR`9RU!tx@{T}sa)Xiud%|}boPSMWMuF)RR-qC*1fzi6?u;|F>F41w( z3DKtLPFF-u}r#k?5v zR?Oj;k7B-xxg7IjtP~p?n-)7Tc1Ubd?6BC8v14M##g@fZfU~hWwk~#l?0vC|Vjqls zICe?w9!?#sUV!TKWoF#SmVXnmEw zUT@Vmf=hFjUeV9h->YAsU#4HJe^LLMeuw@I{Z9Qp{k!@D`a}A|`cL&2^gro;*Wb|p zrN0?3#B1W6;+^BQ@nP|C@#*nB<1^!P;`8JC#Se%d7(Xd~as1QqTjICIZ;Rg^|3>_- z_&xFa;@^#bKmN1$FXGR~Ux@!E{&M{H@ju4@68~%b?+MxjeL~lS!3pycmL|NMus`8! z!gmQjC0tARE#WT%V_*%uA%j~SjYylFUKIAS<%IA!?6 zaMtjp;cLSs!)3!&!|z6SV}LQj7;iKhlZ>gxuEy@hTw{T8u(8NE%sA3G+GsJ>8mAZ) z<3i&D#>K`Z#>b6M7*`tC8#fuZ7`Ga?8DBH*HXbk@GJa@0W;|*9$avQHrSWUyCF6Bd z4^xII+mvU@H}y9SGz~Eon}(Z4nZ}yTrgGDG(*#qEsovCJnrxb8nrWJ2nrph(bf0OF z=^@i2rpHWAn3kDVm{yuro4z%DXS!v6XyXjBU%|x8YCrXL`Pu2GM-n60iahx&= zg;EX$%HFFSb{uC9XM4wrZQ1gY{PKFRBn>ysOjHzsdp&t+$^ zbJ!eq0sCk6eReDR5&O3kDrHH^(v)Q>D^o|LPEDPjIwN&f>YmgeQ;(;fOl?WyrGaV6 zG*y~5?L}H=+S|0Q^q%R<)2q^J(reSd&X|_L%3x=tW@Kc1pK&(he8z>0%bAu;PbQJ+ z&kSb%lhrrtgRB8rA7!n~s>!O&+K^SBotj;kU7XF$7G$5vzMg#}``7F{IcSbQCy+zs zgme4m4$b`}cSP>!+^xCIxd(F(=l;MceoOwj0(pUbl07B+N)B+v zTs0TvVq7=Z!}W0k+z>ayUC|xI*KniUDsFXxbNG4u0=|vEiochCQ_w>&T~I9G3giNnKqG(!CV@p@7dQk#0WDZ6hzn{2>jia! z20@cxi(tFpu;7T`sNk63gy58*MQ~2=lb}sFT9_v^3%?NV6kZbE5w;2+34aql7rqp} z7XB&fC3;^pL^Me>RrIN7rf806z9?CgDk>InyQ98PBo;|TWg@vqAqt7U5uFje5Dyh+ zidAB(*x4QXE5trADW=4 z;ydDdrF}|gmr6_hrHRtxrLCo}O5c?JRr*h9m*hQ3Z^`?TVUiJ&sgh(#sw6{_E#XKC zB*hY*L@7~8v=Y6)%Zik}_XeRoM?^ zkE8>oqom`d6Qxt6Go&-6bENa6xzc=Tp%jqnrADbmYL_~tE-5Z0qzk2sq)VhrrOTu% zq^qQ>rE8@Jqz`2MWV2*tvVbfmYmjZ0ZI$hi?UwD8HOmgl&dAQoZpxm@p2=RyUd!Id zI%J))ck+SqLGr=!A@X7J;qsC4G4gTp0=Yx}rF@V4SFk5I5u5|EKsJ~LW`nt4K3E7! zK@c>8I7ombNP%In5?lx_2G@acum)TY)`1OR6SxK323`jLQB3G26;$!1;#W-kWiRE&%3;b8%F)Vk%8AM;%IV4!WtuWWnWfB8 za+LYXB4vrvsa&Hxpu7Y1hGs&1NC9ae9fUv@$Obte3<^OJXc<%u)k0rG-#{Co&CoXJ zTj&UM6gm!_gib?epmWeq&_(Dk)hDVfm0q<-wMBJBbx-w3^+ff%>ZR%rRa-an^i~g6 zPf$-*PgBoO&r;7-C#l)$LUpm4tLCePYOz|Pma66Ipt??dTK!D(u_j%k)R;A>#;I{> zyc(Y-prJHNHOnm(H8(W3Gzp1R(;A-Yd=lXXctwk}PVsmsyj=?ZlvI#8$7sdQSM zUT4smbXJ{Rw?em9cMI+TPlH9U6Ar*(n1L6-OW>vOa(E?N3x5r7hY!O)z{lW|a0`46 zz5ri_@52w_C-Cp^bNCh92Dif<`tkZ4y-B}Bzg>St->H9#^hX9EgOQ=gNMtlJ4w-<= zMUs$ABpb;^goql^AqZkZtO$x=h#QF@mB<3*Gh{LHIr0Uv0$GLZL2es*8KxUV2CreY zVS}N;u+gyDu*2}3VYgwg;e_F|;i}=G;fdjQ!*jzcLz|)9@VBv_vA=PkagcGaafor4 zakz1$kz<67pBXn9FBtzcjWNwI%`we0u}o>E3{$o#*CaLpCY=d0xlJCE&lE6)OcB%n zn7%ZvHmx;9O>tATDPh`RsxzH3y)+Lqr<-B(B6EXzr+J^b*?h=+)O^f*(tO%{-F(yh z#N2NF+x)-gE=x~KA4@;W0Lv)L7|VFeB+FFGrODachlri*=jzTkB5iZtFg4v-Obm zduyw0fNj1_Zli2Bf&S}mW&RNd6&Lk(>ndZ!N@|_~5#3^;kol2+LsdMU`i=B+Cb_KhJJ;I(~PqAm% zOY9G<4Qt0b%Ey)$b;IY%@;&9Z$~(*7y862Yxdyw2x<!d+gMubWDPu8=G2s&p-IHMuUj+TEkv9JjR_PglER?kab}UFZJBz0tkN zz2AM%ecFB9ebas0eb3$Me(Zkge&+6Uzjb$2yjRhyqEAKNivATJR?M$}Dk2s26)oNH zItU+wPsAtV)9{)2YrnJ3_hc^W*MJzG6HJi9%6J~Fo|~Sho@btyp4Xl?o(@l^=bd+; zcaZmE?=bIh?6W<@v0>6~1l01HL1^qrT(57T;Ol zPri%3yS@j$m%exY_x!#6ef|CY1O5N<5Ajd(PxXK5pXs0DpYKohr~1?VI{za7R{uqR zJ2{rjB6CO%nNOCIG7=;qQb+1ZBiTJbBK_n-ay7Y*jFUCwda{meAe+d2WHWh?JWL)T zkCMm8ljLdgd0IQX-x)bUXniArN%0p{H&7u3D*3hfa zo6ujOe?ndKdvtI5eR>!@f*wUrr~ggQrsvTtnoSqb0Ij24G)@yVNmF!~uA~>zi|H6$ zO(*E}bRFG5H_=<@ZS)ShnLbY6rvD6o5FQs!373Y=;l}W`@b2*U;j`h(;j7_a!oP+e zgdc@}3;!qlJTf7Y8IeV_5nIF&DUVb{yb*sS5Lpyi9$6Jx9a$GiL^ed~BaM-!$fZbE z_vd6XlgaQHkkK-F#>iM0jBzs_#>bFMC9{C}oLR>tm<>!l)5vUNzGZeXdzt;rL8gVd z#@uG^F|EvF<~j3QA(I2BHqL-srqt~N1qqn1X zqxYk&v3{}HF-5F0wlwxttU6X3+Zfv(+ZFpcb}e={_8|5!_BhrSYmarrI%DtRJ>nn4 zKa77A|5toud{lf)d}=%+o)yoH=f{iU+_)evjstO7ToH%jmbfjB#;v#4fu&Dxr1O;uuYVqPLCk(@|P l97?n#&L++$F4oFxt+mct{J$pJv*&;BfT91-NPE *)sectionController; -- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController; +- (void)didTouchSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController; +- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController; @end @@ -24,10 +24,10 @@ @interface IGCollapseSupplementary : NSObject @property (nonatomic, readwrite, weak) id delegate; -@property (nonatomic, readwrite, weak) IGListSectionController *sectionController; +@property (nonatomic, readwrite, weak) IGListSectionController *sectionController; - (instancetype)init __attribute__((unavailable("use initWithSectionController: instead"))); -- (instancetype)initWithSectionController:(IGListSectionController *)sectionController; +- (instancetype)initWithSectionController:(IGListSectionController *)sectionController; @end diff --git a/ZaloMessageUI/ZaloMessageUI/IGCollapseSupplementary.m b/ZaloMessageUI/ZaloMessageUI/IGCollapseSupplementary.m index 9da8903..04ebf80 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGCollapseSupplementary.m +++ b/ZaloMessageUI/ZaloMessageUI/IGCollapseSupplementary.m @@ -13,7 +13,7 @@ @implementation IGCollapseSupplementary -- (instancetype)initWithSectionController:(IGListSectionController *)sectionController { +- (instancetype)initWithSectionController:(IGListSectionController *)sectionController { self = [super init]; if (self) { diff --git a/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.h b/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.h index 68f0534..488cb18 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.h +++ b/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.h @@ -14,11 +14,11 @@ @protocol IGEmbeddedAdapterDataSource -- (IGListSectionController *)listAdapter:(IGListAdapter *)adapter sectionControllerFor:(id)object; +- (IGListSectionController *)listAdapter:(IGListAdapter *)adapter sectionControllerFor:(id)object; @end -@interface IGEmbeddedAdapterSectionController : IGListSectionController +@interface IGEmbeddedAdapterSectionController : IGListSectionController < IGListAdapterDataSource, IGCollapseSupplementaryDelegate> @property (nonatomic, readwrite) MainMessageViewModel *viewModel; diff --git a/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.m b/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.m index f74f937..a87a880 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.m +++ b/ZaloMessageUI/ZaloMessageUI/IGEmbeddedAdapterSectionController.m @@ -106,7 +106,7 @@ - (void)didSelectItemAtIndex:(NSInteger)index { return self.viewModel.subViewModels; } -- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object { +- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object { return [self.dataSource listAdapter:listAdapter sectionControllerFor:object]; } @@ -120,7 +120,7 @@ - (void)didTouchSupplementary:(UIView *)supplementaryView ofSectionController:(I [self updateSection]; } -- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { +- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { if (!self.expanded) { self.expanded = YES; [self updateSection]; @@ -145,10 +145,14 @@ - (void)updateSection { NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 1)]; // Update cell if (self.isExpanded) { - [self.collectionContext insertInSectionController:self atIndexes:indexSet]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext insertInSectionController:self atIndexes:indexSet]; + } completion:nil]; } else { - [self.collectionContext deleteInSectionController:self atIndexes:indexSet]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext deleteInSectionController:self atIndexes:indexSet]; + } completion:nil]; } } diff --git a/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.h b/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.h index f3fa1a9..33dc4ca 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.h +++ b/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.h @@ -15,7 +15,7 @@ // //@end -@interface IGFriendSectionController : IGListSectionController +@interface IGFriendSectionController : IGListSectionController //@property (nonatomic, readwrite, weak) id delegate; diff --git a/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.m b/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.m index fb3f5be..e7bc7bb 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.m +++ b/ZaloMessageUI/ZaloMessageUI/IGFriendSectionController.m @@ -53,7 +53,9 @@ - (void)didSelectItemAtIndex:(NSInteger)index { - (void)collectionViewCellWillHide:(SuggestFriendCollectionViewCell *)cell { self.friendViewModel = nil; NSInteger index = [self.collectionContext indexForCell:cell sectionController:self]; - [self .collectionContext deleteInSectionController:self atIndexes:[NSIndexSet indexSetWithIndex:index]]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext deleteInSectionController:self atIndexes:[NSIndexSet indexSetWithIndex:index]]; + } completion:nil]; } @end diff --git a/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.h b/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.h index b46b7ac..89e8b14 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.h +++ b/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.h @@ -10,6 +10,7 @@ #import "IGCollapseSupplementary.h" #import "ZASwippableCell.h" -@interface IGIncomingMessageSectionController : IGListSectionController - +@interface IGIncomingMessageSectionController : IGListSectionController < IGCollapseSupplementaryDelegate, IGListDisplayDelegate, ZASwippableCellDelegate> +@property (nonatomic, readwrite, copy) NSString *sectionTitle; +@property (nonatomic, assign, getter=isExpanded) BOOL expanded; @end diff --git a/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.m b/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.m index a9013fe..281431e 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.m +++ b/ZaloMessageUI/ZaloMessageUI/IGIncomingMessageSectionController.m @@ -102,7 +102,7 @@ - (void)didSelectItemAtIndex:(NSInteger)index { } #pragma mark - IGListDisplayDelgate -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { id messageViewModel = self.viewModel.subViewModels[index]; @@ -123,29 +123,31 @@ - (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(I incomingMessageCell.utilityButtons = @[deleteButton, testButton]; } -- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController { +- (void)listAdapter:(IGListAdapter *)listAdapter willDisplaySectionController:(IGListSectionController *)sectionController { } -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController { +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController { } -- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { +- (void)listAdapter:(IGListAdapter *)listAdapter didEndDisplayingSectionController:(IGListSectionController *)sectionController cell:(UICollectionViewCell *)cell atIndex:(NSInteger)index { } #pragma mark - IGCollapseSupplementaryDelegate -- (void)didTouchSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { +- (void)didTouchSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { self.expanded = !self.expanded; //[self.collectionContext reloadSectionController:self]; [self updateSection]; } -- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { +- (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionController:(IGListSectionController *)sectionController { if (!self.expanded) { self.expanded = YES; - [self.collectionContext reloadSectionController:self]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext reloadSectionController:self]; + } completion:nil]; } NSUInteger index = [self.viewModel.subViewModels count]; @@ -160,7 +162,9 @@ - (void)didTouchAddButtonInSupplementary:(UIView *)supplementaryView ofSectionCo id messageViewModel = [IncomingMessageFactory createMessageViewModel:messageEntity]; [self.viewModel.subViewModels insertObject:messageViewModel atIndex:0]; - [self.collectionContext insertInSectionController:self atIndexes:[NSIndexSet indexSetWithIndex:0]]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext insertInSectionController:self atIndexes:[NSIndexSet indexSetWithIndex:0]]; + } completion:nil]; } #pragma mark - Private @@ -168,10 +172,14 @@ - (void)updateSection { NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.viewModel.subViewModels.count)]; // Update cell if (self.isExpanded) { - [self.collectionContext insertInSectionController:self atIndexes:indexSet]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext insertInSectionController:self atIndexes:indexSet]; + } completion:nil]; } else { - [self.collectionContext deleteInSectionController:self atIndexes:indexSet]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext deleteInSectionController:self atIndexes:indexSet]; + } completion:nil]; } } @@ -182,7 +190,9 @@ - (void)swippableCell:(ZASwippableCell *)cell didTriggerRightUtilityButtonsAtInd [self.viewModel.subViewModels removeObjectAtIndex:cellIndex]; NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:cellIndex]; - [self.collectionContext deleteInSectionController:self atIndexes:indexSet]; + [self.collectionContext performBatchAnimated:YES updates:^(id _Nonnull batchContext) { + [batchContext deleteInSectionController:self atIndexes:indexSet]; + } completion:nil]; } } diff --git a/ZaloMessageUI/ZaloMessageUI/IGMainMessageDataSource.m b/ZaloMessageUI/ZaloMessageUI/IGMainMessageDataSource.m index 11f49c3..d666491 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGMainMessageDataSource.m +++ b/ZaloMessageUI/ZaloMessageUI/IGMainMessageDataSource.m @@ -47,9 +47,9 @@ - (instancetype)initWithViewModels:(NSArray> *)viewModels { return self.viewModels; } -- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object { +- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter sectionControllerForObject:(id)object { MainMessageViewModel *viewModel = object; - IGListSectionController *sectionController; + IGListSectionController *sectionController; switch (viewModel.type) { case MainMessageViewModelTypeLastMessage: diff --git a/ZaloMessageUI/ZaloMessageUI/IGSuggestFriendDataSource.m b/ZaloMessageUI/ZaloMessageUI/IGSuggestFriendDataSource.m index 33dea8d..ade1cf7 100644 --- a/ZaloMessageUI/ZaloMessageUI/IGSuggestFriendDataSource.m +++ b/ZaloMessageUI/ZaloMessageUI/IGSuggestFriendDataSource.m @@ -11,7 +11,7 @@ @implementation IGSuggestFriendDataSource -- (IGListSectionController *)listAdapter:(IGListAdapter *)adapter sectionControllerFor:(id)object { +- (IGListSectionController *)listAdapter:(IGListAdapter *)adapter sectionControllerFor:(id)object { return [[IGFriendSectionController alloc] init]; } @end diff --git a/ZaloMessageUI/ZaloMessageUI/MainMessageViewController.m b/ZaloMessageUI/ZaloMessageUI/MainMessageViewController.m index e308179..a2ebfd3 100644 --- a/ZaloMessageUI/ZaloMessageUI/MainMessageViewController.m +++ b/ZaloMessageUI/ZaloMessageUI/MainMessageViewController.m @@ -117,7 +117,7 @@ - (void)setUpSuggestFriendSection { - (void)setUpCollectionView { // init collectionView UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - self.collectionView = [[IGListCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; + self.collectionView = [[IGListCollectionView alloc] initWithFrame:self.view.bounds listCollectionViewLayout:layout]; [self.view addSubview:self.collectionView]; // configurate collectionView