Skip to content

Commit

Permalink
[Issue-1826] Implement Export Account
Browse files Browse the repository at this point in the history
  • Loading branch information
dominhquang committed Nov 4, 2024
1 parent 59820d8 commit 50d8bb4
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 65 deletions.
50 changes: 28 additions & 22 deletions src/components/Modal/AccountNameModal.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -29,19 +29,20 @@ export const AccountNameModal = ({
}: Props) => {
const theme = useSubWalletTheme().swThemes;
const modalRef = useRef<SWModalRefProps>(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;
Expand All @@ -52,12 +53,9 @@ export const AccountNameModal = ({
name: i18n.common.accountName,
value: '',
require: true,
validateFunc: (value: string) => {
return validatorFunc(value);
},
},
}),
[validatorFunc],
[],
);

const _onSubmit = useCallback(
Expand All @@ -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(
() => (
Expand Down Expand Up @@ -115,15 +117,19 @@ export const AccountNameModal = ({
isAllowSwipeDown={Platform.OS === 'ios'}
modalBaseV2Ref={modalRef}
footer={footerNode}>
<Typography.Text style={{ color: theme.colorTextTertiary, textAlign: 'center', paddingBottom: theme.paddingLG }}>
{'Enter a name for your account.\n' + ' You can edit this later.'}
</Typography.Text>
<EditAccountInputText
ref={formState.refs.accountName}
label={formState.labels.accountName}
editAccountInputStyle={{ marginBottom: theme.margin }}
editAccountInputStyle={{ marginBottom: theme.margin, paddingBottom: theme.paddingXS }}
value={formState.data.accountName}
onChangeText={onChangeAccountName}
onSubmitField={onSubmitField('accountName')}
accountType={accountType}
isDisabled={isLoading}
errorMessages={formState.errors.accountName}
/>
</SwModal>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 0 additions & 3 deletions src/components/common/Modal/DeriveAccountModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ export const AccountChainAddressItem = ({ item, onPress, onPressCopyButton, onPr
<Logo network={item.slug} shape={'circle'} size={28} />

<View style={styles.centerPart}>
<Typography.Text style={styles.chainName}>{item.name}</Typography.Text>
<Typography.Text ellipsis style={styles.chainName}>
{item.name}
</Typography.Text>
<Typography.Text style={styles.address}>{toShort(item.address, 4, 5)}</Typography.Text>
</View>

Expand Down Expand Up @@ -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,
Expand Down
12 changes: 7 additions & 5 deletions src/components/design-system-ui/web3-block/Web3Block/index.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -19,6 +19,7 @@ export interface Web3BlockProps {
renderRightItem?: (dItem: React.ReactNode) => React.ReactNode;
onPress?: () => void;
customStyle?: Web3BlockCustomStyle;
disabled?: boolean;
}

function defaultRender(x: React.ReactNode) {
Expand All @@ -35,20 +36,21 @@ const Web3Block: React.FC<Web3BlockProps> = (props: Web3BlockProps) => {
renderRightItem = defaultRender,
rightItem,
customStyle,
disabled,
} = props;
const theme = useSubWalletTheme().swThemes;
const styles = useMemo(() => createStyle(theme), [theme]);

const Wrapper = useMemo((): React.FC<ViewProps> => {
const Wrapper = useMemo(() => {
if (onPress) {
return (_props: ViewProps) => <TouchableOpacity onPress={onPress} activeOpacity={0.8} {..._props} />;
return (_props: TouchableOpacityProps) => <TouchableOpacity onPress={onPress} activeOpacity={0.8} {..._props} />;
} else {
return (_props: ViewProps) => <View {..._props} />;
}
}, [onPress]);

return (
<Wrapper style={[styles.container, customStyle?.container]}>
<Wrapper style={[styles.container, customStyle?.container]} disabled={disabled}>
{!!leftItem && <View style={[styles.left, customStyle?.left]}>{renderLeftItem(leftItem)}</View>}
{!!middleItem && <View style={[styles.middle, customStyle?.middle]}>{renderMiddleItem(middleItem)}</View>}
{!!rightItem && <View style={[styles.right, customStyle?.right]}>{renderRightItem(rightItem)}</View>}
Expand Down
1 change: 0 additions & 1 deletion src/screens/Account/ConnectQrSigner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ const ConnectQrSigner: React.FC<Props> = (props: Props) => {
const [accountNameModalVisible, setAccountNameModalVisible] = useState<boolean>(false);
const styles = useMemo(() => createStyle(theme), [theme]);
const goHome = useGoHome();
console.log('accountNameModalVisible', accountNameModalVisible);

const onComplete = useCallback(() => {
navigation.reset({
Expand Down
17 changes: 9 additions & 8 deletions src/screens/Account/CreateAccount/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean>(false);
console.log('selectedMnemonicType', selectedMnemonicType);

useHandlerHardwareBackPress(isLoading);

Expand Down Expand Up @@ -110,13 +109,15 @@ export const CreateAccount = ({ route: { params } }: CreateAccountProps) => {
<>
{!!seedPhrase && <SecretPhraseArea seed={seedPhrase} onPressSubmit={onSubmit(onPressSubmitInitSecretPhrase)} />}

<AccountNameModal
modalVisible={accountNameModalVisible}
setModalVisible={setAccountNameModalVisible}
accountType={selectedMnemonicType === 'general' ? AccountProxyType.UNIFIED : AccountProxyType.SOLO}
isLoading={isLoading}
onSubmit={_onSubmit}
/>
{accountNameModalVisible && (
<AccountNameModal
modalVisible={accountNameModalVisible}
setModalVisible={setAccountNameModalVisible}
accountType={selectedMnemonicType === 'general' ? AccountProxyType.UNIFIED : AccountProxyType.SOLO}
isLoading={isLoading}
onSubmit={_onSubmit}
/>
)}

<TnCSeedPhraseModal
onBackButtonPress={() => navigation.goBack()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
() => (
<View style={{ position: 'relative' }}>
Expand Down Expand Up @@ -144,14 +160,44 @@ export const ImportJsonAccountItem = (props: Props) => {
[accountProxy.chainTypes, accountProxy.name, chainTypeLogoMap, theme.colorWhite, theme.paddingXS],
);

const rightItems = useMemo(() => {
return (
<View style={{ flexDirection: 'row', alignItems: 'center', gap: theme.paddingSM - 2 }}>
{isDuplicated && (
<Icon
iconColor={isDuplicated ? theme.colorWarning : theme.colorTextLight4}
phosphorIcon={Warning}
size="sm"
type="phosphor"
weight="fill"
/>
)}

{isSelected && (
<Icon
iconColor={isSelected ? theme.colorSuccess : theme.colorTextLight4}
phosphorIcon={CheckCircle}
size="sm"
type="phosphor"
weight="fill"
/>
)}
</View>
);
}, [isDuplicated, isSelected, theme.colorSuccess, theme.colorTextLight4, theme.colorWarning, theme.paddingSM]);

return (
<AccountItemBase
customStyle={{ container: { marginBottom: theme.marginXS, height: 58 } }}
customStyle={{
container: [{ marginBottom: theme.marginXS, height: 58 }, disabled && { opacity: theme.opacityDisable }],
}}
disabled={disabled}
onPress={onPress}
isSelected={isSelected}
address={''}
leftItem={leftItemNode}
middleItem={middleItemNode}
rightItem={rightItems}
/>
);
};
33 changes: 23 additions & 10 deletions src/screens/Account/RestoreJson/ImportJsonAccountSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -23,10 +25,19 @@ interface Props {
}

export const ImportJsonAccountSelector = ({ grouping, items, accountProxiesSelected, onSelect }: Props) => {
const theme = useSubWalletTheme().swThemes;
const renderItem = useCallback(
({ item }: ListRenderItemInfo<AccountProxyExtra_>) => {
const selected = accountProxiesSelected.includes(item.id);
return <ImportJsonAccountItem key={item.id} accountProxy={item} isSelected={selected} onPress={onSelect(item)} />;
return (
<ImportJsonAccountItem
disabled={item.group === 'existed_accounts'}
key={item.id}
accountProxy={item}
isSelected={selected}
onPress={onSelect(item)}
/>
);
},
[accountProxiesSelected, onSelect],
);
Expand All @@ -42,14 +53,16 @@ export const ImportJsonAccountSelector = ({ grouping, items, accountProxiesSelec
};

return (
<LazySectionList
items={items}
renderItem={renderItem}
renderListEmptyComponent={renderEmptyList}
groupBy={grouping?.groupBy}
renderSectionHeader={grouping?.renderSectionHeader}
estimatedItemSize={60}
extraData={accountProxiesSelected}
/>
<View style={{ paddingTop: theme.paddingXS }}>
<LazySectionList
items={items}
renderItem={renderItem}
renderListEmptyComponent={renderEmptyList}
groupBy={grouping?.groupBy}
renderSectionHeader={grouping?.renderSectionHeader}
estimatedItemSize={60}
extraData={accountProxiesSelected}
/>
</View>
);
};
Loading

0 comments on commit 50d8bb4

Please sign in to comment.