Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix pinned messages not re-linkifying on edit #9042

Merged
merged 2 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/HtmlUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<string[]>, opts: IOptsReturnString): string;
export function bodyToHtml(content: IContent, highlights: Optional<string[]>, opts: IOptsReturnNode): ReactNode;
export function bodyToHtml(content: IContent, highlights: Optional<string[]>, opts: IOpts = {}) {
const isFormattedBody = content.format === "org.matrix.custom.html" && content.formatted_body;
let bodyHasEmoji = false;
let isHtmlMessage = false;
Expand Down
6 changes: 5 additions & 1 deletion src/components/structures/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,11 @@ export default class RightPanel extends React.Component<IProps, IState> {

case RightPanelPhases.PinnedMessages:
if (SettingsStore.getValue("feature_pinning")) {
card = <PinnedMessagesCard room={this.props.room} onClose={this.onClose} />;
card = <PinnedMessagesCard
room={this.props.room}
onClose={this.onClose}
permalinkCreator={this.props.permalinkCreator}
/>;
}
break;
case RightPanelPhases.Timeline:
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/messages/IBodyProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/messages/MessageEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
public context!: React.ContextType<typeof MatrixClientContext>;

public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
super(props);
super(props, context);

if (MediaEventHelper.isEligible(this.props.mxEvent)) {
this.mediaHelper = new MediaEventHelper(this.props.mxEvent);
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/messages/TextualBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -565,7 +565,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {

// 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)) {
Expand Down
5 changes: 4 additions & 1 deletion src/components/views/right_panel/PinnedMessagesCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -78,7 +80,7 @@ export const useReadPinnedEvents = (room: Room): Set<string> => {
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));
Expand Down Expand Up @@ -152,6 +154,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => {
key={ev.getId()}
event={ev}
onUnpinClicked={canUnpin ? () => onUnpinClicked(ev) : undefined}
permalinkCreator={permalinkCreator}
/>
));
} else {
Expand Down
4 changes: 4 additions & 0 deletions src/components/views/rooms/PinnedEventTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -140,6 +142,8 @@ export default class PinnedEventTile extends React.Component<IProps> {
className="mx_PinnedEventTile_body"
maxImageHeight={150}
onHeightChanged={() => {}} // we need to give this, apparently
permalinkCreator={this.props.permalinkCreator}
replacingEventId={this.props.event.replacingEventId()}
/>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/events/EventTileFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline";
export interface EventTileTypeProps {
ref?: React.RefObject<any>; // `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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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("<PinnedMessagesCard />", () => {
stubClient();
Expand Down Expand Up @@ -85,7 +86,11 @@ describe("<PinnedMessagesCard />", () => {
const mountPins = async (room: Room): Promise<ReactWrapper<ComponentProps<typeof PinnedMessagesCard>>> => {
let pins;
await act(async () => {
pins = mount(<PinnedMessagesCard room={room} onClose={jest.fn()} />, {
pins = mount(<PinnedMessagesCard
room={room}
onClose={jest.fn()}
permalinkCreator={new RoomPermalinkCreator(room, room.roomId)}
/>, {
wrappingComponent: MatrixClientContext.Provider,
wrappingComponentProps: { value: cli },
});
Expand Down