-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update layout props without crossing JS bridge #45
Conversation
…nto update-jsprops-without-bridge
src/ConfigHelper.js
Outdated
}; | ||
|
||
function configureJSPropsHandledNatively() { | ||
ReanimatedModule.configureJSPropsHandledNatively( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets move this to a common method that would take both lists at once
src/ConfigHelper.js
Outdated
@@ -35,3 +35,74 @@ export function addWhitelistedNativeProps(props) { | |||
} | |||
|
|||
configureNativeProps(); | |||
|
|||
const JS_PROPS_HANDLED_NATIVELY_WHITELIST = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment:
Whitelist of view props that can be updated in native thread via UIManagerModule
Change NATIVE_PROPS_WHITELIST
to UI_THREAD_PROPS_WHITELIST
and also change comment to tell that the props are updated directly on UI thread
Change JS_PROPS_HANDLED_
to NATIVE_THREAD_PROPS_WHITELIST
@@ -68,13 +69,15 @@ | |||
public double currentFrameTimeMs; | |||
public final UpdateContext updateContext; | |||
public Set<String> nativeProps = Collections.emptySet(); | |||
public Set<String> jsPropsHandledNatively = Collections.emptySet(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use uiProps
for what used to be nativeProps
and nativeProps
for jsPropsHandledNatively
new GuardedRunnable(mContext) { | ||
@Override | ||
public void runGuarded() { | ||
mUIManager.onBatchComplete(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we shouldn't just call onBatchComplete
like that. This may intercept batched calls being made at the same time from JS. Would be the best to detect if we are in the middle of a batch and if so we can skip calling onBatchComplete
and rely on getting it dispatched from JS thread. Also May be worth enqueuing all the UIManager operations here such that we can call it from a single runnable without risking some other operations being enqueued in the meantime
@Override | ||
public void runGuarded() { | ||
while (!mOperationsInBatch.isEmpty()) { | ||
NativeUpdateOperation op = mOperationsInBatch.remove(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sync this quuee
@@ -284,6 +318,10 @@ public void disconnectNodeFromView(int nodeID, int viewTag) { | |||
((PropsNode) node).disconnectFromView(viewTag); | |||
} | |||
|
|||
public void setUpdateView(int viewTag, WritableMap nativeProps) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename
@@ -137,6 +155,30 @@ private void onAnimationFrame(long frameTimeNanos) { | |||
Node.runUpdates(updateContext); | |||
} | |||
|
|||
if (!mOperationsInBatch.isEmpty()) { | |||
final Queue<NativeUpdateOperation> copiedProps = new LinkedList<>(mOperationsInBatch); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename copiedProps
evt.putMap("props", jsProps); | ||
mNodesManager.sendEvent("onReanimatedPropsChange", evt); | ||
if (hasNativeProps) { | ||
mNodesManager.updateView(mConnectedViewTag, nativeProps); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enqueueUpdateViewOnNativeThread
@@ -0,0 +1,8 @@ | |||
package com.facebook.react.uimanager; | |||
|
|||
// This class has been made in order to export package method of UIImplementation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use javadoc format to document this class
ios/REAModule.m
Outdated
@@ -107,13 +107,15 @@ - (void)setBridge:(RCTBridge *)bridge | |||
}]; | |||
} | |||
|
|||
RCT_EXPORT_METHOD(configureNativeProps:(nonnull NSArray<NSString *> *)nativeProps) | |||
RCT_EXPORT_METHOD(configureProps:(nonnull NSArray<NSString *> *)nativeProps | |||
nativeProps:(nonnull NSArray<NSString *> *)uiProps) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uiProps:(nonnull NSArray<NSString *> *)uiProps)
boolean hasNativeProps = false; | ||
boolean hasJSProps = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets keep the code responsible for updating props in JS. I believe there are still some props that we haven't whitelisted, we don't want to restrict usages that are curerntly possible
ios/REANodesManager.m
Outdated
RCTExecuteOnUIManagerQueue(^{ | ||
BOOL shouldFinishBatch = ((NSHashTable<RCTShadowView *> *)[self.uiManager valueForKey:@"_shadowViewsWithUpdatedChildren"]).count == 0; | ||
for (int i = 0; i < copiedNumberOfOperationsInBatch; i++) { | ||
[self.uiManager updateView:copiedProps[i].reactTag viewName:copiedProps[i].viewName props:copiedProps[i].nativeProps]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copiedProps[i](self.uiManager);
ios/REANodesManager.m
Outdated
- (void)updateView:(nonnull NSNumber *)reactTag | ||
viewName:(NSString *) viewName | ||
nativeProps:(NSMutableDictionary *)nativeProps { | ||
[_operationsInBatch addObject:[[REANativeUpdateOperation alloc] initWithReactTag:reactTag viewName:viewName nativeProps:nativeProps]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[_operationsInBatch addObject:^(RCTUIManager *uiManager) {
[uiManager updateView:reactTag viewName:viewName props:nativeProps];
}
ios/REANodesManager.m
Outdated
[self.uiManager updateView:copiedProps[i].reactTag viewName:copiedProps[i].viewName props:copiedProps[i].nativeProps]; | ||
} | ||
if (shouldFinishBatch) { | ||
[self.uiManager batchDidComplete]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(cherry picked from commit 255bb74)
} | ||
} | ||
if (shouldDispatchUpdates) { | ||
mUIImplementation.dispatchViewUpdates(-1); // no associated batchId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kmagiera,
decided not to use onBatchCompleted
because it sometimes makes unexpected behaviour.
While changing screen via navigator it sometimes "blink" with old layout (v easy to repro)
Indeed I figured out that batchId should not have any impact because it only matters in systrace.
https://github.com/facebook/react-native/search?q=batchId&unscoped_q=batchId&type=Code
But it makes this error 🤷♂️
ios/REANodesManager.m
Outdated
#import "Nodes/REAAlwaysNode.h" | ||
|
||
@interface RCTUIManager () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comment
This commit facebook/react-native@2558c3d added string to `transform` type and it broke Reanimated types. <!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please follow the template so that the reviewers can easily understand what the code changes affect. --> ## Summary fixes [#45](#4548)
This commit facebook/react-native@2558c3d added string to `transform` type and it broke Reanimated types. <!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please follow the template so that the reviewers can easily understand what the code changes affect. --> ## Summary fixes [software-mansion#45](software-mansion#4548)
* Separate animation from transition * Separate config creation from class implementation * Add transitions registry to the manager, add null check * Changes after rebase
* Separate animation from transition * Separate config creation from class implementation * Add transitions registry to the manager, add null check * Changes after rebase
Motivation
The problem occurs if we wish to update props which are not supported natively to be modifier via Aniamted.Value. It refers to props like top, width etc.
Changes
Initially wish to add handling for greater number of properties in RN core which came out to be quite difficult and I gave up with this idea.
The another approach I decided to try was to use flow of updating properties from JS, but call them from native code.
Before these changes the flow was:
Changing property not supported natively e.g. width:
The bias of passing bridge seems to be extremely useless and therefore I managed to omit it.
now it looks more or less like: