fix+feat: bug fixes, deleted message placeholder, poll display
Bug fixes: - IncomingCallNotification: track ring setTimeout ID and clear it on cleanup/dismiss — prevents orphaned callbacks after unmount - RoomTimeline: allow redacted m.room.message, m.room.encrypted and m.sticker events past the early-return filter so they hit the existing RedactedContent renderer showing the trash-icon placeholder New features: - PollContent component: read-only display of m.poll.start and org.matrix.msc3381.poll.start events (both stable Matrix 1.7 and MSC3381 unstable content keys); renders poll question + answer options inside the standard Message bubble; registered both as top-level event renderers and inside EncryptedContent callback so encrypted polls also render after decryption - Deleted message placeholder: m.room.message and m.room.encrypted redacted events now show the existing MessageDeletedContent component (trash icon + italic notice) instead of disappearing entirely — matches Element, FluffyChat, Commet, Nheko behaviour
This commit is contained in:
@@ -63,6 +63,7 @@ import {
|
||||
MessageNotDecryptedContent,
|
||||
RedactedContent,
|
||||
MSticker,
|
||||
PollContent,
|
||||
ImageContent,
|
||||
EventContent,
|
||||
} from '../../components/message';
|
||||
@@ -1217,6 +1218,11 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (
|
||||
mEvent.getType() === 'm.poll.start' ||
|
||||
mEvent.getType() === 'org.matrix.msc3381.poll.start'
|
||||
)
|
||||
return <PollContent content={mEvent.getContent()} />;
|
||||
if (mEvent.getType() === MessageEvent.RoomMessageEncrypted)
|
||||
return (
|
||||
<Text>
|
||||
@@ -1297,6 +1303,112 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||
</Message>
|
||||
);
|
||||
},
|
||||
'org.matrix.msc3381.poll.start': (mEventId, mEvent, item, timelineSet, collapse) => {
|
||||
const reactionRelations = getEventReactions(timelineSet, mEventId);
|
||||
const reactions = reactionRelations && reactionRelations.getSortedAnnotationsByKey();
|
||||
const hasReactions = reactions && reactions.length > 0;
|
||||
const highlighted = focusItem?.index === item && focusItem.highlight;
|
||||
return (
|
||||
<Message
|
||||
key={mEvent.getId()}
|
||||
data-message-item={item}
|
||||
data-message-id={mEventId}
|
||||
room={room}
|
||||
mEvent={mEvent}
|
||||
messageSpacing={messageSpacing}
|
||||
messageLayout={messageLayout}
|
||||
collapse={collapse}
|
||||
highlight={highlighted}
|
||||
canDelete={canRedact || (canDeleteOwn && mEvent.getSender() === mx.getUserId())}
|
||||
canSendReaction={canSendReaction}
|
||||
canPinEvent={canPinEvent}
|
||||
imagePackRooms={imagePackRooms}
|
||||
relations={hasReactions ? reactionRelations : undefined}
|
||||
onUserClick={handleUserClick}
|
||||
onUsernameClick={handleUsernameClick}
|
||||
onReplyClick={handleReplyClick}
|
||||
onReactionToggle={handleReactionToggle}
|
||||
reactions={
|
||||
reactionRelations && (
|
||||
<Reactions
|
||||
style={{ marginTop: config.space.S200 }}
|
||||
room={room}
|
||||
relations={reactionRelations}
|
||||
mEventId={mEventId}
|
||||
canSendReaction={canSendReaction}
|
||||
onReactionToggle={handleReactionToggle}
|
||||
/>
|
||||
)
|
||||
}
|
||||
hideReadReceipts={hideActivity}
|
||||
showDeveloperTools={showDeveloperTools}
|
||||
memberPowerTag={getMemberPowerTag(mEvent.getSender() ?? '')}
|
||||
accessibleTagColors={accessiblePowerTagColors}
|
||||
legacyUsernameColor={legacyUsernameColor || direct}
|
||||
hour24Clock={hour24Clock}
|
||||
dateFormatString={dateFormatString}
|
||||
>
|
||||
{mEvent.isRedacted() ? (
|
||||
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
||||
) : (
|
||||
<PollContent content={mEvent.getContent()} />
|
||||
)}
|
||||
</Message>
|
||||
);
|
||||
},
|
||||
'm.poll.start': (mEventId, mEvent, item, timelineSet, collapse) => {
|
||||
const reactionRelations = getEventReactions(timelineSet, mEventId);
|
||||
const reactions = reactionRelations && reactionRelations.getSortedAnnotationsByKey();
|
||||
const hasReactions = reactions && reactions.length > 0;
|
||||
const highlighted = focusItem?.index === item && focusItem.highlight;
|
||||
return (
|
||||
<Message
|
||||
key={mEvent.getId()}
|
||||
data-message-item={item}
|
||||
data-message-id={mEventId}
|
||||
room={room}
|
||||
mEvent={mEvent}
|
||||
messageSpacing={messageSpacing}
|
||||
messageLayout={messageLayout}
|
||||
collapse={collapse}
|
||||
highlight={highlighted}
|
||||
canDelete={canRedact || (canDeleteOwn && mEvent.getSender() === mx.getUserId())}
|
||||
canSendReaction={canSendReaction}
|
||||
canPinEvent={canPinEvent}
|
||||
imagePackRooms={imagePackRooms}
|
||||
relations={hasReactions ? reactionRelations : undefined}
|
||||
onUserClick={handleUserClick}
|
||||
onUsernameClick={handleUsernameClick}
|
||||
onReplyClick={handleReplyClick}
|
||||
onReactionToggle={handleReactionToggle}
|
||||
reactions={
|
||||
reactionRelations && (
|
||||
<Reactions
|
||||
style={{ marginTop: config.space.S200 }}
|
||||
room={room}
|
||||
relations={reactionRelations}
|
||||
mEventId={mEventId}
|
||||
canSendReaction={canSendReaction}
|
||||
onReactionToggle={handleReactionToggle}
|
||||
/>
|
||||
)
|
||||
}
|
||||
hideReadReceipts={hideActivity}
|
||||
showDeveloperTools={showDeveloperTools}
|
||||
memberPowerTag={getMemberPowerTag(mEvent.getSender() ?? '')}
|
||||
accessibleTagColors={accessiblePowerTagColors}
|
||||
legacyUsernameColor={legacyUsernameColor || direct}
|
||||
hour24Clock={hour24Clock}
|
||||
dateFormatString={dateFormatString}
|
||||
>
|
||||
{mEvent.isRedacted() ? (
|
||||
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
||||
) : (
|
||||
<PollContent content={mEvent.getContent()} />
|
||||
)}
|
||||
</Message>
|
||||
);
|
||||
},
|
||||
[StateEvent.RoomMember]: (mEventId, mEvent, item) => {
|
||||
const membershipChanged = isMembershipChanged(mEvent);
|
||||
if (membershipChanged && hideMembershipEvents) return null;
|
||||
@@ -1639,7 +1751,14 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||
return null;
|
||||
}
|
||||
if (mEvent.isRedacted() && !showHiddenEvents) {
|
||||
return null;
|
||||
const t = mEvent.getType();
|
||||
if (
|
||||
t !== MessageEvent.RoomMessage &&
|
||||
t !== MessageEvent.RoomMessageEncrypted &&
|
||||
t !== MessageEvent.Sticker
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!newDivider && readUptoEventIdRef.current) {
|
||||
|
||||
Reference in New Issue
Block a user