Skip to content
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

feat: enable bridgeless #48160

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import com.expensify.chat.bootsplash.BootSplashPackage
import com.expensify.chat.shortcutManagerModule.ShortcutManagerPackage
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.modules.i18nmanager.I18nUtil
import com.facebook.soloader.SoLoader
Expand Down Expand Up @@ -44,6 +46,9 @@ class MainApplication : MultiDexApplication(), ReactApplication {
get() = BuildConfig.IS_HERMES_ENABLED
})

override val reactHost: ReactHost
get() = getDefaultReactHost(applicationContext, reactNativeHost)

override fun onCreate() {
super.onCreate()
ReactFontManager.getInstance().addCustomFont(this, "Expensify New Kansas", R.font.expensify_new_kansas)
Expand All @@ -59,7 +64,7 @@ class MainApplication : MultiDexApplication(), ReactApplication {
SoLoader.init(this, /* native exopackage */false)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load(bridgelessEnabled = false)
load()
}
if (BuildConfig.DEBUG) {
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false)
Expand Down
5 changes: 0 additions & 5 deletions ios/NewExpensify/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ - (NSURL *)bundleURL
#endif
}

- (BOOL)bridgelessEnabled
{
return NO;
}

// This methods is needed to support the hardware keyboard shortcuts
- (NSArray *)keyCommands {
return [HardwareShortcuts sharedInstance].keyCommands;
Expand Down
9 changes: 0 additions & 9 deletions ios/NewExpensify/RCTBootSplash.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
//
// RCTBootSplash.h
// NewExpensify
//
// Created by Mathieu Acthernoene on 07/01/2022.
//

#import <React/RCTBridgeModule.h>
#import <React/RCTRootView.h>

@interface RCTBootSplash : NSObject <RCTBridgeModule>

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

Expand Down
177 changes: 81 additions & 96 deletions ios/NewExpensify/RCTBootSplash.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,50 @@

#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 RCTSurfaceHostingProxyRootView *_rootView = nil;

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

@implementation RCTBootSplash

RCT_EXPORT_MODULE();

- (dispatch_queue_t)methodQueue {
return dispatch_get_main_queue();
+ (BOOL)requiresMainQueueSetup {
return NO;
}

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

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

+ (bool)hasResolveQueue {
return _resolveQueue != nil;
+ (bool)isLoadingViewVisible {
return _loadingView != nil && ![_loadingView isHidden];
}

+ (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])
+ (void)hideAndClearPromiseQueue {
if (![self isLoadingViewVisible]) {
return [RCTBootSplash clearResolveQueue];
}

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

if (_rootView == nil)
return;

[UIView transitionWithView:_rootView
duration:_duration / 1000.0
duration:0.250
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
_loadingView.hidden = YES;
Expand All @@ -70,7 +54,6 @@ + (void)hideLoadingView {
[_loadingView removeFromSuperview];
_loadingView = nil;

_transitioning = false;
return [RCTBootSplash clearResolveQueue];
}];
});
Expand All @@ -85,30 +68,9 @@ + (void)hideLoadingView {

+ (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())
if (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
Expand All @@ -117,70 +79,93 @@ + (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
_nativeHidden = true;

// hide has been called before native launch screen fade out
if ([self hasResolveQueue])
[self hideLoadingView];
if ([_resolveQueue count] > 0) {
[self hideAndClearPromiseQueue];
}
}];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onJavaScriptDidLoad)
name:RCTJavaScriptDidLoadNotification
object:nil];
if (rootView != nil) {
#ifdef RCT_NEW_ARCH_ENABLED
_rootView = (RCTSurfaceHostingProxyRootView *)rootView;
#else
_rootView = (RCTRootView *)rootView;
#endif

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onJavaScriptDidFailToLoad)
name:RCTJavaScriptDidFailToLoadNotification
object:nil];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];

_loadingView = [[storyboard instantiateInitialViewController] view];
_loadingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_loadingView.frame = _rootView.bounds;
_loadingView.center = (CGPoint){CGRectGetMidX(_rootView.bounds), CGRectGetMidY(_rootView.bounds)};
_loadingView.hidden = NO;

#if RCT_NEW_ARCH_ENABLED
[_rootView disableActivityIndicatorAutoHide:YES];
[_rootView setLoadingView:_loadingView];
#else
[_rootView addSubview:_loadingView];
#endif

[[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];
[self hideAndClearPromiseQueue];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)hide:(double)duration
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject {
if (_resolveQueue == nil)
_resolveQueue = [[NSMutableArray alloc] init];
- (NSDictionary *)constantsToExport {
UIWindow *window = RCTKeyWindow();
__block bool darkModeEnabled = false;

[_resolveQueue addObject:resolve];
RCTUnsafeExecuteOnMainQueueSync(^{
darkModeEnabled = window != nil && window.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark;
});

if ([RCTBootSplash isLoadingViewHidden] || RCTRunningInAppExtension())
return [RCTBootSplash clearResolveQueue];
return @{
@"darkModeEnabled": @(darkModeEnabled)
};
}

_duration = lroundf((float)duration);
- (void)hideImpl:(BOOL)fade
resolve:(RCTPromiseResolveBlock)resolve {
if (RCTRunningInAppExtension()) {
return resolve(@(true));
}

if (_nativeHidden)
return [RCTBootSplash hideLoadingView];
[_resolveQueue addObject:resolve];
_fade = fade;

if (_nativeHidden) {
return [RCTBootSplash hideAndClearPromiseQueue];
}
}

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

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

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

@end
50 changes: 50 additions & 0 deletions patches/@react-native-firebase+app+12.9.3+002+bridgeless.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
diff --git a/node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.m b/node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.m
index f980834..8937cdf 100644
--- a/node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.m
+++ b/node_modules/@react-native-firebase/app/ios/RNFBApp/RNFBVersion.m
@@ -15,7 +15,7 @@
*
*/

-#import "RCTVersion.h"
+#import <React/RCTVersion.h>

// generated file - do not modify or commit
NSString* const RNFBVersionString = @"12.9.3";
diff --git a/node_modules/@react-native-firebase/app/lib/internal/registry/nativeModule.js b/node_modules/@react-native-firebase/app/lib/internal/registry/nativeModule.js
index 03f001c..cf8410a 100644
--- a/node_modules/@react-native-firebase/app/lib/internal/registry/nativeModule.js
+++ b/node_modules/@react-native-firebase/app/lib/internal/registry/nativeModule.js
@@ -64,15 +64,15 @@ function nativeModuleWrapped(namespace, NativeModule, argToPrepend) {
if (!NativeModule) {
return NativeModule;
}
-
- const properties = Object.keys(NativeModule);
-
- for (let i = 0, len = properties.length; i < len; i++) {
- const property = properties[i];
- if (typeof NativeModule[property] === 'function') {
- native[property] = nativeModuleMethodWrapped(namespace, NativeModule[property], argToPrepend);
- } else {
- native[property] = NativeModule[property];
+ const moduleMethods = ["metaGetAll","jsonGetAll","preferencesSetBool","preferencesSetString","preferencesGetAll","preferencesClearAll","eventsNotifyReady","eventsGetListeners","eventsPing","eventsAddListener","eventsRemoveListener","addListener","removeListeners","initializeApp","setLogLevel","setAutomaticDataCollectionEnabled","deleteApp","getConstants","NATIVE_FIREBASE_APPS","FIREBASE_RAW_JSON","checkForUnsentReports","crash","crashWithStackPromise","deleteUnsentReports","didCrashOnPreviousExecution","log","logPromise","sendUnsentReports","setAttribute","setAttributes","setUserId","recordError","recordErrorPromise","setCrashlyticsCollectionEnabled","isErrorGenerationOnJSCrashEnabled","isCrashlyticsJavascriptExceptionHandlerChainingEnabled","isCrashlyticsCollectionEnabled","getConstants"];
+ for (let i = 0, len = moduleMethods.length; i < len; i++) {
+ const method = moduleMethods[i];
+ if (NativeModule[method]) {
+ if (typeof NativeModule[method] === 'function') {
+ native[method] = nativeModuleMethodWrapped(namespace, NativeModule[method], argToPrepend);
+ } else {
+ native[method] = NativeModule[method];
+ }
}
}

@@ -133,7 +133,6 @@ function initialiseNativeModule(module) {
}

Object.freeze(multiModuleRoot);
-
NATIVE_MODULE_REGISTRY[key] = multiModuleRoot;

return NATIVE_MODULE_REGISTRY[key];
Loading
Loading