basic useNativeDriver functionality
Summary: Not super clean, but not terrible. Unfortunately this still relies on the old Paper UIManager calling delegate methods to flush the operations queues. This will work for Marketplace You since Paper will be active, but we need to fix this, along with Animated Events which don't work at all yet. Random aside: it seems like taps are less responsive in fabric vs. paper, at least on iOS. There is a sporadic delay between the touches event coming in nativly to the JS callback invoking the native module function to start the animation - this will need some debugging. Reviewed By: shergin Differential Revision: D14143331 fbshipit-source-id: 63a17eaafa1217d77a532a2716d9f886a96fae59
This commit is contained in:
Родитель
53e15c9e95
Коммит
ea54ceca13
|
@ -7,14 +7,14 @@
|
|||
|
||||
#import "RCTAnimatedNode.h"
|
||||
|
||||
@class RCTUIManager;
|
||||
@class RCTBridge;
|
||||
@class RCTViewPropertyMapper;
|
||||
|
||||
@interface RCTPropsAnimatedNode : RCTAnimatedNode
|
||||
|
||||
- (void)connectToView:(NSNumber *)viewTag
|
||||
viewName:(NSString *)viewName
|
||||
uiManager:(RCTUIManager *)uiManager;
|
||||
bridge:(RCTBridge *)bridge;
|
||||
|
||||
- (void)disconnectFromView:(NSNumber *)viewTag;
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#import "RCTPropsAnimatedNode.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
|
||||
|
@ -14,12 +16,33 @@
|
|||
#import "RCTStyleAnimatedNode.h"
|
||||
#import "RCTValueAnimatedNode.h"
|
||||
|
||||
// TODO: Eventually we should just include RCTSurfacePresenter.h, but that pulls in all of fabric
|
||||
// which doesn't compile in open source yet, so we mirror the protocol and duplicate the category
|
||||
// here for now.
|
||||
|
||||
@protocol SyncViewUpdater <NSObject>
|
||||
|
||||
- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (SurfacePresenterShadow)
|
||||
|
||||
- (id<SyncViewUpdater>)surfacePresenter
|
||||
{
|
||||
return objc_getAssociatedObject(self, @selector(surfacePresenter));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RCTPropsAnimatedNode
|
||||
{
|
||||
NSNumber *_connectedViewTag;
|
||||
NSNumber *_rootTag;
|
||||
NSString *_connectedViewName;
|
||||
__weak RCTUIManager *_uiManager;
|
||||
NSMutableDictionary<NSString *, NSObject *> *_propsDictionary;
|
||||
__weak RCTBridge *_bridge;
|
||||
NSMutableDictionary<NSString *, NSObject *> *_propsDictionary; // TODO: use RawProps or folly::dynamic directly
|
||||
}
|
||||
|
||||
- (instancetype)initWithTag:(NSNumber *)tag
|
||||
|
@ -33,18 +56,32 @@
|
|||
|
||||
- (void)connectToView:(NSNumber *)viewTag
|
||||
viewName:(NSString *)viewName
|
||||
uiManager:(RCTUIManager *)uiManager
|
||||
bridge:(RCTBridge *)bridge
|
||||
{
|
||||
_connectedViewTag = viewTag;
|
||||
_connectedViewName = viewName;
|
||||
_uiManager = uiManager;
|
||||
_bridge = bridge;
|
||||
_rootTag = nil;
|
||||
}
|
||||
|
||||
- (void)disconnectFromView:(NSNumber *)viewTag
|
||||
{
|
||||
_connectedViewTag = nil;
|
||||
_connectedViewName = nil;
|
||||
_uiManager = nil;
|
||||
_bridge = nil;
|
||||
_rootTag = nil;
|
||||
}
|
||||
|
||||
- (void)updateView
|
||||
{
|
||||
BOOL fabricUpdateSuccess = [_bridge.surfacePresenter synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
||||
props:_propsDictionary];
|
||||
if (fabricUpdateSuccess) {
|
||||
return;
|
||||
}
|
||||
[_bridge.uiManager synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
||||
viewName:_connectedViewName
|
||||
props:_propsDictionary];
|
||||
}
|
||||
|
||||
- (void)restoreDefaultValues
|
||||
|
@ -55,9 +92,7 @@
|
|||
}
|
||||
|
||||
if (_propsDictionary.count) {
|
||||
[_uiManager synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
||||
viewName:_connectedViewName
|
||||
props:_propsDictionary];
|
||||
[self updateView];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,12 +118,12 @@
|
|||
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];
|
||||
CGFloat value = [(RCTValueAnimatedNode *)parentNode value];
|
||||
|
@ -97,9 +132,7 @@
|
|||
}
|
||||
|
||||
if (_propsDictionary.count) {
|
||||
[_uiManager synchronouslyUpdateViewOnUIThread:_connectedViewTag
|
||||
viewName:_connectedViewName
|
||||
props:_propsDictionary];
|
||||
[self updateView];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ RCT_EXPORT_MODULE();
|
|||
{
|
||||
[super setBridge:bridge];
|
||||
|
||||
_nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithUIManager:self.bridge.uiManager];
|
||||
_nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithBridge:self.bridge];
|
||||
_operations = [NSMutableArray new];
|
||||
_preOperations = [NSMutableArray new];
|
||||
|
||||
[bridge.eventDispatcher addDispatchObserver:self];
|
||||
[bridge.uiManager.observerCoordinator addObserver:self];
|
||||
[bridge.uiManager.observerCoordinator addObserver:self]; // TODO: add fabric equivalent?
|
||||
}
|
||||
|
||||
#pragma mark -- API
|
||||
|
@ -196,7 +196,7 @@ RCT_EXPORT_METHOD(removeAnimatedEventFromView:(nonnull NSNumber *)viewTag
|
|||
|
||||
#pragma mark - RCTUIManagerObserver
|
||||
|
||||
- (void)uiManagerWillPerformMounting:(RCTUIManager *)uiManager
|
||||
- (void)uiManagerWillPerformMounting:(RCTUIManager *)uiManager // TODO: need fabric equivalent
|
||||
{
|
||||
if (_preOperations.count == 0 && _operations.count == 0) {
|
||||
return;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
@interface RCTNativeAnimatedNodesManager : NSObject
|
||||
|
||||
- (nonnull instancetype)initWithUIManager:(nonnull RCTUIManager *)uiManager;
|
||||
- (nonnull instancetype)initWithBridge:(nonnull RCTBridge *)bridge;
|
||||
|
||||
- (void)updateAnimations;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
@implementation RCTNativeAnimatedNodesManager
|
||||
{
|
||||
__weak RCTUIManager *_uiManager;
|
||||
__weak RCTBridge *_bridge;
|
||||
NSMutableDictionary<NSNumber *, RCTAnimatedNode *> *_animationNodes;
|
||||
// Mapping of a view tag and an event name to a list of event animation drivers. 99% of the time
|
||||
// there will be only one driver per mapping so all code code should be optimized around that.
|
||||
|
@ -39,10 +39,10 @@
|
|||
CADisplayLink *_displayLink;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUIManager:(nonnull RCTUIManager *)uiManager
|
||||
- (instancetype)initWithBridge:(nonnull RCTBridge *)bridge
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_uiManager = uiManager;
|
||||
_bridge = bridge;
|
||||
_animationNodes = [NSMutableDictionary new];
|
||||
_eventDrivers = [NSMutableDictionary new];
|
||||
_activeAnimations = [NSMutableSet new];
|
||||
|
@ -124,7 +124,7 @@
|
|||
{
|
||||
RCTAnimatedNode *node = _animationNodes[nodeTag];
|
||||
if ([node isKindOfClass:[RCTPropsAnimatedNode class]]) {
|
||||
[(RCTPropsAnimatedNode *)node connectToView:viewTag viewName:viewName uiManager:_uiManager];
|
||||
[(RCTPropsAnimatedNode *)node connectToView:viewTag viewName:viewName bridge:_bridge];
|
||||
}
|
||||
[node setNeedsUpdate];
|
||||
}
|
||||
|
|
|
@ -127,8 +127,10 @@ static id RCTPropChecker(NSString *prop, NSNumber *value)
|
|||
{
|
||||
[super setUp];
|
||||
|
||||
RCTBridge *bridge = [OCMockObject niceMockForClass:[RCTBridge class]];
|
||||
_uiManager = [OCMockObject niceMockForClass:[RCTUIManager class]];
|
||||
_nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithUIManager:_uiManager];
|
||||
OCMStub([bridge uiManager]).andReturn(_uiManager);
|
||||
_nodesManager = [[RCTNativeAnimatedNodesManager alloc] initWithBridge:bridge];
|
||||
_displayLink = [RCTFakeDisplayLink new];
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
*/
|
||||
- (void)optimisticallyCreateComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle;
|
||||
|
||||
- (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
|
||||
oldProps:(facebook::react::SharedProps)oldProps
|
||||
newProps:(facebook::react::SharedProps)newProps;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -176,6 +176,17 @@ using namespace facebook::react;
|
|||
[self.delegate mountingManager:self didMountComponentsWithRootTag:rootTag];
|
||||
}
|
||||
|
||||
- (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
|
||||
oldProps:(SharedProps)oldProps
|
||||
newProps:(SharedProps)newProps
|
||||
{
|
||||
RCTUpdatePropsMountItem *mountItem = [[RCTUpdatePropsMountItem alloc] initWithTag:reactTag
|
||||
oldProps:oldProps
|
||||
newProps:newProps];
|
||||
RCTAssertMainQueue();
|
||||
[mountItem executeWithRegistry:self->_componentViewRegistry];
|
||||
}
|
||||
|
||||
- (void)optimisticallyCreateComponentViewWithComponentHandle:(ComponentHandle)componentHandle
|
||||
{
|
||||
if (RCTIsMainQueue()) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#import <memory>
|
||||
|
||||
#import <React/RCTPrimitives.h>
|
||||
#import <react/core/ComponentDescriptor.h>
|
||||
#import <react/core/LayoutConstraints.h>
|
||||
#import <react/core/LayoutContext.h>
|
||||
#import <react/mounting/ShadowViewMutation.h>
|
||||
|
@ -54,6 +55,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
layoutContext:(facebook::react::LayoutContext)layoutContext
|
||||
surfaceId:(facebook::react::SurfaceId)surfaceId;
|
||||
|
||||
- (const facebook::react::ComponentDescriptor &)getComponentDescriptor:(facebook::react::ComponentHandle)handle;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -107,4 +107,9 @@ private:
|
|||
_scheduler->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext);
|
||||
}
|
||||
|
||||
- (const ComponentDescriptor &)getComponentDescriptor:(ComponentHandle)handle
|
||||
{
|
||||
return _scheduler->getComponentDescriptor(handle);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
#import <react/uimanager/ContextContainer.h>
|
||||
#import <React/RCTPrimitives.h>
|
||||
#import <react/config/ReactNativeConfig.h>
|
||||
#import <react/uimanager/ContextContainer.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
@ -66,6 +66,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
maximumSize:(CGSize)maximumSize
|
||||
surface:(RCTFabricSurface *)surface;
|
||||
|
||||
- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTSurfacePresenter (Deprecated)
|
||||
|
|
|
@ -16,17 +16,18 @@
|
|||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTComponentViewRegistry.h>
|
||||
#import <React/RCTFabricSurface.h>
|
||||
#import <React/RCTFollyConvert.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <React/RCTMountingManager.h>
|
||||
#import <React/RCTMountingManagerDelegate.h>
|
||||
#import <React/RCTScheduler.h>
|
||||
#import <React/RCTSurfaceRegistry.h>
|
||||
#import <React/RCTSurfaceView.h>
|
||||
#import <React/RCTSurfaceView+Internal.h>
|
||||
#import <React/RCTSurfaceView.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <react/core/LayoutContext.h>
|
||||
#import <react/core/LayoutConstraints.h>
|
||||
#import <react/components/root/RootShadowNode.h>
|
||||
#import <react/core/LayoutConstraints.h>
|
||||
#import <react/core/LayoutContext.h>
|
||||
#import <react/imagemanager/ImageManager.h>
|
||||
#import <react/uimanager/ContextContainer.h>
|
||||
|
||||
|
@ -59,6 +60,7 @@ using namespace facebook::react;
|
|||
if (self = [super init]) {
|
||||
_bridge = bridge;
|
||||
_batchedBridge = [_bridge batchedBridge] ?: _bridge;
|
||||
[_batchedBridge setSurfacePresenter:self];
|
||||
|
||||
_surfaceRegistry = [[RCTSurfaceRegistry alloc] init];
|
||||
|
||||
|
@ -161,6 +163,29 @@ using namespace facebook::react;
|
|||
surfaceId:surface.rootTag];
|
||||
}
|
||||
|
||||
- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props
|
||||
{
|
||||
ReactTag tag = [reactTag integerValue];
|
||||
UIView<RCTComponentViewProtocol> *componentView = [_mountingManager.componentViewRegistry componentViewByTag:tag];
|
||||
if (componentView == nil) {
|
||||
return NO; // This view probably isn't managed by Fabric
|
||||
}
|
||||
ComponentHandle handle = [[componentView class] componentHandle];
|
||||
const facebook::react::ComponentDescriptor &componentDescriptor = [self._scheduler getComponentDescriptor:handle];
|
||||
|
||||
// Note: we use an empty object for `oldProps` to rely on the diffing algorithm internal to the
|
||||
// RCTComponentViewProtocol::updateProps method. If there is a bug in that diffing, some props
|
||||
// could get reset. One way around this would be to require all RCTComponentViewProtocol
|
||||
// implementations to expose their current props so we could clone them, but that could be
|
||||
// problematic for threading and other reasons.
|
||||
facebook::react::SharedProps newProps =
|
||||
componentDescriptor.cloneProps(nullptr, RawProps(convertIdToFollyDynamic(props)));
|
||||
facebook::react::SharedProps oldProps = componentDescriptor.cloneProps(nullptr, RawProps(folly::dynamic::object()));
|
||||
|
||||
[self->_mountingManager synchronouslyUpdateViewOnUIThread:tag oldProps:oldProps newProps:newProps];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (RCTScheduler *)_scheduler
|
||||
|
|
|
@ -190,6 +190,11 @@ void Scheduler::constraintSurfaceLayout(
|
|||
});
|
||||
}
|
||||
|
||||
const ComponentDescriptor &Scheduler::getComponentDescriptor(
|
||||
ComponentHandle handle) {
|
||||
return componentDescriptorRegistry_->at(handle);
|
||||
}
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
void Scheduler::setDelegate(SchedulerDelegate *delegate) {
|
||||
|
|
|
@ -67,6 +67,8 @@ class Scheduler final : public UIManagerDelegate, public ShadowTreeDelegate {
|
|||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const;
|
||||
|
||||
const ComponentDescriptor &getComponentDescriptor(ComponentHandle handle);
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче