Files
jam-session-web/src/app/page.tsx
T
2025-01-13 12:37:08 +01:00

166 lines
5.2 KiB
TypeScript

"use client";
import {useEffect, useMemo, useState} from "react";
import {fetchConfig} from "@/app/utils/fetchConfig";
import BusControlTabs from "@/app/components/BusControlTabs";
import MainMix from "@/app/components/MainMix";
import Settings from "@/app/components/Settings";
import {Config} from "@/app/types/config";
// initialize global websocket connection
import {fetchValue, initConnection, isConnected} from "@/app/lib/x32CommunicationManager";
function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {
return new Promise<T>((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error("Request timed out"));
}, timeoutMs);
promise
.then((result) => {
clearTimeout(timeout);
resolve(result);
})
.catch((error) => {
clearTimeout(timeout);
reject(error);
});
});
}
const Page = () => {
const [appConfig, setAppConfig] = useState(null);
const [activeTab, setActiveTab] = useState("mainMix");
const [webSocketConnected, setWebSocketConnected] = useState(false);
const [mixerConnected, setMixerConnected] = useState(false);
useEffect(() => {
fetchConfig().then((config: Config) => {
setAppConfig(config);
initConnection(`ws://${window.location.hostname}:${config.webserver.port}`);
});
}, []);
// periodically check if the websocket connection is still alive
useEffect(() => {
const interval = setInterval(() => {
// wait for appConfig to be fetched
if (!appConfig) {
console.log("AppConfig not fetched yet");
return;
}
setWebSocketConnected(isConnected);
if (!isConnected) {
console.log("Reconnecting to WebSocket");
initConnection(`ws://${window.location.hostname}:${appConfig.webserver.port}`);
} else {
// check if mixer is connected
withTimeout(fetchValue("/info"), 1500)
.then((response) => {
// response is a string starting with "V", which is the API version, if the mixer is connected
if (response.startsWith("V")) {
setMixerConnected(true);
} else {
setMixerConnected(false);
}
})
.catch((error) => {
console.log("Mixer connection check failed:", error.message);
setMixerConnected(false);
});
}
}, 2000);
return () => clearInterval(interval);
}, [appConfig]);
const tabComponents = useMemo(() => {
return [
{
id: "mainMix",
label: "Main Mix",
content: (
<MainMix/>
),
},
{
id: "busControl",
label: "Bus Control",
content: (
<BusControlTabs/>
),
},
{
id: "recording",
label: "Recording",
content: (
<div>
<h2>Recording</h2>
<p>Coming soon...</p>
</div>
),
},
{
id: "settings",
label: "Settings",
content: (
<Settings/>
),
}
]
}
, []);
if (!appConfig) {
return <p>Error fetching config</p>;
}
if (!webSocketConnected) {
return <p>WebSocket not connected</p>;
}
if (!mixerConnected) {
return <p>Mixer not connected</p>;
}
return (
<div>
<div className="p-4">
{/* Tabs Header */}
<div className="flex border-b mb-4">
{tabComponents.map((tab) => (
<button
key={tab.id}
className={`px-4 py-2 ${
activeTab === tab.id
? "border-b-2 border-blue-500 text-blue-500"
: "text-gray-500"
}`}
onClick={() => setActiveTab(tab.id)}
>
{tab.label}
</button>
))}
</div>
{/* Tabs Content */}
<div>
{tabComponents.map((tab) => (
<div
key={tab.id}
style={{display: activeTab === tab.id ? "block" : "none"}}
>
{tab.content}
</div>
))}
</div>
</div>
</div>
);
};
export default Page;