ComponentKit/TransactionalDataSources/Common/Internal/CKDataSourceUpdateStateModification.mm (98 lines of code) (raw):

/* * Copyright (c) 2014-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 "CKDataSourceUpdateStateModification.h" #import "CKDataSourceConfiguration.h" #import "CKDataSourceConfigurationInternal.h" #import "CKDataSourceStateInternal.h" #import "CKDataSourceChange.h" #import "CKDataSourceItemInternal.h" #import "CKDataSourceAppliedChanges.h" #import "CKBuildComponent.h" #import "CKComponentControllerEvents.h" #import "CKComponentControllerHelper.h" #import "CKComponentLayout.h" #import "CKComponentProvider.h" #import "CKComponentScopeHandle.h" #import "CKComponentScopeRoot.h" #import "CKDataSourceModificationHelper.h" using namespace CKComponentControllerHelper; @implementation CKDataSourceUpdateStateModification { CKComponentStateUpdatesMap _stateUpdates; std::shared_ptr<CKTreeLayoutCache> _treeLayoutCache; } - (instancetype)initWithStateUpdates:(const CKComponentStateUpdatesMap &)stateUpdates treeLayoutCache:(std::shared_ptr<CKTreeLayoutCache>)treeLayoutCache { if (self = [super init]) { _stateUpdates = stateUpdates; _treeLayoutCache = std::move(treeLayoutCache); } return self; } - (CKDataSourceChange *)changeFromState:(CKDataSourceState *)oldState { CKDataSourceConfiguration *configuration = [oldState configuration]; id<NSObject> context = [configuration context]; const CKSizeRange sizeRange = [configuration sizeRange]; NSMutableArray *newSections = [NSMutableArray array]; NSMutableSet *updatedIndexPaths = [NSMutableSet set]; NSMutableArray<CKComponentController *> *addedComponentControllers = [NSMutableArray array]; NSMutableArray<CKComponentController *> *invalidComponentControllers = [NSMutableArray array]; __block CKComponentScopeRootIdentifier globalIdentifier = 0; [[oldState sections] enumerateObjectsUsingBlock:^(NSArray *items, NSUInteger sectionIdx, BOOL *sectionStop) { NSMutableArray *newItems = [NSMutableArray array]; [items enumerateObjectsUsingBlock:^(CKDataSourceItem *item, NSUInteger itemIdx, BOOL *itemStop) { const auto scopeRootGlobalIdentifier = [[item scopeRoot] globalIdentifier]; const auto stateUpdatesForItem = _stateUpdates.find(scopeRootGlobalIdentifier); if (stateUpdatesForItem == _stateUpdates.end()) { [newItems addObject:item]; } else { const auto stateUpdateMap = stateUpdatesForItem->second; const auto stateUpdate = stateUpdateMap.begin(); if (stateUpdate != stateUpdateMap.end()) { globalIdentifier = stateUpdate->first.globalIdentifier; } [updatedIndexPaths addObject:[NSIndexPath indexPathForItem:itemIdx inSection:sectionIdx]]; const auto layoutCache = _treeLayoutCache ? _treeLayoutCache->find(scopeRootGlobalIdentifier) : nullptr; CKDataSourceItem *const newItem = CKBuildDataSourceItem([item scopeRoot], stateUpdatesForItem->second, sizeRange, configuration, [item model], context, layoutCache); [newItems addObject:newItem]; for (auto componentController : addedControllersFromPreviousScopeRootMatchingPredicate(newItem.scopeRoot, item.scopeRoot, &CKComponentControllerInitializeEventPredicate)) { [addedComponentControllers addObject:componentController]; } for (auto componentController : removedControllersFromPreviousScopeRootMatchingPredicate(newItem.scopeRoot, item.scopeRoot, &CKComponentControllerInvalidateEventPredicate)) { [invalidComponentControllers addObject:componentController]; } } }]; [newSections addObject:newItems]; }]; CKDataSourceState *newState = [[CKDataSourceState alloc] initWithConfiguration:configuration sections:newSections]; CKDataSourceAppliedChanges *appliedChanges = [[CKDataSourceAppliedChanges alloc] initWithUpdatedIndexPaths:updatedIndexPaths removedIndexPaths:nil removedSections:nil movedIndexPaths:nil insertedSections:nil insertedIndexPaths:nil userInfo:@{@"updatedComponentIdentifier":@(globalIdentifier)}]; return [[CKDataSourceChange alloc] initWithState:newState previousState:oldState appliedChanges:appliedChanges appliedChangeset:nil deferredChangeset:nil addedComponentControllers:addedComponentControllers invalidComponentControllers:invalidComponentControllers]; } - (NSDictionary *)userInfo { return nil; } - (CKDataSourceQOS)qos { return CKDataSourceQOSDefault; } @end