Skip to content

Commit

Permalink
Performance improvements (#6376)
Browse files Browse the repository at this point in the history
* Replace persistedQueryStorage with MMKVPersister

* Memoize favorites

* Conditionally load boot-related modules

* Clean up AppDelegate, fix warnings

* Propagate dapps data changes to browser search

Now when the data changes, search results will always update — fixes a bug where results would occasionally be empty if data only became available after initial mount

* [Dev fix] Remove codegen changes from react-native-screen-corner-radius patch

* Remove @tanstack/query-async-storage-persister dep

* Fix userAssets memory management

The previous Map structure was resulting in all userAssets stores accessed during runtime being held permanently in memory.

On top of that, `useWalletsHiddenBalances` was repeatedly looping through all wallets on app launch, causing every userAssets store to be accessed and thus held in memory.

Now, hidden asset balances are summed any time a specific wallet's assets are synced to Zustand, and any time `setHiddenAssets` is called. That total is saved to `userAssetsStoreManager`'s persisted state, allowing all of the user's hidden wallet balances to be read from a single source, with no need to loop through individual stores.

The tradeoff here, which I think is acceptable, is that users will temporarily see their hidden balances reflected in each wallet's total balance, until that wallet next fetches assets. That seems benign enough to forgo a migration.

* Add `time` util

* Bump packages

* Add `maxAge`, increase `queryClient` throttle time, remove `ENABLE_LOGS`

* Make `isLoadingUserAssets` check more accurate

`chainBalances.size` will only be zero if `setUserAssets` has never been called for the active store.

If `setUserAssets` has been called, `chainBalances` will be populated, regardless of whether the wallet has assets.

* [Browser] Avoid JS thread Shared Value reads

The first run of any `useAnimatedStyle` or `useDerivedValue` is executed on the JS thread.

The first run can be detected by checking if `_WORKLET` is `false`, which allows bypassing expensive JS thread SV reads if you can set the hook's initial return value through other means.

These changes bypass the vast majority of JS thread SV reads throughout the browser, which reduces JS thread blocking post app launch and during browser tab creation.

* [Browser] Fix tab switch gesture activation criteria

Prevents tab switch gestures from activating when the browser search UI is open

* Clean up `hiddenAssetsBalance` calculations, types

* Fix `hiddenBalances` lookup

* [Android] Fix bottom bar handling and boot jank

- Fixes Android device height and safe area determinations, which were previously inconsistent in what was considered part of the safe area vs. part of the device height — this was causing various UI dimensions to be miscalculated, for instance browser tab heights
- Provides the `SafeAreaProvider` with `initialWindowMetrics` which on Android prevents layout shift on initial app launch
- Sets the bottom bar background to transparent when button navigation isn't being used
- Now correctly handling dimensions regardless of whether the device uses button navigation

* Reduce `useMeteorology` cache time

* Replace `SwapSheetGestureBlocker` with `DecoyScrollView`

The gesture blocking isn't needed

* Merge cleanup

* Fix Detox
  • Loading branch information
christianbaroni authored Jan 10, 2025
1 parent 91af6c1 commit d312658
Show file tree
Hide file tree
Showing 37 changed files with 505 additions and 721 deletions.
2 changes: 1 addition & 1 deletion android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<item name="colorAccent">@color/blue60</item>
</style>

<style name="BootTheme" parent="Theme.BootSplash">
<style name="BootTheme" parent="Theme.BootSplash.EdgeToEdge">
<item name="bootSplashBackground">@color/blue100</item>
<item adjustViewBounds="true" name="bootSplashLogo">@mipmap/bootsplash_logo</item>
<item name="postBootSplashTheme">@style/AppTheme</item>
Expand Down
5 changes: 3 additions & 2 deletions e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ export async function checkIfElementHasString(elementID: string | RegExp, text:
export async function relaunchApp() {
try {
await device.terminateApp('me.rainbow');
return await device.launchApp({ newInstance: true });
return await device.launchApp({ newInstance: true, launchArgs: { IS_TEST: true } });
} catch (error) {
throw new Error(`Error relaunching app: ${error}`);
}
Expand Down Expand Up @@ -493,7 +493,7 @@ export async function sendETHtoTestWallet() {
export async function openDeeplinkColdStart(url: string) {
await device.terminateApp();
await device.launchApp({
launchArgs: { detoxEnableSynchronization: 0 },
launchArgs: { detoxEnableSynchronization: 0, IS_TEST: true },
newInstance: true,
url,
});
Expand All @@ -504,6 +504,7 @@ export async function openDeeplinkFromBackground(url: string) {
await device.sendToHome();
await device.enableSynchronization();
await device.launchApp({
launchArgs: { IS_TEST: true },
newInstance: false,
url,
});
Expand Down
2 changes: 1 addition & 1 deletion e2e/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ beforeAll(async () => {
exec('yarn adb-all shell cmd overlay enable com.android.internal.systemui.navbar.threebutton');
}
await device.clearKeychain();
await device.launchApp({ newInstance: true, delete: true });
await device.launchApp({ newInstance: true, delete: true, launchArgs: { IS_TEST: true } });
await device.setURLBlacklist([
'.*api.thegraph.com.*',
'.*gateway-arbitrum.network.thegraph.com.*',
Expand Down
36 changes: 18 additions & 18 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ PODS:
- MetricsReporter (1.2.1):
- RSCrashReporter (= 1.0.1)
- RudderKit (= 1.4.0)
- MMKV (1.3.9):
- MMKVCore (~> 1.3.9)
- MMKVCore (1.3.9)
- MMKV (2.0.0):
- MMKVCore (~> 2.0.0)
- MMKVCore (2.0.0)
- mobile-wallet-protocol-host (0.1.7):
- CoinbaseWalletSDK/Host
- React-Core
Expand Down Expand Up @@ -1268,7 +1268,7 @@ PODS:
- DoubleConversion
- glog
- hermes-engine
- MMKV (>= 1.3.3)
- MMKV (>= 2.0.0)
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
Expand Down Expand Up @@ -1303,7 +1303,7 @@ PODS:
- React-Core
- react-native-screen-corner-radius (0.2.2):
- React
- react-native-skia (1.5.10):
- react-native-skia (1.8.2):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -1751,7 +1751,7 @@ PODS:
- React-Core
- RNReactNativeHapticFeedback (2.2.0):
- React-Core
- RNReanimated (3.16.3):
- RNReanimated (3.16.6):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -1771,10 +1771,10 @@ PODS:
- React-utils
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNReanimated/reanimated (= 3.16.3)
- RNReanimated/worklets (= 3.16.3)
- RNReanimated/reanimated (= 3.16.6)
- RNReanimated/worklets (= 3.16.6)
- Yoga
- RNReanimated/reanimated (3.16.3):
- RNReanimated/reanimated (3.16.6):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -1794,9 +1794,9 @@ PODS:
- React-utils
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNReanimated/reanimated/apple (= 3.16.3)
- RNReanimated/reanimated/apple (= 3.16.6)
- Yoga
- RNReanimated/reanimated/apple (3.16.3):
- RNReanimated/reanimated/apple (3.16.6):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -1817,7 +1817,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- RNReanimated/worklets (3.16.3):
- RNReanimated/worklets (3.16.6):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -2462,8 +2462,8 @@ SPEC CHECKSUMS:
hermes-engine: 1f547997900dd0752dc0cc0ae6dd16173c49e09b
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
MetricsReporter: 99596ee5003c69949ed2f50acc34aee83c42f843
MMKV: 817ba1eea17421547e01e087285606eb270a8dcb
MMKVCore: af055b00e27d88cd92fad301c5fecd1ff9b26dd9
MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801
MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390
mobile-wallet-protocol-host: 8ed897dcf4f846d39b35767540e6a695631cab73
MultiplatformBleAdapter: b1fddd0d499b96b607e00f0faa8e60648343dc1d
nanopb: 438bc412db1928dac798aa6fd75726007be04262
Expand Down Expand Up @@ -2511,7 +2511,7 @@ SPEC CHECKSUMS:
react-native-mail: a864fb211feaa5845c6c478a3266de725afdce89
react-native-menu: c30eb7a85d7b04d51945f61ea8a8986ed366ac5c
react-native-minimizer: b94809a769ac3825b46fd081d4f0ae2560791536
react-native-mmkv: 8c9a677e64a1ac89b0c6cf240feea528318b3074
react-native-mmkv: c1610488a9960dc0e5f7c264caf7667930d439de
react-native-netinfo: 5b664b2945a8f02102b296f0f812bddd6827ed9c
react-native-pager-view: 95d0418c3c74279840abec6926653d32447bafb6
react-native-palette-full: 99a6fd796d16fab6a2d3770649070e31c2602fad
Expand All @@ -2520,7 +2520,7 @@ SPEC CHECKSUMS:
react-native-restart: 733a51ad137f15b0f8dc34c4082e55af7da00979
react-native-safe-area-context: 4532f1a0c5d34a46b9324ccaaedcb5582a302b7d
react-native-screen-corner-radius: 67064efbb78f2d48f01626713ae8142f6a20f925
react-native-skia: 6e137273ac478a9c840b45ca53b7a248f9103fe2
react-native-skia: 2bae63532997971033b297348f4156d6a012cbef
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
react-native-text-input-mask: 07227297075f9653315f43b0424d596423a01736
react-native-udp: 96a517e5a121cfe69f4b05eeeafefe00c623debf
Expand Down Expand Up @@ -2574,7 +2574,7 @@ SPEC CHECKSUMS:
RNOS: 31db6fa4a197d179afbba9e6b4d28d450a7f250b
RNPermissions: 4e3714e18afe7141d000beae3755e5b5fb2f5e05
RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9
RNReanimated: e1c250aeb93d6738eaf51e3d93871873a0c41b81
RNReanimated: 5a19d7bc2fd0f1929d81301359a627d83c3684be
RNRudderSdk: 805d4b7064714f3295bf5f152d3812cc67f67a93
RNScreens: 6b641f232990a9d505a6d139fd18c3c759c9d290
RNSentry: 6a5d9f48370070c1d4697dfe74044b7f45512420
Expand All @@ -2597,7 +2597,7 @@ SPEC CHECKSUMS:
ToolTipMenu: 8ac61aded0fbc4acfe7e84a7d0c9479d15a9a382
TurboHaptics: 6381613d33ab97aeb30d9b15c3df94dc616a25e4
VisionCamera: 2af28201c3de77245f8c58b7a5274d5979df70df
Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c
Yoga: 88480008ccacea6301ff7bf58726e27a72931c8d

PODFILE CHECKSUM: 98c3fc206d7041ac7388693bb0753109d1884b57

Expand Down
4 changes: 1 addition & 3 deletions ios/Rainbow/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@

@class RCTBridge;

@interface AppDelegate : EXAppDelegateWrapper
@interface AppDelegate : EXAppDelegateWrapper <UNUserNotificationCenterDelegate>

- (void)hideSplashScreenAnimated;

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic) BOOL isRapRunning;
@property (nonatomic, strong) RCTBridge *bridge;

@end
98 changes: 43 additions & 55 deletions ios/Rainbow/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
#import "Firebase.h"
#import "AppDelegate.h"

// expo modules MUST be imported before Rainbow-Swift.h
// Expo modules must be imported before Rainbow-Swift.h
#import "ExpoModulesCore-Swift.h"
#import "Rainbow-Swift.h"
// end expo modules

#import <RNBranch/RNBranch.h>
#import <React/RCTBundleURLProvider.h>
Expand All @@ -20,7 +19,6 @@
#import <AVFoundation/AVFoundation.h>
#import <mach/mach.h>


@interface RainbowSplashScreenManager : NSObject <RCTBridgeModule>
@end

Expand All @@ -39,6 +37,7 @@ - (dispatch_queue_t)methodQueue {
@end

@implementation AppDelegate

- (void)hideSplashScreenAnimated {
UIView* subview = self.window.rootViewController.view.subviews.lastObject;
UIView* rainbowIcon = subview.subviews.firstObject;
Expand All @@ -59,44 +58,49 @@ - (void)hideSplashScreenAnimated {

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"Rainbow";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.moduleName = @"Rainbow";
// Add custom initial props in the dictionary below. These are passed to the React Native ViewController.
self.initialProps = @{};

NSLog(@"⚙️ Rainbow internals are %@.", RAINBOW_INTERNALS_ENABLED ? @"enabled" : @"disabled");

// Firebase Init

[FIRApp configure];

// Branch Init
[RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES];

// Define UNUserNotificationCenter

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRapInProgress:)
name:@"rapInProgress"
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRapInProgress:)
name:@"rapInProgress"
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRapComplete:)
name:@"rapCompleted"
object:nil];
selector:@selector(handleRapComplete:)
name:@"rapCompleted"
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRsEscape:)
name:@"rsEscape"
object:nil];
selector:@selector(handleRsEscape:)
name:@"rsEscape"
object:nil];

BOOL success = [super application:application didFinishLaunchingWithOptions:launchOptions];
BOOL isDetox = [[[NSProcessInfo processInfo] arguments] containsObject:@"-IS_TEST"];

if (isDetox) return success;

return [super application:application didFinishLaunchingWithOptions:launchOptions];
if (success) {
UIView *rootView = self.window.rootViewController.view;
[RNSplashScreen showSplash:@"LaunchScreen" inRootView:rootView];
}
return success;
}


- (void)handleRsEscape:(NSNotification *)notification {
NSDictionary* userInfo = notification.userInfo;
NSString *msg = [NSString stringWithFormat:@"Escape via %@", userInfo[@"url"]];

SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] init];
[breadcrumb setMessage:msg];
[SentrySDK addBreadcrumb:breadcrumb];
Expand Down Expand Up @@ -125,53 +129,38 @@ - (NSURL *)bundleURL
#endif
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
if (@available(iOS 14.0, *)) {
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
} else {
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNNotificationPresentationOptionAlert);
}
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
}


- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
if ([RNBranch application:application openURL:url options:options]) {
return YES;
}
return [RCTLinkingManager application:application openURL:url options:options];
}

// Only if your app is using [Universal Links]
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
[RNBranch continueUserActivity:userActivity];
return YES;

}

- (void)applicationWillTerminate:(UIApplication *)application {

if(self.isRapRunning){
if (self.isRapRunning) {
SentryMessage *msg = [[SentryMessage alloc] initWithFormatted:@"applicationWillTerminate was called"];
SentryEvent *sentryEvent = [[SentryEvent alloc] init];
[sentryEvent setMessage: msg];
[SentrySDK captureEvent:sentryEvent];
}

}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
[RNBranch application:app openURL:url options:options];
return YES;
}

- (void)applicationDidBecomeActive:(UIApplication *)application{
// delete the badge
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Reset the app icon badge
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
// delete the notifications from WC
// Clear WC notifications
[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
NSMutableArray *identifiers = [[NSMutableArray alloc] init];
[notifications enumerateObjectsUsingBlock:^(UNNotification * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
Expand All @@ -184,7 +173,6 @@ - (void)applicationDidBecomeActive:(UIApplication *)application{
}];
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:identifiers];
}];

}

@end
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@
"@rudderstack/rudder-sdk-react-native": "1.12.1",
"@sentry/react-native": "5.35.0",
"@shopify/flash-list": "1.7.2",
"@shopify/react-native-skia": "1.5.10",
"@tanstack/query-async-storage-persister": "4.2.1",
"@shopify/react-native-skia": "1.8.2",
"@tanstack/react-query": "4.2.1",
"@tanstack/react-query-persist-client": "4.2.1",
"@tradle/react-native-http": "2.0.1",
Expand Down Expand Up @@ -254,7 +253,7 @@
"react-native-quick-md5": "3.0.6",
"react-native-radial-gradient": "rainbow-me/react-native-radial-gradient#b99ab59d27dba70364ef516bd5193c37657ba95c",
"react-native-randombytes": "3.5.3",
"react-native-reanimated": "3.16.3",
"react-native-reanimated": "3.16.6",
"react-native-redash": "16.3.0",
"react-native-restart": "0.0.22",
"react-native-safe-area-context": "4.14.0",
Expand Down Expand Up @@ -306,7 +305,7 @@
"url-join": "4.0.1",
"url-parse": "1.5.10",
"use-debounce": "10.0.0",
"use-deep-compare": "1.1.0",
"use-deep-compare": "1.3.0",
"use-memo-one": "1.1.1",
"util": "0.10.4",
"viem": "2.21.54",
Expand Down
Loading

0 comments on commit d312658

Please sign in to comment.