From 72b54ff86a688fbff4ef6fcb814104add70b3602 Mon Sep 17 00:00:00 2001 From: Gaubee Date: Sat, 17 Jan 2026 00:51:46 +0800 Subject: [PATCH] feat: edit icon visibility + random wallet name from BIP39 wordlist Changes: - MyCardPage: Make edit pencil icon always visible (opacity-50) - wallet/create: Generate random wallet name from locale-specific BIP39 wordlist - Add wallet-utils.ts with generateWalletName function - Support zh-CN, zh-TW, ja, ko wordlists (CJK no space between word and suffix) - Add walletSuffix i18n key to all locales --- src/i18n/locales/ar/onboarding.json | 3 +- src/i18n/locales/en/onboarding.json | 3 +- src/i18n/locales/zh-CN/onboarding.json | 3 +- src/i18n/locales/zh-TW/onboarding.json | 3 +- src/lib/wallet-utils.ts | 45 ++++++++++++++++++++++++++ src/pages/my-card/index.tsx | 4 +-- src/pages/wallet/create.tsx | 8 +++-- 7 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 src/lib/wallet-utils.ts diff --git a/src/i18n/locales/ar/onboarding.json b/src/i18n/locales/ar/onboarding.json index 5b6e9bc14..c6cf688ac 100644 --- a/src/i18n/locales/ar/onboarding.json +++ b/src/i18n/locales/ar/onboarding.json @@ -39,6 +39,7 @@ "confirmWritten": "لقد كتبتها", "createFailed": "فشل في إنشاء المحفظة", "defaultWalletName": "المحفظة الرئيسية", + "walletSuffix": "محفظة", "enterWallet": "دخول المحفظة", "form": { "agreementPrefix": "لقد قرأت ووافقت على", @@ -197,4 +198,4 @@ "similarExists": "يوجد لون مشابه", "auto": "تلقائي" } -} +} \ No newline at end of file diff --git a/src/i18n/locales/en/onboarding.json b/src/i18n/locales/en/onboarding.json index 611fc8bb3..baac4b4d3 100644 --- a/src/i18n/locales/en/onboarding.json +++ b/src/i18n/locales/en/onboarding.json @@ -41,6 +41,7 @@ "confirmWritten": "I have written it down", "createFailed": "Failed to create wallet", "defaultWalletName": "Main Wallet", + "walletSuffix": "Wallet", "enterWallet": "Enter Wallet", "themeTitle": "Choose Card Theme", "themeSubtitle": "Select a theme color for your wallet card", @@ -197,4 +198,4 @@ "similarExists": "Similar color exists", "auto": "Auto" } -} +} \ No newline at end of file diff --git a/src/i18n/locales/zh-CN/onboarding.json b/src/i18n/locales/zh-CN/onboarding.json index 92dc1cebc..3654aa090 100644 --- a/src/i18n/locales/zh-CN/onboarding.json +++ b/src/i18n/locales/zh-CN/onboarding.json @@ -30,6 +30,7 @@ "wordIncorrect": "单词不正确", "complete": "完成创建", "defaultWalletName": "主钱包", + "walletSuffix": "钱包", "createFailed": "创建钱包失败", "themeTitle": "选择卡片主题", "themeSubtitle": "为您的钱包卡片选择一个主题色", @@ -197,4 +198,4 @@ "similarExists": "已有相似颜色", "auto": "自动" } -} +} \ No newline at end of file diff --git a/src/i18n/locales/zh-TW/onboarding.json b/src/i18n/locales/zh-TW/onboarding.json index 414f204c4..5397ae565 100644 --- a/src/i18n/locales/zh-TW/onboarding.json +++ b/src/i18n/locales/zh-TW/onboarding.json @@ -39,6 +39,7 @@ "confirmWritten": "我已抄寫完成", "createFailed": "建立錢包失敗", "defaultWalletName": "主錢包", + "walletSuffix": "錢包", "enterWallet": "進入錢包", "form": { "agreementPrefix": "我已閱讀並同意", @@ -197,4 +198,4 @@ "similarExists": "已有相似顏色", "auto": "自動" } -} +} \ No newline at end of file diff --git a/src/lib/wallet-utils.ts b/src/lib/wallet-utils.ts new file mode 100644 index 000000000..557e8c91a --- /dev/null +++ b/src/lib/wallet-utils.ts @@ -0,0 +1,45 @@ +/** + * Wallet Utilities + * + * Helper functions for wallet management + */ + +import { wordlists } from 'bip39'; + +/** Locale to BIP39 wordlist mapping */ +const LOCALE_WORDLIST_MAP: Record = { + 'zh-CN': wordlists.chinese_simplified, + 'zh-TW': wordlists.chinese_traditional, + 'ja': wordlists.japanese, + 'ko': wordlists.korean, +}; + +/** + * Locales that don't use spaces between words + * (Chinese, Japanese, Korean - CJK languages) + */ +const NO_SPACE_LOCALES = ['zh-CN', 'zh-TW', 'ja', 'ko']; + +/** + * Generate a random wallet name using BIP39 wordlist + * @param locale Current locale (e.g. 'zh-CN', 'en') + * @param suffix Localized suffix (e.g. '钱包', 'Wallet') + * @returns Generated wallet name (e.g. '爱钱包', 'Garden Wallet') + */ +export function generateWalletName(locale: string, suffix: string): string { + // Get wordlist for locale, fallback to English + const wordlist = LOCALE_WORDLIST_MAP[locale] ?? wordlists.english!; + + // Pick a random word + const randomWord = wordlist[Math.floor(Math.random() * wordlist.length)]; + + // Capitalize first letter for non-CJK languages + const formattedWord = NO_SPACE_LOCALES.includes(locale) + ? randomWord + : randomWord.charAt(0).toUpperCase() + randomWord.slice(1); + + // CJK languages don't use spaces + const useSpace = !NO_SPACE_LOCALES.includes(locale); + + return useSpace ? `${formattedWord} ${suffix}` : `${formattedWord}${suffix}`; +} diff --git a/src/pages/my-card/index.tsx b/src/pages/my-card/index.tsx index b6681bba8..66113c87d 100644 --- a/src/pages/my-card/index.tsx +++ b/src/pages/my-card/index.tsx @@ -148,7 +148,7 @@ export function MyCardPage() { }, [handleUsernameSave]); // Snapdom share hook - const { isProcessing: isDownloading, download: handleDownload, share: handleShare, canShare } = useSnapdomShare( + const { isProcessing: isDownloading, download: handleDownload, share: handleShare } = useSnapdomShare( cardRef, { filename: `my-card-${Date.now()}`, @@ -197,7 +197,7 @@ export function MyCardPage() { className="group mb-6 flex items-center gap-2 text-xl font-semibold" > {displayName} - + )} diff --git a/src/pages/wallet/create.tsx b/src/pages/wallet/create.tsx index 4f87abc62..7779b0108 100644 --- a/src/pages/wallet/create.tsx +++ b/src/pages/wallet/create.tsx @@ -17,8 +17,9 @@ import { IconCircleKey as KeyRound, IconCircleCheck as CheckCircle, } from '@tabler/icons-react'; -import { useChainConfigs, walletActions } from '@/stores'; +import { useChainConfigs, walletActions, useLanguage } from '@/stores'; import { generateMnemonic } from '@/lib/crypto'; +import { generateWalletName } from '@/lib/wallet-utils'; import { deriveWalletChainAddresses } from '@/services/chain-adapter'; import { deriveThemeHue } from '@/hooks/useWalletTheme'; import type { ChainConfig } from '@/services/chain-config'; @@ -31,6 +32,7 @@ export function WalletCreatePage() { const { goBack, navigate } = useNavigation(); const { t } = useTranslation('onboarding'); const chainConfigs = useChainConfigs(); + const currentLanguage = useLanguage(); const [step, setStep] = useState('pattern'); const [patternKey, setPatternKey] = useState(''); const [mnemonic] = useState(() => { @@ -122,7 +124,7 @@ export function WalletCreatePage() { const wallet = await walletActions.createWallet( { - name: t('create.defaultWalletName'), + name: generateWalletName(currentLanguage, t('create.walletSuffix')), keyType: 'mnemonic', address: primaryChain.address, chain: primaryChain.chain, @@ -138,7 +140,7 @@ export function WalletCreatePage() { setCreatedWalletId(wallet.id); setStep('theme'); } catch (error) { - + } finally { setIsCreating(false); }