feat(web): animated GIF avatars that refresh across chat and member list [CI]
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/dev-image unknown status

This commit is contained in:
justme committed 2026-10-17 13:25:14 +08:00
1 parent 3b062687cd
commit a08aa7568f
10 files changed
+163 -19

No files matched your search

+9 -4
View File
@@ -70,10 +70,14 @@ export function reduce(s: WorkspaceData, e: WorkspaceEvent): WorkspaceData {
const person = location.authorAccount ? people.get(location.authorAccount) : undefined;
if (person) authors[location.itemId] = { username: person.username, displayName: person.displayName || person.username, avatar: person.avatar ?? undefined };
}
const byId = Object.fromEntries(Object.entries(s.byId).map(([id, item]) => [id, {
...item, ...(locations[id] ?? {}), ...(authors[id] ? { author: authors[id] } : {}),
}]));
const profiles = Object.fromEntries(e.people.map(person => [person.username, { username: person.username, displayName: person.displayName || person.username, ...(person.avatar ? { avatar: person.avatar } : {}) }]));
// 资料改了(头像、名字),已经显示的消息也要跟着换:作者按账号取最新的资料
const fresh = (author: SenderInfo | undefined) => (author && profiles[author.username]) || author;
for (const id of Object.keys(authors)) authors[id] = fresh(authors[id])!;
const byId = Object.fromEntries(Object.entries(s.byId).map(([id, item]) => {
const author = fresh(authors[id] ?? item.author);
return [id, { ...item, ...(locations[id] ?? {}), ...(author ? { author } : {}) }];
}));
return { ...s, people: profiles, threads: e.state.channels.map(c => ({ ...c, groupId: c.groupId ?? undefined })), groups: e.state.groups, roles: e.state.roles ?? [],
folders: e.state.folders.map(f => ({ ...f, parentId: f.parentId ?? undefined })), locations, authors, byId };
}
@@ -96,7 +100,8 @@ export function reduce(s: WorkspaceData, e: WorkspaceEvent): WorkspaceData {
const known = e.item.id in s.byId;
let item = e.item;
const current = s.byId[item.id];
const author = s.authors[item.id] ?? item.author ?? current?.author;
const known0 = s.authors[item.id] ?? item.author ?? current?.author;
const author = (known0 && s.people[known0.username]) || known0;
if (author) item = { ...item, author };
if (e.t === 'item' && item.kind === 'file' && item.metadataHidden && current?.kind === 'file' && !current.metadataHidden) return s;
const location = s.locations[item.id];