diff --git a/apps/ui-icons/src/Loader.tsx b/apps/ui-icons/src/Loader.tsx new file mode 100644 index 00000000000..fba3de2c72d --- /dev/null +++ b/apps/ui-icons/src/Loader.tsx @@ -0,0 +1,23 @@ +// Copyright (c) 2024 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import { SVGProps } from 'react'; +export default function SvgLoader(props: SVGProps) { + return ( + + + + ); +} diff --git a/apps/ui-icons/src/index.ts b/apps/ui-icons/src/index.ts index 14d5ea0af18..21ce449ee70 100644 --- a/apps/ui-icons/src/index.ts +++ b/apps/ui-icons/src/index.ts @@ -44,6 +44,7 @@ export { default as Ledger } from './Ledger'; export { default as ListViewLarge } from './ListViewLarge'; export { default as ListViewMedium } from './ListViewMedium'; export { default as ListViewSmall } from './ListViewSmall'; +export { default as Loader } from './Loader'; export { default as LockLocked } from './LockLocked'; export { default as LockUnlocked } from './LockUnlocked'; export { default as Logout } from './Logout'; diff --git a/apps/ui-icons/svgs/loader.svg b/apps/ui-icons/svgs/loader.svg new file mode 100644 index 00000000000..afefe5b4702 --- /dev/null +++ b/apps/ui-icons/svgs/loader.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/wallet/src/ui/app/components/Overlay.tsx b/apps/wallet/src/ui/app/components/Overlay.tsx index f654648db4b..f1fe4ec000d 100644 --- a/apps/wallet/src/ui/app/components/Overlay.tsx +++ b/apps/wallet/src/ui/app/components/Overlay.tsx @@ -16,6 +16,7 @@ interface OverlayProps { closeIcon?: ReactNode | null; setShowModal?: (showModal: boolean) => void; background?: 'bg-iota-lightest'; + titleCentered?: boolean; showBackButton?: boolean; } @@ -24,8 +25,9 @@ export function Overlay({ children, showModal, closeOverlay, - showBackButton, setShowModal, + titleCentered = true, + showBackButton, }: OverlayProps) { const closeModal = useCallback( (e: React.MouseEvent) => { @@ -42,9 +44,9 @@ export function Overlay({ {title && (
)}
diff --git a/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx b/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx index 3201fa7f001..4c4f021c47f 100644 --- a/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx +++ b/apps/wallet/src/ui/app/components/ledger/LedgerAccountList.tsx @@ -2,8 +2,19 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { LedgerAccountRow } from './LedgerAccountRow'; +import { + Table, + TableBody, + TableBodyRow, + TableCell, + TableCellType, + TableHeader, + TableHeaderCell, + TableHeaderRow, +} from '@iota/apps-ui-kit'; import { type DerivedLedgerAccount } from './useDeriveLedgerAccounts'; +import { formatAddress, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; +import { useBalance, useFormatCoin, useResolveIotaNSName } from '@iota/core'; export type SelectableLedgerAccount = DerivedLedgerAccount & { isSelected: boolean; @@ -12,26 +23,57 @@ export type SelectableLedgerAccount = DerivedLedgerAccount & { interface LedgerAccountListProps { accounts: SelectableLedgerAccount[]; onAccountClick: (account: SelectableLedgerAccount) => void; + selectAll: () => void; } -export function LedgerAccountList({ accounts, onAccountClick }: LedgerAccountListProps) { +export function LedgerAccountList({ accounts, onAccountClick, selectAll }: LedgerAccountListProps) { + const headersData = [ + { label: 'Address', columnKey: 1 }, + { label: '', columnKey: 2 }, + ]; + + const rowsData = accounts.map((account) => { + const { data: coinBalance } = useBalance(account.address); + const { data: domainName } = useResolveIotaNSName(account.address); + const [totalAmount, totalAmountSymbol] = useFormatCoin( + coinBalance?.totalBalance ?? 0, + IOTA_TYPE_ARG, + ); + + return [ + { + label: domainName ?? formatAddress(account.address), + }, + { + label: `${totalAmount} ${totalAmountSymbol}`, + }, + ]; + }); + return ( -
    - {accounts.map((account) => ( -
  • - -
  • - ))} -
+ { + onAccountClick(accounts[index]); + }} + onHeaderCheckboxChange={() => selectAll()} + > + + + {headersData.map((header, index) => ( + + ))} + + + + {rowsData.map((row, rowIndex) => ( + + {row.map((cell, cellIndex) => ( + + ))} + + ))} + +
); } diff --git a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx b/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx deleted file mode 100644 index 8dff991603b..00000000000 --- a/apps/wallet/src/ui/app/components/ledger/LedgerAccountRow.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Mysten Labs, Inc. -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -import { Text } from '_src/ui/app/shared/text'; -import { useBalance, useFormatCoin, useResolveIotaNSName } from '@iota/core'; -import { CheckFill16 } from '@iota/icons'; -import { formatAddress, IOTA_TYPE_ARG } from '@iota/iota-sdk/utils'; -import cl from 'clsx'; - -interface LedgerAccountRowProps { - isSelected: boolean; - address: string; -} - -export function LedgerAccountRow({ isSelected, address }: LedgerAccountRowProps) { - const { data: coinBalance } = useBalance(address); - const { data: domainName } = useResolveIotaNSName(address); - const [totalAmount, totalAmountSymbol] = useFormatCoin( - coinBalance?.totalBalance ?? 0, - IOTA_TYPE_ARG, - ); - - return ( -
- - - {domainName ?? formatAddress(address)} - -
- - {totalAmount} {totalAmountSymbol} - -
-
- ); -} diff --git a/apps/wallet/src/ui/app/components/ledger/index.ts b/apps/wallet/src/ui/app/components/ledger/index.ts index e9111408bb9..59794993c1e 100644 --- a/apps/wallet/src/ui/app/components/ledger/index.ts +++ b/apps/wallet/src/ui/app/components/ledger/index.ts @@ -4,6 +4,5 @@ export * from './ConnectLedgerModal'; export * from './IotaLedgerClientProvider'; export * from './LedgerAccountList'; -export * from './LedgerAccountRow'; export * from './ledgerErrors'; export * from './useDeriveLedgerAccounts'; diff --git a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx b/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx index 7554fa27075..a17f3efd372 100644 --- a/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx +++ b/apps/wallet/src/ui/app/pages/accounts/ImportLedgerAccountsPage.tsx @@ -2,18 +2,9 @@ // Modifications Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -import { Button } from '_src/ui/app/shared/ButtonUI'; -import { Link } from '_src/ui/app/shared/Link'; -import { Text } from '_src/ui/app/shared/text'; -import { - Spinner16 as SpinnerIcon, - ThumbUpStroke32 as ThumbUpIcon, - LockUnlocked16 as UnlockedLockIcon, -} from '@iota/icons'; import { useCallback, useEffect, useState } from 'react'; import toast from 'react-hot-toast'; import { useNavigate, useSearchParams } from 'react-router-dom'; - import { AccountsFormType, useAccountsFormContext, @@ -25,6 +16,8 @@ import { } from '_components'; import { getIotaApplicationErrorMessage } from '../../helpers/errorMessages'; import { useAccounts } from '../../hooks/useAccounts'; +import { Button } from '@iota/apps-ui-kit'; +import { CheckmarkFilled, Loader } from '@iota/ui-icons'; const NUM_LEDGER_ACCOUNTS_TO_DERIVE_BY_DEFAULT = 10; @@ -74,107 +67,91 @@ export function ImportLedgerAccountsPage() { const numImportableAccounts = ledgerAccounts?.length; const numSelectedAccounts = selectedLedgerAccounts.length; const areAllAccountsImported = numImportableAccounts === 0; - const areAllAccountsSelected = numSelectedAccounts === numImportableAccounts; const isUnlockButtonDisabled = numSelectedAccounts === 0; - const isSelectAllButtonDisabled = areAllAccountsImported || areAllAccountsSelected; const [, setAccountsFormValues] = useAccountsFormContext(); - let summaryCardBody: JSX.Element | null = null; + let importLedgerAccountsBody: JSX.Element | null = null; if (areLedgerAccountsLoading) { - summaryCardBody = ( -
- - - Looking for accounts - -
- ); + importLedgerAccountsBody = ; } else if (areAllAccountsImported) { - summaryCardBody = ( -
- - - All Ledger accounts have been imported. - -
- ); + importLedgerAccountsBody = ; } else if (!encounteredDerviceAccountsError) { const selectedLedgerAddresses = selectedLedgerAccounts.map(({ address }) => address); - summaryCardBody = ( -
+ importLedgerAccountsBody = ( +
({ ...ledgerAccount, isSelected: selectedLedgerAddresses.includes(ledgerAccount.address), }))} onAccountClick={onAccountClick} + selectAll={selectAllAccounts} />
); } + function selectAllAccounts() { + if (ledgerAccounts) { + setSelectedLedgerAccounts(ledgerAccounts); + } + } + + function handleNextClick() { + setAccountsFormValues({ + type: AccountsFormType.ImportLedger, + accounts: selectedLedgerAccounts.map(({ address, derivationPath, publicKey }) => ({ + address, + derivationPath, + publicKey: publicKey!, + })), + }); + navigate( + `/accounts/protect-account?${new URLSearchParams({ + accountsFormType: AccountsFormType.ImportLedger, + successRedirect, + }).toString()}`, + ); + } + return ( { navigate(-1); }} + titleCentered={false} > -
-
-
- - {areAllAccountsImported - ? 'Ledger Accounts ' - : 'Connect Ledger Accounts'} - -
-
{summaryCardBody}
-
-
- { - if (ledgerAccounts) { - setSelectedLedgerAccounts(ledgerAccounts); - } - }} - disabled={isSelectAllButtonDisabled} - /> -
-
-
+
+ {importLedgerAccountsBody}
); } + +function LedgerViewLoading() { + return ( +
+ + Looking for Accounts... +
+ ); +} + +function LedgerViewAllAccountsImported() { + return ( +
+ + Imported all Ledger Accounts +
+ ); +}