feat: voice message

This commit is contained in:
Tristan Yang
2023-04-06 19:42:51 +08:00
parent 29675f593f
commit 4105204555
9 changed files with 132 additions and 30 deletions
+5
View File
@@ -22,6 +22,11 @@ const renderContent = (data: MessagePayload) => {
</span>
);
break;
case ContentTypes.audio:
res = (
<span className="text-gray-400 italic">[Voice Message]</span>
);
break;
case ContentTypes.markdown:
res = (
<div className="max-h-[152px] overflow-hidden dark:text-gray-100">
@@ -7,7 +7,7 @@ import MarkdownRender from "../MarkdownRender";
import FileMessage from "../FileMessage";
import { ContentType } from "../../../types/message";
import LinkifyText from '../LinkifyText';
import VoiceMessage, { VoiceMessageProps } from "../VoiceMessage";
import VoiceMessage from "../VoiceMessage";
type Props = {
context: "user" | "channel";
@@ -55,7 +55,7 @@ const renderContent = ({
case ContentTypes.audio:
{
// const { url, secure_url } = properties; todo
ctn = <VoiceMessage data={content as VoiceMessageProps} />;
ctn = <VoiceMessage file_path={content} />;
}
break;
case ContentTypes.file:
+7
View File
@@ -20,6 +20,13 @@ const renderContent = (data: MessagePayload) => {
// });
break;
case ContentTypes.audio:
res = (
<div className="text-sm">
<span className="text-gray-400 italic">[Voice Message]</span>
</div>
);
break;
case ContentTypes.markdown:
res = (
<div className="max-h-[100px] overflow-auto">
+67 -12
View File
@@ -1,4 +1,8 @@
import { useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import WaveSurfer from 'wavesurfer.js';
import IconPause from '../../assets/icons/pause.svg';
import IconPlay from '../../assets/icons/play.circle.svg';
import BASE_URL from '../../app/config';
export type VoiceMessageProps = {
type: string,
@@ -6,19 +10,70 @@ export type VoiceMessageProps = {
secure_url: string,
}
const VoiceMessage = ({ data }: { data: VoiceMessageProps }) => {
const [audio, setAudio] = useState(new Audio(data.url));
// useEffect(() => {
// first
// return () => {
// second
// }
// }, [url])
const VoiceMessage = ({ file_path }: { file_path: string }) => {
const waveRef = useRef<WaveSurfer | null>(null);
const containerRef = useRef(null);
const [playing, setPlaying] = useState(false);
const [duration, setDuration] = useState(0);
// const [audio, setAudio] = useState<HTMLAudioElement>(new Audio(`${BASE_URL}/resource/file?file_path=${encodeURIComponent(
// file_path
// )}`));
useEffect(() => {
let wave: WaveSurfer | null = null;
if (containerRef.current && file_path) {
const audioSrc = `${BASE_URL}/resource/file?file_path=${encodeURIComponent(
file_path
)}`;
wave = WaveSurfer.create({
container: containerRef.current,
maxCanvasWidth: 200,
height: 32,
waveColor: '#0BA5EC',
cursorColor: '#0BA5AA',
progressColor: "#0BA5AA",
hideScrollbar: true,
// mediaControls: true,
normalize: true
});
wave.load(audioSrc);
wave.on('play', function () {
setPlaying(true);
});
wave.on('pause', function () {
setPlaying(false);
});
wave.on('ready', function () {
if (waveRef.current) {
const dur = waveRef.current.getDuration();
setDuration(Math.ceil(dur));
}
});
waveRef.current = wave;
}
return () => {
if (waveRef.current) {
waveRef.current.destroy();
}
};
}, [file_path]);
const handleClick = () => {
if (waveRef.current) {
if (waveRef.current.isPlaying()) {
waveRef.current.pause();
} else {
waveRef.current.play();
}
}
};
return (
<div className='bg-green-800'>
audio message
<div className="select-none flex items-center gap-2 p-2 rounded-lg bg-primary-100 dark:bg-primary-900 max-w-sm">
<button onClick={handleClick}>
{playing ? <IconPause className="stroke-primary-500" /> : <IconPlay className="stroke-primary-500" />}
</button>
<div ref={containerRef} className='flex-1 h-8' >
</div>
<time className='text-primary-500 text-xs whitespace-nowrap text-left'>{duration}'</time>
</div>
);
};
+5
View File
@@ -59,6 +59,11 @@ export const renderPreviewMessage = (message = null) => {
res = <LinkifyText text={content} url={false} mentionTextOnly={true} />;
}
break;
case ContentTypes.audio:
{
res = `[${i18n.t("voice_message", { ns: "chat" })}]`;
}
break;
case ContentTypes.markdown:
{
res = `[markdown]`;