From 964e0e32fadc46921a059e22d27dc055c5427375 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Jul 2022 14:18:09 +0100 Subject: [PATCH 1/2] Fix pinned messages not re-linkifying on edit --- src/HtmlUtils.tsx | 7 ++++--- src/components/structures/RightPanel.tsx | 6 +++++- src/components/views/messages/IBodyProps.ts | 4 ++-- src/components/views/messages/MessageEvent.tsx | 2 +- src/components/views/messages/TextualBody.tsx | 4 ++-- src/components/views/right_panel/PinnedMessagesCard.tsx | 5 ++++- src/components/views/rooms/PinnedEventTile.tsx | 4 ++++ src/events/EventTileFactory.tsx | 4 ++-- 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index c2fe3e31c9d..dac79a37a1d 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -26,6 +26,7 @@ import { split } from 'lodash'; import katex from 'katex'; import { AllHtmlEntities } from 'html-entities'; import { IContent } from 'matrix-js-sdk/src/models/event'; +import { Optional } from 'matrix-events-sdk'; import { _linkifyElement, @@ -456,9 +457,9 @@ function formatEmojis(message: string, isHtmlMessage: boolean): (JSX.Element | s * opts.forComposerQuote: optional param to lessen the url rewriting done by sanitization, for quoting into composer * opts.ref: React ref to attach to any React components returned (not compatible with opts.returnString) */ -export function bodyToHtml(content: IContent, highlights: string[], opts: IOptsReturnString): string; -export function bodyToHtml(content: IContent, highlights: string[], opts: IOptsReturnNode): ReactNode; -export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts = {}) { +export function bodyToHtml(content: IContent, highlights: Optional, opts: IOptsReturnString): string; +export function bodyToHtml(content: IContent, highlights: Optional, opts: IOptsReturnNode): ReactNode; +export function bodyToHtml(content: IContent, highlights: Optional, opts: IOpts = {}) { const isFormattedBody = content.format === "org.matrix.custom.html" && content.formatted_body; let bodyHasEmoji = false; let isHtmlMessage = false; diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 599c2949890..f0c0eb87864 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -199,7 +199,11 @@ export default class RightPanel extends React.Component { case RightPanelPhases.PinnedMessages: if (SettingsStore.getValue("feature_pinning")) { - card = ; + card = ; } break; case RightPanelPhases.Timeline: diff --git a/src/components/views/messages/IBodyProps.ts b/src/components/views/messages/IBodyProps.ts index 2487f2c1a91..1e66d1d1933 100644 --- a/src/components/views/messages/IBodyProps.ts +++ b/src/components/views/messages/IBodyProps.ts @@ -26,10 +26,10 @@ export interface IBodyProps { mxEvent: MatrixEvent; /* a list of words to highlight */ - highlights: string[]; + highlights?: string[]; /* link URL for the highlights */ - highlightLink: string; + highlightLink?: string; /* callback called when dynamic content in events are loaded */ onHeightChanged: () => void; diff --git a/src/components/views/messages/MessageEvent.tsx b/src/components/views/messages/MessageEvent.tsx index a47b70a7a82..840f2c79f13 100644 --- a/src/components/views/messages/MessageEvent.tsx +++ b/src/components/views/messages/MessageEvent.tsx @@ -67,7 +67,7 @@ export default class MessageEvent extends React.Component implements IMe public context!: React.ContextType; public constructor(props: IProps, context: React.ContextType) { - super(props); + super(props, context); if (MediaEventHelper.isEligible(this.props.mxEvent)) { this.mediaHelper = new MediaEventHelper(this.props.mxEvent); diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index ce58886c88e..459f3845580 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { createRef, SyntheticEvent, MouseEvent } from 'react'; +import React, { createRef, SyntheticEvent, MouseEvent, ReactNode } from 'react'; import ReactDOM from 'react-dom'; import highlight from 'highlight.js'; import { MsgType } from "matrix-js-sdk/src/@types/event"; @@ -565,7 +565,7 @@ export default class TextualBody extends React.Component { // only strip reply if this is the original replying event, edits thereafter do not have the fallback const stripReply = !mxEvent.replacingEvent() && !!getParentEventId(mxEvent); - let body; + let body: ReactNode; if (SettingsStore.isEnabled("feature_extensible_events")) { const extev = this.props.mxEvent.unstableExtensibleEvent as MessageEvent; if (extev?.isEquivalentTo(M_MESSAGE)) { diff --git a/src/components/views/right_panel/PinnedMessagesCard.tsx b/src/components/views/right_panel/PinnedMessagesCard.tsx index 1f4aac0f199..1c14828e70d 100644 --- a/src/components/views/right_panel/PinnedMessagesCard.tsx +++ b/src/components/views/right_panel/PinnedMessagesCard.tsx @@ -33,9 +33,11 @@ import { useRoomState } from "../../../hooks/useRoomState"; import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext"; import { ReadPinsEventId } from "./types"; import Heading from '../typography/Heading'; +import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; interface IProps { room: Room; + permalinkCreator: RoomPermalinkCreator; onClose(): void; } @@ -78,7 +80,7 @@ export const useReadPinnedEvents = (room: Room): Set => { return readPinnedEvents; }; -const PinnedMessagesCard = ({ room, onClose }: IProps) => { +const PinnedMessagesCard = ({ room, onClose, permalinkCreator }: IProps) => { const cli = useContext(MatrixClientContext); const roomContext = useContext(RoomContext); const canUnpin = useRoomState(room, state => state.mayClientSendStateEvent(EventType.RoomPinnedEvents, cli)); @@ -152,6 +154,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => { key={ev.getId()} event={ev} onUnpinClicked={canUnpin ? () => onUnpinClicked(ev) : undefined} + permalinkCreator={permalinkCreator} /> )); } else { diff --git a/src/components/views/rooms/PinnedEventTile.tsx b/src/components/views/rooms/PinnedEventTile.tsx index f9e4d858050..941c42a7fe5 100644 --- a/src/components/views/rooms/PinnedEventTile.tsx +++ b/src/components/views/rooms/PinnedEventTile.tsx @@ -33,9 +33,11 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { getUserNameColorClass } from "../../../utils/FormattingUtils"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; +import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; interface IProps { event: MatrixEvent; + permalinkCreator: RoomPermalinkCreator; onUnpinClicked?(): void; } @@ -140,6 +142,8 @@ export default class PinnedEventTile extends React.Component { className="mx_PinnedEventTile_body" maxImageHeight={150} onHeightChanged={() => {}} // we need to give this, apparently + permalinkCreator={this.props.permalinkCreator} + replacingEventId={this.props.event.replacingEventId()} /> diff --git a/src/events/EventTileFactory.tsx b/src/events/EventTileFactory.tsx index 17713108233..9315741c593 100644 --- a/src/events/EventTileFactory.tsx +++ b/src/events/EventTileFactory.tsx @@ -48,8 +48,8 @@ import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline"; export interface EventTileTypeProps { ref?: React.RefObject; // `any` because it's effectively impossible to convince TS of a reasonable type mxEvent: MatrixEvent; - highlights: string[]; - highlightLink: string; + highlights?: string[]; + highlightLink?: string; showUrlPreview?: boolean; onHeightChanged: () => void; forExport?: boolean; From f161081647be187a0d0480fdfb5070aeac79974a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Jul 2022 14:54:02 +0100 Subject: [PATCH 2/2] Fix tests --- .../views/right_panel/PinnedMessagesCard-test.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/components/views/right_panel/PinnedMessagesCard-test.tsx b/test/components/views/right_panel/PinnedMessagesCard-test.tsx index da30ae50ee4..23bdc2c7ff8 100644 --- a/test/components/views/right_panel/PinnedMessagesCard-test.tsx +++ b/test/components/views/right_panel/PinnedMessagesCard-test.tsx @@ -42,6 +42,7 @@ import PinnedMessagesCard from "../../../../src/components/views/right_panel/Pin import PinnedEventTile from "../../../../src/components/views/rooms/PinnedEventTile"; import MPollBody from "../../../../src/components/views/messages/MPollBody"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; +import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; describe("", () => { stubClient(); @@ -85,7 +86,11 @@ describe("", () => { const mountPins = async (room: Room): Promise>> => { let pins; await act(async () => { - pins = mount(, { + pins = mount(, { wrappingComponent: MatrixClientContext.Provider, wrappingComponentProps: { value: cli }, });