Files
cinny/src/app/features/room/msgContent.ts
T
Lotus Bot 266e47f240 chore: upgrade TypeScript 4.9 to 5.9, ESLint 8.29 to 8.57, @typescript-eslint 5 to 7
Resolves all TS2345/TS2347/TS7006 type errors introduced by stricter TypeScript 5.x.
Fix Icons.Settings to Icons.Setting, cast account data returns, fix implicit any.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 11:16:11 -04:00

172 lines
4.6 KiB
TypeScript

import { IContent, MatrixClient, MsgType } from 'matrix-js-sdk';
import to from 'await-to-js';
import {
IThumbnailContent,
MATRIX_BLUR_HASH_PROPERTY_NAME,
MATRIX_SPOILER_PROPERTY_NAME,
} from '../../../types/matrix/common';
import {
getImageFileUrl,
getThumbnail,
getThumbnailDimensions,
getVideoFileUrl,
loadImageElement,
loadVideoElement,
} from '../../utils/dom';
import { encryptFile, getImageInfo, getThumbnailContent, getVideoInfo } from '../../utils/matrix';
import { TUploadItem } from '../../state/room/roomInputDrafts';
import { encodeBlurHash } from '../../utils/blurHash';
import { scaleYDimension } from '../../utils/common';
const generateThumbnailContent = async (
mx: MatrixClient,
img: HTMLImageElement | HTMLVideoElement,
dimensions: [number, number],
encrypt: boolean,
): Promise<IThumbnailContent> => {
const thumbnail = await getThumbnail(img, ...dimensions);
if (!thumbnail) throw new Error('Can not create thumbnail!');
const encThumbData = encrypt ? await encryptFile(thumbnail) : undefined;
const thumbnailFile = encThumbData?.file ?? thumbnail;
if (!thumbnailFile) throw new Error('Can not create thumbnail!');
const data = await mx.uploadContent(thumbnailFile);
const thumbMxc = data?.content_uri;
if (!thumbMxc) throw new Error('Failed when uploading thumbnail!');
const thumbnailContent = getThumbnailContent({
thumbnail: thumbnailFile,
encInfo: encThumbData?.encInfo,
mxc: thumbMxc,
width: dimensions[0],
height: dimensions[1],
});
return thumbnailContent;
};
export const getImageMsgContent = async (
mx: MatrixClient,
item: TUploadItem,
mxc: string,
): Promise<IContent> => {
const { file, originalFile, encInfo, metadata } = item;
const [imgError, imgEl] = await to(loadImageElement(getImageFileUrl(originalFile)));
if (imgError) console.warn(imgError);
const content: IContent = {
msgtype: MsgType.Image,
filename: (file as File).name,
body: metadata.caption?.trim() || (file as File).name,
[MATRIX_SPOILER_PROPERTY_NAME]: metadata.markedAsSpoiler,
};
if (imgEl) {
const blurHash = encodeBlurHash(imgEl, 512, scaleYDimension(imgEl.width, 512, imgEl.height));
content.info = {
...getImageInfo(imgEl, file),
[MATRIX_BLUR_HASH_PROPERTY_NAME]: blurHash,
};
}
if (encInfo) {
content.file = {
...encInfo,
url: mxc,
};
} else {
content.url = mxc;
}
return content;
};
export const getVideoMsgContent = async (
mx: MatrixClient,
item: TUploadItem,
mxc: string,
): Promise<IContent> => {
const { file, originalFile, encInfo, metadata } = item;
const [videoError, videoEl] = await to(loadVideoElement(getVideoFileUrl(originalFile)));
if (videoError) console.warn(videoError);
const content: IContent = {
msgtype: MsgType.Video,
filename: (file as File).name,
body: metadata.caption?.trim() || (file as File).name,
[MATRIX_SPOILER_PROPERTY_NAME]: metadata.markedAsSpoiler,
};
if (videoEl) {
const [thumbError, thumbContent] = await to(
generateThumbnailContent(
mx,
videoEl,
getThumbnailDimensions(videoEl.videoWidth, videoEl.videoHeight),
!!encInfo,
),
);
if (thumbContent && thumbContent.thumbnail_info) {
thumbContent.thumbnail_info[MATRIX_BLUR_HASH_PROPERTY_NAME] = encodeBlurHash(
videoEl,
512,
scaleYDimension(videoEl.videoWidth, 512, videoEl.videoHeight),
);
}
if (thumbError) console.warn(thumbError);
content.info = {
...getVideoInfo(videoEl, file),
...thumbContent,
};
}
if (encInfo) {
content.file = {
...encInfo,
url: mxc,
};
} else {
content.url = mxc;
}
return content;
};
export const getAudioMsgContent = (item: TUploadItem, mxc: string): IContent => {
const { file, encInfo } = item;
const content: IContent = {
msgtype: MsgType.Audio,
filename: (file as File).name,
body: (file as File).name,
info: {
mimetype: file.type,
size: file.size,
},
};
if (encInfo) {
content.file = {
...encInfo,
url: mxc,
};
} else {
content.url = mxc;
}
return content;
};
export const getFileMsgContent = (item: TUploadItem, mxc: string): IContent => {
const { file, encInfo } = item;
const content: IContent = {
msgtype: MsgType.File,
body: (file as File).name,
filename: (file as File).name,
info: {
mimetype: file.type,
size: file.size,
},
};
if (encInfo) {
content.file = {
...encInfo,
url: mxc,
};
} else {
content.url = mxc;
}
return content;
};