commit a59f1968260a1c5c6c7d1cc7f58ec5133df3b4f7
parent 6fe0136e3e1da266b60a95a5ffda05bc6ec1d80a
Author: finwo <finwo@pm.me>
Date: Sat, 13 Sep 2025 19:13:34 +0200
Ability to remove existing accounts
Diffstat:
4 files changed, 56 insertions(+), 15 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -837,6 +837,12 @@
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/lucide": {
+ "version": "0.544.0",
+ "resolved": "https://registry.npmjs.org/lucide/-/lucide-0.544.0.tgz",
+ "integrity": "sha512-U5ORwr5z9Sx7bNTDFaW55RbjVdQEnAcT3vws9uz3vRT1G4XXJUDAhRZdxhFoIyHEvjmTkzzlEhjSLYM5n4mb5w==",
+ "license": "ISC"
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -1136,6 +1142,7 @@
"license": "MIT",
"dependencies": {
"bip39": "^3.1.0",
+ "lucide": "^0.544.0",
"mithril": "^2.3.7"
},
"devDependencies": {
diff --git a/packages/app/package.json b/packages/app/package.json
@@ -21,6 +21,7 @@
},
"dependencies": {
"bip39": "^3.1.0",
+ "lucide": "^0.544.0",
"mithril": "^2.3.7"
}
}
diff --git a/packages/app/src/component/screen-account-select.tsx b/packages/app/src/component/screen-account-select.tsx
@@ -1,6 +1,8 @@
import { Vnode } from 'mithril';
import { AccountCreateScreen } from './screen-account-create.tsx';
+import Trash from 'lucide/dist/esm/icons/trash-2.js';
+
import { getDirectoryHandle, getFileHandle } from '../util/opfs';
type _Vnode = Vnode<{}, typeof AccountSelectScreen>;
@@ -8,28 +10,42 @@ type _Vnode = Vnode<{}, typeof AccountSelectScreen>;
export const AccountSelectScreen = {
routePath: '/account/select',
- accounts: [] as Array<{accountId: string}>,
+ accounts: [] as Array<{id:string,name:string}>,
- async oninit(vnode: _Vnode) {
- vnode.state.accounts = [];
-
- const accountsHandle = await getDirectoryHandle('/accounts');
- for await (const [accountId, handle] of accountsHandle.entries()) {
- const accountConfigHandle = await getFileHandle(`/accounts/${accountId}/config.json`)
- const accountConfig = JSON.parse(Buffer.from(await (await accountConfigHandle.getFile()).bytes()));
- vnode.state.accounts.push({
- ...accountConfig,
- accountId,
- });
- }
+ handler: {
+ loadAccounts: async (vnode: _Vnode, redraw: boolean = false) => {
+ vnode.state.accounts = [];
+
+ const accountsHandle = await getDirectoryHandle('/accounts');
+ for await (const [accountId, handle] of accountsHandle.entries()) {
+ try {
+ const accountConfigHandle = await getFileHandle(`/accounts/${accountId}/config.json`)
+ const accountConfig = JSON.parse(Buffer.from(await (await accountConfigHandle.getFile()).bytes()));
+ vnode.state.accounts.push({
+ ...accountConfig,
+ id: accountId,
+ });
+ } catch {
+ // Intentionally empty
+ }
+ }
- console.log(vnode.state.accounts);
+ if (redraw) m.redraw();
+ },
+ deleteAccount: (vnode: _Vnode, account:{id:string,name:string}) => async () => {
+ if (!confirm(`Delete account ${account.name}?`)) return;
+ const accountsHandle = await getDirectoryHandle(`/accounts`)
+ await accountsHandle.removeEntry(account.id, { recursive: true })
+ vnode.state.handler.loadAccounts(vnode, true);
+ }
+ },
+ async oninit(vnode: _Vnode) {
+ await vnode.state.handler.loadAccounts(vnode);
if (!vnode.state.accounts.length) {
document.location.href = `#!${AccountCreateScreen.routePath}`;
return;
}
-
m.redraw();
},
@@ -41,6 +57,9 @@ export const AccountSelectScreen = {
{vnode.state.accounts.map(account => (
<div style="padding:1em">
{account.name}
+ <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;" class="accountListDeleteButton" onclick={vnode.state.handler.deleteAccount(vnode, account)}>
+ {Trash.map(el => m(...el))}
+ </svg>
</div>
))}
</div>
diff --git a/packages/app/src/global.css b/packages/app/src/global.css
@@ -60,6 +60,15 @@ button {
}
}
+.accountListDeleteButton {
+ display: none;
+ cursor: pointer;
+ float: right;
+ stroke: #FFF;
+ &:hover {
+ stroke: #F00 !important;
+ }
+}
#accountSelectList > * {
padding: 1em;
&:not(:first-child) {
@@ -68,5 +77,10 @@ button {
}
&:hover:not(:first-child) {
background: #FFF2;
+ > .accountListDeleteButton {
+ display: inline-block;
+ }
}
}
+
+