mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
Merge branch 'main' of github.com:Monadical-SAS/reflector into jose/markers
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import "./globals.scss";
|
||||
import "./styles/globals.scss";
|
||||
import { Roboto } from "next/font/google";
|
||||
|
||||
import Head from "next/head";
|
||||
|
||||
@@ -17,15 +17,3 @@ 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;
|
||||
};
|
||||
11
www/app/lib/time.js
Normal file
11
www/app/lib/time.js
Normal file
@@ -0,0 +1,11 @@
|
||||
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;
|
||||
};
|
||||
@@ -1,57 +1,4 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Recorder from "./components/record.js";
|
||||
import { Dashboard } from "./components/dashboard.js";
|
||||
import useWebRTC from "./components/webrtc.js";
|
||||
import useTranscript from "./components/transcript.js";
|
||||
import { useWebSockets } from "./components/websocket.js";
|
||||
import "../public/button.css";
|
||||
|
||||
const App = () => {
|
||||
const [stream, setStream] = useState(null);
|
||||
const [disconnected, setDisconnected] = useState(false);
|
||||
const useActiveTopic = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (process.env.NEXT_PUBLIC_ENV === "development") {
|
||||
document.onkeyup = (e) => {
|
||||
if (e.key === "d") {
|
||||
setDisconnected((prev) => !prev);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
const transcript = useTranscript();
|
||||
const webRTC = useWebRTC(stream, transcript.response?.id);
|
||||
const webSockets = useWebSockets(transcript.response?.id);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center h-[100svh] bg-gradient-to-r from-[#8ec5fc30] to-[#e0c3fc42]">
|
||||
<div className="h-[13svh] flex flex-col justify-center items-center">
|
||||
<h1 className="text-5xl font-bold text-blue-500">Reflector</h1>
|
||||
<p className="text-gray-500">Capture The Signal, Not The Noise</p>
|
||||
</div>
|
||||
|
||||
<Recorder
|
||||
setStream={setStream}
|
||||
onStop={() => {
|
||||
webRTC?.peer?.send(JSON.stringify({ cmd: "STOP" }));
|
||||
setStream(null);
|
||||
}}
|
||||
topics={webSockets.topics}
|
||||
useActiveTopic={useActiveTopic}
|
||||
/>
|
||||
<Dashboard
|
||||
transcriptionText={webSockets.transcriptText}
|
||||
finalSummary={webSockets.finalSummary}
|
||||
topics={webSockets.topics}
|
||||
stream={stream}
|
||||
disconnected={disconnected}
|
||||
useActiveTopic={useActiveTopic}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
import { redirect } from "next/navigation";
|
||||
export default async function Index({ params }) {
|
||||
redirect("/transcripts/new");
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 84 KiB |
123
www/app/styles/button.css
Normal file
123
www/app/styles/button.css
Normal file
@@ -0,0 +1,123 @@
|
||||
/* Define basic button styles */
|
||||
input[type="button"],
|
||||
button {
|
||||
/* Reset default button styles */
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-family: inherit;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
/* Visual */
|
||||
background-color: #3e68ff;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.18);
|
||||
/* Size */
|
||||
padding: 0.25em 0.75em;
|
||||
min-width: 10ch;
|
||||
min-height: 44px;
|
||||
/* Text */
|
||||
text-align: center;
|
||||
line-height: 1.1;
|
||||
/* Display */
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-self: start;
|
||||
/* Optional - see "Gotchas" */
|
||||
/* Animation */
|
||||
transition: 220ms all ease-in-out;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Button modifiers */
|
||||
input[type="button"].small,
|
||||
button.small {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
input[type="button"].block,
|
||||
button.block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Disabled styles */
|
||||
input[type="button"][disabled],
|
||||
button[disabled] {
|
||||
border-color: #ccc;
|
||||
background: #b8b8b8 !important;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
input[type="button"][disabled]:hover,
|
||||
button[disabled]:hover {
|
||||
background: #b8b8b8 !important;
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
/* Custom button properties */
|
||||
input[type="button"],
|
||||
button {
|
||||
width: 243px;
|
||||
border: solid 1px #dadada;
|
||||
}
|
||||
|
||||
/* Red button states */
|
||||
input[type="button"][data-color="red"],
|
||||
button[data-color="red"],
|
||||
input[type="button"][data-color="red"]:hover,
|
||||
button[data-color="red"]:hover,
|
||||
input[type="button"][data-color="red"]:active,
|
||||
button[data-color="red"]:active {
|
||||
background-color: #cc3347;
|
||||
}
|
||||
|
||||
/* Green button states */
|
||||
input[type="button"][data-color="green"],
|
||||
button[data-color="green"],
|
||||
input[type="button"][data-color="green"]:hover,
|
||||
button[data-color="green"]:hover,
|
||||
input[type="button"][data-color="green"]:active,
|
||||
button[data-color="green"]:active {
|
||||
background-color: #33cc47;
|
||||
}
|
||||
|
||||
/* Blue button states */
|
||||
input[type="button"][data-color="blue"],
|
||||
button[data-color="blue"],
|
||||
input[type="button"][data-color="blue"]:hover,
|
||||
button[data-color="blue"]:hover,
|
||||
input[type="button"][data-color="blue"]:active,
|
||||
button[data-color="blue"]:active {
|
||||
background-color: #3347cc;
|
||||
}
|
||||
|
||||
/* Orange button states */
|
||||
input[type="button"][data-color="orange"],
|
||||
button[data-color="orange"],
|
||||
input[type="button"][data-color="orange"]:hover,
|
||||
button[data-color="orange"]:hover,
|
||||
input[type="button"][data-color="orange"]:active,
|
||||
button[data-color="orange"]:active {
|
||||
background-color: #ff7f00;
|
||||
}
|
||||
|
||||
/* Purple button states */
|
||||
input[type="button"][data-color="purple"],
|
||||
button[data-color="purple"],
|
||||
input[type="button"][data-color="purple"]:hover,
|
||||
button[data-color="purple"]:hover,
|
||||
input[type="button"][data-color="purple"]:active,
|
||||
button[data-color="purple"]:active {
|
||||
background-color: #800080;
|
||||
}
|
||||
|
||||
/* Yellow button states */
|
||||
input[type="button"][data-color="yellow"],
|
||||
button[data-color="yellow"],
|
||||
input[type="button"][data-color="yellow"]:hover,
|
||||
button[data-color="yellow"]:hover,
|
||||
input[type="button"][data-color="yellow"]:active,
|
||||
button[data-color="yellow"]:active {
|
||||
background-color: #ffff00;
|
||||
}
|
||||
56
www/app/transcripts/new/page.js
Normal file
56
www/app/transcripts/new/page.js
Normal file
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Recorder from "../recorder";
|
||||
import { Dashboard } from "../dashboard";
|
||||
import useWebRTC from "../useWebRTC";
|
||||
import useTranscript from "../useTranscript";
|
||||
import { useWebSockets } from "../useWebSockets";
|
||||
import "../../styles/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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
|
||||
const transcript = useTranscript();
|
||||
const webRTC = useWebRTC(stream, transcript.response?.id);
|
||||
const webSockets = useWebSockets(transcript.response?.id);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center h-[100svh] bg-gradient-to-r from-[#8ec5fc30] to-[#e0c3fc42]">
|
||||
<div className="h-[13svh] flex flex-col justify-center items-center">
|
||||
<h1 className="text-5xl font-bold text-blue-500">Reflector</h1>
|
||||
<p className="text-gray-500">Capture The Signal, Not The Noise</p>
|
||||
</div>
|
||||
|
||||
<Recorder
|
||||
setStream={setStream}
|
||||
onStop={() => {
|
||||
webRTC?.peer?.send(JSON.stringify({ cmd: "STOP" }));
|
||||
setStream(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
<Dashboard
|
||||
transcriptionText={webSockets.transcriptText}
|
||||
finalSummary={webSockets.finalSummary}
|
||||
topics={webSockets.topics}
|
||||
stream={stream}
|
||||
disconnected={disconnected}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -10,7 +10,7 @@ import Dropdown from "react-dropdown";
|
||||
import "react-dropdown/style.css";
|
||||
|
||||
import CustomRecordPlugin from "./CustomRecordPlugin";
|
||||
import { formatTime } from "../utils";
|
||||
import { formatTime } from "../lib/time";
|
||||
|
||||
const AudioInputsDropdown = (props) => {
|
||||
const [ddOptions, setDdOptions] = useState([]);
|
||||
Reference in New Issue
Block a user