mirror of https://github.com/vector-im/riot-web
Fix pinned messages not re-linkifying on edit (#9042)
* Fix pinned messages not re-linkifying on edit * Fix testspull/28217/head
parent
2587aa1369
commit
e576347b62
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue