mirror of
https://github.com/Blah-IM/Weblah.git
synced 2025-04-30 16:21:09 +00:00
refactor: account management system
Replace store-based approach with manager-based implementation and update related components to use the new system. Change ProfilePicture props from `account` to `identity`.
This commit is contained in:
parent
055f7240df
commit
b467ec1491
8 changed files with 91 additions and 88 deletions
|
@ -6,7 +6,6 @@ import {
|
|||
} from '@blah-im/core/identity';
|
||||
import { type IdentityDB, openIdentityDB } from './identityFileDB';
|
||||
import { BlahKeyPair } from '@blah-im/core/crypto';
|
||||
import { persisted } from 'svelte-persisted-store';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
export type Account = BlahIdentityDescription & {
|
||||
|
@ -30,24 +29,25 @@ class AccountManager {
|
|||
constructor() {
|
||||
if (browser) {
|
||||
this.currentAccountId = localStorage.getItem(localStorageCurrentAccountIdKey);
|
||||
console.log('currentAccountId', this.currentAccountId);
|
||||
|
||||
$effect.root(() => {
|
||||
$effect(() =>
|
||||
this.currentAccountId
|
||||
? localStorage.setItem(localStorageCurrentAccountIdKey, this.currentAccountId)
|
||||
: localStorage.removeItem(localStorageCurrentAccountIdKey)
|
||||
);
|
||||
});
|
||||
|
||||
(async () => {
|
||||
this.inProgress = true;
|
||||
const [keyDB, identityDB] = await Promise.all([openAccountKeyDB(), openIdentityDB()]);
|
||||
this.keyDB = keyDB;
|
||||
this.identityDB = identityDB;
|
||||
await this.loadAccounts();
|
||||
this.inProgress = false;
|
||||
})();
|
||||
}
|
||||
|
||||
$effect.root(() => {
|
||||
$effect(() =>
|
||||
this.currentAccountId
|
||||
? localStorage.setItem(localStorageCurrentAccountIdKey, this.currentAccountId)
|
||||
: localStorage.removeItem(localStorageCurrentAccountIdKey)
|
||||
);
|
||||
});
|
||||
|
||||
(async () => {
|
||||
this.inProgress = true;
|
||||
const [keyDB, identityDB] = await Promise.all([openAccountKeyDB(), openIdentityDB()]);
|
||||
this.keyDB = keyDB;
|
||||
this.identityDB = identityDB;
|
||||
await this.loadAccounts();
|
||||
this.inProgress = false;
|
||||
})();
|
||||
}
|
||||
|
||||
async loadAccounts() {
|
||||
|
|
|
@ -2,7 +2,6 @@ import { persisted } from 'svelte-persisted-store';
|
|||
import { get } from 'svelte/store';
|
||||
import { BlahChatServerConnection } from './blah/connection/chatServer';
|
||||
import { BlahKeyPair, type EncodedBlahKeyPair } from '@blah-im/core/crypto';
|
||||
import { currentKeyPair } from './keystore';
|
||||
import { ChatListManager } from './chatList';
|
||||
import { browser } from '$app/environment';
|
||||
import { GlobalSearchManager } from './globalSearch';
|
||||
|
@ -18,7 +17,7 @@ class ChatServerConnectionPool {
|
|||
constructor() {
|
||||
if (browser) {
|
||||
chatServers.subscribe(this.onChatServersChange.bind(this));
|
||||
currentKeyPair.subscribe(this.onKeyPairChange.bind(this));
|
||||
// currentKeyPair.subscribe(this.onKeyPairChange.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { tw } from '$lib/tw';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
interface Props {
|
||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||
class?: string;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { children, class: classNames }: Props = $props();
|
||||
let { children, class: classNames, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class={tw('px-4 py-3', classNames)}>
|
||||
<div class={tw('px-4 py-3', classNames)} {...rest}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { formatMessageDate, formatFullMessageDate, formatUnreadCount } from '$lib/formatters';
|
||||
import type { Chat } from '$lib/types';
|
||||
import { currentKeyPair } from '$lib/keystore';
|
||||
import accountManager from '$lib/accounts/manager.svelte';
|
||||
import { toPlainText } from '@blah-im/core/richText';
|
||||
import { page } from '$app/state';
|
||||
import { tw } from '$lib/tw';
|
||||
|
@ -56,7 +56,7 @@
|
|||
{#if chat.lastMessage}
|
||||
{#if chat.id !== chat.lastMessage.sender.id}
|
||||
<span class="text-sf-primary">
|
||||
{chat.lastMessage.sender.id === $currentKeyPair.id
|
||||
{chat.lastMessage.sender.id === accountManager.currentAccountId
|
||||
? 'You'
|
||||
: chat.lastMessage.sender.name}:
|
||||
</span>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
{#if accountStore && $accountStore}
|
||||
{@const currentAccount = $accountStore.find((account) => account.id_key === $currentAccountStore)}
|
||||
<ProfilePicture account={currentAccount} {size} />
|
||||
<ProfilePicture identity={currentAccount} {size} />
|
||||
{:else}
|
||||
<ProfilePicture account={undefined} {size} />
|
||||
<ProfilePicture identity={undefined} {size} />
|
||||
{/if}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<script lang="ts">
|
||||
import LoadingIndicator from '$lib/components/LoadingIndicator.svelte';
|
||||
import PageHeader from '$lib/components/PageHeader.svelte';
|
||||
import { Button } from 'bits-ui';
|
||||
import accountsManager from '$lib/accounts/manager.svelte';
|
||||
|
||||
const currentAccount = $derived(accountsManager.currentAccount);
|
||||
</script>
|
||||
|
||||
{#if currentAccount}
|
||||
<PageHeader>
|
||||
<h3 class="flex-1">{currentAccount.profile.signee.payload.name}</h3>
|
||||
</PageHeader>
|
||||
{/if}
|
|
@ -2,76 +2,66 @@
|
|||
import { GroupedListItem, GroupedListSection } from '$lib/components/GroupedList';
|
||||
import { ArrowRightEndOnRectangle, Plus, 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 manager, { type Account } from '$lib/accounts/manager.svelte';
|
||||
import ProfilePicture from '$lib/components/ProfilePicture.svelte';
|
||||
import { flip } from 'svelte/animate';
|
||||
import { blur } from 'svelte/transition';
|
||||
import GroupedListContent from '$lib/components/GroupedList/GroupedListContent.svelte';
|
||||
|
||||
let accountStore: AccountStore | undefined = $state();
|
||||
|
||||
onMount(() => {
|
||||
openAccountStore().then((store) => {
|
||||
accountStore = store;
|
||||
});
|
||||
});
|
||||
const currentAccount = $derived(manager.currentAccount);
|
||||
const remainingAccounts = $derived(
|
||||
manager.accounts
|
||||
.filter((acc) => acc.id_key !== manager.currentAccountId)
|
||||
.toSorted((a, b) =>
|
||||
a.profile.signee.payload.name.localeCompare(b.profile.signee.payload.name)
|
||||
)
|
||||
);
|
||||
|
||||
function switchToAccount(account: Account) {
|
||||
$currentAccountStore = account.id_key;
|
||||
manager.currentAccountId = account.id_key;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if accountStore && $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-sf-primary text-xl font-semibold">
|
||||
{currentAccount.profile.signee.payload.name}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<code class="text-sf-secondary text-sm">
|
||||
{currentAccount.id_key.slice(0, 4) + '..' + currentAccount.id_key.slice(-4)}
|
||||
</code>
|
||||
</p>
|
||||
{#if currentAccount}
|
||||
{#key currentAccount.id_key}
|
||||
<div class="mt-6 p-4 text-center" in:blur>
|
||||
<div class="inline-block">
|
||||
<ProfilePicture identity={currentAccount} size={68} />
|
||||
</div>
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
{#if remainingAccounts.length > 0}
|
||||
<GroupedListSection>
|
||||
{#each remainingAccounts as account (account.id_key)}
|
||||
<div animate:flip={{ duration: 250 }} transition:blur>
|
||||
<GroupedListItem onclick={() => switchToAccount(account)}>
|
||||
<div class="-mx-0.5"><ProfilePicture {account} size={24} /></div>
|
||||
{account.profile.signee.payload.name}
|
||||
</GroupedListItem>
|
||||
</div>
|
||||
{/each}
|
||||
</GroupedListSection>
|
||||
{/if}
|
||||
<p>
|
||||
<span class="text-sf-primary text-xl font-semibold">
|
||||
{currentAccount.profile.signee.payload.name}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<code class="text-sf-secondary text-sm">
|
||||
{currentAccount.id_key.slice(0, 4) + '..' + currentAccount.id_key.slice(-4)}
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
<GroupedListSection>
|
||||
{#if ($accountStore?.length ?? 0) > 0}
|
||||
{#if remainingAccounts.length > 0}
|
||||
<GroupedListSection>
|
||||
{#each remainingAccounts as account (account.id_key)}
|
||||
<GroupedListContent
|
||||
class="flex gap-2"
|
||||
role="button"
|
||||
tabindex={0}
|
||||
onclick={() => switchToAccount(account)}
|
||||
>
|
||||
<div class="-mx-0.5"><ProfilePicture identity={account} size={24} /></div>
|
||||
{account.profile.signee.payload.name}
|
||||
</GroupedListContent>
|
||||
{/each}
|
||||
<SettingsListItem icon={Plus} route="/account/add">Add Account</SettingsListItem>
|
||||
{:else}
|
||||
</GroupedListSection>
|
||||
{:else}
|
||||
<GroupedListSection>
|
||||
<SettingsListItem icon={ArrowRightEndOnRectangle} route="/account/add">
|
||||
Sign in
|
||||
</SettingsListItem>
|
||||
<SettingsListItem icon={UserPlus} route="/account/new">Create Account</SettingsListItem>
|
||||
{/if}
|
||||
</GroupedListSection>
|
||||
</GroupedListSection>
|
||||
{/if}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { currentAccountStore, openAccountStore } from '$lib/accounts/accountStore';
|
||||
import accountsManager from '$lib/accounts/manager.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import {
|
||||
GroupedListContainer,
|
||||
|
@ -47,9 +47,8 @@
|
|||
isBusy = true;
|
||||
|
||||
try {
|
||||
const accountStore = await openAccountStore();
|
||||
const idKeyId = await accountStore.createAccount(profile, password);
|
||||
$currentAccountStore = idKeyId;
|
||||
const idKeyId = await accountsManager.createAccount(profile, password);
|
||||
accountsManager.currentAccountId = idKeyId;
|
||||
goto('/settings');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@ -70,7 +69,7 @@
|
|||
<GroupedListContainer>
|
||||
<GroupedListSection>
|
||||
<GroupedListContent class="flex items-center">
|
||||
<ProfilePicture size={64} account={undefined} />
|
||||
<ProfilePicture size={64} identity={undefined} />
|
||||
<input
|
||||
type="text"
|
||||
bind:value={name}
|
||||
|
|
Loading…
Add table
Reference in a new issue