diff --git a/package.json b/package.json
index a95aed3a..b8731c0f 100644
--- a/package.json
+++ b/package.json
@@ -65,8 +65,8 @@
"react-textarea-autosize": "^8.4.1",
"react-use-wizard": "^2.2.1",
"react-viewport-list": "^7.0.0",
- "react-virtuoso": "^4.1.1",
- "resolve": "^1.22.1",
+ "react-virtuoso": "^4.2.0",
+ "resolve": "^1.22.2",
"rooks": "^7.10.0",
"slate": "^0.93.0",
"slate-history": "^0.93.0",
@@ -77,7 +77,8 @@
"terser-webpack-plugin": "^5.3.7",
"tippy.js": "^6.3.7",
"typescript": "^5.0.3",
- "webpack": "^5.77.0",
+ "wavesurfer.js": "^6.6.3",
+ "webpack": "^5.78.0",
"webpack-dev-server": "^4.13.2",
"webpack-manifest-plugin": "^5.0.0",
"workbox-background-sync": "^6.5.4",
@@ -125,6 +126,7 @@
"@types/masonry-layout": "^4.2.5",
"@types/react-helmet": "^6.1.6",
"@types/react-syntax-highlighter": "^15.5.6",
+ "@types/wavesurfer.js": "^6.0.4",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"@welldone-software/why-did-you-render": "^7.0.1",
@@ -143,7 +145,7 @@
"md5-file": "^5.0.0",
"patch-package": "^6.5.1",
"postcss": "^8.4.21",
- "postcss-loader": "^7.2.3",
+ "postcss-loader": "^7.2.4",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.7",
"tailwindcss": "^3.3.1"
diff --git a/public/locales/en/chat.json b/public/locales/en/chat.json
index d3ffe957..cc996118 100644
--- a/public/locales/en/chat.json
+++ b/public/locales/en/chat.json
@@ -46,6 +46,7 @@
"file": "file",
"image": "image",
"forward": "forward",
+ "voice_message": "voice message",
"voice": "Voice Chat",
"deafen": "Deafen",
"undeafen": "Undeafen",
diff --git a/public/locales/zh/chat.json b/public/locales/zh/chat.json
index ebf25a68..bd79898f 100644
--- a/public/locales/zh/chat.json
+++ b/public/locales/zh/chat.json
@@ -47,6 +47,7 @@
"file": "文件",
"image": "图片",
"forward": "转发",
+ "voice_message": "语音消息",
"voice": "音频通话",
"deafen": "静默",
"undeafen": "取消静默",
diff --git a/src/common/component/Message/Reply.tsx b/src/common/component/Message/Reply.tsx
index 8024bfe5..dc720e3f 100644
--- a/src/common/component/Message/Reply.tsx
+++ b/src/common/component/Message/Reply.tsx
@@ -22,6 +22,11 @@ const renderContent = (data: MessagePayload) => {
);
break;
+ case ContentTypes.audio:
+ res = (
+ [Voice Message]
+ );
+ break;
case ContentTypes.markdown:
res = (
diff --git a/src/common/component/Message/renderContent.tsx b/src/common/component/Message/renderContent.tsx
index a3d288ae..f231e9b0 100644
--- a/src/common/component/Message/renderContent.tsx
+++ b/src/common/component/Message/renderContent.tsx
@@ -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 =
;
+ ctn =
;
}
break;
case ContentTypes.file:
diff --git a/src/common/component/Send/Replying.tsx b/src/common/component/Send/Replying.tsx
index d6087167..bb9194a2 100644
--- a/src/common/component/Send/Replying.tsx
+++ b/src/common/component/Send/Replying.tsx
@@ -20,6 +20,13 @@ const renderContent = (data: MessagePayload) => {
// });
break;
+ case ContentTypes.audio:
+ res = (
+
+ [Voice Message]
+
+ );
+ break;
case ContentTypes.markdown:
res = (
diff --git a/src/common/component/VoiceMessage.tsx b/src/common/component/VoiceMessage.tsx
index d9bc4a66..63e3f6b7 100644
--- a/src/common/component/VoiceMessage.tsx
+++ b/src/common/component/VoiceMessage.tsx
@@ -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
(null);
+ const containerRef = useRef(null);
+ const [playing, setPlaying] = useState(false);
+ const [duration, setDuration] = useState(0);
+ // const [audio, setAudio] = useState(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 (
-
- audio message
+
+
+
+
+
);
};
diff --git a/src/routes/chat/utils.tsx b/src/routes/chat/utils.tsx
index 438bb5b8..7c092cbb 100644
--- a/src/routes/chat/utils.tsx
+++ b/src/routes/chat/utils.tsx
@@ -59,6 +59,11 @@ export const renderPreviewMessage = (message = null) => {
res =
;
}
break;
+ case ContentTypes.audio:
+ {
+ res = `[${i18n.t("voice_message", { ns: "chat" })}]`;
+ }
+ break;
case ContentTypes.markdown:
{
res = `[markdown]`;
diff --git a/yarn.lock b/yarn.lock
index 6b9266d9..92f94c7e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2659,6 +2659,11 @@
dependencies:
"@types/node" "*"
+"@types/debounce@*":
+ version "1.2.1"
+ resolved "https://mirrors.cloud.tencent.com/npm/@types/debounce/-/debounce-1.2.1.tgz#79b65710bc8b6d44094d286aecf38e44f9627852"
+ integrity sha512-epMsEE85fi4lfmJUH/89/iV/LI+F5CvNIvmgs5g5jYFPfhO2S/ae8WSsLOKWdwtoaZw9Q2IhJ4tQ5tFCcS/4HA==
+
"@types/emoji-mart@^3.0.9":
version "3.0.9"
resolved "https://mirrors.cloud.tencent.com/npm/@types/emoji-mart/-/emoji-mart-3.0.9.tgz#2f7ef5d9ec194f28029c46c81a5fc1e5b0efa73c"
@@ -2978,6 +2983,13 @@
resolved "https://mirrors.cloud.tencent.com/npm/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
+"@types/wavesurfer.js@^6.0.4":
+ version "6.0.4"
+ resolved "https://mirrors.cloud.tencent.com/npm/@types/wavesurfer.js/-/wavesurfer.js-6.0.4.tgz#7ae92d5752dba5b96df27560484da3cb4ff380f4"
+ integrity sha512-TGWy48OTZc9fuedxBmtM5WGNK4WDloRzf6/mE+OXmM9JuLzshhWZXSbZHiGnzpYB19mfdwnoEE4/8PNvyr/JBQ==
+ dependencies:
+ "@types/debounce" "*"
+
"@types/ws@^8.5.1":
version "8.5.4"
resolved "https://mirrors.cloud.tencent.com/npm/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5"
@@ -9658,10 +9670,10 @@ postcss-loader@^6.2.1:
klona "^2.0.5"
semver "^7.3.5"
-postcss-loader@^7.2.3:
- version "7.2.3"
- resolved "https://mirrors.cloud.tencent.com/npm/postcss-loader/-/postcss-loader-7.2.3.tgz#c2d491a769102e0aac228d53fb1ad376cc158bb2"
- integrity sha512-H/PIjgbn2q7zFnmUMPvEupIFnOAg+fYWC/4F6DugK8uPITVYyEflnSjLFV0u20B3Qi88PzPiAlzn8hBSu3f8oA==
+postcss-loader@^7.2.4:
+ version "7.2.4"
+ resolved "https://mirrors.cloud.tencent.com/npm/postcss-loader/-/postcss-loader-7.2.4.tgz#2884f4ca172de633b2cf1f93dc852968f0632ba9"
+ integrity sha512-F88rpxxNspo5hatIc+orYwZDtHFaVFOSIVAx+fBfJC1GmhWbVmPWtmg2gXKE1OxJbneOSGn8PWdIwsZFcruS+w==
dependencies:
cosmiconfig "^8.1.3"
cosmiconfig-typescript-loader "^4.3.0"
@@ -10748,10 +10760,10 @@ react-viewport-list@^7.0.0:
resolved "https://mirrors.cloud.tencent.com/npm/react-viewport-list/-/react-viewport-list-7.0.0.tgz#4d662dec3fcacd04dd99d0110c2145782ca6037d"
integrity sha512-iI1R4yqqdAfDmov2BEDiFaHTCijfGYyquhdhMeTis4ke84pSW9Ccfbna6I9q+/7VAtV81atpIAIWQjU47dnh2Q==
-react-virtuoso@^4.1.1:
- version "4.1.1"
- resolved "https://mirrors.cloud.tencent.com/npm/react-virtuoso/-/react-virtuoso-4.1.1.tgz#df42fe867377068562890752dc9282fde71499c7"
- integrity sha512-G2lyifG5UIRZI9vgcBt+6OLDL6CO5/O6YiGS+O9z+VNRjVSTioSwfBC7sVSLspYq7iyL60aIXlVqSKVJiSVhlg==
+react-virtuoso@^4.2.0:
+ version "4.2.0"
+ resolved "https://mirrors.cloud.tencent.com/npm/react-virtuoso/-/react-virtuoso-4.2.0.tgz#29d47c1075793ea5cbc6b9fc3f2345cf17749e2b"
+ integrity sha512-lO1akVyALlDMp+eIo4E99HjSQ8Cn2AKXBVfq7GaBjdlnlJaRvou8az6tVYGHFD6Az5EcPUc7OfzHvAyojOhgqw==
react@^18.2.0:
version "18.2.0"
@@ -10979,6 +10991,15 @@ resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
+resolve@^1.22.2:
+ version "1.22.2"
+ resolved "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+ integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+ dependencies:
+ is-core-module "^2.11.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
resolve@^2.0.0-next.4:
version "2.0.0-next.4"
resolved "https://mirrors.cloud.tencent.com/npm/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
@@ -12492,6 +12513,11 @@ watchpack@^2.4.0:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
+wavesurfer.js@^6.6.3:
+ version "6.6.3"
+ resolved "https://mirrors.cloud.tencent.com/npm/wavesurfer.js/-/wavesurfer.js-6.6.3.tgz#eadebf0542be702f1eef2f52c3e312b839030166"
+ integrity sha512-XqUOXe8+SOTe8uKCHaqW0vJ5etCCQvq/NgaPycn9HAX/nUi+2zoWD+w9i7H5vBT9UCDNawOia+vS5Ct3kZGQzA==
+
wbuf@^1.1.0, wbuf@^1.7.3:
version "1.7.3"
resolved "https://mirrors.cloud.tencent.com/npm/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
@@ -12669,10 +12695,10 @@ webpack@^5.64.4:
watchpack "^2.4.0"
webpack-sources "^3.2.3"
-webpack@^5.77.0:
- version "5.77.0"
- resolved "https://mirrors.cloud.tencent.com/npm/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4"
- integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q==
+webpack@^5.78.0:
+ version "5.78.0"
+ resolved "https://mirrors.cloud.tencent.com/npm/webpack/-/webpack-5.78.0.tgz#836452a12416af2a7beae906b31644cb2562f9e6"
+ integrity sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==
dependencies:
"@types/eslint-scope" "^3.7.3"
"@types/estree" "^0.0.51"