This commit is contained in:
Ginger 2025-09-12 09:50:49 -04:00 committed by GitHub
commit 8197903694
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 125 additions and 0 deletions

View file

@ -0,0 +1,8 @@
import { style } from '@vanilla-extract/css';
export const messageJumpLink = style({
':hover': {
cursor: 'pointer',
textDecoration: 'underline',
},
});

View file

@ -0,0 +1,13 @@
import React from "react";
import { messageJumpLink } from "./MessageJumpLink.css";
import { useRoomNavigate } from "../../hooks/useRoomNavigate";
export function MessageJumpLink({ roomId, eventId }: { roomId: string, eventId: string }) {
const { navigateRoom } = useRoomNavigate();
return (
<button type="button" className={messageJumpLink} onClick={() => navigateRoom(roomId, eventId)}>
a message
</button>
);
}

View file

@ -126,6 +126,7 @@ import { useAccessiblePowerTagColors, useGetMemberPowerTag } from '../../hooks/u
import { useTheme } from '../../hooks/useTheme';
import { useRoomCreatorsTag } from '../../hooks/useRoomCreatorsTag';
import { usePowerLevelTags } from '../../hooks/usePowerLevelTags';
import { usePinnedEventParser } from '../../hooks/usePinnedEventParser';
const TimelineFloat = as<'div', css.TimelineFloatVariants>(
({ position, className, ...props }, ref) => (
@ -532,6 +533,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
[mx, room, linkifyOpts, spoilerClickHandler, mentionClickHandler, useAuthentication]
);
const parseMemberEvent = useMemberEventParser();
const parsePinnedEvent = usePinnedEventParser(room.roomId);
const [timeline, setTimeline] = useState<Timeline>(() =>
eventId ? getEmptyTimeline() : getInitialTimeline(room)
@ -1468,6 +1470,47 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
</Event>
);
},
[StateEvent.RoomPinnedEvents]: (mEventId, mEvent, item) => {
const highlighted = focusItem?.index === item && focusItem.highlight;
const parsed = parsePinnedEvent(mEvent);
const timeJSX = (
<Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
);
return (
<Event
key={mEvent.getId()}
data-message-item={item}
data-message-id={mEventId}
room={room}
mEvent={mEvent}
highlight={highlighted}
messageSpacing={messageSpacing}
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
hideReadReceipts={hideActivity}
showDeveloperTools={showDeveloperTools}
>
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Pin}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
{parsed}
</Text>
</Box>
}
/>
</Event>
);
}
},
(mEventId, mEvent, item) => {
if (!showHiddenEvents) return null;

View file

@ -0,0 +1,57 @@
import { MatrixEvent } from 'matrix-js-sdk';
import React, { ReactNode } from 'react';
import { IRoomPinnedEventsContent } from '../../types/matrix/room';
import { getMxIdLocalPart } from '../utils/matrix';
import { MessageJumpLink } from '../components/message/MessageJumpLink';
export type PinnedEventParser = (mEvent: MatrixEvent) => ReactNode;
export const usePinnedEventParser = (roomId: string): PinnedEventParser => {
const pinnedEventParser = (mEvent: MatrixEvent) => {
const { pinned } = mEvent.getContent<IRoomPinnedEventsContent>();
const prevPinned = (mEvent.getPrevContent() as Partial<IRoomPinnedEventsContent>).pinned;
const senderId = mEvent.getSender() ?? '';
const senderName = getMxIdLocalPart(senderId);
const addedPins = pinned.filter((pdu) => !(prevPinned?.includes(pdu) ?? false));
const removedPins = prevPinned?.filter((pdu) => !pinned.includes(pdu)) ?? [];
return (
<>
<b>{senderName}</b>
{addedPins.length === 0 && removedPins.length === 0 ? (
' made no changes to the pinned messages'
) : (
<>
{addedPins.length > 0 && (
<>
{' pinned '}
<b>
{addedPins.length === 1 ? (
<MessageJumpLink roomId={roomId} eventId={addedPins[0]} />
) : (
`${addedPins.length} messages`
)}
</b>
</>
)}
{addedPins.length > 0 && removedPins.length > 0 && 'and'}
{removedPins.length > 0 && (
<>
{' unpinned '}
<b>
{removedPins.length === 1 ? (
<MessageJumpLink roomId={roomId} eventId={removedPins[0]} />
) : (
`${removedPins.length} messages`
)}
</b>
</>
)}
</>
)}
</>
);
};
return pinnedEventParser;
};

View file

@ -77,6 +77,10 @@ export type IRoomCreateContent = {
};
};
export type IRoomPinnedEventsContent = {
pinned: string[];
};
export type GetContentCallback = <T>() => T;
export type RoomToParents = Map<string, Set<string>>;