2024-05-31 16:19:46 +02:00
|
|
|
import React from 'react';
|
|
|
|
import { MsgType } from 'matrix-js-sdk';
|
|
|
|
import { HTMLReactParserOptions } from 'html-react-parser';
|
2024-07-30 14:18:59 +02:00
|
|
|
import { Opts } from 'linkifyjs';
|
2024-05-31 16:19:46 +02:00
|
|
|
import {
|
|
|
|
AudioContent,
|
|
|
|
DownloadFile,
|
|
|
|
FileContent,
|
|
|
|
ImageContent,
|
|
|
|
MAudio,
|
|
|
|
MBadEncrypted,
|
|
|
|
MEmote,
|
|
|
|
MFile,
|
|
|
|
MImage,
|
|
|
|
MLocation,
|
|
|
|
MNotice,
|
|
|
|
MText,
|
|
|
|
MVideo,
|
|
|
|
ReadPdfFile,
|
|
|
|
ReadTextFile,
|
|
|
|
RenderBody,
|
|
|
|
ThumbnailContent,
|
|
|
|
UnsupportedContent,
|
|
|
|
VideoContent,
|
|
|
|
} from './message';
|
|
|
|
import { UrlPreviewCard, UrlPreviewHolder } from './url-preview';
|
|
|
|
import { Image, MediaControl, Video } from './media';
|
|
|
|
import { ImageViewer } from './image-viewer';
|
|
|
|
import { PdfViewer } from './Pdf-viewer';
|
|
|
|
import { TextViewer } from './text-viewer';
|
2024-07-30 14:18:59 +02:00
|
|
|
import { testMatrixTo } from '../plugins/matrix-to';
|
2025-01-06 02:44:22 +01:00
|
|
|
import {IImageContent} from "../../types/matrix/common";
|
2024-05-31 16:19:46 +02:00
|
|
|
|
|
|
|
type RenderMessageContentProps = {
|
|
|
|
displayName: string;
|
|
|
|
msgType: string;
|
|
|
|
ts: number;
|
|
|
|
edited?: boolean;
|
|
|
|
getContent: <T>() => T;
|
|
|
|
mediaAutoLoad?: boolean;
|
|
|
|
urlPreview?: boolean;
|
|
|
|
highlightRegex?: RegExp;
|
|
|
|
htmlReactParserOptions: HTMLReactParserOptions;
|
2024-07-30 14:18:59 +02:00
|
|
|
linkifyOpts: Opts;
|
2024-05-31 16:19:46 +02:00
|
|
|
outlineAttachment?: boolean;
|
|
|
|
};
|
|
|
|
export function RenderMessageContent({
|
|
|
|
displayName,
|
|
|
|
msgType,
|
|
|
|
ts,
|
|
|
|
edited,
|
|
|
|
getContent,
|
|
|
|
mediaAutoLoad,
|
|
|
|
urlPreview,
|
|
|
|
highlightRegex,
|
|
|
|
htmlReactParserOptions,
|
2024-07-30 14:18:59 +02:00
|
|
|
linkifyOpts,
|
2024-05-31 16:19:46 +02:00
|
|
|
outlineAttachment,
|
|
|
|
}: RenderMessageContentProps) {
|
2024-07-30 14:18:59 +02:00
|
|
|
const renderUrlsPreview = (urls: string[]) => {
|
|
|
|
const filteredUrls = urls.filter((url) => !testMatrixTo(url));
|
|
|
|
if (filteredUrls.length === 0) return undefined;
|
|
|
|
return (
|
|
|
|
<UrlPreviewHolder>
|
|
|
|
{filteredUrls.map((url) => (
|
|
|
|
<UrlPreviewCard key={url} url={url} ts={ts} />
|
|
|
|
))}
|
|
|
|
</UrlPreviewHolder>
|
|
|
|
);
|
|
|
|
};
|
2025-01-06 02:44:22 +01:00
|
|
|
const renderCaption = () => {
|
|
|
|
const content: IImageContent = getContent();
|
|
|
|
if(content.filename && content.filename !== content.body) {
|
|
|
|
return (
|
|
|
|
<MText
|
|
|
|
edited={edited}
|
|
|
|
content={content}
|
|
|
|
renderBody={(props) => (
|
|
|
|
<RenderBody
|
|
|
|
{...props}
|
|
|
|
highlightRegex={highlightRegex}
|
|
|
|
htmlReactParserOptions={htmlReactParserOptions}
|
|
|
|
linkifyOpts={linkifyOpts}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
)}
|
2025-01-06 02:44:22 +01:00
|
|
|
renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const renderFile = () => (
|
|
|
|
<>
|
|
|
|
<MFile
|
|
|
|
content={getContent()}
|
|
|
|
renderFileContent={({ body, mimeType, info, encInfo, url }) => (
|
|
|
|
<FileContent
|
2024-05-31 16:19:46 +02:00
|
|
|
body={body}
|
|
|
|
mimeType={mimeType}
|
2025-01-06 02:44:22 +01:00
|
|
|
renderAsPdfFile={() => (
|
|
|
|
<ReadPdfFile
|
|
|
|
body={body}
|
|
|
|
mimeType={mimeType}
|
|
|
|
url={url}
|
|
|
|
encInfo={encInfo}
|
|
|
|
renderViewer={(p) => <PdfViewer {...p} />}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
renderAsTextFile={() => (
|
|
|
|
<ReadTextFile
|
|
|
|
body={body}
|
|
|
|
mimeType={mimeType}
|
|
|
|
url={url}
|
|
|
|
encInfo={encInfo}
|
|
|
|
renderViewer={(p) => <TextViewer {...p} />}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
>
|
|
|
|
<DownloadFile body={body} mimeType={mimeType} url={url} encInfo={encInfo} info={info} />
|
|
|
|
</FileContent>
|
|
|
|
|
|
|
|
)}
|
|
|
|
outlined={outlineAttachment}
|
|
|
|
/>
|
|
|
|
{renderCaption()}
|
|
|
|
</>
|
2024-05-31 16:19:46 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if (msgType === MsgType.Text) {
|
|
|
|
return (
|
|
|
|
<MText
|
|
|
|
edited={edited}
|
|
|
|
content={getContent()}
|
|
|
|
renderBody={(props) => (
|
|
|
|
<RenderBody
|
|
|
|
{...props}
|
|
|
|
highlightRegex={highlightRegex}
|
|
|
|
htmlReactParserOptions={htmlReactParserOptions}
|
2024-07-30 14:18:59 +02:00
|
|
|
linkifyOpts={linkifyOpts}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
)}
|
2024-07-30 14:18:59 +02:00
|
|
|
renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Emote) {
|
|
|
|
return (
|
|
|
|
<MEmote
|
|
|
|
displayName={displayName}
|
|
|
|
edited={edited}
|
|
|
|
content={getContent()}
|
|
|
|
renderBody={(props) => (
|
|
|
|
<RenderBody
|
|
|
|
{...props}
|
|
|
|
highlightRegex={highlightRegex}
|
|
|
|
htmlReactParserOptions={htmlReactParserOptions}
|
2024-07-30 14:18:59 +02:00
|
|
|
linkifyOpts={linkifyOpts}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
)}
|
2024-07-30 14:18:59 +02:00
|
|
|
renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Notice) {
|
|
|
|
return (
|
|
|
|
<MNotice
|
|
|
|
edited={edited}
|
|
|
|
content={getContent()}
|
|
|
|
renderBody={(props) => (
|
|
|
|
<RenderBody
|
|
|
|
{...props}
|
|
|
|
highlightRegex={highlightRegex}
|
|
|
|
htmlReactParserOptions={htmlReactParserOptions}
|
2024-07-30 14:18:59 +02:00
|
|
|
linkifyOpts={linkifyOpts}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
)}
|
2024-07-30 14:18:59 +02:00
|
|
|
renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
|
2024-05-31 16:19:46 +02:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Image) {
|
|
|
|
return (
|
2025-01-06 02:44:22 +01:00
|
|
|
<>
|
|
|
|
<MImage
|
|
|
|
content={getContent()}
|
|
|
|
renderImageContent={(props) => (
|
|
|
|
<ImageContent
|
|
|
|
{...props}
|
|
|
|
autoPlay={mediaAutoLoad}
|
|
|
|
renderImage={(p) => <Image {...p} loading="lazy" />}
|
|
|
|
renderViewer={(p) => <ImageViewer {...p} />}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
outlined={outlineAttachment}
|
|
|
|
/>
|
|
|
|
{renderCaption()}
|
|
|
|
</>
|
2024-05-31 16:19:46 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Video) {
|
|
|
|
return (
|
2025-01-06 02:44:22 +01:00
|
|
|
<>
|
|
|
|
<MVideo
|
|
|
|
content={getContent()}
|
|
|
|
renderAsFile={renderFile}
|
|
|
|
renderVideoContent={({ body, info, mimeType, url, encInfo }) => (
|
|
|
|
<VideoContent
|
|
|
|
body={body}
|
|
|
|
info={info}
|
|
|
|
mimeType={mimeType}
|
|
|
|
url={url}
|
|
|
|
encInfo={encInfo}
|
|
|
|
renderThumbnail={
|
|
|
|
mediaAutoLoad
|
|
|
|
? () => (
|
2024-05-31 16:19:46 +02:00
|
|
|
<ThumbnailContent
|
|
|
|
info={info}
|
|
|
|
renderImage={(src) => (
|
|
|
|
<Image alt={body} title={body} src={src} loading="lazy" />
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
)
|
2025-01-06 02:44:22 +01:00
|
|
|
: undefined
|
|
|
|
}
|
|
|
|
renderVideo={(p) => <Video {...p} />}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
outlined={outlineAttachment}
|
|
|
|
/>
|
|
|
|
{renderCaption()}
|
|
|
|
</>
|
|
|
|
|
2024-05-31 16:19:46 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Audio) {
|
|
|
|
return (
|
2025-01-06 02:44:22 +01:00
|
|
|
<>
|
|
|
|
<MAudio
|
|
|
|
content={getContent()}
|
|
|
|
renderAsFile={renderFile}
|
|
|
|
renderAudioContent={(props) => (
|
|
|
|
<AudioContent {...props} renderMediaControl={(p) => <MediaControl {...p} />} />
|
|
|
|
)}
|
|
|
|
outlined={outlineAttachment}
|
|
|
|
/>
|
|
|
|
{renderCaption()}
|
|
|
|
</>
|
|
|
|
|
2024-05-31 16:19:46 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.File) {
|
|
|
|
return renderFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === MsgType.Location) {
|
|
|
|
return <MLocation content={getContent()} />;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType === 'm.bad.encrypted') {
|
|
|
|
return <MBadEncrypted />;
|
|
|
|
}
|
|
|
|
|
|
|
|
return <UnsupportedContent />;
|
|
|
|
}
|