screen-account-select.tsx (2731B)
1 import { Vnode } from 'mithril'; 2 import { AccountCreateScreen } from './screen-account-create.tsx'; 3 4 import TrashIcon from 'lucide/dist/esm/icons/trash-2.js'; 5 6 import { getDirectoryHandle, getFileHandle } from '../util/opfs'; 7 import {HomeScreen} from './screen-home.js'; 8 9 type _Vnode = Vnode<{}, typeof AccountSelectScreen>; 10 11 export const AccountSelectScreen = { 12 routePath: '/account/select', 13 14 accounts: [] as Array<{id:string,displayName:string}>, 15 16 handler: { 17 selectAccount: (account: {id:string}) => () => { 18 localStorage.selectedAccount = account.id; 19 document.location.href = `#!${HomeScreen.routePath}`; 20 }, 21 loadAccounts: async (vnode: _Vnode, redraw: boolean = false) => { 22 vnode.state.accounts = []; 23 24 const accountsHandle = await getDirectoryHandle('/local/accounts'); 25 for await (const accountId of accountsHandle.keys()) { 26 try { 27 const accountConfigHandle = await getFileHandle(`/local/accounts/${accountId}/config.json`) 28 const accountConfig = JSON.parse(Buffer.from(await (await accountConfigHandle.getFile()).arrayBuffer())); 29 vnode.state.accounts.push({ 30 ...accountConfig, 31 id: accountId, 32 }); 33 } catch { 34 // Intentionally empty 35 } 36 } 37 if (!vnode.state.accounts.length) { 38 document.location.href = `#!${AccountCreateScreen.routePath}`; 39 return; 40 } 41 if (redraw) m.redraw(); 42 }, 43 deleteAccount: async (vnode: _Vnode, account:{id:string,displayName:string}) => { 44 if (!confirm(`Delete account ${account.displayName}?`)) return false; 45 const accountsHandle = await getDirectoryHandle(`/local/accounts`) 46 await accountsHandle.removeEntry(account.id, { recursive: true }) 47 vnode.state.handler.loadAccounts(vnode, true); 48 } 49 }, 50 51 async oninit(vnode: _Vnode) { 52 await vnode.state.handler.loadAccounts(vnode, true); 53 }, 54 55 view(vnode: _Vnode) { 56 return ( 57 <div class="main"> 58 <h3>Select account</h3> 59 <div id="accountSelectList" class="entry-list"> 60 {vnode.state.accounts.map(account => ( 61 <a style="display:block;padding:1em" onclick={vnode.state.handler.selectAccount(account)}> 62 <label>{account.displayName}</label> 63 <svg ns="http://www.w3.org/2000/svg" fill="transparent" class="icon accountListDeleteButton" onclick={()=>{vnode.state.handler.deleteAccount(vnode, account);return false;}}> 64 {TrashIcon.map(el => m(...el))} 65 </svg> 66 </a> 67 ))} 68 </div> 69 <center> 70 <a href={`#!${AccountCreateScreen.routePath}`}>Create new account</a> 71 </center> 72 </div> 73 ); 74 }, 75 };