feat: account switching

This commit is contained in:
Shibo Lyu 2024-10-16 03:21:26 +08:00
parent 2b47eeb146
commit e78279114a
6 changed files with 98 additions and 31 deletions

View file

@ -75,13 +75,15 @@ class AccountStore implements Readable<Account[]> {
await this.identityFileDB.updateIdentityFile(identityFile);
}
async createAccount(profile: BlahProfile, password: string) {
async createAccount(profile: BlahProfile, password: string): Promise<string> {
const idKeyPair = await BlahKeyPair.generate(true);
const actKeyPair = await BlahKeyPair.generate(false);
const identity = await BlahIdentity.create(idKeyPair, actKeyPair, profile);
const encodedIdKeyPair = await idKeyPair.encode(password);
await this.keyDB.addAccount(idKeyPair.id, actKeyPair, encodedIdKeyPair);
await this.saveIdentityFile(identity);
await this.loadAccounts();
return idKeyPair.id;
}
}

View file

@ -8,12 +8,15 @@
</script>
<svelte:element
this={href ? 'a' : 'div'}
this={href ? 'a' : 'button'}
{href}
class={tw(
'flex cursor-default items-center gap-2 px-4 py-3 font-medium text-sf-primary first:rounded-t-lg last:rounded-b-lg',
'flex w-full cursor-default items-center gap-2 px-4 py-3 font-medium text-sf-primary first:rounded-t-lg last:rounded-b-lg',
selected && 'bg-accent-500 text-white shadow-inner dark:bg-accent-900 dark:text-sf-primary'
)}
tabindex="0"
role="button"
on:click
>
{#if icon}
<Icon

View file

@ -2,31 +2,25 @@
import {
currentAccountStore,
openAccountStore,
type Account,
type AccountStore
} from '$lib/accounts/accountStore';
import ProfilePicture from '$lib/components/ProfilePicture.svelte';
import { onMount } from 'svelte';
export let size: number = 32;
let accountStore: AccountStore;
async function getAccount(idKeyId: string | null): Promise<Account | undefined> {
if (!accountStore) {
accountStore = await openAccountStore();
}
if (!idKeyId) return;
let currentAccount = $accountStore.find((account) => account.id_key === idKeyId);
if (!currentAccount && $accountStore.length > 0) {
currentAccount = $accountStore[0];
$currentAccountStore = currentAccount.id_key;
}
return currentAccount;
}
onMount(() => {
openAccountStore().then((store) => {
accountStore = store;
});
});
</script>
{#await getAccount($currentAccountStore)}
<ProfilePicture account={undefined} />
{:then currentAccount}
{#if accountStore}
{@const currentAccount = $accountStore.find((account) => account.id_key === $currentAccountStore)}
<ProfilePicture account={currentAccount} {size} />
{/await}
{:else}
<ProfilePicture account={undefined} {size} />
{/if}

View file

@ -0,0 +1,71 @@
<script lang="ts">
import { GroupedListItem, GroupedListSection } from '$lib/components/GroupedList';
import { ArrowRightEndOnRectangle, UserPlus } from 'svelte-hero-icons';
import SettingsListItem from './SettingsListItem.svelte';
import {
openAccountStore,
currentAccountStore,
type AccountStore,
type Account
} from '$lib/accounts/accountStore';
import { onMount } from 'svelte';
import ProfilePicture from '$lib/components/ProfilePicture.svelte';
import { flip } from 'svelte/animate';
import { blur, scale } from 'svelte/transition';
let accountStore: AccountStore;
onMount(() => {
openAccountStore().then((store) => {
accountStore = store;
});
});
function switchToAccount(account: Account) {
$currentAccountStore = account.id_key;
}
</script>
{#if accountStore}
{@const currentAccount = $accountStore.find((acc) => acc.id_key === $currentAccountStore)}
{@const remainingAccounts = $accountStore
.filter((acc) => acc.id_key !== $currentAccountStore)
.toSorted((a, b) => a.profile.signee.payload.name.localeCompare(b.profile.signee.payload.name))}
{#if currentAccount}
{#key currentAccount.id_key}
<div class="mt-6 p-4 text-center" in:blur>
<div class="inline-block">
<ProfilePicture account={currentAccount} size={68} />
</div>
<p>
<span class="text-xl font-semibold text-sf-primary">
{currentAccount.profile.signee.payload.name}
</span>
</p>
<p>
<code class="text-sm text-sf-secondary">
{currentAccount.profile.signee.id_key.slice(0, 6) +
'...' +
currentAccount.profile.signee.id_key.slice(-6)}
</code>
</p>
</div>
{/key}
{/if}
<GroupedListSection>
{#each remainingAccounts as account (account.id_key)}
<div animate:flip={{ duration: 250 }} transition:blur>
<GroupedListItem on:click={() => switchToAccount(account)}>
<div class="-mx-0.5"><ProfilePicture {account} size={24} /></div>
{account.profile.signee.payload.name}
</GroupedListItem>
</div>
{/each}
</GroupedListSection>
{/if}
<GroupedListSection>
<SettingsListItem icon={ArrowRightEndOnRectangle} route="/account/add">Sign in</SettingsListItem>
<SettingsListItem icon={UserPlus} route="/account/new">Create Account</SettingsListItem>
</GroupedListSection>

View file

@ -3,18 +3,17 @@
import { GroupedListSection, GroupedListItem } from '$lib/components/GroupedList';
import { tw } from '$lib/tw';
import {
ArrowRightEndOnRectangle,
Bell,
Cog,
DevicePhoneMobile,
InformationCircle,
LockClosed,
QuestionMarkCircle,
UserPlus
QuestionMarkCircle
} from 'svelte-hero-icons';
import { scale } from 'svelte/transition';
import SettingsListItem from './SettingsListItem.svelte';
import PageHeader from '$lib/components/PageHeader.svelte';
import SettingsAccountSections from './SettingsAccountSections.svelte';
let className = '';
export { className as class };
@ -30,18 +29,15 @@
<Button href="/account/profile">Edit</Button>
</PageHeader>
<div class="flex-1 overflow-y-scroll">
<GroupedListSection>
<SettingsListItem icon={ArrowRightEndOnRectangle} route="/account/add">
Sign in
</SettingsListItem>
<SettingsListItem icon={UserPlus} route="/account/new">Create Account</SettingsListItem>
</GroupedListSection>
<SettingsAccountSections />
<GroupedListSection>
<SettingsListItem icon={Cog} route="">General</SettingsListItem>
<GroupedListItem icon={Bell}>Notifications</GroupedListItem>
<GroupedListItem icon={LockClosed}>Privacy and Security</GroupedListItem>
<GroupedListItem icon={DevicePhoneMobile}>Devices</GroupedListItem>
</GroupedListSection>
<GroupedListSection>
<GroupedListItem icon={InformationCircle}>About Blah & Weblah</GroupedListItem>
<GroupedListItem icon={QuestionMarkCircle}>Ask a Question</GroupedListItem>

View file

@ -1,6 +1,6 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { openAccountStore } from '$lib/accounts/accountStore';
import { currentAccountStore, openAccountStore } from '$lib/accounts/accountStore';
import Button from '$lib/components/Button.svelte';
import {
GroupedListContainer,
@ -57,7 +57,8 @@
try {
const accountStore = await openAccountStore();
await accountStore.createAccount(profile, password);
const idKeyId = await accountStore.createAccount(profile, password);
$currentAccountStore = idKeyId;
} catch (error) {
console.error(error);
}