Skip to content

Commit

Permalink
Merge pull request #13767 from WoLewicki/andrew-fabric
Browse files Browse the repository at this point in the history
Enable Fabric and TurboModules on iOS & Android
  • Loading branch information
roryabraham authored Apr 9, 2024
2 parents 455dce4 + 444bfaa commit d088580
Show file tree
Hide file tree
Showing 70 changed files with 18,432 additions and 1,140 deletions.
1 change: 1 addition & 0 deletions android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# Add any project specific keep options here:
-keep class com.expensify.chat.BuildConfig { *; }
-keep class com.facebook.** { *; }
-keep, allowoptimization, allowobfuscation class expo.modules.** { *; }

# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
Expand Down
3 changes: 2 additions & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ AsyncStorage_useNextStorage=true
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64

# Use this property to enable support to the new architecture.
# This will allow you to use TurboModules and the Fabric render in
# your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that
# are providing them.
newArchEnabled=false
newArchEnabled=true

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
Expand Down
8 changes: 8 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ project(':react-native-dev-menu').projectDir = new File(rootProject.projectDir,
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../node_modules/@react-native/gradle-plugin')
includeBuild('../node_modules/react-native') {
dependencySubstitution {
substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
}
}

apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle")
useExpoModules()
472 changes: 270 additions & 202 deletions ios/NewExpensify.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug Production"
buildConfiguration = "DebugProduction"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/RCTBootSplash.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@

+ (void)invalidateBootSplash;
+ (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
rootView:(RCTRootView * _Nullable)rootView;
rootView:(UIView * _Nullable)rootView;

@end
147 changes: 0 additions & 147 deletions ios/NewExpensify/RCTBootSplash.m

This file was deleted.

186 changes: 186 additions & 0 deletions ios/NewExpensify/RCTBootSplash.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#import "RCTBootSplash.h"

#import <React/RCTUtils.h>

#if RCT_NEW_ARCH_ENABLED
#import <React/RCTSurfaceHostingProxyRootView.h>
#import <React/RCTSurfaceHostingView.h>
#else
#import <React/RCTRootView.h>
#endif

static NSMutableArray<RCTPromiseResolveBlock> *_resolveQueue = nil;
static UIView *_loadingView = nil;
static UIView *_rootView = nil;
static float _duration = 0;
static bool _nativeHidden = false;
static bool _transitioning = false;

@implementation RCTBootSplash

RCT_EXPORT_MODULE();

- (dispatch_queue_t)methodQueue {
return dispatch_get_main_queue();
}

+ (void)invalidateBootSplash {
_resolveQueue = nil;
_rootView = nil;
_nativeHidden = false;
}

+ (bool)isLoadingViewHidden {
return _loadingView == nil || [_loadingView isHidden];
}

+ (bool)hasResolveQueue {
return _resolveQueue != nil;
}

+ (void)clearResolveQueue {
if (![self hasResolveQueue])
return;

while ([_resolveQueue count] > 0) {
RCTPromiseResolveBlock resolve = [_resolveQueue objectAtIndex:0];
[_resolveQueue removeObjectAtIndex:0];
resolve(@(true));
}
}

+ (void)hideLoadingView {
if ([self isLoadingViewHidden])
return [RCTBootSplash clearResolveQueue];

if (_duration > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
_transitioning = true;

if (_rootView == nil)
return;

[UIView transitionWithView:_rootView
duration:_duration / 1000.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
_loadingView.hidden = YES;
}
completion:^(__unused BOOL finished) {
[_loadingView removeFromSuperview];
_loadingView = nil;

_transitioning = false;
return [RCTBootSplash clearResolveQueue];
}];
});
} else {
_loadingView.hidden = YES;
[_loadingView removeFromSuperview];
_loadingView = nil;

return [RCTBootSplash clearResolveQueue];
}
}

+ (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
rootView:(UIView * _Nullable)rootView {
if (rootView == nil
#ifdef RCT_NEW_ARCH_ENABLED
|| ![rootView isKindOfClass:[RCTSurfaceHostingProxyRootView class]]
#else
|| ![rootView isKindOfClass:[RCTRootView class]]
#endif
|| _rootView != nil
|| [self hasResolveQueue] // hide has already been called, abort init
|| RCTRunningInAppExtension())
return;

#ifdef RCT_NEW_ARCH_ENABLED
RCTSurfaceHostingProxyRootView *proxy = (RCTSurfaceHostingProxyRootView *)rootView;
_rootView = (RCTSurfaceHostingView *)proxy.surface.view;
#else
_rootView = (RCTRootView *)rootView;
#endif

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];

_loadingView = [[storyboard instantiateInitialViewController] view];
_loadingView.hidden = NO;

[_rootView addSubview:_loadingView];

[NSTimer scheduledTimerWithTimeInterval:0.35
repeats:NO
block:^(NSTimer * _Nonnull timer) {
// wait for native iOS launch screen to fade out
_nativeHidden = true;

// hide has been called before native launch screen fade out
if ([self hasResolveQueue])
[self hideLoadingView];
}];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onJavaScriptDidLoad)
name:RCTJavaScriptDidLoadNotification
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onJavaScriptDidFailToLoad)
name:RCTJavaScriptDidFailToLoadNotification
object:nil];
}

+ (void)onJavaScriptDidLoad {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

+ (void)onJavaScriptDidFailToLoad {
[self hideLoadingView];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)hide:(double)duration
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
if (_resolveQueue == nil)
_resolveQueue = [[NSMutableArray alloc] init];

[_resolveQueue addObject:resolve];

if ([RCTBootSplash isLoadingViewHidden] || RCTRunningInAppExtension())
return [RCTBootSplash clearResolveQueue];

_duration = lroundf((float)duration);

if (_nativeHidden)
return [RCTBootSplash hideLoadingView];
}

- (void)getVisibilityStatus:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
if ([RCTBootSplash isLoadingViewHidden])
return resolve(@"hidden");
else if (_transitioning)
return resolve(@"transitioning");
else
return resolve(@"visible");
}

RCT_REMAP_METHOD(hide,
resolve:(RCTPromiseResolveBlock)resolve
rejecte:(RCTPromiseRejectBlock)reject) {
[self hide:0
resolve:resolve
reject:reject];
}

RCT_REMAP_METHOD(getVisibilityStatus,
getVisibilityStatusWithResolve:(RCTPromiseResolveBlock)resolve
rejecte:(RCTPromiseRejectBlock)reject) {
[self getVisibilityStatus:resolve
reject:reject];
}

@end
Loading

0 comments on commit d088580

Please sign in to comment.