From 325209891d95c08577a0f8f61fc48fef32f64910 Mon Sep 17 00:00:00 2001 From: Jose B Date: Tue, 8 Aug 2023 12:54:49 -0500 Subject: [PATCH 1/3] download recording --- www/app/components/record.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/www/app/components/record.js b/www/app/components/record.js index f683f2b7..de27b7d3 100644 --- a/www/app/components/record.js +++ b/www/app/components/record.js @@ -2,6 +2,9 @@ import React, { useRef, useEffect, useState } from "react"; import WaveSurfer from "wavesurfer.js"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faDownload } from "@fortawesome/free-solid-svg-icons"; + import Dropdown from "react-dropdown"; import "react-dropdown/style.css"; @@ -87,6 +90,17 @@ export default function Recorder(props) { } }, []); + useEffect(() => { + if (record) { + return record.on("stopRecording", () => { + const link = document.getElementById("download-recording"); + link.href = record.getRecordedUrl(); + link.download = "reflector-recording.webm"; + link.style.visibility = "visible"; + }); + } + }, [record]); + const handleRecClick = async () => { if (!record) return console.log("no record"); @@ -135,9 +149,15 @@ export default function Recorder(props) { > {isPlaying ? "Pause" : "Play"} + + +
- {/* TODO: Download audio tag */} {/* TODO: current time / audio duration */} ); From 033bbaa347ebd73d7badfbd1f12aa11ed80b4e55 Mon Sep 17 00:00:00 2001 From: Jose B Date: Tue, 8 Aug 2023 15:12:06 -0500 Subject: [PATCH 2/3] clock element --- www/app/components/record.js | 37 ++++++++++++++++++++++++++++++++++-- www/app/utils.js | 12 ++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/www/app/components/record.js b/www/app/components/record.js index de27b7d3..0ad807c0 100644 --- a/www/app/components/record.js +++ b/www/app/components/record.js @@ -9,6 +9,7 @@ import Dropdown from "react-dropdown"; import "react-dropdown/style.css"; import CustomRecordPlugin from "./CustomRecordPlugin"; +import { formatTime } from "../utils"; const AudioInputsDropdown = (props) => { const [ddOptions, setDdOptions] = useState([]); @@ -54,6 +55,9 @@ export default function Recorder(props) { const [isRecording, setIsRecording] = useState(false); const [isPlaying, setIsPlaying] = useState(false); const [deviceId, setDeviceId] = useState(null); + const [currentTime, setCurrentTime] = useState(0); + const [timeInterval, setTimeInterval] = useState(null); + const [duration, setDuration] = useState(0); useEffect(() => { document.getElementById("play-btn").disabled = true; @@ -79,6 +83,7 @@ export default function Recorder(props) { _wavesurfer.on("pause", () => { setIsPlaying(false); }); + _wavesurfer.on("timeupdate", setCurrentTime); setRecord(_wavesurfer.registerPlugin(CustomRecordPlugin.create())); setWavesurfer(_wavesurfer); @@ -101,6 +106,22 @@ export default function Recorder(props) { } }, [record]); + useEffect(() => { + if (isRecording) { + const interval = setInterval(() => { + setCurrentTime((prev) => prev + 1); + }, 1000); + setTimeInterval(interval); + return () => clearInterval(interval); + } else { + clearInterval(timeInterval); + setCurrentTime((prev) => { + setDuration(prev); + return 0; + }); + } + }, [isRecording]); + const handleRecClick = async () => { if (!record) return console.log("no record"); @@ -127,8 +148,15 @@ export default function Recorder(props) { wavesurfer?.playPause(); }; + const timeLabel = () => { + if (isRecording) return formatTime(currentTime); + else if (duration) + return `${formatTime(currentTime)}/${formatTime(duration)}`; + else ""; + }; + return ( -
+
  @@ -158,7 +186,12 @@ export default function Recorder(props) {
- {/* TODO: current time / audio duration */} +
+ {isRecording && ( +
+ )} + {timeLabel()} +
); } diff --git a/www/app/utils.js b/www/app/utils.js index 37c4dee7..79e8ceae 100644 --- a/www/app/utils.js +++ b/www/app/utils.js @@ -17,3 +17,15 @@ export function Mulberry32(seed) { return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } + +export const formatTime = (seconds) => { + let hours = Math.floor(seconds / 3600); + let minutes = Math.floor((seconds % 3600) / 60); + let secs = Math.floor(seconds % 60); + + let timeString = `${hours > 0 ? hours + ":" : ""}${minutes + .toString() + .padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; + + return timeString; +}; From 06569000c4e6641d70694908384cbd05c7353e4b Mon Sep 17 00:00:00 2001 From: Jose B Date: Tue, 8 Aug 2023 15:51:12 -0500 Subject: [PATCH 3/3] disconnected UI --- www/app/components/dashboard.js | 15 +++++++++++---- www/app/components/record.js | 2 +- www/app/page.js | 14 +++++++++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/www/app/components/dashboard.js b/www/app/components/dashboard.js index 9c73f6f3..f20f7427 100644 --- a/www/app/components/dashboard.js +++ b/www/app/components/dashboard.js @@ -1,18 +1,16 @@ -import { Mulberry32 } from "../utils.js"; import React, { useState, useEffect } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChevronRight, faChevronDown, + faLinkSlash, } from "@fortawesome/free-solid-svg-icons"; export function Dashboard({ - isRecording, - onRecord, transcriptionText, finalSummary, topics, - stream, + disconnected, }) { const [openIndex, setOpenIndex] = useState(null); const [autoscrollEnabled, setAutoscrollEnabled] = useState(true); @@ -98,6 +96,15 @@ export function Dashboard({ )}
+ {disconnected && ( +
+
+ + Disconnected +
+
+ )} + diff --git a/www/app/components/record.js b/www/app/components/record.js index 0ad807c0..445f7e50 100644 --- a/www/app/components/record.js +++ b/www/app/components/record.js @@ -186,7 +186,7 @@ export default function Recorder(props) {
-
+
{isRecording && (
)} diff --git a/www/app/page.js b/www/app/page.js index 128d8703..56119bb1 100644 --- a/www/app/page.js +++ b/www/app/page.js @@ -1,5 +1,5 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Recorder from "./components/record.js"; import { Dashboard } from "./components/dashboard.js"; import useWebRTC from "./components/webrtc.js"; @@ -7,6 +7,17 @@ import "../public/button.css"; const App = () => { const [stream, setStream] = useState(null); + const [disconnected, setDisconnected] = useState(false); + + useEffect(() => { + if (process.env.NEXT_PUBLIC_ENV === "development") { + document.onkeyup = (e) => { + if (e.key === "d") { + setDisconnected((prev) => !prev); + } + }; + } + }, []); // This is where you'd send the stream and receive the data from the server. // transcription, summary, etc @@ -28,6 +39,7 @@ const App = () => { finalSummary={serverData.finalSummary} topics={serverData.topics ?? []} stream={stream} + disconnected={disconnected} />
);