diff --git a/android/app/src/main/java/com/helium/wallet/app/MainActivity.kt b/android/app/src/main/java/com/helium/wallet/app/MainActivity.kt index c09a64f09..e6c0cf178 100644 --- a/android/app/src/main/java/com/helium/wallet/app/MainActivity.kt +++ b/android/app/src/main/java/com/helium/wallet/app/MainActivity.kt @@ -4,6 +4,7 @@ import com.facebook.react.ReactActivity import com.facebook.react.ReactActivityDelegate import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled import com.facebook.react.defaults.DefaultReactActivityDelegate +import com.zoontek.rnbootsplash.RNBootSplash import expo.modules.ReactActivityDelegateWrapper class MainActivity : ReactActivity() { @@ -20,4 +21,9 @@ class MainActivity : ReactActivity() { */ override fun createReactActivityDelegate(): ReactActivityDelegate = ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)) -} \ No newline at end of file + + override fun onCreate(savedInstanceState: Bundle?) { + RNBootSplash.init(this, R.style.BootTheme) + super.onCreate(null) + } +} diff --git a/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png b/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png new file mode 100644 index 000000000..c84d7eaa0 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/bootsplash_logo.png differ diff --git a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png b/android/app/src/main/res/drawable-hdpi/splashscreen_image.png deleted file mode 100644 index f23de954b..000000000 Binary files a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png b/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png new file mode 100644 index 000000000..5e7b823f3 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/bootsplash_logo.png differ diff --git a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png b/android/app/src/main/res/drawable-mdpi/splashscreen_image.png deleted file mode 100644 index 144407479..000000000 Binary files a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png b/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png new file mode 100644 index 000000000..760e188ab Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/bootsplash_logo.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png deleted file mode 100644 index 923ece4b5..000000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png b/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png new file mode 100644 index 000000000..760e188ab Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/bootsplash_logo.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png deleted file mode 100644 index cbb1b5182..000000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable/splashscreen.xml b/android/app/src/main/res/drawable/splashscreen.xml deleted file mode 100644 index c8568e162..000000000 --- a/android/app/src/main/res/drawable/splashscreen.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index b33739bf4..6d47aba6b 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,4 +1,4 @@ - #000000 - #000000 - \ No newline at end of file + #0E0E0E + #00A3FF + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index fe1b3dd05..d361c6228 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,10 +1,14 @@ - + \ No newline at end of file diff --git a/assets/bootsplash/android/drawable-hdpi/bootsplash_logo.png b/assets/bootsplash/android/drawable-hdpi/bootsplash_logo.png new file mode 100644 index 000000000..2cc0e4321 Binary files /dev/null and b/assets/bootsplash/android/drawable-hdpi/bootsplash_logo.png differ diff --git a/assets/bootsplash/android/drawable-mdpi/bootsplash_logo.png b/assets/bootsplash/android/drawable-mdpi/bootsplash_logo.png new file mode 100644 index 000000000..7ba5c81cd Binary files /dev/null and b/assets/bootsplash/android/drawable-mdpi/bootsplash_logo.png differ diff --git a/assets/bootsplash/android/drawable-xhdpi/bootsplash_logo.png b/assets/bootsplash/android/drawable-xhdpi/bootsplash_logo.png new file mode 100644 index 000000000..752a19d75 Binary files /dev/null and b/assets/bootsplash/android/drawable-xhdpi/bootsplash_logo.png differ diff --git a/assets/bootsplash/android/drawable-xxhdpi/bootsplash_logo.png b/assets/bootsplash/android/drawable-xxhdpi/bootsplash_logo.png new file mode 100644 index 000000000..583623482 Binary files /dev/null and b/assets/bootsplash/android/drawable-xxhdpi/bootsplash_logo.png differ diff --git a/assets/bootsplash/android/drawable-xxxhdpi/bootsplash_logo.png b/assets/bootsplash/android/drawable-xxxhdpi/bootsplash_logo.png new file mode 100644 index 000000000..81772a27b Binary files /dev/null and b/assets/bootsplash/android/drawable-xxxhdpi/bootsplash_logo.png differ diff --git a/assets/bootsplash/ios/BootSplash.storyboard b/assets/bootsplash/ios/BootSplash.storyboard new file mode 100644 index 000000000..8547d84d3 --- /dev/null +++ b/assets/bootsplash/ios/BootSplash.storyboard @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/bootsplash/ios/Colors.xcassets/BootSplashBackground-6f9bda.colorset/Contents.json b/assets/bootsplash/ios/Colors.xcassets/BootSplashBackground-6f9bda.colorset/Contents.json new file mode 100644 index 000000000..f13e5711b --- /dev/null +++ b/assets/bootsplash/ios/Colors.xcassets/BootSplashBackground-6f9bda.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors": [ + { + "idiom": "universal", + "color": { + "color-space": "srgb", + "components": { + "blue": "1.00000000000000", + "green": "1.00000000000000", + "red": "1.00000000000000", + "alpha": "1.000" + } + } + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/Contents.json b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/Contents.json new file mode 100644 index 000000000..f5db71fa1 --- /dev/null +++ b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "logo-6f9bda.png", + "scale": "1x" + }, + { + "idiom": "universal", + "filename": "logo-6f9bda@2x.png", + "scale": "2x" + }, + { + "idiom": "universal", + "filename": "logo-6f9bda@3x.png", + "scale": "3x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda.png b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda.png new file mode 100644 index 000000000..cad5b2c6a Binary files /dev/null and b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda.png differ diff --git a/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@2x.png b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@2x.png new file mode 100644 index 000000000..8c92a3de4 Binary files /dev/null and b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@2x.png differ diff --git a/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@3x.png b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@3x.png new file mode 100644 index 000000000..34932a0c3 Binary files /dev/null and b/assets/bootsplash/ios/Images.xcassets/BootSplashLogo-6f9bda.imageset/logo-6f9bda@3x.png differ diff --git a/assets/bootsplash/logo.png b/assets/bootsplash/logo.png new file mode 100644 index 000000000..cad5b2c6a Binary files /dev/null and b/assets/bootsplash/logo.png differ diff --git a/assets/bootsplash/logo@1,5x.png b/assets/bootsplash/logo@1,5x.png new file mode 100644 index 000000000..3bc07fc3e Binary files /dev/null and b/assets/bootsplash/logo@1,5x.png differ diff --git a/assets/bootsplash/logo@2x.png b/assets/bootsplash/logo@2x.png new file mode 100644 index 000000000..8c92a3de4 Binary files /dev/null and b/assets/bootsplash/logo@2x.png differ diff --git a/assets/bootsplash/logo@3x.png b/assets/bootsplash/logo@3x.png new file mode 100644 index 000000000..34932a0c3 Binary files /dev/null and b/assets/bootsplash/logo@3x.png differ diff --git a/assets/bootsplash/logo@4x.png b/assets/bootsplash/logo@4x.png new file mode 100644 index 000000000..1a428e477 Binary files /dev/null and b/assets/bootsplash/logo@4x.png differ diff --git a/assets/bootsplash/manifest.json b/assets/bootsplash/manifest.json new file mode 100644 index 000000000..db974f314 --- /dev/null +++ b/assets/bootsplash/manifest.json @@ -0,0 +1,7 @@ +{ + "background": "#ffffff", + "logo": { + "width": 100, + "height": 100 + } +} diff --git a/ios/BootSplash.storyboard b/ios/BootSplash.storyboard new file mode 100644 index 000000000..8805e563b --- /dev/null +++ b/ios/BootSplash.storyboard @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/HeliumWallet.xcodeproj/project.pbxproj b/ios/HeliumWallet.xcodeproj/project.pbxproj index 1ca57faaf..089aa01c5 100644 --- a/ios/HeliumWallet.xcodeproj/project.pbxproj +++ b/ios/HeliumWallet.xcodeproj/project.pbxproj @@ -18,10 +18,10 @@ 7AA19242A2DE47E8AFC56882 /* Figtree-Italic-VariableFont_wght.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3440BC62530D461681D28DD7 /* Figtree-Italic-VariableFont_wght.ttf */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 9609D00027F4DE8D00CE3F93 /* RCTDateModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9609CFFF27F4DE8D00CE3F93 /* RCTDateModule.mm */; }; - 962862712BDCCAF70073839C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; - 962862722BDCCAF70073839C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; - 962862732BDCCAF70073839C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; - 962862742BDCCAF70073839C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; + 962862712BDCCAF70073839C /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + 962862722BDCCAF70073839C /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + 962862732BDCCAF70073839C /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + 962862742BDCCAF70073839C /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 96E4147327BEE4C300CE6EC1 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E4147227BEE4C300CE6EC1 /* NotificationService.swift */; }; 96E4147727BEE4C300CE6EC1 /* OneSignalNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 96E4147027BEE4C300CE6EC1 /* OneSignalNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 9D05C88528527DF0008198FC /* HeliumWalletWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D05C88428527DF0008198FC /* HeliumWalletWidgetProvider.swift */; }; @@ -45,6 +45,7 @@ 9D7DB3B82850EC15004D9409 /* HeliumWalletWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 9D7DB3B42850EC14004D9409 /* HeliumWalletWidget.intentdefinition */; }; 9D7DB3B92850EC15004D9409 /* HeliumWalletWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 9D7DB3B42850EC14004D9409 /* HeliumWalletWidget.intentdefinition */; }; 9D7DB3BC2850EC15004D9409 /* HeliumWalletWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 9D7DB3AE2850EC14004D9409 /* HeliumWalletWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 9D932A5B2D052F67002F924E /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D932A5A2D052F67002F924E /* BootSplash.storyboard */; }; 9DB500B5285D341D009C8341 /* HeliumBalanceWidgetSmallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB500B1285D341D009C8341 /* HeliumBalanceWidgetSmallView.swift */; }; 9DB500B7285D341D009C8341 /* HeliumBalanceWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB500B3285D341D009C8341 /* HeliumBalanceWidget.swift */; }; 9DB500B8285D341D009C8341 /* HeliumBalanceWidgetProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB500B4285D341D009C8341 /* HeliumBalanceWidgetProvider.swift */; }; @@ -168,6 +169,7 @@ 9D7DB3B52850EC15004D9409 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9D7DB3B72850EC15004D9409 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D8E25E5285CE4810079494A /* HeliumWalletWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HeliumWalletWidgetExtension.entitlements; sourceTree = ""; }; + 9D932A5A2D052F67002F924E /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = ../assets/bootsplash/ios/BootSplash.storyboard; sourceTree = ""; }; 9DB500B1285D341D009C8341 /* HeliumBalanceWidgetSmallView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeliumBalanceWidgetSmallView.swift; sourceTree = ""; }; 9DB500B3285D341D009C8341 /* HeliumBalanceWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeliumBalanceWidget.swift; sourceTree = ""; }; 9DB500B4285D341D009C8341 /* HeliumBalanceWidgetProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeliumBalanceWidgetProvider.swift; sourceTree = ""; }; @@ -195,7 +197,7 @@ buildActionMask = 2147483647; files = ( 9DEC730E2CAB265100DA649B /* Mapbox in Frameworks */, - 962862742BDCCAF70073839C /* BuildFile in Frameworks */, + 962862742BDCCAF70073839C /* (null) in Frameworks */, B3469F859005A4F164D08293 /* libPods-HeliumWallet-HeliumWalletTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -205,7 +207,7 @@ buildActionMask = 2147483647; files = ( 9DEC730B2CAB265100DA649B /* Mapbox in Frameworks */, - 962862712BDCCAF70073839C /* BuildFile in Frameworks */, + 962862712BDCCAF70073839C /* (null) in Frameworks */, 31B6D29CFC726A9C37946D71 /* libPods-HeliumWallet.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -215,7 +217,7 @@ buildActionMask = 2147483647; files = ( 9DEC730C2CAB265100DA649B /* Mapbox in Frameworks */, - 962862722BDCCAF70073839C /* BuildFile in Frameworks */, + 962862722BDCCAF70073839C /* (null) in Frameworks */, C4EB4BD0A9AAABC0002181CC /* libPods-OneSignalNotificationServiceExtension.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -225,7 +227,7 @@ buildActionMask = 2147483647; files = ( 9DEC730D2CAB265100DA649B /* Mapbox in Frameworks */, - 962862732BDCCAF70073839C /* BuildFile in Frameworks */, + 962862732BDCCAF70073839C /* (null) in Frameworks */, 9D7DB3B02850EC14004D9409 /* SwiftUI.framework in Frameworks */, 9D7DB3AF2850EC14004D9409 /* WidgetKit.framework in Frameworks */, 9DCA365F28E6781D000F2A66 /* Charts in Frameworks */, @@ -263,6 +265,7 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 9D932A5A2D052F67002F924E /* BootSplash.storyboard */, 13B07FB71A68108700A75B9A /* main.mm */, 508E6F6B26FA22F400774B67 /* HeliumWallet-Bridging-Header.h */, 9609CFFE27F4DE6200CE3F93 /* RCTDateModule.h */, @@ -634,6 +637,7 @@ 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, AB02F1297F7F91A0FD2532BD /* PrivacyInfo.xcprivacy in Resources */, + 9D932A5B2D052F67002F924E /* BootSplash.storyboard in Resources */, 7AA19242A2DE47E8AFC56882 /* Figtree-Italic-VariableFont_wght.ttf in Resources */, 117516811AB44418A8ACF34F /* Figtree-VariableFont_wght.ttf in Resources */, ); @@ -1200,10 +1204,7 @@ ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -1264,10 +1265,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/ios/HeliumWallet/AppDelegate.mm b/ios/HeliumWallet/AppDelegate.mm index 22576f039..c13810026 100644 --- a/ios/HeliumWallet/AppDelegate.mm +++ b/ios/HeliumWallet/AppDelegate.mm @@ -2,6 +2,7 @@ #import #import +#import "RNBootSplash.h" @implementation AppDelegate @@ -40,6 +41,11 @@ - (BOOL)application:(UIApplication *)application return [RCTLinkingManager application:application openURL:url options:options]; } +- (void)customizeRootView:(RCTRootView *)rootView { + [super customizeRootView:rootView]; + [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; // ⬅️ initialize the splash screen +} + - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { diff --git a/ios/HeliumWallet/Images.xcassets/Contents.json b/ios/HeliumWallet/Images.xcassets/Contents.json index 74d6a722c..73c00596a 100644 --- a/ios/HeliumWallet/Images.xcassets/Contents.json +++ b/ios/HeliumWallet/Images.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info": { - "author": "xcode", - "version": 1 + "info" : { + "author" : "xcode", + "version" : 1 } } diff --git a/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/Contents.json b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/Contents.json new file mode 100644 index 000000000..a8927aa86 --- /dev/null +++ b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "bootsplash_logo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "bootsplash_logo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "bootsplash_logo@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo.png b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo.png new file mode 100644 index 000000000..c84d7eaa0 Binary files /dev/null and b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo.png differ diff --git a/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@2x.png b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@2x.png new file mode 100644 index 000000000..5e7b823f3 Binary files /dev/null and b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@2x.png differ diff --git a/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@3x.png b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@3x.png new file mode 100644 index 000000000..760e188ab Binary files /dev/null and b/ios/HeliumWallet/Images.xcassets/bootsplash_logo.imageset/bootsplash_logo@3x.png differ diff --git a/ios/HeliumWallet/Info.plist b/ios/HeliumWallet/Info.plist index 99d6bd42d..7d8cce33b 100644 --- a/ios/HeliumWallet/Info.plist +++ b/ios/HeliumWallet/Info.plist @@ -86,7 +86,7 @@ remote-notification UILaunchStoryboardName - LaunchScreen + BootSplash.storyboard UIRequiredDeviceCapabilities arm64 diff --git a/ios/HeliumWallet/LaunchScreen.storyboard b/ios/HeliumWallet/LaunchScreen.storyboard index 4450c8b37..c9d5f4476 100644 --- a/ios/HeliumWallet/LaunchScreen.storyboard +++ b/ios/HeliumWallet/LaunchScreen.storyboard @@ -1,28 +1,18 @@ - + - - + - - - - - - - + - - - diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4a38b3db0..55931b9fe 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -67,28 +67,6 @@ PODS: - Yoga - ExpoSecureStore (13.0.2): - ExpoModulesCore - - EXSplashScreen (0.27.5): - - DoubleConversion - - ExpoModulesCore - - glog - - hermes-engine - - RCT-Folly (= 2024.01.01.00) - - RCTRequired - - RCTTypeSafety - - React-Codegen - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - FBLazyVector (0.74.5) - fmt (9.1.0) - glog (0.3.5) @@ -1138,6 +1116,29 @@ PODS: - react-native-simple-toast (1.1.4): - React-Core - Toast (~> 4.0.0) + - react-native-skia (1.5.10): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React + - React-callinvoker + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - react-native-slider (4.5.2): - DoubleConversion - glog @@ -1418,6 +1419,8 @@ PODS: - React-logger (= 0.74.5) - React-perflogger (= 0.74.5) - React-utils (= 0.74.5) + - RNBootSplash (6.3.2): + - React-Core - RNCAsyncStorage (1.18.1): - React-Core - RNCCheckbox (0.5.17): @@ -1578,7 +1581,6 @@ DEPENDENCIES: - ExpoLocalAuthentication (from `../node_modules/expo-local-authentication/ios`) - ExpoModulesCore (from `../node_modules/expo-modules-core`) - ExpoSecureStore (from `../node_modules/expo-secure-store/ios`) - - EXSplashScreen (from `../node_modules/expo-splash-screen/ios`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) @@ -1628,6 +1630,7 @@ DEPENDENCIES: - react-native-randombytes (from `../node_modules/react-native-randombytes`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - react-native-simple-toast (from `../node_modules/react-native-simple-toast`) + - "react-native-skia (from `../node_modules/@shopify/react-native-skia`)" - "react-native-slider (from `../node_modules/@react-native-community/slider`)" - react-native-sodium (from `../node_modules/react-native-sodium`) - react-native-udp (from `../node_modules/react-native-udp`) @@ -1656,6 +1659,7 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - RNBootSplash (from `../node_modules/react-native-bootsplash`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)" - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" @@ -1731,8 +1735,6 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-modules-core" ExpoSecureStore: :path: "../node_modules/expo-secure-store/ios" - EXSplashScreen: - :path: "../node_modules/expo-splash-screen/ios" FBLazyVector: :path: "../node_modules/react-native/Libraries/FBLazyVector" fmt: @@ -1824,6 +1826,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-safe-area-context" react-native-simple-toast: :path: "../node_modules/react-native-simple-toast" + react-native-skia: + :path: "../node_modules/@shopify/react-native-skia" react-native-slider: :path: "../node_modules/@react-native-community/slider" react-native-sodium: @@ -1880,6 +1884,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/utils" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNBootSplash: + :path: "../node_modules/react-native-bootsplash" RNCAsyncStorage: :path: "../node_modules/@react-native-async-storage/async-storage" RNCCheckbox: @@ -1943,7 +1949,6 @@ SPEC CHECKSUMS: ExpoLocalAuthentication: 9e02a56a4cf9868f0052656a93d4c94101a42ed7 ExpoModulesCore: 5440e96a8ee014f4fd88e77264985fd0a65f5f8c ExpoSecureStore: 060cebcb956b80ddae09821610ac1aa9e1ac74cd - EXSplashScreen: fbf0ec78e9cee911df188bf17b4fe51d15a84b87 FBLazyVector: ac12dc084d1c8ec4cc4d7b3cf1b0ebda6dab85af fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f @@ -1994,6 +1999,7 @@ SPEC CHECKSUMS: react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846 react-native-safe-area-context: b7daa1a8df36095a032dff095a1ea8963cb48371 react-native-simple-toast: 8ee5d23f0b92b935ab7434cdb65159ce12dfb4b7 + react-native-skia: 6e137273ac478a9c840b45ca53b7a248f9103fe2 react-native-slider: ce295d2bf830a7990af05b0bd70ab28c133e230c react-native-sodium: 274874541aa6bd00040f28c2e1e5118cbf113c0e react-native-udp: ff9d13e523f2b58e6bc5d4d32321ac60671b5dc9 @@ -2022,6 +2028,7 @@ SPEC CHECKSUMS: React-runtimescheduler: cfbe85c3510c541ec6dc815c7729b41304b67961 React-utils: f242eb7e7889419d979ca0e1c02ccc0ea6e43b29 ReactCommon: f7da14a8827b72704169a48c929bcde802698361 + RNBootSplash: 3a44c2c3ebfce98254de887ceed22c4941c8c6c5 RNCAsyncStorage: b90b71f45b8b97be43bc4284e71a6af48ac9f547 RNCCheckbox: a3ca9978cb0846b981d28da4e9914bd437403d77 RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 diff --git a/package.json b/package.json index 14848b8f4..54f4df8ae 100644 --- a/package.json +++ b/package.json @@ -68,10 +68,10 @@ "@helium/wallet-link": "4.11.0", "@jup-ag/api": "^6.0.6", "@keystonehq/keystone-sdk": "^0.8.0", - "@ledgerhq/hw-app-solana": "7.0.13", - "@ledgerhq/react-native-hid": "6.30.0", - "@ledgerhq/react-native-hw-transport-ble": "6.29.5", - "@ledgerhq/types-devices": "^6.22.4", + "@ledgerhq/hw-app-solana": "7.2.4", + "@ledgerhq/react-native-hid": "6.32.4", + "@ledgerhq/react-native-hw-transport-ble": "6.29.4", + "@ledgerhq/types-devices": "^6.25.3", "@metaplex-foundation/js": "^0.19.5", "@metaplex-foundation/mpl-bubblegum": "0.6.0", "@metaplex-foundation/mpl-token-metadata": "2.10.0", @@ -93,6 +93,7 @@ "@react-navigation/stack": "6.2.2", "@reduxjs/toolkit": "1.9.1", "@rnmapbox/maps": "^10.1.31", + "@shopify/react-native-skia": "^1.5.10", "@shopify/restyle": "2.4.2", "@solana/spl-account-compression": "0.1.4", "@solana/spl-memo": "0.2.3", @@ -143,7 +144,6 @@ "expo-local-authentication": "14.0.1", "expo-location": "^17.0.1", "expo-secure-store": "13.0.2", - "expo-splash-screen": "0.27.5", "fuse.js": "6.6.2", "geolib": "^3.3.4", "h3-js": "4.1.0", @@ -170,6 +170,7 @@ "react-native-animated-numbers": "^0.6.2", "react-native-appstate-hook": "1.0.6", "react-native-ble-plx": "2.0.3", + "react-native-bootsplash": "^6.3.2", "react-native-charts-wrapper": "0.5.10", "react-native-compass-heading": "^1.5.0", "react-native-confetti-cannon": "^1.5.2", diff --git a/public/index.html b/public/index.html new file mode 100644 index 000000000..534a1cfb8 --- /dev/null +++ b/public/index.html @@ -0,0 +1,55 @@ + + + + + + + %WEB_TITLE% + + + + + + + + +
+
+ +
+ + diff --git a/src/app/App.tsx b/src/app/App.tsx index 5e3bd0983..79295a120 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -9,11 +9,9 @@ import TokensProvider from '@config/storage/TokensProvider' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import globalStyles from '@config/theme/globalStyles' import { darkTheme } from '@config/theme/theme' -import * as SplashLib from 'expo-splash-screen' -import React, { useMemo } from 'react' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import Mapbox from '@rnmapbox/maps' import { LogBox, Platform, StatusBar, UIManager } from 'react-native' -import useAppState from 'react-native-appstate-hook' import Config from 'react-native-config' import { GestureHandlerRootView } from 'react-native-gesture-handler' import { OneSignal } from 'react-native-onesignal' @@ -27,21 +25,16 @@ import { useNotificationStorage } from '@config/storage/NotificationStorageProvi import { BalanceProvider } from '@utils/Balance' import { useDeepLinking } from '@utils/linking' import KeystoneOnboardingProvider from '@features/keystone/KeystoneOnboardingProvider' -import SplashScreen from '../components/SplashScreen' +import BootSplash from 'react-native-bootsplash' import WalletConnectProvider from '../features/dappLogin/WalletConnectProvider' import LockScreen from '../features/lock/LockScreen' import InsufficientSolConversionModal from '../features/modals/InsufficientSolConversionModal' import WalletOnboardingProvider from '../features/onboarding/OnboardingProvider' -import SecurityScreen from '../features/security/SecurityScreen' import useMount from '../hooks/useMount' import { navigationRef } from './NavigationHelper' import RootNavigator from './RootNavigator' import '../polyfill' -SplashLib.preventAutoHideAsync().catch(() => { - /* reloading the app might trigger some race conditions, ignore them */ -}) - const App = () => { // Note that the Android SDK is slightly peculiar // in that it requires setting an access token, @@ -66,9 +59,10 @@ const App = () => { 'VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.', ]) - const { appState } = useAppState() const { restored: accountsRestored } = useAccountStorage() const { setOpenedNotification } = useNotificationStorage() + const [navReady, setNavReady] = useState(false) + const splashHidden = useRef(false) const linking = useDeepLinking() @@ -76,6 +70,21 @@ const App = () => { return darkTheme }, []) + const onReady = useCallback(async () => { + setNavReady(true) + }, []) + + useEffect(() => { + if (splashHidden.current) { + return + } + + if (navReady) { + splashHidden.current = true + BootSplash.hide({ fade: true }) + } + }, [navReady, splashHidden]) + if (Platform.OS === 'android') { if (UIManager.setLayoutAnimationEnabledExperimental) { UIManager.setLayoutAnimationEnabledExperimental(true) @@ -125,53 +134,44 @@ const App = () => { - - - - - - - {accountsRestored && ( - <> - - - - - - - - + + + + + + {accountsRestored && ( + <> + + + + + + + + - {/* place app specific modals here */} - - - - - - - - - - )} - - - - - - + {/* place app specific modals here */} + + + + + + + + + )} + + + + + diff --git a/src/app/NavigationHelper.ts b/src/app/NavigationHelper.ts index e887d1886..56964fce2 100644 --- a/src/app/NavigationHelper.ts +++ b/src/app/NavigationHelper.ts @@ -1,5 +1,5 @@ import { createNavigationContainerRef } from '@react-navigation/native' -import { AccountsServiceStackParamList } from 'src/app/services/AccountsService' +import { AccountsServiceStackParamList } from 'src/app/services/AccountsService/pages/YourWalletsPage' import { RootStackParamList } from './rootTypes' export const navigationRef = createNavigationContainerRef() @@ -8,5 +8,6 @@ export const navToImportAccount = ( params: AccountsServiceStackParamList['ReImportAccountNavigator'], ) => { if (!navigationRef.isReady()) return + // eslint-disable-next-line @typescript-eslint/no-explicit-any navigationRef.navigate('ReImportAccountNavigator' as any, params as any) } diff --git a/src/app/RootNavigator.tsx b/src/app/RootNavigator.tsx index 1535cdc85..ebc059786 100644 --- a/src/app/RootNavigator.tsx +++ b/src/app/RootNavigator.tsx @@ -15,7 +15,8 @@ import ImportPrivateKey from '@features/onboarding/import/ImportPrivateKey' import PaymentScreen from '@features/payment/PaymentScreen' import LinkWallet from '@features/txnDelegation/LinkWallet' import SignHotspot from '@features/txnDelegation/SignHotspot' -import { RootStackParamList } from './rootTypes' +import { useNavigation } from '@react-navigation/native' +import { RootNavigationProp, RootStackParamList } from './rootTypes' const screenOptions = { headerShown: false } as StackNavigationOptions @@ -23,6 +24,7 @@ const RootNavigator = () => { const { currentAccount } = useAccountStorage() const colors = useColors() const RootStack = createStackNavigator() + const rootNav = useNavigation() useEffect(() => { if (currentAccount) { @@ -36,6 +38,18 @@ const RootNavigator = () => { return currentAccount ? 'ServiceSheetNavigator' : 'OnboardingNavigator' }, [currentAccount]) + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const firstRoute = (rootNav as any).getRootState().routes[0].key || '' + if (currentAccount && firstRoute.includes('OnboardingNavigator')) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(rootNav as any).reset({ + index: 0, + routes: [{ name: 'ServiceSheetNavigator' }], + }) + } + }, [currentAccount, initialRouteName, rootNav]) + return ( +export type YourWalletsServiceNavigationProp = + StackNavigationProp -const AccountsServiceStack = - createStackNavigator() +const YourWalletsService = () => { + const options = useMemo((): Array => { + return [ + { name: 'YourWalletsPage', Icon: Wallet, component: YourWalletsPage }, + { + name: 'CreateSeedPhrasePage', + Icon: Add, + component: CreateSeedPhrasePage, + }, + { + name: 'AddExistingWalletPage', + Icon: AddExistingWallet, + component: AddExistingWalletPage, + }, + { + name: 'PairLedgerPage', + Icon: Ledger, + IconActive: LedgerSelected, + component: PairLedgerPage, + }, + { + name: 'ConnectKeystonePage', + Icon: Keystone, + IconActive: KeystoneSelected, + component: ConnectKeystonePage, + }, + ] + }, []) -const AccountsService = () => { - const colors = useColors() - const screenOptions: StackNavigationOptions = useMemo( - () => ({ - headerShown: false, - animationEnabled: false, - cardStyle: { backgroundColor: colors.primaryBackground }, - }), - [colors], - ) - return ( - - - - - - - - ) + return } -export default AccountsService +export default YourWalletsService diff --git a/src/app/services/AccountsService/pages/AddExistingWalletPage.tsx b/src/app/services/AccountsService/pages/AddExistingWalletPage.tsx new file mode 100644 index 000000000..40d146e2f --- /dev/null +++ b/src/app/services/AccountsService/pages/AddExistingWalletPage.tsx @@ -0,0 +1,186 @@ +import Box from '@components/Box' +import ScrollBox from '@components/ScrollBox' +import { NavBarHeight } from '@components/ServiceNavBar' +import { useSpacing, useColors } from '@config/theme/themeHooks' +import Text from '@components/Text' +import React, { useCallback, useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { StyleProp, ViewStyle } from 'react-native' +import SecretPhrase from '@assets/svgs/secretPhrase.svg' +import PrivateKey from '@assets/svgs/privateKey.svg' +import CarotRight from '@assets/svgs/carot-right.svg' +import CommandLine from '@assets/svgs/commandLine.svg' +import TouchableContainer from '@components/TouchableContainer' +import { + createStackNavigator, + StackNavigationOptions, + StackNavigationProp, +} from '@react-navigation/stack' +import { useTheme } from '@shopify/restyle' +import ImportAccountNavigator from '@features/onboarding/import/ImportAccountNavigator' +import { + OnboardingSheetRef, + FlowType, + OnboardingSheetWrapper, +} from '@features/onboarding/OnboardingSheet' + +const AddExistingWalletPage = () => { + const { t } = useTranslation() + const spacing = useSpacing() + const colors = useColors() + const { bottom } = useSafeAreaInsets() + const onboardingSheetRef = useRef(null) + + const onAddExistingWallet = useCallback( + (flowType: FlowType) => () => { + onboardingSheetRef.current?.show(flowType) + }, + [onboardingSheetRef], + ) + + const contentContainerStyle = useMemo( + () => ({ + paddingHorizontal: spacing['2xl'], + flex: 1, + justifyContent: 'center', + gap: spacing.xl, + paddingBottom: bottom + spacing['2xl'] + NavBarHeight, + }), + [spacing, bottom], + ) + + return ( + } + > + + {t('AddExistingWalletPage.title')} + + + {t('AddExistingWalletPage.subtitle')} + + + + + + + {t('AddExistingWalletPage.secretPhrase')} + + + {t('AddExistingWalletPage.twelveOrTwentyFourWords')} + + + + + + + + + {t('AddExistingWalletPage.privateKey')} + + + {t('AddExistingWalletPage.aStringOfCharacters')} + + + + + + + + + {t('AddExistingWalletPage.commandLine')} + + + {t('AddExistingWalletPage.scanCli')} + + + + + + + + ) +} + +export type AddExistingWalletStackParamList = { + AddExistingWalletPage: undefined + ImportAccount: + | undefined + | { + screen: 'AccountImportScreen' + params: { + restoringAccount?: boolean + accountAddress?: string + } + } +} + +export type AddExistingWalletNavigationProp = + StackNavigationProp + +const AddExistingWalletStack = + createStackNavigator() + +const AddExistingWalletNavigator = () => { + const { colors } = useTheme() + const screenOptions = useMemo( + () => + ({ + headerShown: false, + cardStyle: { + backgroundColor: colors.primaryBackground, + }, + } as StackNavigationOptions), + [colors], + ) + return ( + + + + + ) +} + +export default AddExistingWalletNavigator diff --git a/src/app/services/AccountsService/pages/ConnectKeystonePage.tsx b/src/app/services/AccountsService/pages/ConnectKeystonePage.tsx new file mode 100644 index 000000000..5027d6187 --- /dev/null +++ b/src/app/services/AccountsService/pages/ConnectKeystonePage.tsx @@ -0,0 +1,72 @@ +import ButtonPressable from '@components/ButtonPressable' +import ImageBox from '@components/ImageBox' +import ScrollBox from '@components/ScrollBox' +import Text from '@components/Text' +import { useColors, useSpacing } from '@config/theme/themeHooks' +import React, { useCallback, useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import Scan from '@assets/svgs/scan.svg' +import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { NavBarHeight } from '@components/ServiceNavBar' +import { StyleProp, ViewStyle } from 'react-native' +import { + OnboardingSheetRef, + OnboardingSheetWrapper, +} from '@features/onboarding/OnboardingSheet' + +const ConnectKeystonePage = () => { + const { t } = useTranslation() + const spacing = useSpacing() + const colors = useColors() + const { bottom } = useSafeAreaInsets() + const onboardingSheetRef = useRef(null) + const contentContainerStyle = useMemo( + () => ({ + paddingHorizontal: spacing['2xl'], + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingBottom: bottom + spacing['2xl'] + NavBarHeight, + }), + [spacing, bottom], + ) + + const openOnboarding = useCallback(() => { + onboardingSheetRef.current?.show('keystone') + }, [onboardingSheetRef]) + + return ( + } + > + + + {t('ConnectKeystonePage.title')} + + + {t('ConnectKeystonePage.subtitle')} + + + } + onPress={openOnboarding} + /> + + + ) +} + +export default ConnectKeystonePage diff --git a/src/app/services/AccountsService/pages/CreateSeedPhrasePage.tsx b/src/app/services/AccountsService/pages/CreateSeedPhrasePage.tsx new file mode 100644 index 000000000..4b6251109 --- /dev/null +++ b/src/app/services/AccountsService/pages/CreateSeedPhrasePage.tsx @@ -0,0 +1,82 @@ +import Box from '@components/Box' +import ButtonPressable from '@components/ButtonPressable' +import ImageBox from '@components/ImageBox' +import ScrollBox from '@components/ScrollBox' +import Text from '@components/Text' +import { useColors, useSpacing } from '@config/theme/themeHooks' +import React, { useCallback, useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import { StyleProp, ViewStyle } from 'react-native' +import Add from '@assets/svgs/add.svg' +import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { NavBarHeight } from '@components/ServiceNavBar' +import { + OnboardingSheetRef, + OnboardingSheetWrapper, +} from '@features/onboarding/OnboardingSheet' + +const CreateSeedPhrasePage = () => { + const { t } = useTranslation() + const spacing = useSpacing() + const colors = useColors() + const { bottom } = useSafeAreaInsets() + const onboardingSheetRef = useRef(null) + + const contentContainerStyle = useMemo( + () => ({ + paddingHorizontal: spacing['2xl'], + flex: 1, + justifyContent: 'center', + alignItems: 'center', + gap: spacing.xl, + paddingBottom: bottom + spacing['2xl'] + NavBarHeight, + }), + [spacing, bottom], + ) + + const showBottomSheet = useCallback(() => { + onboardingSheetRef.current?.show('create-account') + }, [onboardingSheetRef]) + + return ( + } + > + + + {t('CreateSeedPhrasePage.title')} + + + {t('CreateSeedPhrasePage.subtitle')} + + + + {t('CreateSeedPhrasePage.disclaimer')} + + + + + } + onPress={showBottomSheet} + /> + + + ) +} + +export default CreateSeedPhrasePage diff --git a/src/app/services/AccountsService/pages/PairLedgerPage.tsx b/src/app/services/AccountsService/pages/PairLedgerPage.tsx new file mode 100644 index 000000000..1b1b8c921 --- /dev/null +++ b/src/app/services/AccountsService/pages/PairLedgerPage.tsx @@ -0,0 +1,77 @@ +import ButtonPressable from '@components/ButtonPressable' +import ImageBox from '@components/ImageBox' +import ScrollBox from '@components/ScrollBox' +import Text from '@components/Text' +import { useColors, useSpacing } from '@config/theme/themeHooks' +import React, { useCallback, useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import Bluetooth from '@assets/svgs/bluetooth.svg' +import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { NavBarHeight } from '@components/ServiceNavBar' +import { StyleProp, ViewStyle } from 'react-native' +import { + OnboardingSheetRef, + OnboardingSheetWrapper, +} from '@features/onboarding/OnboardingSheet' + +const PairLedgerPage = () => { + const { t } = useTranslation() + const spacing = useSpacing() + const colors = useColors() + const onboardingSheetRef = useRef(null) + const { bottom } = useSafeAreaInsets() + + const contentContainerStyle = useMemo( + () => ({ + paddingHorizontal: spacing['2xl'], + flex: 1, + justifyContent: 'center', + alignItems: 'center', + paddingBottom: bottom + spacing['2xl'] + NavBarHeight, + }), + [spacing, bottom], + ) + + const openOnboardingSheet = useCallback(() => { + onboardingSheetRef.current?.show('ledger') + }, [onboardingSheetRef]) + + return ( + } + > + + + {t('PairLedgerPage.title')} + + + {t('PairLedgerPage.subtitle')} + + + } + onPress={openOnboardingSheet} + /> + + + ) +} + +export default PairLedgerPage diff --git a/src/app/services/AccountsService/pages/YourWalletsPage.tsx b/src/app/services/AccountsService/pages/YourWalletsPage.tsx index 395af534b..f2e4f9b93 100644 --- a/src/app/services/AccountsService/pages/YourWalletsPage.tsx +++ b/src/app/services/AccountsService/pages/YourWalletsPage.tsx @@ -1,418 +1,74 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react' -import Text from '@components/Text' -import { useTranslation } from 'react-i18next' -import { ReAnimatedBox } from '@components/AnimatedBox' -import { FadeIn } from 'react-native-reanimated' -import Box from '@components/Box' -import { Image, SectionList } from 'react-native' -import { useAccountStorage } from '@config/storage/AccountStorageProvider' -import { NetTypes } from '@helium/address' -import { CSAccount } from '@config/storage/cloudStorage' -import TouchableContainer from '@components/TouchableContainer' -import AccountIcon from '@components/AccountIcon' -import { ellipsizeAddress } from '@utils/accountUtils' -import { useColors, useSpacing } from '@config/theme/themeHooks' -import SmallAdd from '@assets/svgs/smallAdd.svg' -import BigAdd from '@assets/svgs/bigAdd.svg' -import Checkmark from '@assets/svgs/checkmark.svg' -import { useNavigation } from '@react-navigation/native' +import React, { useMemo } from 'react' import { - HELIUM_DERIVATION, - keypairFromSeed, - solanaDerivation, -} from '@hooks/useDerivationAccounts' -import { getSecureAccount } from '@config/storage/secureStorage' -import * as bip39 from 'bip39' -import { useOnboarding } from '@features/onboarding/OnboardingProvider' -import Toast from 'react-native-simple-toast' -import { useSafeAreaInsets } from 'react-native-safe-area-context' -import TouchableOpacityBox from '@components/TouchableOpacityBox' -import useLayoutHeight from '@hooks/useLayoutHeight' -import { ServiceSheetNavigationProp } from 'src/app/services/serviceSheetTypes' -import CircleLoader from '@components/CircleLoader' -import ScrollBox from '@components/ScrollBox' -import { AccountsServiceNavigationProp } from '../accountServiceTypes' - -const YourWalletsPage = () => { - const { t } = useTranslation() - const [addingSubAccount, setAddingSubAccount] = useState(false) - const [switchingAccounts, setSwitchingAccounts] = useState< - CSAccount | undefined - >() - const spacing = useSpacing() - const { setOnboardingData, onboardingData } = useOnboarding() - const colors = useColors() - const navigation = useNavigation< - AccountsServiceNavigationProp & ServiceSheetNavigationProp - >() - const { sortedAccounts, currentAccount, setCurrentAccount, accounts } = - useAccountStorage() - const { bottom } = useSafeAreaInsets() - const [footerHeight, setFooterHeight] = useLayoutHeight() - - const handleAddSub = useCallback( - async (acc: CSAccount) => { - setAddingSubAccount(true) - try { - if (!currentAccount) { - throw new Error('No current account') - } - const storage = await getSecureAccount(currentAccount.address) - const seed = bip39.mnemonicToSeedSync( - storage?.mnemonic?.join(' ') || '', - '', - ) - - if (!seed || !acc?.derivationPath) { - throw new Error('Missing seed or derivation path') + StackNavigationOptions, + StackNavigationProp, + createStackNavigator, +} from '@react-navigation/stack' +import { useColors } from '@config/theme/themeHooks' +import AddNewAccountNavigator from '@features/home/addNewAccount/AddNewAccountNavigator' +import AccountAssignScreen from '@features/onboarding/AccountAssignScreen' +import { RouteAccount } from '@features/onboarding/create/createAccountNavTypes' +import ImportAccountNavigator from '@features/onboarding/import/ImportAccountNavigator' +import KeystoneNavigator from '@features/keystone/KeystoneNavigator' +import WalletList from '@features/accounts/WalletList' + +export type AccountsServiceStackParamList = { + WalletList: undefined + AddNewAccountNavigator: undefined + AccountAssignScreen: undefined | RouteAccount + ReImportAccountNavigator: + | undefined + | { + screen: 'AccountImportScreen' + params: { + restoringAccount?: boolean + accountAddress?: string } - const currentPath = acc.derivationPath - const takenAddresses = new Set( - Object.values(accounts || {}).map((a) => a.solanaAddress), - ) - let currentAccountNum = - currentPath === HELIUM_DERIVATION - ? 0 - : Number(currentPath.split('/')[3].replace("'", '')) + 1 - let derivationPath = solanaDerivation(currentAccountNum, 0) - let keypair = await keypairFromSeed(seed, derivationPath) - while ( - currentAccountNum < 100 && - (!keypair || takenAddresses.has(keypair.publicKey.toBase58())) - ) { - currentAccountNum += 1 - derivationPath = solanaDerivation(currentAccountNum, 0) - keypair = await keypairFromSeed(seed, derivationPath) - } - if (currentAccountNum >= 100) { - throw new Error('More than 100 accounts are not supported') - } - if (keypair) { - const words = (await getSecureAccount(acc.address))?.mnemonic - setOnboardingData({ - ...onboardingData, - words, - paths: [ - { - derivationPath, - keypair, - }, - ], - }) - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - navigation.navigate('AccountAssignScreen', { - words, - }) - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - } catch (e: any) { - Toast.show(e.message || e.toString()) - } finally { - setAddingSubAccount(false) } - }, - [accounts, currentAccount, navigation, onboardingData, setOnboardingData], - ) - - const filteredAccounts = useMemo(() => { - const grouped = sortedAccounts - .filter((a) => a.netType !== NetTypes.TESTNET) - .reduce((acc, account) => { - acc[account.mnemonicHash || 'none'] = [ - ...(acc[account.mnemonicHash || 'none'] || []), - account, - ] - return acc - }, {} as { [key: string]: CSAccount[] }) - - const { none, ...rest } = grouped - const ret = Object.values(rest).map((accs, index) => ({ - title: `Seed Phrase ${index + 1}`, - data: accs, - })) - if (none) { - ret.push({ - title: 'Private Keys', - data: none, - }) + KeystoneNavigator: { + screen: 'KeystoneNavigator' + params: { + screen: string } + } +} - return ret - }, [sortedAccounts]) - - const Header = useCallback(() => { - return ( - - - - {t('accountsService.title')} - - - ) - }, [t]) - - const keyExtractor = useCallback((item) => item.address, []) - - const handleAccountChange = useCallback( - (item: CSAccount) => () => { - setSwitchingAccounts(item) - }, - [setSwitchingAccounts], - ) - - useEffect(() => { - if (!switchingAccounts) return - - // Need to wait for a UI tick to allow the animation to finish - setTimeout(() => { - setCurrentAccount(switchingAccounts) - navigation.replace('WalletService') - }, 0) - }, [switchingAccounts, setCurrentAccount, navigation]) - - const renderItem = useCallback( - ({ - item, - index, - section, - }: { - // eslint-disable-next-line react/no-unused-prop-types - index: number - // eslint-disable-next-line react/no-unused-prop-types - item: CSAccount - // eslint-disable-next-line react/no-unused-prop-types - section: { - title: string - data: CSAccount[] - } - }) => { - const { data } = section - - const isSelected = item.address === currentAccount?.address - const showBottomBorder = - (data[index] && - data[index].mnemonicHash !== currentAccount?.mnemonicHash) || - section.title === 'Private Keys' - const isLast = index === data.length - 1 - const accountAddress = item?.solanaAddress - const borderTopStartRadius = index === 0 ? '2xl' : undefined - const borderTopEndRadius = index === 0 ? '2xl' : undefined - const borderBottomStartRadius = - index === data.length - 1 && showBottomBorder ? '2xl' : undefined - const borderBottomEndRadius = - index === data.length - 1 && showBottomBorder ? '2xl' : undefined - - return ( - - - - - {item.alias} - - - {ellipsizeAddress(accountAddress || '', { - numChars: 4, - })} - - - {isSelected && ( - - )} - - ) - }, - [currentAccount, handleAccountChange, colors], - ) - - const handleNetTypeChange = useCallback( - (nextNetType?: NetTypes.NetType) => { - setOnboardingData((prev) => { - let netType = nextNetType - if (netType === undefined) { - netType = - prev.netType === NetTypes.MAINNET - ? NetTypes.TESTNET - : NetTypes.MAINNET - } - return { ...prev, netType } - }) - }, - [setOnboardingData], - ) - - const handleAddNew = useCallback(() => { - handleNetTypeChange(NetTypes.MAINNET) - navigation.navigate('AddNewAccountNavigator') - }, [handleNetTypeChange, navigation]) - - const renderSectionHeader = useCallback( - ({ section: { title, data } }) => { - const firstSection = filteredAccounts[0].title === title - - return ( - - - {title} - - - ) - }, - [filteredAccounts, currentAccount], - ) - - const renderSectionFooter = useCallback( - ({ section: { data } }) => { - return ( - - ) - }, - [handleAddSub, currentAccount?.mnemonicHash], - ) - - const Footer = useCallback(() => { - return ( - - {/** TODO: Bring back when stickers page is added */} - {/* - - */} - - - - - - ) - }, [bottom, handleAddNew, setFooterHeight]) +export type AccountsServiceNavigationProp = + StackNavigationProp - if (switchingAccounts || addingSubAccount) { - return ( - - - {addingSubAccount - ? t('accountsService.addingSubAccount') - : t('accountsService.switchingAccounts')} - - - {t('accountsService.pleaseBePatient')} - - - - - - ) - } +const AccountsServiceStack = + createStackNavigator() - return ( - - - - -