mirror of
https://github.com/status-im/react-native.git
synced 2025-02-13 18:06:37 +00:00
Revert "Reverted commit D3417194"
Summary: This reverts commit 7df2af58c78d57d95dc1577e489dc795bafe7ce8. cc janicduplessis Closes https://github.com/facebook/react-native/pull/8049 Differential Revision: D3417557 fbshipit-source-id: 3853b06e91a2aae441835807f73fb78e6ef79344
This commit is contained in:
parent
4f4b6d467a
commit
0d572e40f0
@ -210,6 +210,7 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim
|
|||||||
|
|
||||||
// Animation
|
// Animation
|
||||||
RCTLayoutAnimation *_layoutAnimation; // Main thread only
|
RCTLayoutAnimation *_layoutAnimation; // Main thread only
|
||||||
|
NSMutableSet<UIView *> *_viewsToBeDeleted; // Main thread only
|
||||||
|
|
||||||
NSMutableDictionary<NSNumber *, RCTShadowView *> *_shadowViewRegistry; // RCT thread only
|
NSMutableDictionary<NSNumber *, RCTShadowView *> *_shadowViewRegistry; // RCT thread only
|
||||||
NSMutableDictionary<NSNumber *, UIView *> *_viewRegistry; // Main thread only
|
NSMutableDictionary<NSNumber *, UIView *> *_viewRegistry; // Main thread only
|
||||||
@ -318,6 +319,8 @@ RCT_EXPORT_MODULE()
|
|||||||
|
|
||||||
_bridgeTransactionListeners = [NSMutableSet new];
|
_bridgeTransactionListeners = [NSMutableSet new];
|
||||||
|
|
||||||
|
_viewsToBeDeleted = [NSMutableSet new];
|
||||||
|
|
||||||
// Get view managers from bridge
|
// Get view managers from bridge
|
||||||
NSMutableDictionary *componentDataByName = [NSMutableDictionary new];
|
NSMutableDictionary *componentDataByName = [NSMutableDictionary new];
|
||||||
for (Class moduleClass in _bridge.moduleClasses) {
|
for (Class moduleClass in _bridge.moduleClasses) {
|
||||||
@ -339,7 +342,6 @@ RCT_EXPORT_MODULE()
|
|||||||
selector:@selector(interfaceOrientationWillChange:)
|
selector:@selector(interfaceOrientationWillChange:)
|
||||||
name:UIApplicationWillChangeStatusBarOrientationNotification
|
name:UIApplicationWillChangeStatusBarOrientationNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
[RCTAnimation initializeStatics];
|
[RCTAnimation initializeStatics];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,53 +780,61 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containe
|
|||||||
|
|
||||||
- (void)_removeChildren:(NSArray<id<RCTComponent>> *)children
|
- (void)_removeChildren:(NSArray<id<RCTComponent>> *)children
|
||||||
fromContainer:(id<RCTComponent>)container
|
fromContainer:(id<RCTComponent>)container
|
||||||
permanent:(BOOL)permanent
|
|
||||||
{
|
{
|
||||||
RCTLayoutAnimation *layoutAnimation = _layoutAnimation;
|
for (id<RCTComponent> removedChild in children) {
|
||||||
RCTAnimation *deleteAnimation = layoutAnimation.deleteAnimation;
|
[container removeReactSubview:removedChild];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove subviews from their parent with an animation.
|
||||||
|
*/
|
||||||
|
- (void)_removeChildren:(NSArray<UIView *> *)children
|
||||||
|
fromContainer:(UIView *)container
|
||||||
|
withAnimation:(RCTLayoutAnimation *)animation
|
||||||
|
{
|
||||||
|
RCTAssertMainQueue();
|
||||||
|
RCTAnimation *deleteAnimation = animation.deleteAnimation;
|
||||||
|
|
||||||
__block NSUInteger completionsCalled = 0;
|
__block NSUInteger completionsCalled = 0;
|
||||||
|
for (UIView *removedChild in children) {
|
||||||
for (id<RCTComponent> removedChild in children) {
|
|
||||||
|
|
||||||
void (^completion)(BOOL) = ^(BOOL finished) {
|
void (^completion)(BOOL) = ^(BOOL finished) {
|
||||||
completionsCalled++;
|
completionsCalled++;
|
||||||
|
|
||||||
|
[_viewsToBeDeleted removeObject:removedChild];
|
||||||
[container removeReactSubview:removedChild];
|
[container removeReactSubview:removedChild];
|
||||||
|
|
||||||
if (layoutAnimation.callback && completionsCalled == children.count) {
|
if (animation.callback && completionsCalled == children.count) {
|
||||||
layoutAnimation.callback(@[@(finished)]);
|
animation.callback(@[@(finished)]);
|
||||||
|
|
||||||
// It's unsafe to call this callback more than once, so we nil it out here
|
// It's unsafe to call this callback more than once, so we nil it out here
|
||||||
// to make sure that doesn't happen.
|
// to make sure that doesn't happen.
|
||||||
layoutAnimation.callback = nil;
|
animation.callback = nil;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (permanent && deleteAnimation && [removedChild isKindOfClass: [UIView class]]) {
|
[_viewsToBeDeleted addObject:removedChild];
|
||||||
UIView *view = (UIView *)removedChild;
|
|
||||||
|
|
||||||
// Disable user interaction while the view is animating since JS won't receive
|
// Disable user interaction while the view is animating since JS won't receive
|
||||||
// the view events anyway.
|
// the view events anyway.
|
||||||
view.userInteractionEnabled = NO;
|
removedChild.userInteractionEnabled = NO;
|
||||||
|
|
||||||
NSString *property = deleteAnimation.property;
|
NSString *property = deleteAnimation.property;
|
||||||
[deleteAnimation performAnimations:^{
|
[deleteAnimation performAnimations:^{
|
||||||
if ([property isEqualToString:@"scaleXY"]) {
|
if ([property isEqualToString:@"scaleXY"]) {
|
||||||
view.layer.transform = CATransform3DMakeScale(0, 0, 0);
|
removedChild.layer.transform = CATransform3DMakeScale(0, 0, 0);
|
||||||
} else if ([property isEqualToString:@"opacity"]) {
|
} else if ([property isEqualToString:@"opacity"]) {
|
||||||
view.layer.opacity = 0.0;
|
removedChild.layer.opacity = 0.0;
|
||||||
} else {
|
} else {
|
||||||
RCTLogError(@"Unsupported layout animation createConfig property %@",
|
RCTLogError(@"Unsupported layout animation createConfig property %@",
|
||||||
deleteAnimation.property);
|
deleteAnimation.property);
|
||||||
}
|
}
|
||||||
} withCompletionBlock:completion];
|
} withCompletionBlock:completion];
|
||||||
} else {
|
|
||||||
[container removeReactSubview:removedChild];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
|
RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
|
||||||
{
|
{
|
||||||
RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag];
|
RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag];
|
||||||
@ -938,13 +948,19 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerTag
|
|||||||
[self _childrenToRemoveFromContainer:container atIndices:removeAtIndices];
|
[self _childrenToRemoveFromContainer:container atIndices:removeAtIndices];
|
||||||
NSArray<id<RCTComponent>> *temporarilyRemovedChildren =
|
NSArray<id<RCTComponent>> *temporarilyRemovedChildren =
|
||||||
[self _childrenToRemoveFromContainer:container atIndices:moveFromIndices];
|
[self _childrenToRemoveFromContainer:container atIndices:moveFromIndices];
|
||||||
[self _removeChildren:permanentlyRemovedChildren fromContainer:container permanent:true];
|
|
||||||
[self _removeChildren:temporarilyRemovedChildren fromContainer:container permanent:false];
|
|
||||||
|
|
||||||
|
BOOL isUIViewRegistry = ((id)registry == (id)_viewRegistry);
|
||||||
|
if (isUIViewRegistry && _layoutAnimation.deleteAnimation) {
|
||||||
|
[self _removeChildren:(NSArray<UIView *> *)permanentlyRemovedChildren
|
||||||
|
fromContainer:(UIView *)container
|
||||||
|
withAnimation:_layoutAnimation];
|
||||||
|
} else {
|
||||||
|
[self _removeChildren:permanentlyRemovedChildren fromContainer:container];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _removeChildren:temporarilyRemovedChildren fromContainer:container];
|
||||||
[self _purgeChildren:permanentlyRemovedChildren fromRegistry:registry];
|
[self _purgeChildren:permanentlyRemovedChildren fromRegistry:registry];
|
||||||
|
|
||||||
// TODO (#5906496): optimize all these loops - constantly calling array.count is not efficient
|
|
||||||
|
|
||||||
// Figure out what to insert - merge temporary inserts and adds
|
// Figure out what to insert - merge temporary inserts and adds
|
||||||
NSMutableDictionary *destinationsToChildrenToAdd = [NSMutableDictionary dictionary];
|
NSMutableDictionary *destinationsToChildrenToAdd = [NSMutableDictionary dictionary];
|
||||||
for (NSInteger index = 0, length = temporarilyRemovedChildren.count; index < length; index++) {
|
for (NSInteger index = 0, length = temporarilyRemovedChildren.count; index < length; index++) {
|
||||||
@ -960,8 +976,22 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerTag
|
|||||||
NSArray<NSNumber *> *sortedIndices =
|
NSArray<NSNumber *> *sortedIndices =
|
||||||
[destinationsToChildrenToAdd.allKeys sortedArrayUsingSelector:@selector(compare:)];
|
[destinationsToChildrenToAdd.allKeys sortedArrayUsingSelector:@selector(compare:)];
|
||||||
for (NSNumber *reactIndex in sortedIndices) {
|
for (NSNumber *reactIndex in sortedIndices) {
|
||||||
|
NSInteger insertAtIndex = reactIndex.integerValue;
|
||||||
|
|
||||||
|
// When performing a delete animation, views are not removed immediately
|
||||||
|
// from their container so we need to offset the insertion index if a view
|
||||||
|
// that will be removed appears earlier than the view we are inserting.
|
||||||
|
if (isUIViewRegistry && _viewsToBeDeleted.count > 0) {
|
||||||
|
for (NSInteger index = 0; index < insertAtIndex; index++) {
|
||||||
|
UIView *subview = ((UIView *)container).reactSubviews[index];
|
||||||
|
if ([_viewsToBeDeleted containsObject:subview]) {
|
||||||
|
insertAtIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[container insertReactSubview:destinationsToChildrenToAdd[reactIndex]
|
[container insertReactSubview:destinationsToChildrenToAdd[reactIndex]
|
||||||
atIndex:reactIndex.integerValue];
|
atIndex:insertAtIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user