Skip to content

Commit

Permalink
[Issue-281]: Implement Wallet Connect
Browse files Browse the repository at this point in the history
  • Loading branch information
dominhquang committed Aug 7, 2023
1 parent 1a0691d commit 64224ad
Show file tree
Hide file tree
Showing 132 changed files with 1,985 additions and 1,137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import app.subwallet.mobile.nativeModules.RCTMinimizerPackage;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {
Expand All @@ -26,6 +27,7 @@ protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new RCTMinimizerPackage());
return packages;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package app.subwallet.mobile.nativeModules;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import android.util.Log;

public class RCTMinimizer extends ReactContextBaseJavaModule {
private ReactApplicationContext reactContext;
RCTMinimizer(ReactApplicationContext context) {
super(context);
this.reactContext = reactContext;
}

@Override
public String getName() {
return "Minimizer";
}

@ReactMethod
public void goBack() {
android.app.Activity activity = getCurrentActivity();
if (activity != null) {
activity.moveTaskToBack(true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package app.subwallet.mobile.nativeModules;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RCTMinimizerPackage implements ReactPackage {

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}

@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();

modules.add(new RCTMinimizer(reactContext));

return modules;
}

}
22 changes: 22 additions & 0 deletions ios/SubWalletMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
0C80B921A6F3F58F76C31292 /* libPods-SubWalletMobile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-SubWalletMobile.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
355FCA172A72335100B34579 /* RCTMinimizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 355FCA152A72335100B34579 /* RCTMinimizer.m */; };
3577831F29CEA0080036830D /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = 3577831E29CEA0080036830D /* fonts */; };
7699B88040F8A987B510C191 /* libPods-SubWalletMobile-SubWalletMobileTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-SubWalletMobile-SubWalletMobileTests.a */; };
81AB9BB82411601600AC10FF /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* SplashScreen.storyboard */; };
Expand Down Expand Up @@ -40,6 +41,8 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SubWalletMobile/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = SubWalletMobile/main.m; sourceTree = "<group>"; };
19F6CBCC0A4E27FBF8BF4A61 /* libPods-SubWalletMobile-SubWalletMobileTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SubWalletMobile-SubWalletMobileTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
355FCA152A72335100B34579 /* RCTMinimizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTMinimizer.m; path = SubWalletMobile/NativeModules/RCTMinimizer/RCTMinimizer.m; sourceTree = "<group>"; };
355FCA162A72335100B34579 /* RCTMinimizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTMinimizer.h; path = SubWalletMobile/NativeModules/RCTMinimizer/RCTMinimizer.h; sourceTree = "<group>"; };
3577831E29CEA0080036830D /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = fonts; sourceTree = "<group>"; };
3B4392A12AC88292D35C810B /* Pods-SubWalletMobile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SubWalletMobile.debug.xcconfig"; path = "Target Support Files/Pods-SubWalletMobile/Pods-SubWalletMobile.debug.xcconfig"; sourceTree = "<group>"; };
5709B34CF0A7D63546082F79 /* Pods-SubWalletMobile.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SubWalletMobile.release.xcconfig"; path = "Target Support Files/Pods-SubWalletMobile/Pods-SubWalletMobile.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -94,6 +97,7 @@
13B07FAE1A68108700A75B9A /* SubWalletMobile */ = {
isa = PBXGroup;
children = (
355FCA132A7232F000B34579 /* NativeModules */,
990CC4AB2A33104500AB6D8B /* SubWalletMobile.entitlements */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
Expand All @@ -115,6 +119,23 @@
name = Frameworks;
sourceTree = "<group>";
};
355FCA132A7232F000B34579 /* NativeModules */ = {
isa = PBXGroup;
children = (
355FCA142A72333200B34579 /* RCTMinimizer */,
);
name = NativeModules;
sourceTree = "<group>";
};
355FCA142A72333200B34579 /* RCTMinimizer */ = {
isa = PBXGroup;
children = (
355FCA162A72335100B34579 /* RCTMinimizer.h */,
355FCA152A72335100B34579 /* RCTMinimizer.m */,
);
name = RCTMinimizer;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -437,6 +458,7 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
355FCA172A72335100B34579 /* RCTMinimizer.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
15 changes: 15 additions & 0 deletions ios/SubWalletMobile/NativeModules/RCTMinimizer/RCTMinimizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// RCTMinimizer.h
// SubWalletMobile
//
// Created by Do Minh Quang on 27/07/2023.
//

#ifndef RCTMinimizer_h
#define RCTMinimizer_h

#import <React/RCTBridgeModule.h>
@interface RCTMinimizer : NSObject <RCTBridgeModule>
@end

#endif /* RCTMinimizer_h */
30 changes: 30 additions & 0 deletions ios/SubWalletMobile/NativeModules/RCTMinimizer/RCTMinimizer.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#import <Foundation/Foundation.h>
#import "RCTMinimizer.h"

@import UIKit;
@import ObjectiveC.runtime;

@interface UISystemNavigationAction : NSObject
@property(nonatomic, readonly, nonnull) NSArray<NSNumber*>* destinations;
-(BOOL)sendResponseForDestination:(NSUInteger)destination;
@end


@implementation RCTMinimizer

RCT_EXPORT_METHOD(goBack)
{
Ivar sysNavIvar = class_getInstanceVariable(UIApplication.class, "_systemNavigationAction");
UIApplication* app = UIApplication.sharedApplication;
UISystemNavigationAction* action = object_getIvar(app, sysNavIvar);
if (!action) {
return;
}
NSUInteger destination = action.destinations.firstObject.unsignedIntegerValue;
[action sendResponseForDestination:destination];
return;
}

RCT_EXPORT_MODULE();

@end
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@fortawesome/free-regular-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-native-fontawesome": "^0.3.0",
"@gorhom/portal": "^1.0.14",
"@polkadot/api": "^10.9.1",
"@polkadot/react-qr": "^3.5.1",
"@polkadot/reactnative-identicon": "^3.5.1",
Expand Down
64 changes: 31 additions & 33 deletions src/AppNavigator.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { NavigationState } from '@react-navigation/routers';
import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
import React, { ComponentType, useCallback, useEffect, useMemo, useState } from 'react';
import React, { ComponentType, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { LinkingOptions, NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import AttachReadOnly from 'screens/Account/AttachReadOnly';
import ConnectKeystone from 'screens/Account/ConnectQrSigner/ConnectKeystone';
import ConnectParitySigner from 'screens/Account/ConnectQrSigner/ConnectParitySigner';
import ImportQrCode from 'screens/Account/ImportQrCode';
import Login from 'screens/MasterPassword/Login';
import { NetworksSetting } from 'screens/NetworksSetting';
import { GeneralSettings } from 'screens/Settings/General';
import { SendFund } from 'screens/Transaction/SendFund';
Expand Down Expand Up @@ -38,7 +37,7 @@ import { LoadingScreen } from 'screens/LoadingScreen';
import { RootRouteProps, RootStackParamList } from './routes';
import { THEME_PRESET } from 'styles/themes';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { deeplinks, getProtocol, getValidURL } from 'utils/browser';
import { deeplinks, getValidURL } from 'utils/browser';
import ErrorBoundary from 'react-native-error-boundary';
import ApplyMasterPassword from 'screens/MasterPassword/ApplyMasterPassword';
import { NetworkSettingDetail } from 'screens/NetworkSettingDetail';
Expand All @@ -55,7 +54,7 @@ import { AddProvider } from 'screens/AddProvider';
import TransactionScreen from 'screens/Transaction/TransactionScreen';
import SendNFT from 'screens/Transaction/NFT';
import changeNavigationBarColor from 'react-native-navigation-bar-color';
import { Linking, Platform } from 'react-native';
import { Platform, StatusBar } from 'react-native';
import { useSubWalletTheme } from 'hooks/useSubWalletTheme';
import { Home } from 'screens/Home';
import { deviceWidth } from 'constants/index';
Expand All @@ -68,10 +67,11 @@ import useCheckEmptyAccounts from 'hooks/useCheckEmptyAccounts';
import { ConnectionList } from 'screens/Settings/WalletConnect/ConnectionList';
import { ConnectWalletConnect } from 'screens/Settings/WalletConnect/ConnectWalletConnect';
import { ConnectionDetail } from 'screens/Settings/WalletConnect/ConnectionDetail';
import urlParse from 'url-parse';
import queryString from 'querystring';
import { connectWalletConnect } from 'utils/walletConnect';
import { useToast } from 'react-native-toast-notifications';
import useAppLock from 'hooks/useAppLock';
import { LockScreen } from 'screens/LockScreen';
import { STATUS_BAR_LIGHT_CONTENT } from 'styles/sharedStyles';
import { UnlockModal } from 'components/common/Modal/UnlockModal';
import { AppModalContext } from 'providers/AppModalContext';

interface Props {
isAppReady: boolean;
Expand Down Expand Up @@ -142,7 +142,8 @@ const AppNavigator = ({ isAppReady }: Props) => {
const isEmptyAccounts = useCheckEmptyAccounts();
const { hasConfirmations } = useSelector((state: RootState) => state.requestState);
const { accounts, hasMasterPassword } = useSelector((state: RootState) => state.accountState);
const toast = useToast();
const { isLocked } = useAppLock();
const appModalContext = useContext(AppModalContext);

const needMigrate = useMemo(
() =>
Expand All @@ -168,15 +169,17 @@ const AppNavigator = ({ isAppReady }: Props) => {
let amount = true;
if (hasConfirmations && currentRoute && amount) {
if (currentRoute.name !== 'Confirmations' && amount) {
if (currentRoute.name !== 'CreateAccount' && amount) {
navigationRef.current?.navigate('Confirmations');
if (!['CreateAccount', 'CreatePassword', 'Login', 'UnlockModal'].includes(currentRoute.name) && amount) {
appModalContext.hideConfirmModal();
setTimeout(() => navigationRef.current?.navigate('Confirmations'), 1000);
}
}
}

return () => {
amount = false;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasConfirmations, navigationRef, currentRoute]);

useEffect(() => {
Expand All @@ -191,6 +194,20 @@ const AppNavigator = ({ isAppReady }: Props) => {
};
}, [currentRoute, hasMasterPassword, navigationRef, needMigrate]);

useEffect(() => {
let amount = true;
if (isLocked && currentRoute && amount) {
if (currentRoute.name !== 'Login' && amount) {
appModalContext.hideConfirmModal();
setTimeout(() => navigationRef.current?.navigate('Login'), 500);
}
}
return () => {
amount = false;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentRoute, hasMasterPassword, isLocked, navigationRef, needMigrate]);

useEffect(() => {
if (isEmptyAccounts) {
navigationRef.current?.reset({
Expand All @@ -200,29 +217,9 @@ const AppNavigator = ({ isAppReady }: Props) => {
}
}, [isEmptyAccounts, navigationRef]);

useEffect(() => {
Linking.addEventListener('url', ({ url }) => {
const urlParsed = new urlParse(url);
if (getProtocol(url) === 'subwallet') {
if (urlParsed.hostname === 'wc') {
const decodedWcUrl = queryString.decode(urlParsed.query.slice(5));
const finalWcUrl = Object.keys(decodedWcUrl)[0];
connectWalletConnect(finalWcUrl, toast);
}
} else if (getProtocol(url) === 'https') {
if (urlParsed.pathname.split('/')[1] === 'wc') {
const decodedWcUrl = queryString.decode(urlParsed.query.slice(5));
const finalWcUrl = Object.keys(decodedWcUrl)[0];
connectWalletConnect(finalWcUrl, toast);
}
}
});

return () => Linking.removeAllListeners('url');
}, [toast]);

return (
<NavigationContainer linking={linking} ref={navigationRef} theme={theme} onStateChange={onUpdateRoute}>
<StatusBar barStyle={STATUS_BAR_LIGHT_CONTENT} translucent={true} backgroundColor={'transparent'} />
<ErrorBoundary FallbackComponent={ErrorFallback} onError={onError}>
<Stack.Navigator
screenOptions={{
Expand Down Expand Up @@ -321,7 +318,8 @@ const AppNavigator = ({ isAppReady }: Props) => {
component={Confirmations}
options={{ gestureEnabled: false, animationDuration: 100 }}
/>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Login" component={LockScreen} />
{<Stack.Screen name={'UnlockModal'} component={UnlockModal} />}
</Stack.Group>
</>
)}
Expand Down
Loading

0 comments on commit 64224ad

Please sign in to comment.