refactor: audio and video message
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// import { useState } from 'react';
|
||||
import { formatBytes } from '../../utils';
|
||||
import IconDownload from "../../../assets/icons/download.svg";
|
||||
import IconAudio from "../../../assets/icons/file.audio.svg";
|
||||
|
||||
type Props = {
|
||||
url: string,
|
||||
name: string,
|
||||
size: number,
|
||||
download: string
|
||||
}
|
||||
|
||||
const AudioMessage = ({ url, name, size, download }: Props) => {
|
||||
const _size = formatBytes(size);
|
||||
return (
|
||||
<div className='w-96 flex flex-col gap-2 px-3 py-2 rounded-md border border-solid border-gray-300 overflow-hidden bg-[#f1f3f4]'>
|
||||
<div className="flex justify-between z-30 overflow-hidden">
|
||||
<div className="flex gap-2 ">
|
||||
<IconAudio className="w-9 h-auto" />
|
||||
<div className="flex flex-col gap-1 text-sm text-gray-700">
|
||||
<span title={name} className='font-bold whitespace-nowrap text-ellipsis w-[240px] overflow-hidden'>{name}</span>
|
||||
<span>{_size}</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href={download} className="mt-2"><IconDownload className="download_icon gray" /></a>
|
||||
</div>
|
||||
<audio src={url} controls className="w-full object-cover z-10" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AudioMessage;
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useState } from 'react';
|
||||
import { formatBytes } from '../../utils';
|
||||
import IconDownload from "../../../assets/icons/download.svg";
|
||||
import IconVideo from "../../../assets/icons/file.video.svg";
|
||||
|
||||
type Props = {
|
||||
url: string,
|
||||
name: string,
|
||||
size: number,
|
||||
download: string
|
||||
}
|
||||
|
||||
const VideoMessage = ({ url, name, size, download }: Props) => {
|
||||
const [playing, setPlaying] = useState(false);
|
||||
const _size = formatBytes(size);
|
||||
const handlePlaying = () => {
|
||||
setPlaying(true);
|
||||
};
|
||||
const handlePause = () => {
|
||||
setPlaying(false);
|
||||
};
|
||||
return (
|
||||
<div className='w-96 h-52 relative rounded-md border border-solid border-gray-300 overflow-hidden group'>
|
||||
{!playing &&
|
||||
<>
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-black/40 z-20 group-hover:hidden"></div>
|
||||
<div className="absolute top-0 left-0 w-full flex justify-between z-30 px-3 py-2 overflow-hidden group-hover:bg-black/20">
|
||||
<div className="flex gap-2 ">
|
||||
<IconVideo className="w-9 h-auto" />
|
||||
<div className="flex flex-col gap-1 text-sm text-white">
|
||||
<span title={name} className='font-bold whitespace-nowrap text-ellipsis w-[240px] overflow-hidden'>{name}</span>
|
||||
<span>{_size}</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href={download} className="mt-2"><IconDownload className="fill-white" /></a>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
<video onPlaying={handlePlaying} onPause={handlePause} src={url} controls className="absolute left-0 top-0 w-full h-full object-cover z-10" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoMessage;
|
||||
@@ -6,10 +6,12 @@ import useRemoveLocalMessage from "../../hook/useRemoveLocalMessage";
|
||||
import useUploadFile from "../../hook/useUploadFile";
|
||||
import useSendMessage from "../../hook/useSendMessage";
|
||||
import Progress from "./Progress";
|
||||
import { getFileIcon, formatBytes, isImage, getImageSize, ImageSize } from "../../utils";
|
||||
import { getFileIcon, formatBytes, isImage, getImageSize } from "../../utils";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import IconDownload from "../../../assets/icons/download.svg";
|
||||
import IconClose from "../../../assets/icons/close.circle.svg";
|
||||
import VideoMessage from "./VideoMessage";
|
||||
import AudioMessage from "./AudioMessage";
|
||||
|
||||
const isLocalFile = (content: string) => {
|
||||
return content.startsWith("blob:");
|
||||
@@ -41,7 +43,7 @@ const FileMessage: FC<Props> = ({
|
||||
thumbnail = "",
|
||||
properties = { local_id: 0, name: "", size: 0, content_type: "" }
|
||||
}) => {
|
||||
const [imageSize, setImageSize] = useState<ImageSize | null>(null);
|
||||
const [imageSize, setImageSize] = useState(null);
|
||||
const [uploadingFile, setUploadingFile] = useState(false);
|
||||
const removeLocalMessage = useRemoveLocalMessage({ context, id: to });
|
||||
const {
|
||||
@@ -120,7 +122,7 @@ const FileMessage: FC<Props> = ({
|
||||
if (!content || !name) return null;
|
||||
|
||||
const sending = uploadingFile || isSending;
|
||||
|
||||
// image
|
||||
if (isImage(content_type, size))
|
||||
return (
|
||||
<ImageMessage
|
||||
@@ -133,6 +135,26 @@ const FileMessage: FC<Props> = ({
|
||||
thumbnail={thumbnail}
|
||||
/>
|
||||
);
|
||||
// video
|
||||
if (content_type.startsWith("video") && !sending)
|
||||
return (
|
||||
<VideoMessage
|
||||
size={size}
|
||||
url={content}
|
||||
name={name}
|
||||
download={download}
|
||||
/>
|
||||
);
|
||||
// audio
|
||||
if (content_type.startsWith("audio") && !sending)
|
||||
return (
|
||||
<AudioMessage
|
||||
size={size}
|
||||
url={content}
|
||||
name={name}
|
||||
download={download}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Styled className={`file_message ${sending ? "sending" : ""}`}>
|
||||
<div className="basic">
|
||||
|
||||
@@ -22,6 +22,7 @@ const Styled = styled.div`
|
||||
.icon {
|
||||
width: 36px;
|
||||
height: 48px;
|
||||
|
||||
}
|
||||
.info {
|
||||
display: flex;
|
||||
@@ -52,6 +53,9 @@ const Styled = styled.div`
|
||||
}
|
||||
.download {
|
||||
white-space: nowrap;
|
||||
svg path{
|
||||
fill: #616161;
|
||||
}
|
||||
}
|
||||
.cancel {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -82,6 +82,12 @@ const StyledMsg = styled.div`
|
||||
padding: 2px;
|
||||
color: #1fe1f9;
|
||||
}
|
||||
/* 下载图标颜色 */
|
||||
.download_icon.gray{
|
||||
path{
|
||||
fill: #616161;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.archive {
|
||||
|
||||
Reference in New Issue
Block a user