feat(web): avatar thumbnails with original preview, registration avatar, pure-JS crypto fallback for http [CI]
This commit is contained in:
1 parent
283196938e
commit
d66c93fe98
36 files changed
+735
-60
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { importResources, importResourceDeletes, listAllResources, listResourceDeletes, setResourceChangeListener, setResourceScope, type SavedResource } from '../database';
|
||||
import { apiFetch } from './http';
|
||||
import { apiFetch, jsonBody } from './http';
|
||||
import { clearResourceSessions, getSession } from './sessions';
|
||||
import { setAccountIdentity, requireAccount } from './accountSession';
|
||||
import { b64, unb64, deriveAccountKeys, sealJson, openJson, generateInvitationKeys, generateAccountSigningKeys } from './accountCrypto';
|
||||
@@ -11,6 +11,8 @@ import { forgetAccount, localAccountDevice, rememberedAccount, rememberAccount,
|
||||
import type { AccountVaultBody, AccountSaltBody, AccountSessionBody, PublicKeyBody, InvitationBody, InvitationCryptoPlan, AccountDeviceBody, AccountRegisterRequest, AccountSessionRequest } from '../generated/api';
|
||||
|
||||
import { loadPersonal, personalProfile } from './accountProfile';
|
||||
import { primeAvatar } from './avatars';
|
||||
import type { AvatarChange } from '../protocol/account';
|
||||
import type { AccountProfile, AccountProfileRequest } from '../generated/api';
|
||||
|
||||
import type { PersonalProfile } from '../protocol/account';
|
||||
@@ -206,7 +208,8 @@ export async function unlockAuthenticatedAccount(identity: AccountSessionBody, k
|
||||
export async function accountStatus(): Promise<{ username: string | null; revision: number; remembered: boolean; personal?: PersonalProfile; error?: string; unlockUsername?: string }> {
|
||||
return { username: account?.username ?? null, revision: account?.revision ?? 0,
|
||||
remembered: account?.remember ?? false, unlockUsername: passkeyUnlockUsername(),
|
||||
...(account?.personal ? { personal: account.personal } : {}),
|
||||
// 界面每隔几秒就读一次状态:不能每次都带着几 MB 的头像过 postMessage,头像由界面另外取
|
||||
...(account?.personal ? { personal: { displayName: account.personal.displayName, modifiedAt: account.personal.modifiedAt, hasAvatar: account.personal.hasAvatar ?? Boolean(account.personal.avatar) } } : {}),
|
||||
...(account?.error ? { error: '账号资源同步失败,请重试。' } : {}) };
|
||||
}
|
||||
export async function logoutAccount(): Promise<void> {
|
||||
@@ -230,13 +233,20 @@ export async function clearSavedLogin(): Promise<void> {
|
||||
}
|
||||
await forgetAccount(); await forgetLoginFields();
|
||||
}
|
||||
export async function updatePersonal(displayName: string, avatar?: string): Promise<void> {
|
||||
export async function updatePersonal(displayName: string, change?: AvatarChange): Promise<void> {
|
||||
if (!account) throw new Error('请先登录账号');
|
||||
const session = account;
|
||||
const value = await apiFetch('/accounts/profile', { method: 'PATCH', headers: { ...headers(session), 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ displayName, avatar } satisfies AccountProfileRequest) }).then(r => r.json() as Promise<AccountProfile>);
|
||||
const request: AccountProfileRequest = change === 'keep' ? { displayName, keepAvatar: true }
|
||||
: change ? { displayName, keepAvatar: false, avatar: change.avatar, avatarThumb: change.thumb } : { displayName, keepAvatar: false };
|
||||
const { body, headers: encoding } = await jsonBody(request);
|
||||
const value = await apiFetch('/accounts/profile', { method: 'PATCH', headers: { ...headers(session), ...encoding }, body }).then(r => r.json() as Promise<AccountProfile>);
|
||||
stillActive(session);
|
||||
const previous = session.personal?.avatar;
|
||||
session.personal = personalProfile(value);
|
||||
// 本机刚设置的头像直接用,不用再下载;只改名字时沿用现有的
|
||||
const shown = change && change !== 'keep' ? change.thumb : change === 'keep' ? previous : undefined;
|
||||
if (shown) { session.personal.avatar = shown; session.personal.hasAvatar = true; }
|
||||
primeAvatar(value.username, value.modifiedAt, shown);
|
||||
setAccountIdentity(session, session.profile.keys.publicKey, session.personal);
|
||||
await persistSession(session, { vault: await sealJson(session.profile, session.key), revision: session.revision });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user