diff --git a/src/components/SignRequestHandler.tsx b/src/components/SignRequestHandler.tsx index bc24182..78808ee 100644 --- a/src/components/SignRequestHandler.tsx +++ b/src/components/SignRequestHandler.tsx @@ -1,295 +1,32 @@ -// import React, { useState, useEffect } from 'react'; -// import { useNavigation } from '@react-navigation/native'; -// import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -// import { useAccounts } from '../context/AccountsContext'; -// import { useNetworks } from '../context/NetworksContext'; -// import { StackParamsList } from '../types'; -// import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts'; - -// declare global { -// interface Window { -// receiveSignRequestFromAndroid?: (message: string) => void; -// } -// } - -// export const SignRequestHandler: React.FC = () => { -// const navigation = useNavigation>(); -// const { accounts, currentIndex } = useAccounts(); -// const { selectedNetwork } = useNetworks(); -// const [pendingMessage, setPendingMessage] = useState(null); - -// useGetOrCreateAccounts(); - -// useEffect(() => { -// if (pendingMessage && selectedNetwork && accounts && accounts.length > 0) { -// navigation.reset({ -// index: 0, -// routes: [ -// { -// name: 'SignRequest', -// params: { -// address: accounts[currentIndex].address, -// message: pendingMessage, -// requestEvent: null, -// path: `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${accounts[currentIndex].address}/${encodeURIComponent(pendingMessage)}` -// } -// } -// ] -// }); -// setPendingMessage(null); -// } -// }, [pendingMessage, selectedNetwork, accounts, currentIndex, navigation]); - -// useEffect(() => { -// window.receiveSignRequestFromAndroid = (message: string) => { -// if (!selectedNetwork || !accounts || accounts.length === 0) { -// // Store the message and wait for wallet creation -// setPendingMessage(message); -// return; -// } - -// navigation.reset({ -// index: 0, -// routes: [ -// { -// name: 'SignRequest', -// params: { -// address: accounts[currentIndex].address, -// message: message, -// requestEvent: null, -// path: `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${accounts[currentIndex].address}/${encodeURIComponent(message)}` -// } -// } -// ] -// }); -// }; - -// return () => { -// if ('receiveSignRequestFromAndroid' in window) { -// window.receiveSignRequestFromAndroid = undefined; -// } -// }; -// }, [navigation, accounts, currentIndex, selectedNetwork]); - -// return null; -// }; - - -// import React, { useState, useEffect } from 'react'; -// import { useNavigation } from '@react-navigation/native'; -// import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -// import { useAccounts } from '../context/AccountsContext'; -// import { useNetworks } from '../context/NetworksContext'; -// import { StackParamsList } from '../types'; -// import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts'; - -// declare global { -// interface Window { -// receiveSignRequestFromAndroid?: (message: string) => void; -// reactAppReady: boolean; -// reactAppReceiveMessage: (message: string) => void; -// pendingAndroidMessage?: string; -// Android?: any; -// } -// } - -// export const SignRequestHandler: React.FC = () => { -// const navigation = useNavigation>(); -// const { accounts, currentIndex } = useAccounts(); -// const { selectedNetwork } = useNetworks(); -// const [pendingMessage, setPendingMessage] = useState(null); - -// useGetOrCreateAccounts(); - -// const handleMessage = (message: string) => { -// console.log("Handling message in React app:", message); - -// if (!selectedNetwork || !accounts || accounts.length === 0) { -// // Store the message and wait for wallet creation -// console.log("Storing message for later processing"); -// setPendingMessage(message); -// return; -// } - -// console.log("Navigating to SignRequest screen"); -// navigation.reset({ -// index: 0, -// routes: [ -// { -// name: 'SignRequest', -// params: { -// address: accounts[currentIndex].address, -// message: message, -// requestEvent: null, -// path: `/sign/${selectedNetwork.namespace}/${selectedNetwork.chainId}/${accounts[currentIndex].address}/${encodeURIComponent(message)}` -// } -// } -// ] -// }); -// }; - -// useEffect(() => { -// if (pendingMessage && selectedNetwork && accounts && accounts.length > 0) { -// handleMessage(pendingMessage); -// setPendingMessage(null); -// } -// }, [pendingMessage, selectedNetwork, accounts, currentIndex, navigation]); - -// useEffect(() => { -// window.reactAppReceiveMessage = handleMessage; -// window.reactAppReady = true; - -// if (window.pendingAndroidMessage) { -// console.log("Processing pending message:", window.pendingAndroidMessage); -// handleMessage(window.pendingAndroidMessage); -// window.pendingAndroidMessage = undefined; -// } - -// if (window.Android && typeof window.Android.bridgeReady === 'function') { -// window.Android.bridgeReady(); -// } - -// console.log("React app ready to receive messages"); - -// return () => { -// window.reactAppReady = false; -// }; -// }, [navigation, accounts, currentIndex, selectedNetwork]); - -// return null; -// }; - -// import React, { useState, useEffect } from 'react'; -// import { useNavigation } from '@react-navigation/native'; -// import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -// import { useAccounts } from '../context/AccountsContext'; -// import { useNetworks } from '../context/NetworksContext'; -// import { StackParamsList } from '../types'; - -// // declare global { -// // interface Window { -// // receiveTimeFromAndroid?: (timestamp: number) => void; -// // receiveDataFromAndroid?: (data: string) => void; -// // receiveSignRequestFromAndroid?: (message: string) => void; -// // } -// // } - -// export const TimeDisplay: React.FC = () => { -// const navigation = useNavigation>(); -// const [displayContent, setDisplayContent] = useState('Waiting for time...'); -// const { accounts, currentIndex } = useAccounts(); -// const { selectedNetwork } = useNetworks(); - -// useEffect(() => { -// console.log('TimeDisplay mounted useeffect'); - -// window.receiveTimeFromAndroid = (timestamp: number) => { -// const date = new Date(timestamp); -// setDisplayContent(date.toLocaleString()); -// }; - -// window.receiveDataFromAndroid = (data: string) => { -// setDisplayContent(data); -// }; - -// window.receiveSignRequestFromAndroid = (message: string) => { -// if (!selectedNetwork || !accounts || accounts.length === 0) { -// console.error('No network or accounts available'); -// return; -// } - -// // Reset the entire navigation state and go directly to SignMessage -// navigation.reset({ -// index: 0, -// routes: [ -// { -// name: 'SignMessage', -// params: { -// selectedNamespace: selectedNetwork.namespace, -// selectedChainId: selectedNetwork.chainId, -// accountInfo: accounts[currentIndex], -// prefillMessage: message -// } -// } -// ] -// }); -// }; - -// return () => { -// if ('receiveTimeFromAndroid' in window) { -// window.receiveTimeFromAndroid = undefined; -// } -// if ('receiveDataFromAndroid' in window) { -// window.receiveDataFromAndroid = undefined; -// } -// if ('receiveSignRequestFromAndroid' in window) { -// window.receiveSignRequestFromAndroid = undefined; -// } -// }; -// }, [navigation, accounts, currentIndex, selectedNetwork]); - -// return ( -//
-//

Content from Android:

-//

{displayContent}

-//
-// ); -// }; - -// const containerStyle: React.CSSProperties = { -// padding: 20, -// backgroundColor: '#f5f5f5', -// borderRadius: 8, -// textAlign: 'center' -// }; - -// const headingStyle: React.CSSProperties = { -// fontSize: 18, -// fontWeight: 'bold', -// marginBottom: 10 -// }; - -// const timeTextStyle: React.CSSProperties = { -// fontSize: 16, -// color: '#333' -// }; - - - -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useAccounts } from '../context/AccountsContext'; import { useNetworks } from '../context/NetworksContext'; import { StackParamsList } from '../types'; +import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts'; -export const TimeDisplay: React.FC = () => { +export const SignRequestAndroid: React.FC = () => { const navigation = useNavigation>(); - const [displayContent, setDisplayContent] = useState('Waiting for time...'); const { accounts, currentIndex } = useAccounts(); const { selectedNetwork } = useNetworks(); + const pendingMessageRef = useRef(null); + + // Run on mount + useGetOrCreateAccounts(); + + // Retry navigation if message is pending and accounts are ready useEffect(() => { - console.log('TimeDisplay mounted useeffect'); - - // Immediately set up the function on window object - window.receiveTimeFromAndroid = (timestamp: number) => { - const date = new Date(timestamp); - setDisplayContent(date.toLocaleString()); - }; + if ( + pendingMessageRef.current && + selectedNetwork && + accounts && + accounts.length > 0 + ) { + const message = pendingMessageRef.current; + pendingMessageRef.current = null; - window.receiveDataFromAndroid = (data: string) => { - setDisplayContent(data); - }; - - window.receiveSignRequestFromAndroid = (message: string) => { - console.log('Sign request received with message:', message); - if (!selectedNetwork || !accounts || accounts.length === 0) { - console.error('No network or accounts available'); - return; - } - - // Reset the entire navigation state and go directly to SignMessage navigation.reset({ index: 0, routes: [ @@ -299,57 +36,73 @@ export const TimeDisplay: React.FC = () => { selectedNamespace: selectedNetwork.namespace, selectedChainId: selectedNetwork.chainId, accountInfo: accounts[currentIndex], - prefillMessage: message - } - } - ] + prefillMessage: message, + }, + }, + ], + }); + } + }, [accounts, selectedNetwork]); + + useEffect(() => { + window.receiveSignRequestFromAndroid = (message: string) => { + console.log('Sign request received with message:', message); + + if (!selectedNetwork || !accounts || accounts.length === 0) { + console.warn('Delaying sign request until data is ready...'); + pendingMessageRef.current = message; + return; + } + + navigation.reset({ + index: 0, + routes: [ + { + name: 'SignMessage', + params: { + selectedNamespace: selectedNetwork.namespace, + selectedChainId: selectedNetwork.chainId, + accountInfo: accounts[currentIndex], + prefillMessage: message, + }, + }, + ], }); }; - // Signal to Android that the JS bridge is ready if (window.Android) { console.log('Notifying Android that JS bridge is ready'); setTimeout(() => { - // This timeout ensures the function is properly attached before Android tries to use it - window.Android.onJsBridgeReady?.(); + window.Android?.onJsBridgeReady?.(); }, 100); } return () => { - if ('receiveTimeFromAndroid' in window) { - window.receiveTimeFromAndroid = undefined; - } - if ('receiveDataFromAndroid' in window) { - window.receiveDataFromAndroid = undefined; - } - if ('receiveSignRequestFromAndroid' in window) { - window.receiveSignRequestFromAndroid = undefined; - } + window.receiveSignRequestFromAndroid = undefined; }; - }, [navigation, accounts, currentIndex, selectedNetwork]); + }, []); - return ( -
-

Content from Android:

-

{displayContent}

-
- ); + return null; }; -const containerStyle: React.CSSProperties = { - padding: 20, - backgroundColor: '#f5f5f5', - borderRadius: 8, - textAlign: 'center' -}; -const headingStyle: React.CSSProperties = { - fontSize: 18, - fontWeight: 'bold', - marginBottom: 10 -}; -const timeTextStyle: React.CSSProperties = { - fontSize: 16, - color: '#333' -}; \ No newline at end of file + + + + + + + + + + + + + + + + + + + diff --git a/src/global.d.ts b/src/global.d.ts index 5b950f6..903501c 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -6,13 +6,9 @@ declare global { onSignatureCancelled?: () => void; onJsBridgeReady?: () => void; }; - // Android WebView bridge methods (from TimeDisplay) receiveTimeFromAndroid?: (timestamp: number) => void; receiveDataFromAndroid?: (data: string) => void; receiveSignRequestFromAndroid?: (message: string) => void; - - // Android native bridge object (from useGetOrCreateAccount) - } } diff --git a/src/hooks/useGetOrCreateAccounts.ts b/src/hooks/useGetOrCreateAccounts.ts index be58643..fc6bff4 100644 --- a/src/hooks/useGetOrCreateAccounts.ts +++ b/src/hooks/useGetOrCreateAccounts.ts @@ -4,16 +4,6 @@ import { sendMessage } from "../utils/misc"; import useAccountsData from "./useAccountsData"; import { useNetworks } from "../context/NetworksContext"; -// declare global { -// interface Window { -// Android?: { -// onSignatureComplete?: (signature: string) => void; -// onSignatureError?: (error: string) => void; -// onSignatureCancelled?: () => void; -// }; -// } -// } - const useGetOrCreateAccounts = (onWalletCreated?: () => void) => { const { networksData } = useNetworks(); const { getAccountsData } = useAccountsData(); diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 17ead86..1ce9dc3 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -18,7 +18,7 @@ import { useNetworks } from "../context/NetworksContext"; import ImportWalletDialog from "../components/ImportWalletDialog"; import { MnemonicDialog } from "../components/MnemonicDialog"; import { Container } from "../components/Container"; -import { TimeDisplay } from '../components/SignRequestHandler'; +import { SignRequestAndroid } from '../components/SignRequestHandler'; import useGetOrCreateAccounts from '../hooks/useGetOrCreateAccounts'; import { IS_IMPORT_WALLET_ENABLED } from "../utils/constants"; @@ -185,7 +185,7 @@ const HomeScreen = () => { )} )} - + setImportWalletDialog(false)} diff --git a/src/screens/SignMessage.tsx b/src/screens/SignMessage.tsx index 1271326..3883334 100644 --- a/src/screens/SignMessage.tsx +++ b/src/screens/SignMessage.tsx @@ -1,64 +1,3 @@ -// import React, { useState } from "react"; -// import { Text, TextInput } from "react-native-paper"; -// import { Button, Divider, Stack } from "@mui/material"; - -// import { NativeStackScreenProps } from "@react-navigation/native-stack"; - -// import { StackParamsList } from "../types"; -// import { signMessage } from "../utils/sign-message"; -// import AccountDetails from "../components/AccountDetails"; -// import { Layout } from "../components/Layout"; - -// type SignProps = NativeStackScreenProps; - -// const SignMessage = ({ route }: SignProps) => { -// const namespace = route.params.selectedNamespace; -// const chainId = route.params.selectedChainId; -// const account = route.params.accountInfo; - -// const [message, setMessage] = useState(""); - -// const signMessageHandler = async () => { -// const signedMessage = await signMessage({ -// message, -// namespace, -// chainId, -// accountId: account.index, -// }); -// alert(`Signature ${signedMessage}`); -// }; - -// return ( -// -// -// {account && `Account ${account.index + 1}`} -// -// - -// -// -// setMessage(text)} -// value={message} -// /> - -// -// -// -// ); -// }; - -// export default SignMessage; - - import React, { useState, useEffect } from "react"; import { Text, TextInput } from "react-native-paper"; import { Button, Divider, Stack, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; @@ -105,7 +44,6 @@ const SignMessage = ({ route, navigation }: SignProps) => { alert(`Signature: ${signedMessage}`); } - // Close dialog setShowConfirmDialog(false); // If this was opened from Android, we should return @@ -144,7 +82,6 @@ const SignMessage = ({ route, navigation }: SignProps) => { } }; - // This is triggered by the main "Sign" button const showSignConfirmation = () => { setShowConfirmDialog(true); }; @@ -184,7 +121,6 @@ const SignMessage = ({ route, navigation }: SignProps) => { - {/* Confirmation Dialog */} { Are you sure you want to sign the following message? - + {message}