mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-10-05 19:28:26 +00:00
Improve UX of seed recovery process
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "minibits_wallet",
|
||||
"version": "0.1.11-beta.6",
|
||||
"version": "0.1.11-beta.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android:clean": "cd android && ./gradlew clean",
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"change": "Change",
|
||||
"close": "Close",
|
||||
"complete": "Complete",
|
||||
"completed": "Completed",
|
||||
"confirm": "Confirm",
|
||||
"confirmAlertTitle": "Confirmation",
|
||||
"confirmCreateInvoice": "Create invoice",
|
||||
|
||||
@@ -176,7 +176,7 @@ export const WalletStoreModel = types
|
||||
|
||||
if (!keys) {
|
||||
throw new AppError(
|
||||
Err.VALIDATION_ERROR,
|
||||
Err.NOTFOUND_ERROR,
|
||||
'Device secure storage could not return wallet keys, please reinstall and use your seed phrase to recover wallet.'
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export const ImportBackupScreen: FC<AppStackScreenProps<'ImportBackup'>> = obser
|
||||
if(existing && existing.SEED.mnemonic) {
|
||||
setMnemonicExists(true)
|
||||
}
|
||||
} catch (e: any) {
|
||||
} catch (e: any) {
|
||||
handleError(e)
|
||||
}
|
||||
}
|
||||
@@ -502,7 +502,7 @@ export const ImportBackupScreen: FC<AppStackScreenProps<'ImportBackup'>> = obser
|
||||
)}
|
||||
{error && <ErrorModal error={error} />}
|
||||
{info && <InfoModal message={info} />}
|
||||
{isLoading && <Loading statusMessage={statusMessage} textStyle={{color: 'white'}} style={{backgroundColor: loadingBg, opacity: 1}}/>}
|
||||
{isLoading && <Loading statusMessage={statusMessage} textStyle={{color: 'white'}} style={{backgroundColor: headerBg, opacity: 1}}/>}
|
||||
</Screen>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,12 @@ export const MintsScreen: FC<SettingsStackScreenProps<'Mints'>> = observer(
|
||||
}
|
||||
|
||||
const toggleMintMenuModal = () => setIsMintMenuVisible(previousState => !previousState)
|
||||
const toggleShareModal = () => setIsShareModalVisible(previousState => !previousState)
|
||||
const toggleShareModal = () => {
|
||||
if(isShareModalVisible) {
|
||||
setSelectedMint(undefined)
|
||||
}
|
||||
setIsShareModalVisible(previousState => !previousState)
|
||||
}
|
||||
|
||||
const pasteMintUrl = async () => {
|
||||
const url = await Clipboard.getString()
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
BottomModal,
|
||||
Button,
|
||||
$sizeStyles,
|
||||
Header,
|
||||
} from '../components'
|
||||
import {useHeader} from '../utils/useHeader'
|
||||
import AppError, { Err } from '../utils/AppError'
|
||||
@@ -41,6 +42,7 @@ import { MintUnit, formatCurrency, getCurrency } from '../services/wallet/curren
|
||||
import { isObj } from '@cashu/cashu-ts/src/utils'
|
||||
import { translate } from '../i18n'
|
||||
import { WalletProfileRecord } from '../models/WalletProfileStore'
|
||||
import { MnemonicInput } from './Recovery/MnemonicInput'
|
||||
|
||||
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
|
||||
UIManager.setLayoutAnimationEnabledExperimental(true)
|
||||
@@ -50,13 +52,6 @@ const RESTORE_INDEX_INTERVAL = 50
|
||||
|
||||
export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = observer(function SeedRecoveryScreen(_props) {
|
||||
const {navigation, route} = _props
|
||||
useHeader({
|
||||
leftIcon: 'faArrowLeft',
|
||||
onLeftPress: () => {
|
||||
navigation.goBack()
|
||||
},
|
||||
})
|
||||
|
||||
const {
|
||||
mintsStore,
|
||||
proofsStore,
|
||||
@@ -88,6 +83,7 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
const [isErrorsModalVisible, setIsErrorsModalVisible] = useState(false)
|
||||
const [isIndexModalVisible, setIsIndexModalVisible] = useState(false)
|
||||
const [isKeysetModalVisible, setIsKeysetModalVisible] = useState(false)
|
||||
const [isRecoveryStarted, setIsRecoveryStarted] = useState(false)
|
||||
const [resultModalInfo, setResultModalInfo] = useState<{status: TransactionStatus, message: string} | undefined>()
|
||||
const [isResultModalVisible, setIsResultModalVisible] = useState(false)
|
||||
const [lastRecoveredAmount, setLastRecoveredAmount] = useState<number>(0)
|
||||
@@ -97,15 +93,12 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
|
||||
useEffect(() => {
|
||||
const getMnemonic = async () => {
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const existing = await walletStore.getCachedMnenomic()
|
||||
|
||||
if(existing) {
|
||||
try {
|
||||
const existing = await KeyChain.getWalletKeys()
|
||||
if(existing && existing.SEED.mnemonic) {
|
||||
setMnemonicExists(true)
|
||||
}
|
||||
setIsLoading(false)
|
||||
} catch (e: any) {
|
||||
}
|
||||
} catch (e: any) {
|
||||
handleError(e)
|
||||
}
|
||||
}
|
||||
@@ -233,6 +226,8 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
setInfo(translate("recovery.selectMintFrom"))
|
||||
return
|
||||
}
|
||||
|
||||
setIsRecoveryStarted(true)
|
||||
setStatusMessage(translate("recovery.starting"))
|
||||
setIsLoading(true)
|
||||
setTimeout(() => doRecovery(), 100)
|
||||
@@ -567,6 +562,10 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
if(mnemonicExists) {
|
||||
return (
|
||||
<Screen contentContainerStyle={$screen} preset="auto">
|
||||
<Header
|
||||
leftIcon='faArrowLeft'
|
||||
onLeftPress={() => navigation.goBack()}
|
||||
/>
|
||||
<View style={[$headerContainer, {backgroundColor: headerBg}]}>
|
||||
<Text preset="heading" text="Wallet recovery" style={{color: headerTitle, zIndex: 10}} />
|
||||
</View>
|
||||
@@ -599,31 +598,36 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
} else {
|
||||
return (
|
||||
<Screen contentContainerStyle={$screen} preset="auto">
|
||||
{isRecoveryStarted ? (
|
||||
<Header/>
|
||||
) : (
|
||||
<Header
|
||||
leftIcon='faArrowLeft'
|
||||
onLeftPress={() => navigation.goBack()}
|
||||
/>
|
||||
)}
|
||||
<View style={[$headerContainer, {backgroundColor: headerBg}]}>
|
||||
<Text preset="heading" text="Wallet recovery" style={{color: headerTitle, zIndex: 10}} />
|
||||
</View>
|
||||
<View style={$contentContainer}>
|
||||
<View style={$contentContainer}>
|
||||
<MnemonicInput
|
||||
ref={mnemonicInputRef}
|
||||
mnemonic={mnemonic}
|
||||
isValidMnemonic={isValidMnemonic}
|
||||
setMnemonic={setMnemonic}
|
||||
onConfirm={onConfirmMnemonic}
|
||||
onError={handleError}
|
||||
/>
|
||||
<>
|
||||
{isValidMnemonic ? (
|
||||
<>
|
||||
<Card
|
||||
style={$card}
|
||||
ContentComponent={
|
||||
<ListItem
|
||||
tx='backupScreen.mnemonicTitle'
|
||||
subText={mnemonic}
|
||||
LeftComponent={<View style={[$numIcon, {backgroundColor: numIconColor}]}><Text text='1'/></View>}
|
||||
style={$item}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{isValidMnemonic && (
|
||||
|
||||
<Card
|
||||
style={$card}
|
||||
HeadingComponent={
|
||||
<>
|
||||
<ListItem
|
||||
tx="recoveryFromMints"
|
||||
subTx="recoveryFromMintsDesc"
|
||||
subTx={mintsStore.mintCount > 0 ? undefined : "recoveryFromMintsDesc"}
|
||||
LeftComponent={<View style={[$numIcon, {backgroundColor: numIconColor}]}><Text text='2'/></View>}
|
||||
RightComponent={mintsStore.mintCount > 0 ? (
|
||||
<View style={$rightContainer}>
|
||||
@@ -654,6 +658,7 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
key={mint.mintUrl}
|
||||
mint={mint}
|
||||
mintBalance={proofsStore.getMintBalance(mint.mintUrl)}
|
||||
selectedUnit={selectedKeyset?.unit as MintUnit}
|
||||
onMintSelect={() => onMintSelect(mint)}
|
||||
isSelectable={true}
|
||||
isSelected={selectedMintUrl === mint.mintUrl}
|
||||
@@ -677,29 +682,29 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
{(startIndex > 0 || totalRecoveredAmount > 0) && (
|
||||
<Button
|
||||
onPress={onCompleteAddress}
|
||||
tx="common.complete"
|
||||
tx="common.completed"
|
||||
preset='secondary'
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={$buttonContainer}>
|
||||
<Text
|
||||
text={translate("recovery.intervalParam", {
|
||||
startIndex: startIndex,
|
||||
endIndex: endIndex
|
||||
})}
|
||||
size='xxs'
|
||||
style={{color: textHint, alignSelf: 'center', marginTop: spacing.small}}
|
||||
/>
|
||||
<Pressable onPress={toggleIndexModal}>
|
||||
<Text
|
||||
tx="recovery.setManually"
|
||||
size='xxs'
|
||||
style={{color: textHint, alignSelf: 'center', marginTop: spacing.small}}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
<View style={[$buttonContainer,{marginTop: 0}]}>
|
||||
<Text
|
||||
text={translate("recovery.intervalParam", {
|
||||
startIndex: startIndex,
|
||||
endIndex: endIndex
|
||||
})}
|
||||
size='xxs'
|
||||
style={{color: textHint, alignSelf: 'center', marginTop: spacing.small}}
|
||||
/>
|
||||
<Pressable onPress={toggleIndexModal}>
|
||||
<Text
|
||||
tx="recovery.setManually"
|
||||
size='xxs'
|
||||
style={{color: textHint, alignSelf: 'center', marginTop: spacing.small}}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
<View style={[$buttonContainer,{marginTop: 0}]}>
|
||||
<Text
|
||||
text={translate("recovery.keysetID", {
|
||||
@@ -730,52 +735,8 @@ export const SeedRecoveryScreen: FC<AppStackScreenProps<'SeedRecovery'>> = obser
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Card
|
||||
style={$card}
|
||||
ContentComponent={
|
||||
<ListItem
|
||||
tx="recoveryInsertMnemonic"
|
||||
subTx={'recoveryInsertMnemonicDesc'}
|
||||
LeftComponent={<View style={[$numIcon, {backgroundColor: numIconColor}]}><Text text='1'/></View>}
|
||||
style={$item}
|
||||
/>
|
||||
}
|
||||
FooterComponent={
|
||||
<>
|
||||
<TextInput
|
||||
ref={mnemonicInputRef}
|
||||
onChangeText={(mnemonic: string) => setMnemonic(mnemonic)}
|
||||
value={mnemonic}
|
||||
numberOfLines={3}
|
||||
multiline={true}
|
||||
autoCapitalize='none'
|
||||
keyboardType='default'
|
||||
maxLength={150}
|
||||
placeholder={translate("mnemonicPhrasePlaceholder")}
|
||||
selectTextOnFocus={true}
|
||||
style={[$mnemonicInput, {backgroundColor: inputBg, flexWrap: 'wrap'}]}
|
||||
/>
|
||||
<View style={$buttonContainer}>
|
||||
{mnemonic ? (
|
||||
<Button
|
||||
onPress={onConfirmMnemonic}
|
||||
tx='common.confirm'
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
onPress={onPasteMnemonic}
|
||||
tx='common.paste'
|
||||
/>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
</>
|
||||
</View>
|
||||
<BottomModal
|
||||
|
||||
Reference in New Issue
Block a user