Skip to content

Commit

Permalink
Merge pull request #18073 from margelo/@terrysahaidak/upgrade-reanimated
Browse files Browse the repository at this point in the history
Upgrade reanimated to 3.1.0
  • Loading branch information
roryabraham authored May 18, 2023
2 parents 2090c05 + 5f8ff9c commit 78ec531
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 41 deletions.
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ PODS:
- React-Core
- RNReactNativeHapticFeedback (1.14.0):
- React-Core
- RNReanimated (3.0.0-rc.10):
- RNReanimated (3.1.0):
- DoubleConversion
- FBLazyVector
- FBReactNativeSpec
Expand Down Expand Up @@ -1124,7 +1124,7 @@ SPEC CHECKSUMS:
RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81
RNPermissions: dcdb7b99796bbeda6975a6e79ad519c41b251b1c
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
RNReanimated: fbc356493970e3acddc15586b1bccb5eab3ff1ec
RNReanimated: b1220a0e5168745283ff5d53bfc7d2144b2cee1b
RNScreens: 0df01424e9e0ed7827200d6ed1087ddd06c493f9
RNSVG: 53c661b76829783cdaf9b7a57258f3d3b4c28315
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
Expand Down
1 change: 1 addition & 0 deletions jest/setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'setimmediate';
import 'react-native-gesture-handler/jestSetup';
import * as reanimatedJestUtils from 'react-native-reanimated/src/reanimated2/jestUtils';
import setupMockImages from './setupMockImages';
Expand Down
57 changes: 34 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
"react-native-plaid-link-sdk": "^10.0.0",
"react-native-qrcode-svg": "^6.2.0",
"react-native-quick-sqlite": "^8.0.0-beta.2",
"react-native-reanimated": "3.0.0-rc.10",
"react-native-reanimated": "3.1.0",
"react-native-render-html": "6.3.1",
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "3.17.0",
Expand Down Expand Up @@ -206,6 +206,7 @@
"react-native-performance-flipper-reporter": "^2.0.0",
"react-native-svg-transformer": "^1.0.0",
"react-test-renderer": "18.1.0",
"setimmediate": "^1.0.5",
"shellcheck": "^1.1.0",
"style-loader": "^2.0.0",
"time-analytics-webpack-plugin": "^0.1.17",
Expand Down
177 changes: 177 additions & 0 deletions patches/react-native-reanimated+3.1.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
diff --git a/node_modules/react-native-reanimated/ios/REANodesManager.mm b/node_modules/react-native-reanimated/ios/REANodesManager.mm
index 26bb253..4108293 100644
--- a/node_modules/react-native-reanimated/ios/REANodesManager.mm
+++ b/node_modules/react-native-reanimated/ios/REANodesManager.mm
@@ -85,19 +85,77 @@ - (void)runSyncUIUpdatesWithObserver:(id<RCTUIManagerObserver>)observer

@end

-@interface REANodesManager () <RCTUIManagerObserver>
+#ifndef RCT_NEW_ARCH_ENABLED

+@interface REASyncUpdateObserver : NSObject <RCTUIManagerObserver>
@end

+@implementation REASyncUpdateObserver {
+ volatile void (^_mounting)(void);
+ volatile BOOL _waitTimedOut;
+ dispatch_semaphore_t _semaphore;
+}
+
+- (instancetype)init
+{
+ self = [super init];
+ if (self) {
+ _mounting = nil;
+ _waitTimedOut = NO;
+ _semaphore = dispatch_semaphore_create(0);
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ RCTAssert(_mounting == nil, @"Mouting block was set but never executed. This may lead to UI inconsistencies");
+}
+
+- (void)unblockUIThread
+{
+ RCTAssertUIManagerQueue();
+ dispatch_semaphore_signal(_semaphore);
+}
+
+- (void)waitAndMountWithTimeout:(NSTimeInterval)timeout
+{
+ RCTAssertMainQueue();
+ long result = dispatch_semaphore_wait(_semaphore, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC));
+ if (result != 0) {
+ @synchronized(self) {
+ _waitTimedOut = YES;
+ }
+ }
+ if (_mounting) {
+ _mounting();
+ _mounting = nil;
+ }
+}
+
+- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
+{
+ RCTAssertUIManagerQueue();
+ @synchronized(self) {
+ if (_waitTimedOut) {
+ return NO;
+ } else {
+ _mounting = block;
+ return YES;
+ }
+ }
+}
+
+@end
+
+#endif
+
@implementation REANodesManager {
CADisplayLink *_displayLink;
BOOL _wantRunUpdates;
NSMutableArray<REAOnAnimationCallback> *_onAnimationCallbacks;
BOOL _tryRunBatchUpdatesSynchronously;
REAEventHandler _eventHandler;
- volatile void (^_mounting)(void);
- NSObject *_syncLayoutUpdatesWaitLock;
- volatile BOOL _syncLayoutUpdatesWaitTimedOut;
NSMutableDictionary<NSNumber *, ComponentUpdate *> *_componentUpdateBuffer;
NSMutableDictionary<NSNumber *, UIView *> *_viewRegistry;
#ifdef RCT_NEW_ARCH_ENABLED
@@ -125,7 +183,6 @@ - (nonnull instancetype)initWithModule:(REAModule *)reanimatedModule
_operationsInBatch = [NSMutableDictionary new];
_componentUpdateBuffer = [NSMutableDictionary new];
_viewRegistry = [_uiManager valueForKey:@"_viewRegistry"];
- _syncLayoutUpdatesWaitLock = [NSObject new];
}

_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onAnimationFrame:)];
@@ -241,19 +298,6 @@ - (void)onAnimationFrame:(CADisplayLink *)displayLink
}
}

-- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
-{
- RCTAssert(_mounting == nil, @"Mouting block is expected to not be set");
- @synchronized(_syncLayoutUpdatesWaitLock) {
- if (_syncLayoutUpdatesWaitTimedOut) {
- return NO;
- } else {
- _mounting = block;
- return YES;
- }
- }
-}
-
- (void)performOperations
{
#ifdef RCT_NEW_ARCH_ENABLED
@@ -268,8 +312,7 @@ - (void)performOperations
_tryRunBatchUpdatesSynchronously = NO;

__weak __typeof__(self) weakSelf = self;
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- _syncLayoutUpdatesWaitTimedOut = NO;
+ REASyncUpdateObserver *syncUpdateObserver = [REASyncUpdateObserver new];
RCTExecuteOnUIManagerQueue(^{
__typeof__(self) strongSelf = weakSelf;
if (strongSelf == nil) {
@@ -278,7 +321,7 @@ - (void)performOperations
BOOL canUpdateSynchronously = trySynchronously && ![strongSelf.uiManager hasEnqueuedUICommands];

if (!canUpdateSynchronously) {
- dispatch_semaphore_signal(semaphore);
+ [syncUpdateObserver unblockUIThread];
}

for (int i = 0; i < copiedOperationsQueue.count; i++) {
@@ -286,8 +329,8 @@ - (void)performOperations
}

if (canUpdateSynchronously) {
- [strongSelf.uiManager runSyncUIUpdatesWithObserver:strongSelf];
- dispatch_semaphore_signal(semaphore);
+ [strongSelf.uiManager runSyncUIUpdatesWithObserver:syncUpdateObserver];
+ [syncUpdateObserver unblockUIThread];
}
// In case canUpdateSynchronously=true we still have to send uiManagerWillPerformMounting event
// to observers because some components (e.g. TextInput) update their UIViews only on that event.
@@ -298,17 +341,7 @@ - (void)performOperations
// from CADisplayLink but it is easier to hardcode it for the time being.
// The reason why we use frame duration here is that if takes longer than one frame to complete layout tasks
// there is no point of synchronizing layout with the UI interaction as we get that one frame delay anyways.
- long result = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC));
- if (result != 0) {
- @synchronized(_syncLayoutUpdatesWaitLock) {
- _syncLayoutUpdatesWaitTimedOut = YES;
- }
- }
- }
-
- if (_mounting) {
- _mounting();
- _mounting = nil;
+ [syncUpdateObserver waitAndMountWithTimeout:0.016];
}
}
_wantRunUpdates = NO;
diff --git a/node_modules/react-native-reanimated/mock.js b/node_modules/react-native-reanimated/mock.js
index 68b20d2..b088001 100644
--- a/node_modules/react-native-reanimated/mock.js
+++ b/node_modules/react-native-reanimated/mock.js
@@ -41,6 +41,9 @@ const Reanimated = {
createAnimatedComponent: (Component) => Component,
addWhitelistedUIProps: NOOP,
addWhitelistedNativeProps: NOOP,
+
+ // used by react-navigation fork
+ isConfigured: () => true,
};

module.exports = {
17 changes: 12 additions & 5 deletions src/components/AvatarCropModal/ImageCropView.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,23 @@ const defaultProps = {
const ImageCropView = (props) => {
const containerStyle = StyleUtils.getWidthAndHeightStyle(props.containerSize, props.containerSize);

const originalImageHeight = props.originalImageHeight;
const originalImageWidth = props.originalImageWidth;
const rotation = props.rotation;
const translateX = props.translateX;
const translateY = props.translateY;
const scale = props.scale;

// A reanimated memoized style, which updates when the image's size or scale changes.
const imageStyle = useAnimatedStyle(() => {
const height = props.originalImageHeight.value;
const width = props.originalImageWidth.value;
const height = originalImageHeight.value;
const width = originalImageWidth.value;
const aspectRatio = height > width ? height / width : width / height;
const rotate = interpolate(props.rotation.value, [0, 360], [0, 360]);
const rotate = interpolate(rotation.value, [0, 360], [0, 360]);
return {
transform: [{translateX: props.translateX.value}, {translateY: props.translateY.value}, {scale: props.scale.value * aspectRatio}, {rotate: `${rotate}deg`}],
transform: [{translateX: translateX.value}, {translateY: translateY.value}, {scale: scale.value * aspectRatio}, {rotate: `${rotate}deg`}],
};
}, [props.originalImageHeight, props.originalImageWidth]);
}, [originalImageHeight, originalImageWidth, rotation, translateX, translateY, scale]);

// We're preventing text selection with ControlSelection.blockElement to prevent safari
// default behaviour of cursor - I-beam cursor on drag. See https://github.com/Expensify/App/issues/13688
Expand Down
3 changes: 2 additions & 1 deletion src/components/AvatarCropModal/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ const defaultProps = {

// This component can't be written using class since reanimated API uses hooks.
const Slider = (props) => {
const sliderValue = props.sliderValue;
const [tooltipIsVisible, setTooltipIsVisible] = useState(true);

// A reanimated memoized style, which tracks
// a translateX shared value and updates the slider position.
const rSliderStyle = useAnimatedStyle(() => ({
transform: [{translateX: props.sliderValue.value}],
transform: [{translateX: sliderValue.value}],
}));

// We're preventing text selection with ControlSelection.blockElement to prevent safari
Expand Down
Loading

0 comments on commit 78ec531

Please sign in to comment.