diff --git a/src/components/Modal/AccountNameModal.tsx b/src/components/Modal/AccountNameModal.tsx index cbbd03f0b..36a78e95b 100644 --- a/src/components/Modal/AccountNameModal.tsx +++ b/src/components/Modal/AccountNameModal.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { AccountProxyType } from '@subwallet/extension-base/types'; -import { Button, Icon, SwModal } from 'components/design-system-ui'; +import { Button, Icon, SwModal, Typography } from 'components/design-system-ui'; import { EditAccountInputText } from 'components/EditAccountInputText'; import { Platform } from 'react-native'; import useFormControl, { FormControlConfig, FormState } from 'hooks/screen/useFormControl'; @@ -29,19 +29,20 @@ export const AccountNameModal = ({ }: Props) => { const theme = useSubWalletTheme().swThemes; const modalRef = useRef(null); - const validatorFunc = useCallback((value: string) => { + const validatorFunc = useCallback(async (value: string) => { let result: string[] = []; - if (value) { - validateAccountName({ name: value }) - .then(({ isValid }) => { - if (!isValid) { - result = ['Account name already in use']; - } - }) - .catch(() => { - result = ['Account name invalid']; - }); + if (!value.trim()) { + result = ['This field is required']; + } else { + try { + const { isValid } = await validateAccountName({ name: value.trim() }); + if (!isValid) { + result = ['Account name already in use']; + } + } catch { + result = ['Account name invalid']; + } } return result; @@ -52,12 +53,9 @@ export const AccountNameModal = ({ name: i18n.common.accountName, value: '', require: true, - validateFunc: (value: string) => { - return validatorFunc(value); - }, }, }), - [validatorFunc], + [], ); const _onSubmit = useCallback( @@ -72,14 +70,18 @@ export const AccountNameModal = ({ }); const onChangeAccountName = (value: string) => { - if (!value) { - onUpdateErrors('accountName')([]); - } - onChangeValue('accountName')(value); + validatorFunc(value) + .then(res => { + onUpdateErrors('accountName')(res); + }) + .catch((error: Error) => console.log('error validate name', error.message)); }; - const isDisabled = useMemo(() => !formState.data.accountName || isLoading, [formState.data.accountName, isLoading]); + const isDisabled = useMemo( + () => !formState.data.accountName || isLoading || !!formState.errors.accountName.length, + [formState.data.accountName, formState.errors.accountName, isLoading], + ); const footerNode = useMemo( () => ( @@ -115,15 +117,19 @@ export const AccountNameModal = ({ isAllowSwipeDown={Platform.OS === 'ios'} modalBaseV2Ref={modalRef} footer={footerNode}> + + {'Enter a name for your account.\n' + ' You can edit this later.'} + ); diff --git a/src/components/common/Account/AccountCreationArea/index.tsx b/src/components/common/Account/AccountCreationArea/index.tsx index 27abe080e..fab704d40 100644 --- a/src/components/common/Account/AccountCreationArea/index.tsx +++ b/src/components/common/Account/AccountCreationArea/index.tsx @@ -129,7 +129,6 @@ export const AccountCreationArea = ({ createAccountRef, importAccountRef, attach const createAccountFunc = (item: ActionItemType) => { if (item.key === 'createAcc') { - console.log('run to fucking this'); createAccountRef?.current?.onCloseModal(); setSelectedMnemonicType('general'); mmkvStore.set('use-default-create-content', false); diff --git a/src/components/common/Modal/DeriveAccountModal/index.tsx b/src/components/common/Modal/DeriveAccountModal/index.tsx index 6254bed4c..7717232d3 100644 --- a/src/components/common/Modal/DeriveAccountModal/index.tsx +++ b/src/components/common/Modal/DeriveAccountModal/index.tsx @@ -110,13 +110,11 @@ export const DeriveAccountActionModal = ({ name: _name, }) .then(() => { - console.log('run to then'); closeModal(); onCompleteCb && onCompleteCb(); //go back home }) .catch((e: Error) => { - console.log('run to catch'); onUpdateErrors('accountName')([e.message]); }) .finally(() => { @@ -205,7 +203,6 @@ export const DeriveAccountActionModal = ({ }) .then(rs => { if (!cancel) { - console.log('rs.info', rs.info); if (rs.info) { const suri = rs.info.derivationPath || rs.info.suri; diff --git a/src/components/common/SelectModal/parts/AccountChainAddressItem.tsx b/src/components/common/SelectModal/parts/AccountChainAddressItem.tsx index f331b961b..8b2d67be9 100644 --- a/src/components/common/SelectModal/parts/AccountChainAddressItem.tsx +++ b/src/components/common/SelectModal/parts/AccountChainAddressItem.tsx @@ -23,7 +23,9 @@ export const AccountChainAddressItem = ({ item, onPress, onPressCopyButton, onPr - {item.name} + + {item.name} + {toShort(item.address, 4, 5)} @@ -63,9 +65,11 @@ function createStyle(theme: ThemeTypes) { alignItems: 'center', gap: theme.sizeXXS, marginLeft: 10, + paddingRight: theme.paddingXS, }, chainName: { - color: theme.colorWhite, // Replace with your theme tokens + color: theme.colorWhite, + flex: 1, }, address: { fontSize: 12, diff --git a/src/components/design-system-ui/web3-block/Web3Block/index.tsx b/src/components/design-system-ui/web3-block/Web3Block/index.tsx index 1ea5ecddc..6cb565bae 100644 --- a/src/components/design-system-ui/web3-block/Web3Block/index.tsx +++ b/src/components/design-system-ui/web3-block/Web3Block/index.tsx @@ -1,6 +1,6 @@ import { useSubWalletTheme } from 'hooks/useSubWalletTheme'; -import React, { ReactNode, useMemo } from 'react'; -import { StyleProp, TouchableOpacity, View, ViewProps, ViewStyle } from 'react-native'; +import React, { useMemo } from 'react'; +import { StyleProp, TouchableOpacity, TouchableOpacityProps, View, ViewProps, ViewStyle } from 'react-native'; import createStyle from './styles'; export interface Web3BlockCustomStyle { @@ -19,6 +19,7 @@ export interface Web3BlockProps { renderRightItem?: (dItem: React.ReactNode) => React.ReactNode; onPress?: () => void; customStyle?: Web3BlockCustomStyle; + disabled?: boolean; } function defaultRender(x: React.ReactNode) { @@ -35,20 +36,21 @@ const Web3Block: React.FC = (props: Web3BlockProps) => { renderRightItem = defaultRender, rightItem, customStyle, + disabled, } = props; const theme = useSubWalletTheme().swThemes; const styles = useMemo(() => createStyle(theme), [theme]); - const Wrapper = useMemo((): React.FC => { + const Wrapper = useMemo(() => { if (onPress) { - return (_props: ViewProps) => ; + return (_props: TouchableOpacityProps) => ; } else { return (_props: ViewProps) => ; } }, [onPress]); return ( - + {!!leftItem && {renderLeftItem(leftItem)}} {!!middleItem && {renderMiddleItem(middleItem)}} {!!rightItem && {renderRightItem(rightItem)}} diff --git a/src/screens/Account/ConnectQrSigner/index.tsx b/src/screens/Account/ConnectQrSigner/index.tsx index fc8015004..b32842f0a 100644 --- a/src/screens/Account/ConnectQrSigner/index.tsx +++ b/src/screens/Account/ConnectQrSigner/index.tsx @@ -51,7 +51,6 @@ const ConnectQrSigner: React.FC = (props: Props) => { const [accountNameModalVisible, setAccountNameModalVisible] = useState(false); const styles = useMemo(() => createStyle(theme), [theme]); const goHome = useGoHome(); - console.log('accountNameModalVisible', accountNameModalVisible); const onComplete = useCallback(() => { navigation.reset({ diff --git a/src/screens/Account/CreateAccount/index.tsx b/src/screens/Account/CreateAccount/index.tsx index d2e669ae9..7d2b127e0 100644 --- a/src/screens/Account/CreateAccount/index.tsx +++ b/src/screens/Account/CreateAccount/index.tsx @@ -37,7 +37,6 @@ export const CreateAccount = ({ route: { params } }: CreateAccountProps) => { const storedDeeplink = mmkvStore.getString('storedDeeplink'); const selectedMnemonicType = mmkvStore.getString(SELECTED_MNEMONIC_TYPE) as MnemonicType; const [accountNameModalVisible, setAccountNameModalVisible] = useState(false); - console.log('selectedMnemonicType', selectedMnemonicType); useHandlerHardwareBackPress(isLoading); @@ -110,13 +109,15 @@ export const CreateAccount = ({ route: { params } }: CreateAccountProps) => { <> {!!seedPhrase && } - + {accountNameModalVisible && ( + + )} navigation.goBack()} diff --git a/src/screens/Account/RestoreJson/ImportJsonAccountSelector/ImportJsonAccountItem.tsx b/src/screens/Account/RestoreJson/ImportJsonAccountSelector/ImportJsonAccountItem.tsx index ec154ee31..549ba86b6 100644 --- a/src/screens/Account/RestoreJson/ImportJsonAccountSelector/ImportJsonAccountItem.tsx +++ b/src/screens/Account/RestoreJson/ImportJsonAccountSelector/ImportJsonAccountItem.tsx @@ -3,21 +3,33 @@ import AccountItemBase from 'components/common/Account/Item/AccountItemBase'; import { View } from 'react-native'; import { AccountProxyAvatar } from 'components/design-system-ui/avatar/account-proxy-avatar'; import { Icon, Logo, Typography } from 'components/design-system-ui'; -import { AccountChainType, AccountProxy, AccountProxyType } from '@subwallet/extension-base/types'; -import { Eye, GitCommit, Needle, QrCode, Question, Strategy, Swatches } from 'phosphor-react-native'; +import { AccountChainType, AccountProxyType } from '@subwallet/extension-base/types'; +import { + CheckCircle, + Eye, + GitCommit, + Needle, + QrCode, + Question, + Strategy, + Swatches, + Warning, +} from 'phosphor-react-native'; import { useSubWalletTheme } from 'hooks/useSubWalletTheme'; import { AccountProxyTypeIcon } from 'components/common/SelectAccountItem'; import { FontSemiBold } from 'styles/sharedStyles'; import { VoidFunction } from 'types/index'; +import { AccountProxyExtra_ } from 'screens/Account/RestoreJson'; interface Props { - accountProxy: AccountProxy; + accountProxy: AccountProxyExtra_; isSelected: boolean; onPress: VoidFunction; + disabled?: boolean; } export const ImportJsonAccountItem = (props: Props) => { - const { accountProxy, isSelected, onPress } = props; + const { accountProxy, isSelected, onPress, disabled } = props; const theme = useSubWalletTheme().swThemes; const chainTypeLogoMap = useMemo(() => { return { @@ -88,6 +100,10 @@ export const ImportJsonAccountItem = (props: Props) => { return null; })(); + const isDuplicated = useMemo(() => { + return (accountProxy.isExistName || accountProxy.isNameDuplicated) && !accountProxy.isExistAccount; + }, [accountProxy.isExistAccount, accountProxy.isExistName, accountProxy.isNameDuplicated]); + const leftItemNode = useMemo( () => ( @@ -144,14 +160,44 @@ export const ImportJsonAccountItem = (props: Props) => { [accountProxy.chainTypes, accountProxy.name, chainTypeLogoMap, theme.colorWhite, theme.paddingXS], ); + const rightItems = useMemo(() => { + return ( + + {isDuplicated && ( + + )} + + {isSelected && ( + + )} + + ); + }, [isDuplicated, isSelected, theme.colorSuccess, theme.colorTextLight4, theme.colorWarning, theme.paddingSM]); + return ( ); }; diff --git a/src/screens/Account/RestoreJson/ImportJsonAccountSelector/index.tsx b/src/screens/Account/RestoreJson/ImportJsonAccountSelector/index.tsx index dc1a7ce3a..d858960ca 100644 --- a/src/screens/Account/RestoreJson/ImportJsonAccountSelector/index.tsx +++ b/src/screens/Account/RestoreJson/ImportJsonAccountSelector/index.tsx @@ -7,6 +7,8 @@ import { ListRenderItemInfo } from '@shopify/flash-list'; import { ImportJsonAccountItem } from 'screens/Account/RestoreJson/ImportJsonAccountSelector/ImportJsonAccountItem'; import { EmptyList } from 'components/EmptyList'; import { MagnifyingGlass } from 'phosphor-react-native'; +import { View } from 'react-native'; +import { useSubWalletTheme } from 'hooks/useSubWalletTheme'; interface Props { value?: string; @@ -23,10 +25,19 @@ interface Props { } export const ImportJsonAccountSelector = ({ grouping, items, accountProxiesSelected, onSelect }: Props) => { + const theme = useSubWalletTheme().swThemes; const renderItem = useCallback( ({ item }: ListRenderItemInfo) => { const selected = accountProxiesSelected.includes(item.id); - return ; + return ( + + ); }, [accountProxiesSelected, onSelect], ); @@ -42,14 +53,16 @@ export const ImportJsonAccountSelector = ({ grouping, items, accountProxiesSelec }; return ( - + + + ); }; diff --git a/src/screens/Account/RestoreJson/index.tsx b/src/screens/Account/RestoreJson/index.tsx index 675c40f15..41da440bf 100644 --- a/src/screens/Account/RestoreJson/index.tsx +++ b/src/screens/Account/RestoreJson/index.tsx @@ -140,6 +140,10 @@ export const RestoreJson = () => { if (result.length === 1) { setAccountProxiesSelected([result[0].id]); } + + if (exitedAccount.length) { + result.push(...exitedAccount); + } return result; }, [accountProxies]); @@ -333,7 +337,7 @@ export const RestoreJson = () => { [isRequirePassword, onImport, onValidatePassword], ); - const { formState, onChangeValue, onSubmitField, focus } = useFormControl(formConfig, { + const { formState, onChangeValue, onSubmitField, focus, onUpdateErrors } = useFormControl(formConfig, { onSubmitForm: onSubmit, }); @@ -384,10 +388,11 @@ export const RestoreJson = () => { setAccountProxies([]); setAccountProxiesSelected([]); setStepState(StepState.UPLOAD_JSON_FILE); + onUpdateErrors('password')([]); } else { navigation.goBack(); } - }, [navigation, onChangeValue, stepState]); + }, [navigation, onChangeValue, onUpdateErrors, stepState]); const onPressSubmitButton = () => { onSubmit(formState); @@ -479,7 +484,11 @@ export const RestoreJson = () => { disableRightButton={submitting}> - {i18n.importAccount.importJsonSubtitle} + + {stepState === StepState.SELECT_ACCOUNT_IMPORT && passwordValidateState.status === 'success' + ? "Select the account(s) you'd like to import" + : i18n.importAccount.importJsonSubtitle} + {stepState === StepState.SELECT_ACCOUNT_IMPORT && showNoValidAccountAlert && ( { accountProxiesSelected={accountProxiesSelected} onSelect={onSelect} grouping={grouping} - onClose={() => setStepState(StepState.UPLOAD_JSON_FILE)} + onClose={() => { + setStepState(StepState.UPLOAD_JSON_FILE); + }} /> )} diff --git a/src/screens/Account/RestoreJson/styles/index.ts b/src/screens/Account/RestoreJson/styles/index.ts index 58ec45c6d..5dfcbb518 100644 --- a/src/screens/Account/RestoreJson/styles/index.ts +++ b/src/screens/Account/RestoreJson/styles/index.ts @@ -40,6 +40,7 @@ const createStyles = (theme: ThemeTypes) => { ...FontMedium, }, description: { + marginTop: theme.marginXS, color: theme.colorTextDescription, fontWeight: theme.bodyFontWeight, ...FontMedium, @@ -75,7 +76,6 @@ const createStyles = (theme: ThemeTypes) => { sectionHeaderContainer: { paddingBottom: theme.sizeXS, backgroundColor: theme.colorBgDefault, - paddingHorizontal: theme.padding, }, sectionHeaderTitle: { ...FontSemiBold, diff --git a/src/screens/Home/Crypto/ReceiveModal.tsx b/src/screens/Home/Crypto/ReceiveModal.tsx index aee5565ba..f284c26df 100644 --- a/src/screens/Home/Crypto/ReceiveModal.tsx +++ b/src/screens/Home/Crypto/ReceiveModal.tsx @@ -60,8 +60,6 @@ export const ReceiveModal = ({ return accountInfo?.accountActions.includes(AccountActions.TON_CHANGE_WALLET_CONTRACT_VERSION); }, [accountInfo]); - console.log('isRelatedToTon', isRelatedToTon); - const copyToClipboard = (text: string) => { return () => { Clipboard.setString(text); diff --git a/src/screens/Transaction/Earn/index.tsx b/src/screens/Transaction/Earn/index.tsx index c7e29b84e..2641182a4 100644 --- a/src/screens/Transaction/Earn/index.tsx +++ b/src/screens/Transaction/Earn/index.tsx @@ -123,7 +123,7 @@ const EarnTransaction: React.FC = (props: EarningProps) => { const defaultTarget = useRef(target); const redirectFromPreviewRef = useRef(!!redirectFromPreview); const autoCheckCompoundRef = useRef(true); - console.log('slug', slug); + const { title, form: {