Fix pinned messages not re-linkifying on edit (#9042)

* Fix pinned messages not re-linkifying on edit

* Fix tests
pull/28217/head
Michael Telatynski 2022-07-12 07:27:45 +01:00 committed by GitHub
parent 2587aa1369
commit e576347b62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 30 additions and 13 deletions

View File

@ -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<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;

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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<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)) {

View File

@ -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<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));
@ -152,6 +154,7 @@ const PinnedMessagesCard = ({ room, onClose }: IProps) => {
key={ev.getId()}
event={ev}
onUnpinClicked={canUnpin ? () => onUnpinClicked(ev) : undefined}
permalinkCreator={permalinkCreator}
/>
));
} else {

View File

@ -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<IProps> {
className="mx_PinnedEventTile_body"
maxImageHeight={150}
onHeightChanged={() => {}} // we need to give this, apparently
permalinkCreator={this.props.permalinkCreator}
replacingEventId={this.props.event.replacingEventId()}
/>
</div>

View File

@ -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;

View File

@ -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();
@ -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 },
});