Embed laconic wallet in android without using sign request
This commit is contained in:
parent
23151f95e5
commit
2e84a41aaf
@ -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<NativeStackNavigationProp<StackParamsList>>();
|
||||
// const { accounts, currentIndex } = useAccounts();
|
||||
// const { selectedNetwork } = useNetworks();
|
||||
// const [pendingMessage, setPendingMessage] = useState<string | null>(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<NativeStackNavigationProp<StackParamsList>>();
|
||||
// const { accounts, currentIndex } = useAccounts();
|
||||
// const { selectedNetwork } = useNetworks();
|
||||
// const [pendingMessage, setPendingMessage] = useState<string | null>(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<NativeStackNavigationProp<StackParamsList>>();
|
||||
// const [displayContent, setDisplayContent] = useState<string>('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 (
|
||||
// <div style={containerStyle}>
|
||||
// <h2 style={headingStyle}>Content from Android:</h2>
|
||||
// <p style={timeTextStyle}>{displayContent}</p>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// 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<NativeStackNavigationProp<StackParamsList>>();
|
||||
const [displayContent, setDisplayContent] = useState<string>('Waiting for time...');
|
||||
const { accounts, currentIndex } = useAccounts();
|
||||
const { selectedNetwork } = useNetworks();
|
||||
|
||||
const pendingMessageRef = useRef<string | null>(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 (
|
||||
<div style={containerStyle}>
|
||||
<h2 style={headingStyle}>Content from Android:</h2>
|
||||
<p style={timeTextStyle}>{displayContent}</p>
|
||||
</div>
|
||||
);
|
||||
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'
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
4
src/global.d.ts
vendored
4
src/global.d.ts
vendored
@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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 = () => {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<TimeDisplay />
|
||||
<SignRequestAndroid />
|
||||
<ImportWalletDialog
|
||||
visible={importWalletDialog}
|
||||
hideDialog={() => setImportWalletDialog(false)}
|
||||
|
@ -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<StackParamsList, "SignMessage">;
|
||||
|
||||
// const SignMessage = ({ route }: SignProps) => {
|
||||
// const namespace = route.params.selectedNamespace;
|
||||
// const chainId = route.params.selectedChainId;
|
||||
// const account = route.params.accountInfo;
|
||||
|
||||
// const [message, setMessage] = useState<string>("");
|
||||
|
||||
// const signMessageHandler = async () => {
|
||||
// const signedMessage = await signMessage({
|
||||
// message,
|
||||
// namespace,
|
||||
// chainId,
|
||||
// accountId: account.index,
|
||||
// });
|
||||
// alert(`Signature ${signedMessage}`);
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <Layout title="Sign Message">
|
||||
// <Text variant="titleMedium">
|
||||
// {account && `Account ${account.index + 1}`}
|
||||
// </Text>
|
||||
// <AccountDetails account={account} />
|
||||
|
||||
// <Stack spacing={4}>
|
||||
// <Divider flexItem />
|
||||
// <TextInput
|
||||
// mode="outlined"
|
||||
// placeholder="Enter your message"
|
||||
// onChangeText={(text) => setMessage(text)}
|
||||
// value={message}
|
||||
// />
|
||||
|
||||
// <Button
|
||||
// variant="contained"
|
||||
// onClick={signMessageHandler}
|
||||
// sx={{ width: "200px", px: 4, py: 1, mt: 2 }}
|
||||
// >
|
||||
// Sign
|
||||
// </Button>
|
||||
// </Stack>
|
||||
// </Layout>
|
||||
// );
|
||||
// };
|
||||
|
||||
// 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) => {
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Confirmation Dialog */}
|
||||
<Dialog
|
||||
open={showConfirmDialog}
|
||||
onClose={handleCancelSignature}
|
||||
@ -194,7 +130,7 @@ const SignMessage = ({ route, navigation }: SignProps) => {
|
||||
<DialogContentText>
|
||||
Are you sure you want to sign the following message?
|
||||
</DialogContentText>
|
||||
<DialogContentText sx={{ mt: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1 }}>
|
||||
<DialogContentText sx={{ mt: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1, color: 'black' }}>
|
||||
{message}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
|
Loading…
Reference in New Issue
Block a user