feat: parse width and height when upload image and render image

pull/81/head
moonrailgun 3 years ago
parent d0ee111160
commit a76f52228d

@ -2,17 +2,49 @@ import React from 'react';
import { Image } from '@capital/component';
import type { TagProps } from '../bbcode/type';
const MAX_HEIGHT = 320;
const MAX_WIDTH = 320;
const imageStyle: React.CSSProperties = {
maxHeight: 320,
maxWidth: 320,
maxHeight: MAX_HEIGHT,
maxWidth: MAX_WIDTH,
width: 'auto',
};
function parseImageAttr(attr: { height: string; width: string }): {
height?: number;
width?: number;
} {
const height = Number(attr.height);
const width = Number(attr.width);
if (!(height > 0 && width > 0)) {
// 确保宽高为数字且均大于0
return {};
}
const ratio = Math.max(height / MAX_HEIGHT, width / MAX_WIDTH);
return {
height: height / ratio,
width: width / ratio,
};
}
export const ImgTag: React.FC<TagProps> = React.memo((props) => {
const { node } = props;
const text = node.content.join('');
const url = node.attrs.url ?? text;
return <Image style={imageStyle} preview={true} src={url} />;
return (
<Image
style={{
...imageStyle,
...parseImageAttr(node.attrs as any),
}}
preview={true}
src={url}
/>
);
});
ImgTag.displayName = 'ImgTag';

@ -33,7 +33,7 @@ const DrawModal: React.FC<{
const file = dataUrlToFile(dataUrl);
const res = await uploadFile(file);
sendMsg(`[img]${res.url}[/img]`);
sendMsg(`[img width=400 height=400]${res.url}[/img]`);
onSuccess();
}, [sendMsg, onSuccess]);

@ -18,9 +18,11 @@ export const ChatInputAddon: React.FC = React.memo(() => {
const image = files[0];
if (image) {
// 发送图片
uploadMessageImage(image).then((imageRemoteUrl) => {
uploadMessageImage(image).then(({ url, width, height }) => {
// TODO: not good, should bind with plugin bbcode
actionContext.sendMsg(`[img]${imageRemoteUrl}[/img]`);
actionContext.sendMsg(
`[img width=${width} height=${height}]${url}[/img]`
);
});
}
};

@ -36,9 +36,9 @@ export const ChatInputBox: React.FC<ChatInputBoxProps> = React.memo((props) => {
if (image) {
// 上传图片
e.preventDefault();
uploadMessageImage(image).then((imageRemoteUrl) => {
uploadMessageImage(image).then(({ url, width, height }) => {
// TODO: not good, should bind with plugin bbcode
props.onSendMsg(`[img]${imageRemoteUrl}[/img]`);
props.onSendMsg(`[img width=${width} height=${height}]${url}[/img]`);
});
}
},

@ -7,7 +7,11 @@ import { uploadFile } from 'tailchat-shared';
/**
*
*/
export function uploadMessageImage(image: File): Promise<string> {
export function uploadMessageImage(image: File): Promise<{
url: string;
width: number;
height: number;
}> {
return new Promise((resolve) => {
fileToDataUrl(image).then((imageLocalUrl) => {
const key = openModal(
@ -16,11 +20,15 @@ export function uploadMessageImage(image: File): Promise<string> {
onCancel={() => {
closeModal(key);
}}
onConfirm={async () => {
onConfirm={async (size) => {
const fileInfo = await uploadFile(image);
const imageRemoteUrl = fileInfo.url;
resolve(imageRemoteUrl);
resolve({
url: imageRemoteUrl,
width: size.width,
height: size.height,
});
closeModal(key);
}}
/>

@ -1,22 +1,28 @@
import { ModalWrapper } from '@/plugin/common';
import { Button } from '@/plugin/component';
import React from 'react';
import React, { useCallback, useRef } from 'react';
import { t, useAsyncFn } from 'tailchat-shared';
import { useGlobalKeyDown } from '../../hooks/useGlobalKeyDown';
import { isEnterHotkey, isEscHotkey } from '../../utils/hot-key';
interface ImageSize {
width: number;
height: number;
}
interface ImageUploadPreviewerProps {
imageUrl: string;
onConfirm: () => void;
onConfirm: (imageSize: ImageSize) => Promise<void>;
onCancel: () => void;
}
export const ImageUploadPreviewer: React.FC<ImageUploadPreviewerProps> =
React.memo((props) => {
const { imageUrl } = props;
const imageSizeRef = useRef<ImageSize>({ width: 0, height: 0 });
const [{ loading }, handleConfirm] = useAsyncFn(async () => {
if (typeof props.onConfirm === 'function') {
await Promise.resolve(props.onConfirm());
await Promise.resolve(props.onConfirm(imageSizeRef.current));
}
}, [props.onConfirm]);
@ -35,11 +41,27 @@ export const ImageUploadPreviewer: React.FC<ImageUploadPreviewerProps> =
}
);
const handleLoad = useCallback(
(e: React.SyntheticEvent<HTMLImageElement, Event>) => {
const target = e.currentTarget;
imageSizeRef.current = {
width: target.naturalWidth,
height: target.naturalHeight,
};
},
[]
);
return (
<ModalWrapper style={{ maxHeight: '60vh', maxWidth: '60vw' }}>
<div className="flex">
<div className="w-2/3 p-2.5 bg-black bg-opacity-20 rounded">
<img className="max-h-72 m-auto" src={imageUrl} />
<img
className="max-h-72 m-auto"
src={imageUrl}
onLoad={handleLoad}
/>
</div>
<div className="w-1/3 p-2 flex flex-col items-end justify-between">

Loading…
Cancel
Save