mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
163ec924fb
Summary: Changelog: [Internal] # Problem Before every update, restoreDefaults is called on animated nodes. In paper this makes sure no stale properties are on animated nodes. In paper it works fine because restoreDefaults is called before mounting and animations are triggered after mounting within single commit. Details: https://github.com/facebook/react-native/pull/11819 In Fabric however it is called outside of other mounting operations and it applies default values to the view and then re-applies animated values. Reviewed By: JoshuaGross Differential Revision: D21786765 fbshipit-source-id: a2cb6d6d9cbd39d4c403c97c2f51e7d92078102f
139 lines
3.9 KiB
Objective-C
139 lines
3.9 KiB
Objective-C
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import <React/RCTPropsAnimatedNode.h>
|
|
|
|
#import <React/RCTLog.h>
|
|
#import <React/RCTSurfacePresenterStub.h>
|
|
#import <React/RCTUIManager.h>
|
|
|
|
#import <React/RCTAnimationUtils.h>
|
|
#import <React/RCTStyleAnimatedNode.h>
|
|
#import <React/RCTValueAnimatedNode.h>
|
|
|
|
|
|
|
|
@implementation RCTPropsAnimatedNode
|
|
{
|
|
NSNumber *_connectedViewTag;
|
|
NSNumber *_rootTag;
|
|
NSString *_connectedViewName;
|
|
__weak RCTBridge *_bridge;
|
|
NSMutableDictionary<NSString *, NSObject *> *_propsDictionary; // TODO: use RawProps or folly::dynamic directly
|
|
BOOL _managedByFabric;
|
|
}
|
|
|
|
- (instancetype)initWithTag:(NSNumber *)tag
|
|
config:(NSDictionary<NSString *, id> *)config
|
|
{
|
|
if (self = [super initWithTag:tag config:config]) {
|
|
_propsDictionary = [NSMutableDictionary new];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (BOOL)isManagedByFabric
|
|
{
|
|
return _managedByFabric;
|
|
}
|
|
|
|
- (void)connectToView:(NSNumber *)viewTag
|
|
viewName:(NSString *)viewName
|
|
bridge:(RCTBridge *)bridge
|
|
{
|
|
_bridge = bridge;
|
|
_connectedViewTag = viewTag;
|
|
_connectedViewName = viewName;
|
|
_managedByFabric = RCTUIManagerTypeForTagIsFabric(viewTag);
|
|
_rootTag = nil;
|
|
}
|
|
|
|
- (void)disconnectFromView:(NSNumber *)viewTag
|
|
{
|
|
_bridge = nil;
|
|
_connectedViewTag = nil;
|
|
_connectedViewName = nil;
|
|
_managedByFabric = NO;
|
|
_rootTag = nil;
|
|
}
|
|
|
|
- (void)updateView
|
|
{
|
|
if (_managedByFabric) {
|
|
[_bridge.surfacePresenter synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
|
props:_propsDictionary];
|
|
} else {
|
|
[_bridge.uiManager synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
|
viewName:_connectedViewName
|
|
props:_propsDictionary];
|
|
}
|
|
}
|
|
|
|
- (void)restoreDefaultValues
|
|
{
|
|
if (_managedByFabric) {
|
|
// Restoring to default values causes render of inconsistent state
|
|
// to the user because it isn't synchonised with Fabric's UIManager.
|
|
return;
|
|
}
|
|
// Restore the default value for all props that were modified by this node.
|
|
for (NSString *key in _propsDictionary.allKeys) {
|
|
_propsDictionary[key] = [NSNull null];
|
|
}
|
|
|
|
if (_propsDictionary.count) {
|
|
[self updateView];
|
|
}
|
|
}
|
|
|
|
- (NSString *)propertyNameForParentTag:(NSNumber *)parentTag
|
|
{
|
|
__block NSString *propertyName;
|
|
[self.config[@"props"] enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull property, NSNumber *_Nonnull tag, BOOL *_Nonnull stop) {
|
|
if ([tag isEqualToNumber:parentTag]) {
|
|
propertyName = property;
|
|
*stop = YES;
|
|
}
|
|
}];
|
|
return propertyName;
|
|
}
|
|
|
|
- (void)performUpdate
|
|
{
|
|
[super performUpdate];
|
|
|
|
// Since we are updating nodes after detaching them from views there is a time where it's
|
|
// possible that the view was disconnected and still receive an update, this is normal and we can
|
|
// simply skip that update.
|
|
if (!_connectedViewTag) {
|
|
return;
|
|
}
|
|
|
|
for (NSNumber *parentTag in self.parentNodes.keyEnumerator) {
|
|
RCTAnimatedNode *parentNode = [self.parentNodes objectForKey:parentTag];
|
|
if ([parentNode isKindOfClass:[RCTStyleAnimatedNode class]]) {
|
|
[self->_propsDictionary addEntriesFromDictionary:[(RCTStyleAnimatedNode *)parentNode propsDictionary]];
|
|
|
|
} else if ([parentNode isKindOfClass:[RCTValueAnimatedNode class]]) {
|
|
NSString *property = [self propertyNameForParentTag:parentTag];
|
|
id animatedObject = [(RCTValueAnimatedNode *)parentNode animatedObject];
|
|
if (animatedObject) {
|
|
self->_propsDictionary[property] = animatedObject;
|
|
} else {
|
|
CGFloat value = [(RCTValueAnimatedNode *)parentNode value];
|
|
self->_propsDictionary[property] = @(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_propsDictionary.count) {
|
|
[self updateView];
|
|
}
|
|
}
|
|
|
|
@end
|