mirror of
				https://github.com/cinnyapp/cinny.git
				synced 2025-11-04 06:20:28 +03:00 
			
		
		
		
	Render captions to m.file, m.image, m.video, and m.audio (#2059)
* Add rendering image captions * Handle sending captions for images * Fix caption rendering on m.video and m.audio too * Remove unused renderBody() parameter * Fix m.file rendering body instead of filename where possible * Add caption rendering for generic files + Fix video and audio not properly sending captions * Use m.text for captions & render on demand * Allow custom HTML in sending captions * Don't *send* captions * mvoe content const into renderCaption() --------- Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									3c5afaf33a
								
							
						
					
					
						commit
						02437a6a20
					
				
					 4 changed files with 118 additions and 73 deletions
				
			
		| 
						 | 
				
			
			@ -29,6 +29,7 @@ import { ImageViewer } from './image-viewer';
 | 
			
		|||
import { PdfViewer } from './Pdf-viewer';
 | 
			
		||||
import { TextViewer } from './text-viewer';
 | 
			
		||||
import { testMatrixTo } from '../plugins/matrix-to';
 | 
			
		||||
import {IImageContent} from "../../types/matrix/common";
 | 
			
		||||
 | 
			
		||||
type RenderMessageContentProps = {
 | 
			
		||||
  displayName: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -67,38 +68,63 @@ export function RenderMessageContent({
 | 
			
		|||
      </UrlPreviewHolder>
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
  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}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
          renderUrlsPreview={urlPreview ? renderUrlsPreview : undefined}
 | 
			
		||||
        />
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const renderFile = () => (
 | 
			
		||||
    <MFile
 | 
			
		||||
      content={getContent()}
 | 
			
		||||
      renderFileContent={({ body, mimeType, info, encInfo, url }) => (
 | 
			
		||||
        <FileContent
 | 
			
		||||
          body={body}
 | 
			
		||||
          mimeType={mimeType}
 | 
			
		||||
          renderAsPdfFile={() => (
 | 
			
		||||
            <ReadPdfFile
 | 
			
		||||
    <>
 | 
			
		||||
      <MFile
 | 
			
		||||
        content={getContent()}
 | 
			
		||||
        renderFileContent={({ body, mimeType, info, encInfo, url }) => (
 | 
			
		||||
            <FileContent
 | 
			
		||||
              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}
 | 
			
		||||
    />
 | 
			
		||||
              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()}
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if (msgType === MsgType.Text) {
 | 
			
		||||
| 
						 | 
				
			
			@ -158,36 +184,40 @@ export function RenderMessageContent({
 | 
			
		|||
 | 
			
		||||
  if (msgType === MsgType.Image) {
 | 
			
		||||
    return (
 | 
			
		||||
      <MImage
 | 
			
		||||
        content={getContent()}
 | 
			
		||||
        renderImageContent={(props) => (
 | 
			
		||||
          <ImageContent
 | 
			
		||||
            {...props}
 | 
			
		||||
            autoPlay={mediaAutoLoad}
 | 
			
		||||
            renderImage={(p) => <Image {...p} loading="lazy" />}
 | 
			
		||||
            renderViewer={(p) => <ImageViewer {...p} />}
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
        outlined={outlineAttachment}
 | 
			
		||||
      />
 | 
			
		||||
      <>
 | 
			
		||||
        <MImage
 | 
			
		||||
          content={getContent()}
 | 
			
		||||
          renderImageContent={(props) => (
 | 
			
		||||
              <ImageContent
 | 
			
		||||
                  {...props}
 | 
			
		||||
                  autoPlay={mediaAutoLoad}
 | 
			
		||||
                  renderImage={(p) => <Image {...p} loading="lazy" />}
 | 
			
		||||
                  renderViewer={(p) => <ImageViewer {...p} />}
 | 
			
		||||
              />
 | 
			
		||||
          )}
 | 
			
		||||
          outlined={outlineAttachment}
 | 
			
		||||
        />
 | 
			
		||||
        {renderCaption()}
 | 
			
		||||
      </>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (msgType === MsgType.Video) {
 | 
			
		||||
    return (
 | 
			
		||||
      <MVideo
 | 
			
		||||
        content={getContent()}
 | 
			
		||||
        renderAsFile={renderFile}
 | 
			
		||||
        renderVideoContent={({ body, info, mimeType, url, encInfo }) => (
 | 
			
		||||
          <VideoContent
 | 
			
		||||
            body={body}
 | 
			
		||||
            info={info}
 | 
			
		||||
            mimeType={mimeType}
 | 
			
		||||
            url={url}
 | 
			
		||||
            encInfo={encInfo}
 | 
			
		||||
            renderThumbnail={
 | 
			
		||||
              mediaAutoLoad
 | 
			
		||||
                ? () => (
 | 
			
		||||
      <>
 | 
			
		||||
        <MVideo
 | 
			
		||||
          content={getContent()}
 | 
			
		||||
          renderAsFile={renderFile}
 | 
			
		||||
          renderVideoContent={({ body, info, mimeType, url, encInfo }) => (
 | 
			
		||||
            <VideoContent
 | 
			
		||||
              body={body}
 | 
			
		||||
              info={info}
 | 
			
		||||
              mimeType={mimeType}
 | 
			
		||||
              url={url}
 | 
			
		||||
              encInfo={encInfo}
 | 
			
		||||
              renderThumbnail={
 | 
			
		||||
                mediaAutoLoad
 | 
			
		||||
                  ? () => (
 | 
			
		||||
                    <ThumbnailContent
 | 
			
		||||
                      info={info}
 | 
			
		||||
                      renderImage={(src) => (
 | 
			
		||||
| 
						 | 
				
			
			@ -195,26 +225,33 @@ export function RenderMessageContent({
 | 
			
		|||
                      )}
 | 
			
		||||
                    />
 | 
			
		||||
                  )
 | 
			
		||||
                : undefined
 | 
			
		||||
            }
 | 
			
		||||
            renderVideo={(p) => <Video {...p} />}
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
        outlined={outlineAttachment}
 | 
			
		||||
      />
 | 
			
		||||
                  : undefined
 | 
			
		||||
              }
 | 
			
		||||
              renderVideo={(p) => <Video {...p} />}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
          outlined={outlineAttachment}
 | 
			
		||||
        />
 | 
			
		||||
        {renderCaption()}
 | 
			
		||||
      </>
 | 
			
		||||
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (msgType === MsgType.Audio) {
 | 
			
		||||
    return (
 | 
			
		||||
      <MAudio
 | 
			
		||||
        content={getContent()}
 | 
			
		||||
        renderAsFile={renderFile}
 | 
			
		||||
        renderAudioContent={(props) => (
 | 
			
		||||
          <AudioContent {...props} renderMediaControl={(p) => <MediaControl {...p} />} />
 | 
			
		||||
        )}
 | 
			
		||||
        outlined={outlineAttachment}
 | 
			
		||||
      />
 | 
			
		||||
      <>
 | 
			
		||||
        <MAudio
 | 
			
		||||
          content={getContent()}
 | 
			
		||||
          renderAsFile={renderFile}
 | 
			
		||||
          renderAudioContent={(props) => (
 | 
			
		||||
            <AudioContent {...props} renderMediaControl={(p) => <MediaControl {...p} />} />
 | 
			
		||||
          )}
 | 
			
		||||
          outlined={outlineAttachment}
 | 
			
		||||
        />
 | 
			
		||||
        {renderCaption()}
 | 
			
		||||
      </>
 | 
			
		||||
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -172,6 +172,7 @@ export function MNotice({ edited, content, renderBody, renderUrlsPreview }: MNot
 | 
			
		|||
 | 
			
		||||
type RenderImageContentProps = {
 | 
			
		||||
  body: string;
 | 
			
		||||
  filename?: string;
 | 
			
		||||
  info?: IImageInfo & IThumbnailContent;
 | 
			
		||||
  mimeType?: string;
 | 
			
		||||
  url: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -282,7 +283,7 @@ export function MAudio({ content, renderAsFile, renderAudioContent, outlined }:
 | 
			
		|||
  return (
 | 
			
		||||
    <Attachment outlined={outlined}>
 | 
			
		||||
      <AttachmentHeader>
 | 
			
		||||
        <FileHeader body={content.body ?? 'Audio'} mimeType={safeMimeType} />
 | 
			
		||||
        <FileHeader body={content.filename ?? content.body ?? 'Audio'} mimeType={safeMimeType} />
 | 
			
		||||
      </AttachmentHeader>
 | 
			
		||||
      <AttachmentBox>
 | 
			
		||||
        <AttachmentContent>
 | 
			
		||||
| 
						 | 
				
			
			@ -322,14 +323,14 @@ export function MFile({ content, renderFileContent, outlined }: MFileProps) {
 | 
			
		|||
    <Attachment outlined={outlined}>
 | 
			
		||||
      <AttachmentHeader>
 | 
			
		||||
        <FileHeader
 | 
			
		||||
          body={content.body ?? 'Unnamed File'}
 | 
			
		||||
          body={content.filename ?? content.body ?? 'Unnamed File'}
 | 
			
		||||
          mimeType={fileInfo?.mimetype ?? FALLBACK_MIMETYPE}
 | 
			
		||||
        />
 | 
			
		||||
      </AttachmentHeader>
 | 
			
		||||
      <AttachmentBox>
 | 
			
		||||
        <AttachmentContent>
 | 
			
		||||
          {renderFileContent({
 | 
			
		||||
            body: content.body ?? 'File',
 | 
			
		||||
            body: content.filename ?? content.body ?? 'File',
 | 
			
		||||
            info: fileInfo ?? {},
 | 
			
		||||
            mimeType: fileInfo?.mimetype ?? FALLBACK_MIMETYPE,
 | 
			
		||||
            url: mxcUrl,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ const generateThumbnailContent = async (
 | 
			
		|||
export const getImageMsgContent = async (
 | 
			
		||||
  mx: MatrixClient,
 | 
			
		||||
  item: TUploadItem,
 | 
			
		||||
  mxc: string
 | 
			
		||||
  mxc: string,
 | 
			
		||||
): Promise<IContent> => {
 | 
			
		||||
  const { file, originalFile, encInfo } = item;
 | 
			
		||||
  const [imgError, imgEl] = await to(loadImageElement(getImageFileUrl(originalFile)));
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +50,7 @@ export const getImageMsgContent = async (
 | 
			
		|||
 | 
			
		||||
  const content: IContent = {
 | 
			
		||||
    msgtype: MsgType.Image,
 | 
			
		||||
    filename: file.name,
 | 
			
		||||
    body: file.name,
 | 
			
		||||
  };
 | 
			
		||||
  if (imgEl) {
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +75,7 @@ export const getImageMsgContent = async (
 | 
			
		|||
export const getVideoMsgContent = async (
 | 
			
		||||
  mx: MatrixClient,
 | 
			
		||||
  item: TUploadItem,
 | 
			
		||||
  mxc: string
 | 
			
		||||
  mxc: string,
 | 
			
		||||
): Promise<IContent> => {
 | 
			
		||||
  const { file, originalFile, encInfo } = item;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +84,7 @@ export const getVideoMsgContent = async (
 | 
			
		|||
 | 
			
		||||
  const content: IContent = {
 | 
			
		||||
    msgtype: MsgType.Video,
 | 
			
		||||
    filename: file.name,
 | 
			
		||||
    body: file.name,
 | 
			
		||||
  };
 | 
			
		||||
  if (videoEl) {
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +124,7 @@ export const getAudioMsgContent = (item: TUploadItem, mxc: string): IContent =>
 | 
			
		|||
  const { file, encInfo } = item;
 | 
			
		||||
  const content: IContent = {
 | 
			
		||||
    msgtype: MsgType.Audio,
 | 
			
		||||
    filename: file.name,
 | 
			
		||||
    body: file.name,
 | 
			
		||||
    info: {
 | 
			
		||||
      mimetype: file.type,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,7 @@ export type IThumbnailContent = {
 | 
			
		|||
export type IImageContent = {
 | 
			
		||||
  msgtype: MsgType.Image;
 | 
			
		||||
  body?: string;
 | 
			
		||||
  filename?: string;
 | 
			
		||||
  url?: string;
 | 
			
		||||
  info?: IImageInfo & IThumbnailContent;
 | 
			
		||||
  file?: IEncryptedFile;
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +52,7 @@ export type IImageContent = {
 | 
			
		|||
export type IVideoContent = {
 | 
			
		||||
  msgtype: MsgType.Video;
 | 
			
		||||
  body?: string;
 | 
			
		||||
  filename?: string;
 | 
			
		||||
  url?: string;
 | 
			
		||||
  info?: IVideoInfo & IThumbnailContent;
 | 
			
		||||
  file?: IEncryptedFile;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +61,7 @@ export type IVideoContent = {
 | 
			
		|||
export type IAudioContent = {
 | 
			
		||||
  msgtype: MsgType.Audio;
 | 
			
		||||
  body?: string;
 | 
			
		||||
  filename?: string;
 | 
			
		||||
  url?: string;
 | 
			
		||||
  info?: IAudioInfo;
 | 
			
		||||
  file?: IEncryptedFile;
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +70,7 @@ export type IAudioContent = {
 | 
			
		|||
export type IFileContent = {
 | 
			
		||||
  msgtype: MsgType.File;
 | 
			
		||||
  body?: string;
 | 
			
		||||
  filename?: string;
 | 
			
		||||
  url?: string;
 | 
			
		||||
  info?: IFileInfo & IThumbnailContent;
 | 
			
		||||
  file?: IEncryptedFile;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue