From 282de15601283833d875d55856497da945543eac Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 28 Mar 2026 01:12:49 -0400 Subject: [PATCH 1/6] fix: recover profile and avatar loading --- src/app/components/room-avatar/RoomAvatar.tsx | 6 +++++- src/app/components/user-avatar/UserAvatar.tsx | 6 +++++- src/app/hooks/useUserProfile.ts | 12 +++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/app/components/room-avatar/RoomAvatar.tsx b/src/app/components/room-avatar/RoomAvatar.tsx index 356d9dbc2..33f9f6881 100644 --- a/src/app/components/room-avatar/RoomAvatar.tsx +++ b/src/app/components/room-avatar/RoomAvatar.tsx @@ -1,6 +1,6 @@ import { JoinRule } from '$types/matrix-sdk'; import { AvatarFallback, Icon, Icons, color } from 'folds'; -import { ComponentProps, ReactNode, forwardRef, useState } from 'react'; +import { ComponentProps, ReactNode, forwardRef, useEffect, useState } from 'react'; import { getRoomIconSrc } from '$utils/room'; import colorMXID from '$utils/colorMXID'; import * as css from './RoomAvatar.css'; @@ -17,6 +17,10 @@ type RoomAvatarProps = { export function RoomAvatar({ roomId, src, alt, renderFallback, uniformIcons }: RoomAvatarProps) { const [error, setError] = useState(false); + useEffect(() => { + setError(false); + }, [src]); + if (!src || error) { return ( { + setError(false); + }, [src]); + const handleLoad: ReactEventHandler = (evt) => { evt.currentTarget.setAttribute('data-image-loaded', 'true'); }; diff --git a/src/app/hooks/useUserProfile.ts b/src/app/hooks/useUserProfile.ts index d1de6e890..b50a42960 100644 --- a/src/app/hooks/useUserProfile.ts +++ b/src/app/hooks/useUserProfile.ts @@ -32,6 +32,7 @@ export type UserProfile = { }; const normalizeInfo = (info: any): UserProfile => { + const msc4440Bio = info['gay.fomx.biography'] as MSC4440Bio | undefined; const knownKeys = new Set([ 'avatar_url', 'displayname', @@ -60,10 +61,7 @@ const normalizeInfo = (info: any): UserProfile => { displayName: info.displayname, pronouns: info['io.fsky.nyx.pronouns'], timezone: info['us.cloke.msc4175.tz'] || info['m.tz'], - bio: - (info['gay.fomx.biography'] satisfies MSC4440Bio)['m.text'][0].body || - info['moe.sable.app.bio'] || - info['chat.commet.profile_bio'], + bio: msc4440Bio?.['m.text']?.[0]?.body || info['moe.sable.app.bio'] || info['chat.commet.profile_bio'], status: info['chat.commet.profile_status'], bannerUrl: info['chat.commet.profile_banner'], nameColor: info['moe.sable.app.name_color'], @@ -103,7 +101,11 @@ export const useUserProfile = ( const cached = useAtomValue(userSelector); const setGlobalProfiles = useSetAtom(profilesCacheAtom); - const needsFetch = !!userId && userId !== 'undefined' && !cached?._fetched; + const hasOnlyFetchedMarker = + cached?._fetched === true && Object.keys(cached).every((key) => key === '_fetched'); + + const needsFetch = + !!userId && userId !== 'undefined' && (!cached?._fetched || hasOnlyFetchedMarker); useEffect(() => { if (!needsFetch) return undefined; From 5865c4cc71432420983f372397519de3001f9f48 Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 28 Mar 2026 01:19:57 -0400 Subject: [PATCH 2/6] chore: add changeset for profile/avatar loading fix --- .changeset/fix-profile-avatar-loading.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fix-profile-avatar-loading.md diff --git a/.changeset/fix-profile-avatar-loading.md b/.changeset/fix-profile-avatar-loading.md new file mode 100644 index 000000000..39bcf0471 --- /dev/null +++ b/.changeset/fix-profile-avatar-loading.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Fix profile data loading when MSC4440 bio data is absent or malformed, and recover avatar rendering after transient image load failures. \ No newline at end of file From e7fd523759a89bc39282db94b41eeff666488391 Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 28 Mar 2026 01:25:41 -0400 Subject: [PATCH 3/6] chore: format profile avatar fix files --- .changeset/fix-profile-avatar-loading.md | 2 +- src/app/hooks/useUserProfile.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.changeset/fix-profile-avatar-loading.md b/.changeset/fix-profile-avatar-loading.md index 39bcf0471..3629a6c9f 100644 --- a/.changeset/fix-profile-avatar-loading.md +++ b/.changeset/fix-profile-avatar-loading.md @@ -2,4 +2,4 @@ default: patch --- -Fix profile data loading when MSC4440 bio data is absent or malformed, and recover avatar rendering after transient image load failures. \ No newline at end of file +Fix profile data loading when MSC4440 bio data is absent or malformed, and recover avatar rendering after transient image load failures. diff --git a/src/app/hooks/useUserProfile.ts b/src/app/hooks/useUserProfile.ts index b50a42960..cfa960542 100644 --- a/src/app/hooks/useUserProfile.ts +++ b/src/app/hooks/useUserProfile.ts @@ -61,7 +61,10 @@ const normalizeInfo = (info: any): UserProfile => { displayName: info.displayname, pronouns: info['io.fsky.nyx.pronouns'], timezone: info['us.cloke.msc4175.tz'] || info['m.tz'], - bio: msc4440Bio?.['m.text']?.[0]?.body || info['moe.sable.app.bio'] || info['chat.commet.profile_bio'], + bio: + msc4440Bio?.['m.text']?.[0]?.body || + info['moe.sable.app.bio'] || + info['chat.commet.profile_bio'], status: info['chat.commet.profile_status'], bannerUrl: info['chat.commet.profile_banner'], nameColor: info['moe.sable.app.name_color'], From 2a30a22c2408857761eda4001bd87e3300b96cd8 Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 28 Mar 2026 01:28:15 -0400 Subject: [PATCH 4/6] Update src/app/hooks/useUserProfile.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/app/hooks/useUserProfile.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/hooks/useUserProfile.ts b/src/app/hooks/useUserProfile.ts index cfa960542..9a1c8464e 100644 --- a/src/app/hooks/useUserProfile.ts +++ b/src/app/hooks/useUserProfile.ts @@ -105,7 +105,8 @@ export const useUserProfile = ( const setGlobalProfiles = useSetAtom(profilesCacheAtom); const hasOnlyFetchedMarker = - cached?._fetched === true && Object.keys(cached).every((key) => key === '_fetched'); + cached?._fetched === true && + Object.keys(cached ?? {}).every((key) => key === '_fetched'); const needsFetch = !!userId && userId !== 'undefined' && (!cached?._fetched || hasOnlyFetchedMarker); From 3ffbbb53fec14eed0953ec2e743f2be4ea671ba4 Mon Sep 17 00:00:00 2001 From: Rose Date: Sat, 28 Mar 2026 12:40:09 +0100 Subject: [PATCH 5/6] Delete .changeset/fix-profile-avatar-loading.md --- .changeset/fix-profile-avatar-loading.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/fix-profile-avatar-loading.md diff --git a/.changeset/fix-profile-avatar-loading.md b/.changeset/fix-profile-avatar-loading.md deleted file mode 100644 index 3629a6c9f..000000000 --- a/.changeset/fix-profile-avatar-loading.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -default: patch ---- - -Fix profile data loading when MSC4440 bio data is absent or malformed, and recover avatar rendering after transient image load failures. From 724b45fd6101866cd6d210d92701b0e90b6dd8ee Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 28 Mar 2026 11:00:30 -0400 Subject: [PATCH 6/6] fix: remove extra blank line in useUserProfile.ts --- src/app/hooks/useUserProfile.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/hooks/useUserProfile.ts b/src/app/hooks/useUserProfile.ts index 9a1c8464e..3308e6813 100644 --- a/src/app/hooks/useUserProfile.ts +++ b/src/app/hooks/useUserProfile.ts @@ -105,9 +105,7 @@ export const useUserProfile = ( const setGlobalProfiles = useSetAtom(profilesCacheAtom); const hasOnlyFetchedMarker = - cached?._fetched === true && - Object.keys(cached ?? {}).every((key) => key === '_fetched'); - + cached?._fetched === true && Object.keys(cached ?? {}).every((key) => key === '_fetched'); const needsFetch = !!userId && userId !== 'undefined' && (!cached?._fetched || hasOnlyFetchedMarker);