Unify create/import into single Add Wallet view
All checks were successful
check / check (push) Successful in 13s

Merge "Create new wallet" and "Import recovery phrase" into one
"Add wallet" screen. The recovery phrase textarea starts empty.
A clickable die button generates a random phrase and shows a
backup warning. Users who already have a phrase just paste it.
Welcome screen simplified to two options: "Add wallet" and
"Import private key". README updated to match.
This commit is contained in:
2026-02-25 15:24:24 +07:00
parent 8431488849
commit 1a49665210
3 changed files with 139 additions and 248 deletions

View File

@@ -4,11 +4,9 @@
const VIEWS = [
"lock",
"welcome",
"create",
"import-phrase",
"add-wallet",
"import-key",
"main",
"add-wallet",
"address",
"send",
"receive",
@@ -72,6 +70,25 @@ function makeStubAddress() {
};
}
function generateStubMnemonic() {
// TODO: replace with real BIP-39 generation via background
const words = [
"abandon",
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"absurd",
"abuse",
"access",
"accident",
];
return words.join(" ");
}
// -- render wallet list on main view --
function renderWalletList() {
const container = $("wallet-list");
@@ -102,7 +119,6 @@ function renderWalletList() {
});
container.innerHTML = html;
// bind clicks on address rows
container.querySelectorAll(".address-row").forEach((row) => {
row.addEventListener("click", () => {
state.selectedWallet = parseInt(row.dataset.wallet, 10);
@@ -111,11 +127,11 @@ function renderWalletList() {
});
});
// bind clicks on + buttons within HD wallets
container.querySelectorAll(".btn-add-address").forEach((btn) => {
btn.addEventListener("click", (e) => {
e.stopPropagation();
const wi = parseInt(btn.dataset.wallet, 10);
// TODO: derive next address from seed via background
state.wallets[wi].addresses.push(makeStubAddress());
renderWalletList();
});
@@ -179,39 +195,29 @@ function addWalletAndGoToMain(wallet) {
showView("main");
}
function showImportView(type) {
if (type === "phrase") {
$("import-mnemonic").value = "";
hideError("import-phrase-error");
const needsPw = state.isFirstSetup;
$("import-phrase-password-section").classList.toggle(
"hidden",
!needsPw,
);
$("import-phrase-password-confirm-section").classList.toggle(
"hidden",
!needsPw,
);
showView("import-phrase");
} else {
$("import-private-key").value = "";
hideError("import-key-error");
const needsPw = state.isFirstSetup;
$("import-key-password-section").classList.toggle("hidden", !needsPw);
$("import-key-password-confirm-section").classList.toggle(
"hidden",
!needsPw,
);
showView("import-key");
}
function showAddWalletView() {
$("wallet-mnemonic").value = "";
$("add-wallet-phrase-warning").classList.add("hidden");
hideError("add-wallet-error");
const needsPw = state.isFirstSetup;
$("add-wallet-password-section").classList.toggle("hidden", !needsPw);
$("add-wallet-password-confirm-section").classList.toggle(
"hidden",
!needsPw,
);
showView("add-wallet");
}
function showCreateView() {
// TODO: generate real mnemonic via background
$("create-mnemonic").textContent =
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
hideError("create-error");
showView("create");
function showImportKeyView() {
$("import-private-key").value = "";
hideError("import-key-error");
const needsPw = state.isFirstSetup;
$("import-key-password-section").classList.toggle("hidden", !needsPw);
$("import-key-password-confirm-section").classList.toggle(
"hidden",
!needsPw,
);
showView("import-key");
}
function validatePasswords(pwId, pw2Id, errorId) {
@@ -234,6 +240,15 @@ function validatePasswords(pwId, pw2Id, errorId) {
return true;
}
function backFromWalletAdd() {
if (state.isFirstSetup) {
showView("welcome");
} else {
renderWalletList();
showView("main");
}
}
// -- init --
function init() {
if (!state.hasWallet) {
@@ -260,51 +275,29 @@ function init() {
});
// -- Welcome --
$("btn-welcome-new").addEventListener("click", showCreateView);
$("btn-welcome-recovery").addEventListener("click", () =>
showImportView("phrase"),
);
$("btn-welcome-key").addEventListener("click", () => showImportView("key"));
$("btn-welcome-add").addEventListener("click", showAddWalletView);
$("btn-welcome-key").addEventListener("click", showImportKeyView);
// -- Create wallet --
$("btn-create-confirm").addEventListener("click", () => {
if (
!validatePasswords(
"create-password",
"create-password-confirm",
"create-error",
)
) {
return;
}
hideError("create-error");
const walletNum = state.wallets.length + 1;
addWalletAndGoToMain({
type: "hd",
name: "Wallet " + walletNum,
mnemonic: $("create-mnemonic").textContent,
addresses: [makeStubAddress()],
});
// -- Add wallet (unified create/import) --
$("btn-generate-phrase").addEventListener("click", () => {
const phrase = generateStubMnemonic();
$("wallet-mnemonic").value = phrase;
$("add-wallet-phrase-warning").classList.remove("hidden");
});
$("btn-create-back").addEventListener("click", () => {
showView(state.isFirstSetup ? "welcome" : "add-wallet");
});
// -- Import recovery phrase --
$("btn-import-phrase-confirm").addEventListener("click", () => {
const mnemonic = $("import-mnemonic").value.trim();
$("btn-add-wallet-confirm").addEventListener("click", () => {
const mnemonic = $("wallet-mnemonic").value.trim();
if (!mnemonic) {
showError(
"import-phrase-error",
"Please enter your recovery phrase.",
"add-wallet-error",
"Please enter a recovery phrase or press the die to generate one.",
);
return;
}
const words = mnemonic.split(/\s+/);
if (words.length !== 12 && words.length !== 24) {
showError(
"import-phrase-error",
"add-wallet-error",
"Recovery phrase must be 12 or 24 words. You entered " +
words.length +
".",
@@ -313,14 +306,14 @@ function init() {
}
if (
!validatePasswords(
"import-phrase-password",
"import-phrase-password-confirm",
"import-phrase-error",
"add-wallet-password",
"add-wallet-password-confirm",
"add-wallet-error",
)
) {
return;
}
hideError("import-phrase-error");
hideError("add-wallet-error");
const walletNum = state.wallets.length + 1;
addWalletAndGoToMain({
type: "hd",
@@ -330,9 +323,7 @@ function init() {
});
});
$("btn-import-phrase-back").addEventListener("click", () => {
showView(state.isFirstSetup ? "welcome" : "add-wallet");
});
$("btn-add-wallet-back").addEventListener("click", backFromWalletAdd);
// -- Import private key --
$("btn-import-key-confirm").addEventListener("click", () => {
@@ -360,9 +351,7 @@ function init() {
});
});
$("btn-import-key-back").addEventListener("click", () => {
showView(state.isFirstSetup ? "welcome" : "add-wallet");
});
$("btn-import-key-back").addEventListener("click", backFromWalletAdd);
// -- Main view --
$("btn-lock").addEventListener("click", () => {
@@ -376,21 +365,8 @@ function init() {
showView("settings");
});
$("btn-add-wallet").addEventListener("click", () => {
showView("add-wallet");
});
// -- Add wallet menu (from main view) --
$("btn-add-wallet-new").addEventListener("click", showCreateView);
$("btn-add-wallet-phrase").addEventListener("click", () =>
showImportView("phrase"),
);
$("btn-add-wallet-key").addEventListener("click", () =>
showImportView("key"),
);
$("btn-add-wallet-back").addEventListener("click", () => {
showView("main");
});
$("btn-main-add-wallet").addEventListener("click", showAddWalletView);
$("btn-main-import-key").addEventListener("click", showImportKeyView);
// -- Address detail --
$("address-full").addEventListener("click", () => {