From 0c97bfcadcc1c795c18dc1683fa8843fba91a2d8 Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 23 Mar 2026 01:58:33 +0100 Subject: [PATCH 1/4] fix (per-message-profile): unset fields if their value is oprional, and don't include a fallback if the display name is empty --- src/app/features/room/RoomInput.tsx | 42 +++++++++++++++------------ src/app/hooks/usePerMessageProfile.ts | 20 +++++++++---- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/app/features/room/RoomInput.tsx b/src/app/features/room/RoomInput.tsx index ba0a5fd47..fb0c11657 100644 --- a/src/app/features/room/RoomInput.tsx +++ b/src/app/features/room/RoomInput.tsx @@ -768,30 +768,34 @@ export const RoomInput = forwardRef( const perMessageProfile = await getCurrentlyUsedPerMessageProfileForRoom(mx, roomId); if (perMessageProfile) { - content['com.beeper.per_message_profile'] = - convertPerMessageProfileToBeeperFormat(perMessageProfile); + content['com.beeper.per_message_profile'] = convertPerMessageProfileToBeeperFormat( + perMessageProfile, + perMessageProfile.name !== '' + ); - // if a per-message profile is used, it must per spec include a fallback - const prefix = `${perMessageProfile.name}: `; + if (perMessageProfile.name !== '') { + // if a per-message profile is used, it must per spec include a fallback + const prefix = `${perMessageProfile.name}: `; - if (!content.body.startsWith(prefix)) { - // to prevent double-prefixing when the fallback is already present - content.body = prefix + content.body; - } + if (!content.body.startsWith(prefix)) { + // to prevent double-prefixing when the fallback is already present + content.body = prefix + content.body; + } - /** - * html escaped version of the display name - */ - const escapedName = sanitizeCustomHtml(perMessageProfile.name); + /** + * html escaped version of the display name + */ + const escapedName = sanitizeCustomHtml(perMessageProfile.name); - const htmlPrefix = `${escapedName}: `; + const htmlPrefix = `${escapedName}: `; - if (content.formatted_body && !content.formatted_body.startsWith(htmlPrefix)) { - content.formatted_body = htmlPrefix + content.formatted_body; - } else { - // we don't have a formatted body, but we need one - content.format = 'org.matrix.custom.html'; - content.formatted_body = `${htmlPrefix}${plainText}`; + if (content.formatted_body && !content.formatted_body.startsWith(htmlPrefix)) { + content.formatted_body = htmlPrefix + content.formatted_body; + } else { + // we don't have a formatted body, but we need one + content.format = 'org.matrix.custom.html'; + content.formatted_body = `${htmlPrefix}${plainText}`; + } } } diff --git a/src/app/hooks/usePerMessageProfile.ts b/src/app/hooks/usePerMessageProfile.ts index 8ef2f8d44..fa724b519 100644 --- a/src/app/hooks/usePerMessageProfile.ts +++ b/src/app/hooks/usePerMessageProfile.ts @@ -40,7 +40,7 @@ export type PerMessageProfileBeeperFormat = { /** * the display name to use for messages using this profile. This is required because otherwise the profile would have no effect on the message. */ - displayname: string; + displayname?: string; /** * the avatar url to use for messages using this profile. * Beeper expects this to be a mxc url. @@ -50,7 +50,7 @@ export type PerMessageProfileBeeperFormat = { * using the unstable prefix for pronouns, under which it is also stored in profiles */ 'io.fsky.nyx.pronouns'?: PronounSet[]; - has_fallback: boolean; + has_fallback?: boolean; }; /** @@ -61,15 +61,23 @@ export type PerMessageProfileBeeperFormat = { * @return {*} {PerMessageProfileBeeperFormat} the per message profile in Beeper's format, which can be applied to a message before sending it */ export function convertPerMessageProfileToBeeperFormat( - profile: PerMessageProfile + profile: PerMessageProfile, + has_fallback: boolean ): PerMessageProfileBeeperFormat { - return { + const beeperPMP: PerMessageProfileBeeperFormat = { id: profile.id, displayname: profile.name, avatar_url: profile.avatarUrl, 'io.fsky.nyx.pronouns': profile.pronouns, - has_fallback: true, + has_fallback, }; + // delete empty fields + // to-do maybe find a better way of doing it + if (!profile.name) delete beeperPMP.displayname; + if (!profile.avatarUrl) delete beeperPMP.avatar_url; + if (!profile.pronouns || profile.pronouns?.length === 0) delete beeperPMP['io.fsky.nyx.pronouns']; + if (!has_fallback) delete beeperPMP.has_fallback; + return beeperPMP; } /** @@ -85,7 +93,7 @@ export function convertBeeperFormatToOurPerMessageProfile( ): PerMessageProfile { return { id: beeperProfile.id, - name: beeperProfile.displayname, + name: beeperProfile.displayname ?? '', avatarUrl: beeperProfile.avatar_url, pronouns: beeperProfile['io.fsky.nyx.pronouns'], }; From 4791ed09f4dd1ed0666bf63062bb272f4def802d Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 23 Mar 2026 14:46:11 +0100 Subject: [PATCH 2/4] fix(Per-Message-Profiles): whitespace only names will now disable the addition of fallback text --- .changeset/fix_pmp_empty_displayname.md | 5 +++++ src/app/features/room/RoomInput.tsx | 4 ++-- src/app/hooks/usePerMessageProfile.ts | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/fix_pmp_empty_displayname.md diff --git a/.changeset/fix_pmp_empty_displayname.md b/.changeset/fix_pmp_empty_displayname.md new file mode 100644 index 000000000..97e6e2d7a --- /dev/null +++ b/.changeset/fix_pmp_empty_displayname.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +fix the issue of empty displaynames of a persona, causing an empty fallback message, it will now ommit the fallback, if the name is empty or only consists of whitespace diff --git a/src/app/features/room/RoomInput.tsx b/src/app/features/room/RoomInput.tsx index fb0c11657..b9d2dbb65 100644 --- a/src/app/features/room/RoomInput.tsx +++ b/src/app/features/room/RoomInput.tsx @@ -770,10 +770,10 @@ export const RoomInput = forwardRef( if (perMessageProfile) { content['com.beeper.per_message_profile'] = convertPerMessageProfileToBeeperFormat( perMessageProfile, - perMessageProfile.name !== '' + perMessageProfile.name.trim() !== '' ); - if (perMessageProfile.name !== '') { + if (perMessageProfile.name.trim() !== '') { // if a per-message profile is used, it must per spec include a fallback const prefix = `${perMessageProfile.name}: `; diff --git a/src/app/hooks/usePerMessageProfile.ts b/src/app/hooks/usePerMessageProfile.ts index fa724b519..966db2af9 100644 --- a/src/app/hooks/usePerMessageProfile.ts +++ b/src/app/hooks/usePerMessageProfile.ts @@ -73,7 +73,7 @@ export function convertPerMessageProfileToBeeperFormat( }; // delete empty fields // to-do maybe find a better way of doing it - if (!profile.name) delete beeperPMP.displayname; + if (!profile.name || profile?.name.trim().length === 0) delete beeperPMP.displayname; if (!profile.avatarUrl) delete beeperPMP.avatar_url; if (!profile.pronouns || profile.pronouns?.length === 0) delete beeperPMP['io.fsky.nyx.pronouns']; if (!has_fallback) delete beeperPMP.has_fallback; From dacab844cc620c9525cb9abac90dbc850c0923d9 Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 23 Mar 2026 14:54:09 +0100 Subject: [PATCH 3/4] fix(Message rendering): don't render the "via" for Per-Message-Profiles if the name is unset or whitespace only --- src/app/features/room/message/Message.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx index 88a4349ff..ad7a060cc 100644 --- a/src/app/features/room/message/Message.tsx +++ b/src/app/features/room/message/Message.tsx @@ -403,8 +403,9 @@ function MessageInternal( /** * boolean to indicate wheather we should indicate to the user that it is a pmp + * We want to not show it, when the name is unset, or whitespace only */ - const showPmPInfo = pmp !== undefined; + const showPmPInfo = pmp !== undefined && pmp.name && pmp.name?.trim() !== ''; // Profiles and Colors const profile = useUserProfile(senderId, room); const { color: usernameColor, font: usernameFont } = useSableCosmetics(senderId, room); From 0500b6f70ce734827a469c1e3a49c2d229a21f2c Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 23 Mar 2026 15:02:27 +0100 Subject: [PATCH 4/4] fix(Message): fix type error relating to `showPmPInfo` --- src/app/features/room/message/Message.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx index ad7a060cc..c26e40692 100644 --- a/src/app/features/room/message/Message.tsx +++ b/src/app/features/room/message/Message.tsx @@ -405,7 +405,7 @@ function MessageInternal( * boolean to indicate wheather we should indicate to the user that it is a pmp * We want to not show it, when the name is unset, or whitespace only */ - const showPmPInfo = pmp !== undefined && pmp.name && pmp.name?.trim() !== ''; + const showPmPInfo = parsedPMPContent?.name && parsedPMPContent.name?.trim() !== ''; // Profiles and Colors const profile = useUserProfile(senderId, room); const { color: usernameColor, font: usernameFont } = useSableCosmetics(senderId, room);