mirror of https://github.com/jetkvm/kvm.git
[WIP] Improvements, Bugfixes: Improve audio experience when running in HTTP mode
This commit is contained in:
parent
4dec696c4a
commit
b63af01d73
|
@ -43,6 +43,8 @@ interface MicrophoneHookReturn {
|
||||||
isStarting: boolean;
|
isStarting: boolean;
|
||||||
isStopping: boolean;
|
isStopping: boolean;
|
||||||
isToggling: boolean;
|
isToggling: boolean;
|
||||||
|
// HTTP/HTTPS detection
|
||||||
|
isHttpsRequired: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Actionbar({
|
export default function Actionbar({
|
||||||
|
|
|
@ -87,6 +87,8 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
||||||
isStarting,
|
isStarting,
|
||||||
isStopping,
|
isStopping,
|
||||||
isToggling,
|
isToggling,
|
||||||
|
// HTTP/HTTPS detection
|
||||||
|
isHttpsRequired,
|
||||||
} = microphone;
|
} = microphone;
|
||||||
|
|
||||||
// Use WebSocket data exclusively - no polling fallback
|
// Use WebSocket data exclusively - no polling fallback
|
||||||
|
@ -344,10 +346,24 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
||||||
theme={isMicrophoneActiveFromHook ? "danger" : "primary"}
|
theme={isMicrophoneActiveFromHook ? "danger" : "primary"}
|
||||||
text={isMicrophoneActiveFromHook ? "Disable" : "Enable"}
|
text={isMicrophoneActiveFromHook ? "Disable" : "Enable"}
|
||||||
onClick={handleToggleMicrophoneEnable}
|
onClick={handleToggleMicrophoneEnable}
|
||||||
disabled={isLoading}
|
disabled={isLoading || isHttpsRequired}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* HTTPS requirement notice */}
|
||||||
|
{isHttpsRequired && (
|
||||||
|
<div className="text-xs text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 p-2 rounded-md">
|
||||||
|
<p className="font-medium mb-1">HTTPS Required for Microphone</p>
|
||||||
|
<p>
|
||||||
|
Microphone access requires a secure connection. Please access this device using HTTPS instead of HTTP to enable audio input features.
|
||||||
|
</p>
|
||||||
|
<p className="mt-1">
|
||||||
|
<span className="font-medium">Current:</span> {window.location.protocol + '//' + window.location.host}
|
||||||
|
<br />
|
||||||
|
<span className="font-medium">Secure:</span> {'https://' + window.location.host}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -377,7 +393,7 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
||||||
<select
|
<select
|
||||||
value={selectedInputDevice}
|
value={selectedInputDevice}
|
||||||
onChange={(e) => handleMicrophoneDeviceChange(e.target.value)}
|
onChange={(e) => handleMicrophoneDeviceChange(e.target.value)}
|
||||||
disabled={devicesLoading}
|
disabled={devicesLoading || isHttpsRequired}
|
||||||
className="w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 disabled:bg-slate-50 disabled:text-slate-500 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-300 dark:focus:border-blue-400 dark:disabled:bg-slate-800"
|
className="w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 disabled:bg-slate-50 disabled:text-slate-500 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-300 dark:focus:border-blue-400 dark:disabled:bg-slate-800"
|
||||||
>
|
>
|
||||||
{audioInputDevices.map((device) => (
|
{audioInputDevices.map((device) => (
|
||||||
|
@ -401,7 +417,7 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
||||||
<select
|
<select
|
||||||
value={selectedOutputDevice}
|
value={selectedOutputDevice}
|
||||||
onChange={(e) => handleAudioOutputDeviceChange(e.target.value)}
|
onChange={(e) => handleAudioOutputDeviceChange(e.target.value)}
|
||||||
disabled={devicesLoading}
|
disabled={devicesLoading || isHttpsRequired}
|
||||||
className="w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 disabled:bg-slate-50 disabled:text-slate-500 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-300 dark:focus:border-blue-400 dark:disabled:bg-slate-800"
|
className="w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 disabled:bg-slate-50 disabled:text-slate-500 dark:border-slate-600 dark:bg-slate-700 dark:text-slate-300 dark:focus:border-blue-400 dark:disabled:bg-slate-800"
|
||||||
>
|
>
|
||||||
{audioOutputDevices.map((device) => (
|
{audioOutputDevices.map((device) => (
|
||||||
|
@ -414,7 +430,7 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={refreshDevices}
|
onClick={refreshDevices}
|
||||||
disabled={devicesLoading}
|
disabled={devicesLoading || isHttpsRequired}
|
||||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50 disabled:opacity-50 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-700"
|
className="flex w-full items-center justify-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50 disabled:opacity-50 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-700"
|
||||||
>
|
>
|
||||||
<MdRefresh className={cx("h-4 w-4", devicesLoading && "animate-spin")} />
|
<MdRefresh className={cx("h-4 w-4", devicesLoading && "animate-spin")} />
|
||||||
|
|
|
@ -35,6 +35,15 @@ export function useAudioDevices(): UseAudioDevicesReturn {
|
||||||
try {
|
try {
|
||||||
// Check if getUserMedia is available (requires HTTPS in most browsers)
|
// Check if getUserMedia is available (requires HTTPS in most browsers)
|
||||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||||
|
// Set placeholder devices when HTTPS is required
|
||||||
|
setAudioInputDevices([
|
||||||
|
{ deviceId: 'https-required', label: 'HTTPS Required for Microphone Access', kind: 'audioinput' }
|
||||||
|
]);
|
||||||
|
setAudioOutputDevices([
|
||||||
|
{ deviceId: 'https-required', label: 'HTTPS Required for Speaker Selection', kind: 'audiooutput' }
|
||||||
|
]);
|
||||||
|
setSelectedInputDevice('https-required');
|
||||||
|
setSelectedOutputDevice('https-required');
|
||||||
throw new Error('Microphone access requires HTTPS connection. Please use HTTPS to access audio features.');
|
throw new Error('Microphone access requires HTTPS connection. Please use HTTPS to access audio features.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue