From 82fe62c136ef3c52cfe4f32d37bfd6e9f947222a Mon Sep 17 00:00:00 2001 From: Sergey Zhuravlev Date: Fri, 24 Jan 2025 15:44:20 +0100 Subject: [PATCH] feat: more refined ui flow for extension wallets --- .../components/DropdownOptions.tsx | 79 ++++++++++++++++++ .../components/OnboardingCards.tsx | 56 +++++++++++++ .../features/extension-wallet/index.tsx | 83 ++----------------- src/renderer/shared/i18n/locales/en.json | 7 +- .../WalletOnboardingCard.tsx | 23 +++-- .../shared/ui-kit/Dropdown/Dropdown.tsx | 1 + 6 files changed, 160 insertions(+), 89 deletions(-) create mode 100644 src/renderer/features/extension-wallet/components/DropdownOptions.tsx create mode 100644 src/renderer/features/extension-wallet/components/OnboardingCards.tsx diff --git a/src/renderer/features/extension-wallet/components/DropdownOptions.tsx b/src/renderer/features/extension-wallet/components/DropdownOptions.tsx new file mode 100644 index 0000000000..54a763a167 --- /dev/null +++ b/src/renderer/features/extension-wallet/components/DropdownOptions.tsx @@ -0,0 +1,79 @@ +import { useUnit } from 'effector-react'; +import { type ReactNode } from 'react'; + +import { WalletType } from '@/shared/core'; +import { useI18n } from '@/shared/i18n'; +import { nonNullable, nullable } from '@/shared/lib/utils'; +import { Icon } from '@/shared/ui'; +import { Dropdown, Label } from '@/shared/ui-kit'; +import { walletIcon } from '../constants'; +import { wallets } from '../model/wallets'; + +import { PairingModal } from './PairingModal'; + +export const DropdownOptions = () => { + const { t } = useI18n(); + const polkadotjsExtension = useUnit(wallets.$polkadotJsExtensionWallet); + const talismanExtension = useUnit(wallets.$talismanExtensionWallet); + const subWalletExtension = useUnit(wallets.$subWalletExtensionWallet); + + const installed: ReactNode[] = []; + const notInstalled: ReactNode[] = []; + + const polkadotOption = ( + + + + {t('wallets.addPolkadotExtension')} + {nonNullable(polkadotjsExtension) && } + + + ); + + const talismanOption = ( + + + + {t('wallets.addTalismanExtension')} + {nonNullable(talismanExtension) && } + + + ); + + const subwallet = ( + + + + {t('wallets.addSubWalletExtension')} + {nonNullable(subWalletExtension) && } + + + ); + + if (nonNullable(polkadotjsExtension)) { + installed.push(polkadotOption); + } else { + notInstalled.push(polkadotOption); + } + + if (nonNullable(talismanExtension)) { + installed.push(talismanOption); + } else { + notInstalled.push(talismanOption); + } + + if (nonNullable(subWalletExtension)) { + installed.push(subwallet); + } else { + notInstalled.push(subwallet); + } + + return ( + <> + {installed} + {notInstalled.length > 0 && ( + {notInstalled} + )} + + ); +}; diff --git a/src/renderer/features/extension-wallet/components/OnboardingCards.tsx b/src/renderer/features/extension-wallet/components/OnboardingCards.tsx new file mode 100644 index 0000000000..ecbea6a4ed --- /dev/null +++ b/src/renderer/features/extension-wallet/components/OnboardingCards.tsx @@ -0,0 +1,56 @@ +import { useUnit } from 'effector-react'; + +import { TEST_IDS } from '@/shared/constants'; +import { WalletType } from '@/shared/core'; +import { useI18n } from '@/shared/i18n'; +import { nonNullable, nullable } from '@/shared/lib/utils'; +import { WalletOnboardingCard } from '@/shared/ui-entities'; +import { walletIcon } from '../constants'; +import { wallets } from '../model/wallets'; + +import { PairingModal } from './PairingModal'; + +export const OnboardingCards = () => { + const { t } = useI18n(); + const polkadotjsExtension = useUnit(wallets.$polkadotJsExtensionWallet); + const talismanExtension = useUnit(wallets.$talismanExtensionWallet); + const subWalletExtension = useUnit(wallets.$subWalletExtensionWallet); + + return ( + <> + + + + + + + + + + + ); +}; diff --git a/src/renderer/features/extension-wallet/index.tsx b/src/renderer/features/extension-wallet/index.tsx index 97ca96a180..62b052c390 100644 --- a/src/renderer/features/extension-wallet/index.tsx +++ b/src/renderer/features/extension-wallet/index.tsx @@ -1,18 +1,15 @@ import { useUnit } from 'effector-react'; -import { TEST_IDS } from '@/shared/constants'; import { WalletType } from '@/shared/core'; import { useI18n } from '@/shared/i18n'; -import { nullable } from '@/shared/lib/utils'; import { Icon } from '@/shared/ui'; -import { WalletOnboardingCard } from '@/shared/ui-entities'; -import { Dropdown, Label } from '@/shared/ui-kit'; import { accountsService } from '@/domains/network'; import { walletPairingDropdownOptionsSlot } from '@/features/wallet-pairing'; import { walletGroupSlot, walletIconSlot } from '@/features/wallet-select'; import { onboardingActionsSlot } from '@/pages/Onboarding'; -import { PairingModal } from './components/PairingModal'; +import { DropdownOptions } from './components/DropdownOptions'; +import { OnboardingCards } from './components/OnboardingCards'; import { WalletGroup, walletActionsSlot } from './components/WalletGroup'; import { walletIcon } from './constants'; import { extensionWalletFeature } from './model/feature'; @@ -38,83 +35,13 @@ extensionWalletFeature.inject(walletIconSlot, ({ wallet, size }) => { }); extensionWalletFeature.inject(walletPairingDropdownOptionsSlot, { - order: 3, - render({ t }) { - const polkadotjsExtension = useUnit(wallets.$polkadotJsExtensionWallet); - const talismanExtension = useUnit(wallets.$talismanExtensionWallet); - const subWalletExtension = useUnit(wallets.$subWalletExtensionWallet); - - return ( - <> - - - - {t('wallets.addPolkadotExtension')} - - - - - - - {t('wallets.addTalismanExtension')} - - - - - - - {t('wallets.addSubWalletExtension')} - - - - - ); - }, + order: 4, + render: () => , }); extensionWalletFeature.inject(onboardingActionsSlot, { order: 5, - render() { - const { t } = useI18n(); - const polkadotjsExtension = useUnit(wallets.$polkadotJsExtensionWallet); - const talismanExtension = useUnit(wallets.$talismanExtensionWallet); - const subWalletExtension = useUnit(wallets.$subWalletExtensionWallet); - - return ( - <> - - - - - - - - - - - ); - }, + render: () => , }); extensionWalletFeature.inject(walletGroupSlot, { diff --git a/src/renderer/shared/i18n/locales/en.json b/src/renderer/shared/i18n/locales/en.json index adc995793d..3401fb6cf3 100644 --- a/src/renderer/shared/i18n/locales/en.json +++ b/src/renderer/shared/i18n/locales/en.json @@ -954,11 +954,11 @@ "ledgerDescription": "Ledger's the smartest way to secure, buy, exchange and grow your crypto assets", "ledgerTitle": "Ledger", "polkadotExtensionTitle": "Polkadot js extension", - "polkadotExtensionDescription": "Simple, secure access to Polkadot and Substrate chains via a browser extension", + "polkadotExtensionDescription": "Multi-chain browser extension", "talismanTitle": "Talisman", - "talismanDescription": "Simple, secure access to Polkadot and Substrate chains via a browser extension", + "talismanDescription": "Multi-chain browser extension", "subWalletTitle": "SubWallet extension", - "subWalletDescription": "Simple, secure access to Polkadot and Substrate chains via a browser extension", + "subWalletDescription": "Multi-chain browser extension", "novaWalletDescription": "Seamless and secure transaction signing with Nova Wallet, leading mobile application for Polkadot eco", "novaWalletTitle": "Nova Wallet", "polkadotVaultDescription": "Use dedicated hardware wallet for Polkadot, Kusama, and other Substrate-based chains", @@ -971,6 +971,7 @@ "watchOnlyDescription": "Track the activity of any wallet without injecting your private key to Nova Spektr", "watchOnlyTitle": "Watch-only" }, + "extensionNotInstalled": "Not Installed", "yourAccountsLabel": "Here are your accounts" }, "operation": { diff --git a/src/renderer/shared/ui-entities/WalletOnboardingCard/WalletOnboardingCard.tsx b/src/renderer/shared/ui-entities/WalletOnboardingCard/WalletOnboardingCard.tsx index aae7e11d2a..4663371de6 100644 --- a/src/renderer/shared/ui-entities/WalletOnboardingCard/WalletOnboardingCard.tsx +++ b/src/renderer/shared/ui-entities/WalletOnboardingCard/WalletOnboardingCard.tsx @@ -10,6 +10,7 @@ type Props = { description: string; iconName: IconNames; beta?: boolean; + notInstalled?: boolean; soon?: boolean; disabled?: boolean; testId?: string; @@ -17,16 +18,26 @@ type Props = { }; export const WalletOnboardingCard = forwardRef( - ({ title, beta, soon, description, iconName, disabled, onClick, testId = 'WelcomeCard' }, ref) => { + ({ title, beta, soon, notInstalled, description, iconName, disabled, onClick, testId = 'WelcomeCard' }, ref) => { const { t } = useI18n(); + let farEndLabel; + + if (soon) { + farEndLabel = ; + } else if (notInstalled) { + farEndLabel = ; + } else { + farEndLabel = ; + } + return (