diff --git a/package.json b/package.json
index 20830d2..8b6efaa 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-redux": "^8.0.7",
+ "react-resize-detector": "^9.1.0",
"react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"sha1": "^1.1.1",
@@ -48,4 +49,4 @@
"last 1 safari version"
]
}
-}
+}
\ No newline at end of file
diff --git a/src/MainPage.js b/src/MainPage.js
index 385c552..2be11b0 100644
--- a/src/MainPage.js
+++ b/src/MainPage.js
@@ -40,7 +40,7 @@ export default function () {
dispatch(setList(list.result));
});
}, [accessToken, passportId]);
- return
+ return
@@ -48,10 +48,11 @@ export default function () {
- 2022-12-13 14:39_同传翻译
diff --git a/src/MainPage.module.css b/src/MainPage.module.css
index b7bf5ff..ea01386 100644
--- a/src/MainPage.module.css
+++ b/src/MainPage.module.css
@@ -1,3 +1,7 @@
.title {
background-color: burlywood;
+}
+
+.mainBody {
+ background-color: #FAFAFA;
}
\ No newline at end of file
diff --git a/src/PlayerBar.js b/src/PlayerBar.js
index 8d6f5ce..321ea35 100644
--- a/src/PlayerBar.js
+++ b/src/PlayerBar.js
@@ -1,25 +1,101 @@
-import { Grid, MenuItem, Select, FormControl, InputLabel, Button } from "@mui/material"
+import { MenuItem, Select, IconButton, Typography, Stack, Container } from "@mui/material"
import styles from './PlayerBar.module.css';
+import { useSelector, useDispatch } from 'react-redux'
+import { useEffect, useRef, useState, useCallback } from "react";
+import { useResizeDetector } from 'react-resize-detector';
+import pauseIcon from "./assets/play.png";
+import playIcon from "./assets/pause.png";
+import downloadIcon from "./assets/download.png";
+import { togglePauseState } from "./business/recorderSlice.js"
+import Waveform from "./components/Waveform";
+
+const durationFormat = (time) => {
+ if (isNaN(time)) return "00:00:00";
+ time = parseInt(time);
+ let second = parseInt(time % 60);
+ let minute = parseInt((time / 60) % 60);
+ let hour = parseInt(time / 3600);
+ return hour.toString().padStart(2, '0') + ":" + minute.toString().padStart(2, '0') + ":" + second.toString().padStart(2, '0');
+}
export default function () {
- return
-
- 进度条
-
-
- 速度
-
-
-
-
+ const dispatch = useDispatch();
+ const [duration, setDuration] = useState("00:00:00");
+ const [currentTime, setCurrentTime] = useState("00:00:00");
+ const [canvasWidth, setCanvasWidth] = useState(0);
+ const currentIndex = useSelector(state => state.recorder.currentIndex);
+ const recordList = useSelector(state => state.recorder.list);
+ const currentBlob = useSelector(state => state.recorder.currentBlob);
+ const pause = useSelector(state => state.recorder.pause);
+ const player = useRef(null);
+ useEffect(() => {
+ player.current.url = currentBlob
+ console.log(player.current.url);
+ }, [currentBlob]);
+
+ const toggleState = () => {
+ if (pause) {
+ player.current.play();
+ } else {
+ player.current.pause();
+ }
+ dispatch(togglePauseState());
+ };
+
+ const onDurationChange = (event) => {
+ setDuration(durationFormat(player.current.duration));
+ }
+ const onTimeUpdate = (event) => {
+ setCurrentTime(durationFormat(player.current.currentTime));
+ }
+
+ const onResize = useCallback((width, height) => {
+ setCanvasWidth(width - 90 - 60);
+ }, []);
+
+ const { ref: playerBar } = useResizeDetector({
+ onResize: onResize
+ });
+
+ return
+
+ {recordList.length > 0 ? recordList.at(currentIndex).editName : ""}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {currentTime} / {duration}
+
+
+
}
\ No newline at end of file
diff --git a/src/PlayerBar.module.css b/src/PlayerBar.module.css
index 7efc280..f69ba0a 100644
--- a/src/PlayerBar.module.css
+++ b/src/PlayerBar.module.css
@@ -1,3 +1,6 @@
.playerBar {
display: flex;
+ background-color: #E6EAEC;
+ height: 70px;
+ width: 100%;
}
\ No newline at end of file
diff --git a/src/RecordList.js b/src/RecordList.js
index 147ce92..b853bb5 100644
--- a/src/RecordList.js
+++ b/src/RecordList.js
@@ -7,7 +7,7 @@ import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import Toolbar from '@mui/material/Toolbar';
-import { setCurrentIndex, setCurrentLyric } from "./business/recorderSlice.js"
+import { setCurrentIndex, setCurrentLyric, setCurrentBlob } from "./business/recorderSlice.js"
import yzs from "./business/request.js";
const drawerWidth = 240;
@@ -19,13 +19,17 @@ export default function () {
const recordList = useSelector(state => state.recorder.list);
const onSelected = (event, index) => {
console.log("onSelected", index, recordList.at(index).transResultUrl)
+ dispatch(setCurrentIndex(index));
yzs.download(accessToken, recordList.at(index).transResultUrl).then(
blob => blob.text()
).then(text => {
console.log(text);
- dispatch(setCurrentLyric(JSON.parse(text)));
+ let payload = recordList.at(index).type === 1 ? JSON.parse(text) : text;
+ dispatch(setCurrentLyric(payload));
+ });
+ yzs.download(accessToken, recordList.at(index).audioUrl).then(blob => {
+ dispatch(setCurrentBlob(URL.createObjectURL(blob)));
});
- dispatch(setCurrentIndex(index));
}
return state.recorder.currentLyric);
+ const currentIndex = useSelector(state => state.recorder.currentIndex);
+ const recordList = useSelector(state => state.recorder.list);
- return
- {currentLyric.map((lyric, index) => {
+
+ if (recordList.length === 0) return
;
+
+ return
+ {recordList.at(currentIndex).type === 1 ? (typeof currentLyric === "object" ? currentLyric.map((lyric, index) => {
return
{lyric.text}
{lyric.translation}
- })}
-
+ }) : ) : {typeof currentLyric === "string" ? currentLyric : ""}
}
+
}
\ No newline at end of file
diff --git a/src/RecordLyrics.module.css b/src/RecordLyrics.module.css
index 71c0761..13494e3 100644
--- a/src/RecordLyrics.module.css
+++ b/src/RecordLyrics.module.css
@@ -1,5 +1,7 @@
.lyricsBrowser {
+ margin-top: 16px;
padding-bottom: 40px;
+ padding: 24px;
}
.lyricItem {
diff --git a/src/assets/download.png b/src/assets/download.png
new file mode 100644
index 0000000..832819a
Binary files /dev/null and b/src/assets/download.png differ
diff --git a/src/assets/pause.png b/src/assets/pause.png
new file mode 100644
index 0000000..2fc8b5a
Binary files /dev/null and b/src/assets/pause.png differ
diff --git a/src/assets/play.png b/src/assets/play.png
new file mode 100644
index 0000000..baf04ad
Binary files /dev/null and b/src/assets/play.png differ
diff --git a/src/business/recorderSlice.js b/src/business/recorderSlice.js
index 054db87..b7a0dd1 100644
--- a/src/business/recorderSlice.js
+++ b/src/business/recorderSlice.js
@@ -6,21 +6,30 @@ export const recorderSlice = createSlice({
list: [],
currentIndex: 0,
currentLyric: [],
+ currentBlob: {},
+ pause: true,
},
reducers: {
setList: (state, action) => {
state.list = action.payload;
},
setCurrentIndex: (state, action) => {
+ state.pause = true;
state.currentIndex = action.payload;
},
setCurrentLyric: (state, action) => {
state.currentLyric = action.payload;
- }
+ },
+ setCurrentBlob: (state, action) => {
+ state.currentBlob = action.payload;
+ },
+ togglePauseState: (state) => {
+ state.pause = !state.pause;
+ },
}
})
// Action creators are generated for each case reducer function
-export const { setCurrentIndex, setList, setCurrentLyric } = recorderSlice.actions
+export const { setCurrentIndex, setList, setCurrentLyric, setCurrentBlob, togglePauseState } = recorderSlice.actions
export default recorderSlice.reducer
\ No newline at end of file
diff --git a/src/components/Waveform.js b/src/components/Waveform.js
new file mode 100644
index 0000000..4885d71
--- /dev/null
+++ b/src/components/Waveform.js
@@ -0,0 +1,159 @@
+import { useEffect, useRef, useState, useCallback } from "react";
+import useSetTrackProgress from "./useSetTrackProgress.js"
+import { useResizeDetector } from 'react-resize-detector';
+
+const pointWidth = 2;
+const pointMargin = 3;
+
+const trackDuration = 60; //