233 lines
6.5 KiB
TypeScript
233 lines
6.5 KiB
TypeScript
"use client";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { GearIcon } from "@radix-ui/react-icons";
|
|
import { SettingsIcon, Volume2 } from "lucide-react";
|
|
import MicVolumeBar from "_components/MicVolumeIndication";
|
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
import { editUserAPI, getUserAPI } from "_querys/user";
|
|
import { Prisma } from "@repo/db";
|
|
import { useSession } from "next-auth/react";
|
|
import { useAudioStore } from "_store/audioStore";
|
|
import toast from "react-hot-toast";
|
|
|
|
export const SettingsBtn = () => {
|
|
const session = useSession();
|
|
const { data: user } = useQuery({
|
|
queryKey: ["user", session.data?.user.id],
|
|
queryFn: () => getUserAPI(session.data!.user.id),
|
|
});
|
|
const testSoundRef = useRef<HTMLAudioElement | null>(null);
|
|
|
|
const editUserMutation = useMutation({
|
|
mutationFn: editUserAPI,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") {
|
|
testSoundRef.current = new Audio("/sounds/Melder3.wav");
|
|
}
|
|
}, []);
|
|
|
|
const modalRef = useRef<HTMLDialogElement>(null);
|
|
|
|
const [inputDevices, setInputDevices] = useState<MediaDeviceInfo[]>([]);
|
|
const [selectedDevice, setSelectedDevice] = useState<string | null>(
|
|
user?.settingsMicDevice || null,
|
|
);
|
|
const [showIndication, setShowIndication] = useState<boolean>(false);
|
|
const [micVol, setMicVol] = useState<number>(1);
|
|
const [funkVolume, setFunkVol] = useState<number>(0.8);
|
|
const [dmeVolume, setDmeVol] = useState<number>(0.8);
|
|
|
|
const setMic = useAudioStore((state) => state.setMic);
|
|
|
|
useEffect(() => {
|
|
if (user) {
|
|
setSelectedDevice(user.settingsMicDevice);
|
|
setMic(user.settingsMicDevice, user.settingsMicVolume || 1);
|
|
setMicVol(user.settingsMicVolume || 1);
|
|
setFunkVol(user.settingsRadioVolume || 0.8);
|
|
setDmeVol(user.settingsDmeVolume || 0.8);
|
|
}
|
|
}, [user, setMic]);
|
|
|
|
useEffect(() => {
|
|
navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
setInputDevices(devices.filter((d) => d.kind === "audioinput"));
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<div>
|
|
<button
|
|
className="btn btn-ghost"
|
|
onSubmit={() => false}
|
|
onClick={() => {
|
|
modalRef.current?.showModal();
|
|
}}
|
|
>
|
|
<GearIcon className="w-5 h-5" />
|
|
</button>
|
|
|
|
<dialog ref={modalRef} className="modal">
|
|
<div className="modal-box">
|
|
<h3 className="flex items-center gap-2 text-lg font-bold mb-5">
|
|
<SettingsIcon size={20} /> Einstellungen
|
|
</h3>
|
|
<div className="flex flex-col items-center justify-center">
|
|
<fieldset className="fieldset w-full mb-2">
|
|
<label className="floating-label w-full text-base">
|
|
<span>Eingabegerät</span>
|
|
<select
|
|
className="input w-full"
|
|
value={selectedDevice ? selectedDevice : ""}
|
|
onChange={(e) => {
|
|
setSelectedDevice(e.target.value);
|
|
setShowIndication(true);
|
|
}}
|
|
>
|
|
<option key={0} value={0} disabled>
|
|
Bitte wähle ein Eingabegerät...
|
|
</option>
|
|
{inputDevices.map((device, index) => (
|
|
<option key={index} value={device.deviceId}>
|
|
{device.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</label>
|
|
</fieldset>
|
|
<p className="flex items-center gap-2 text-base mb-2 justify-start w-full">
|
|
<Volume2 size={20} /> Eingabelautstärke
|
|
</p>
|
|
<div className="w-full">
|
|
<input
|
|
type="range"
|
|
min={0}
|
|
max={3}
|
|
step={0.01}
|
|
onChange={(e) => {
|
|
const value = parseFloat(e.target.value);
|
|
setMicVol(value);
|
|
setShowIndication(true);
|
|
}}
|
|
value={micVol}
|
|
className="range range-xs range-accent w-full"
|
|
/>
|
|
<div className="flex justify-between px-2.5 mt-2 text-xs">
|
|
<span>0%</span>
|
|
<span>25%</span>
|
|
<span>50%</span>
|
|
<span>75%</span>
|
|
<span>100%</span>
|
|
</div>
|
|
</div>
|
|
{showIndication && (
|
|
<MicVolumeBar deviceId={selectedDevice ? selectedDevice : ""} volumeInput={micVol} />
|
|
)}
|
|
<div className="divider w-full" />
|
|
</div>
|
|
<p className="flex items-center gap-2 text-base mb-2">
|
|
<Volume2 size={20} /> Funk Lautstärke
|
|
</p>
|
|
<div className="w-full mb-2">
|
|
<input
|
|
type="range"
|
|
min={0}
|
|
max={1}
|
|
step={0.01}
|
|
onChange={(e) => {
|
|
const value = parseFloat(e.target.value);
|
|
setFunkVol(value);
|
|
}}
|
|
value={funkVolume}
|
|
className="range range-xs range-primary w-full"
|
|
/>
|
|
<div className="flex justify-between px-2.5 mt-2 text-xs">
|
|
<span>0%</span>
|
|
<span>25%</span>
|
|
<span>50%</span>
|
|
<span>75%</span>
|
|
<span>100%</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-center w-full">
|
|
<div className="divider w-1/2" />
|
|
</div>
|
|
<p className="flex items-center gap-2 text-base mb-2">
|
|
<Volume2 size={20} /> Melder Lautstärke
|
|
</p>
|
|
<div className="w-full">
|
|
<input
|
|
type="range"
|
|
min={0}
|
|
max={1}
|
|
step={0.01}
|
|
onChange={(e) => {
|
|
const value = parseFloat(e.target.value);
|
|
setDmeVol(value);
|
|
if (!testSoundRef.current) return;
|
|
testSoundRef.current.volume = value;
|
|
testSoundRef.current.play();
|
|
}}
|
|
value={dmeVolume}
|
|
className="range range-xs range-primary w-full"
|
|
/>
|
|
<div className="flex justify-between px-2.5 mt-2 text-xs">
|
|
<span>0%</span>
|
|
<span>25%</span>
|
|
<span>50%</span>
|
|
<span>75%</span>
|
|
<span>100%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-between modal-action">
|
|
<button
|
|
className="btn btn-soft"
|
|
type="submit"
|
|
onSubmit={() => false}
|
|
onClick={() => {
|
|
modalRef.current?.close();
|
|
testSoundRef.current?.pause();
|
|
}}
|
|
>
|
|
Schließen
|
|
</button>
|
|
<button
|
|
className="btn btn-soft btn-success"
|
|
type="submit"
|
|
onSubmit={() => false}
|
|
onClick={async () => {
|
|
testSoundRef.current?.pause();
|
|
await editUserMutation.mutateAsync({
|
|
id: session.data!.user.id,
|
|
user: {
|
|
settingsMicDevice: selectedDevice,
|
|
settingsMicVolume: micVol,
|
|
settingsRadioVolume: funkVolume,
|
|
settingsDmeVolume: dmeVolume,
|
|
},
|
|
});
|
|
setMic(selectedDevice, micVol);
|
|
modalRef.current?.close();
|
|
toast.success("Einstellungen gespeichert");
|
|
}}
|
|
>
|
|
Speichern
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const Settings = () => {
|
|
return (
|
|
<div>
|
|
<SettingsBtn />
|
|
</div>
|
|
);
|
|
};
|