From 62a8b02a8bccde53a10bbb94cede0a0b81422d69 Mon Sep 17 00:00:00 2001 From: dominhquang Date: Sat, 21 Oct 2023 18:22:49 +0700 Subject: [PATCH] [issue-1066]: Swipe to delete/copy account --- .../common/SelectAccountItem/index.tsx | 1 - .../design-system-ui/button/index.tsx | 2 +- src/screens/Account/AccountsScreen/index.tsx | 277 ++++++++++++++++-- 3 files changed, 258 insertions(+), 22 deletions(-) diff --git a/src/components/common/SelectAccountItem/index.tsx b/src/components/common/SelectAccountItem/index.tsx index 49c5b72a8..6b6bd77c4 100644 --- a/src/components/common/SelectAccountItem/index.tsx +++ b/src/components/common/SelectAccountItem/index.tsx @@ -55,7 +55,6 @@ export const SelectAccountItem = ({ paddingLeft: 12, paddingRight: 4, backgroundColor: theme.colorBgSecondary, - marginBottom: theme.marginXS, borderRadius: theme.borderRadiusLG, }} onPress={() => onSelectAccount && onSelectAccount(address)}> diff --git a/src/components/design-system-ui/button/index.tsx b/src/components/design-system-ui/button/index.tsx index 60c404df4..620fe8f99 100644 --- a/src/components/design-system-ui/button/index.tsx +++ b/src/components/design-system-ui/button/index.tsx @@ -128,7 +128,7 @@ const Button: React.FC = props => { onPressOut={_onPressOut} onShowUnderlay={_onShowUnderlay} onHideUnderlay={_onHideUnderlay}> - + {iconNode} {typeof children === 'string' ? ( diff --git a/src/screens/Account/AccountsScreen/index.tsx b/src/screens/Account/AccountsScreen/index.tsx index 28851dc4a..8cd72fa23 100644 --- a/src/screens/Account/AccountsScreen/index.tsx +++ b/src/screens/Account/AccountsScreen/index.tsx @@ -1,23 +1,44 @@ import { AccountJson } from '@subwallet/extension-base/background/types'; import { SelectAccountItem } from 'components/common/SelectAccountItem'; -import React, { useCallback, useMemo, useRef } from 'react'; -import { Keyboard, ListRenderItemInfo, View } from 'react-native'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; +import { Keyboard, ListRenderItemInfo, Share, StyleProp, View } from 'react-native'; import { useNavigation } from '@react-navigation/native'; import { useSelector } from 'react-redux'; import { RootState } from 'stores/index'; -import { FileArrowDown, MagnifyingGlass, PlusCircle, Swatches } from 'phosphor-react-native'; +import { + Copy, + CopySimple, + FileArrowDown, + MagnifyingGlass, + PlusCircle, + QrCode, + Share as ShareIcon, + Swatches, + Trash, +} from 'phosphor-react-native'; import { AccountsScreenProps, RootNavigationProps } from 'routes/index'; import i18n from 'utils/i18n/i18n'; -import { MarginBottomForSubmitButton } from 'styles/sharedStyles'; -import { saveCurrentAccountAddress } from 'messaging/index'; +import { FontMedium, FontSemiBold, MarginBottomForSubmitButton, STATUS_BAR_HEIGHT } from 'styles/sharedStyles'; +import { forgetAccount, saveCurrentAccountAddress } from 'messaging/index'; import { isAccountAll } from '@subwallet/extension-base/utils'; -import { findAccountByAddress } from 'utils/index'; +import { findAccountByAddress, toShort } from 'utils/index'; import { CurrentAccountInfo } from '@subwallet/extension-base/background/KoniTypes'; -import { Button, Icon } from 'components/design-system-ui'; +import { Avatar, Button, Icon, QRCode, SwModal, Typography } from 'components/design-system-ui'; import { AccountCreationArea } from 'components/common/Account/AccountCreationArea'; import { FlatListScreen } from 'components/FlatListScreen'; import { EmptyList } from 'components/EmptyList'; import { ModalRef } from 'types/modalRef'; +import { Swipeable } from 'react-native-gesture-handler'; +import { useSubWalletTheme } from 'hooks/useSubWalletTheme'; +import Clipboard from '@react-native-clipboard/clipboard'; +import Toast, { useToast } from 'react-native-toast-notifications'; +import { deviceHeight, TOAST_DURATION } from 'constants/index'; +import { ColorMap } from 'styles/color'; +import ToastContainer from 'react-native-toast-notifications'; +import { isEthereumAddress } from '@polkadot/util-crypto'; +import DeleteModal from 'components/common/Modal/DeleteModal'; +import useConfirmModal from 'hooks/modal/useConfirmModal'; +import useGoHome from 'hooks/screen/useGoHome'; const renderListEmptyComponent = () => { return ( @@ -36,15 +57,29 @@ const searchFunction = (items: AccountJson[], searchString: string) => { account.address.toLowerCase().includes(searchString.toLowerCase()), ); }; +const OFFSET_BOTTOM = deviceHeight - STATUS_BAR_HEIGHT - 140; + +const receiveModalContentWrapper: StyleProp = { + alignItems: 'center', + width: '100%', +}; export const AccountsScreen = ({ route: { params: { pathName }, }, }: AccountsScreenProps) => { + const toast = useToast(); + const theme = useSubWalletTheme().swThemes; + const goHome = useGoHome(); const navigation = useNavigation(); const fullAccounts = useSelector((state: RootState) => state.accountState.accounts); const currentAccountAddress = useSelector((state: RootState) => state.accountState.currentAccount?.address); + let svg: { toDataURL: (arg0: (data: any) => void) => void }; + const [qrModalVisible, setQrModalVisible] = useState(false); + const [selectedAddress, setSelectedAddress] = useState(''); + const [deleting, setDeleting] = useState(false); + const toastRef = useRef(null); const accounts = useMemo(() => { if (fullAccounts.length > 2) { return fullAccounts; @@ -56,6 +91,47 @@ export const AccountsScreen = ({ const createAccountRef = useRef(); const importAccountRef = useRef(); const attachAccountRef = useRef(); + let row = useRef<(Swipeable | null)[]>([]); + let prevOpenedRow = useRef(null); + const onDelete = useCallback(() => { + if (selectedAddress) { + setDeleting(true); + forgetAccount(selectedAddress) + .then(() => { + goHome(); + }) + .catch((e: Error) => { + toast.show(e.message, { type: 'danger' }); + }) + .finally(() => { + setDeleting(false); + }); + } + }, [selectedAddress, goHome, toast]); + + const closeOpenedRow = (index: number) => { + if (prevOpenedRow && prevOpenedRow.current !== row.current?.[index]) { + prevOpenedRow.current?.close(); + } + prevOpenedRow = { current: row.current?.[index] }; + }; + + const { + onPress: onPressDelete, + onCancelModal: onCancelDelete, + visible: deleteVisible, + onCompleteModal: onCompleteDeleteModal, + setVisible: setDeleteVisible, + } = useConfirmModal(onDelete); + + const copyToClipboard = useCallback( + (text: string) => { + toast.hideAll(); + toast.show(i18n.common.copiedToClipboard); + Clipboard.setString(text); + }, + [toast], + ); const selectAccount = useCallback( (accAddress: string) => { @@ -90,25 +166,98 @@ export const AccountsScreen = ({ [currentAccountAddress, pathName, accounts, navigation], ); + const onShareImg = () => { + svg.toDataURL(data => { + const shareImageBase64 = { + title: 'QR', + message: `My Public Address to Receive ${selectedAddress}`, + url: `data:image/png;base64,${data}`, + }; + Share.share(shareImageBase64); + }); + }; + + const rightSwipeActions = useCallback( + (address: string, index: number) => { + return () => ( + + + + { + + } + + + + ); };