forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRCTPropsAnimatedNode.m
More file actions
133 lines (113 loc) · 3.67 KB
/
RCTPropsAnimatedNode.m
File metadata and controls
133 lines (113 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* 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
{
// 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