fix: VideoButton disabled state, PTT listener leak, TS prop errors

- VideoButton now accepts disabled prop with tooltip and visual feedback;
  PrescreenControls passes disabled=true when cameraOnJoin=false
- PTT key listener in settings tracked via ref, cleaned up on unmount,
  guarded against stacking on double-click; useCallback + useRef
- CallControls screenshare cancel button: variant Surface -> Secondary
- General.tsx Box align prop: align -> alignItems (TS2322 fix)
This commit is contained in:
root
2026-05-15 15:38:02 -04:00
parent c0c0b54280
commit 83cbb09bae
4 changed files with 29 additions and 7 deletions
+1 -1
View File
@@ -235,7 +235,7 @@ export function CallControls({ callEmbed }: CallControlsProps) {
<Text size="B300">Share</Text>
</Button>
<Button
size="300" variant="Surface" fill="Soft" radii="300" outlined
size="300" variant="Secondary" fill="Soft" radii="300" outlined
onClick={() => setShareConfirm(false)}
>
<Text size="B300">Cancel</Text>
+7 -2
View File
@@ -81,15 +81,18 @@ export function SoundButton({ enabled, onToggle }: SoundButtonProps) {
type VideoButtonProps = {
enabled: boolean;
onToggle: () => void;
disabled?: boolean;
};
export function VideoButton({ enabled, onToggle }: VideoButtonProps) {
export function VideoButton({ enabled, onToggle, disabled }: VideoButtonProps) {
return (
<TooltipProvider
position="Top"
delay={500}
tooltip={
<Tooltip>
<Text size="T200">{enabled ? 'Stop Camera' : 'Start Camera'}</Text>
<Text size="T200">
{disabled ? 'Camera disabled in settings' : enabled ? 'Stop Camera' : 'Start Camera'}
</Text>
</Tooltip>
}
>
@@ -102,6 +105,8 @@ export function VideoButton({ enabled, onToggle }: VideoButtonProps) {
size="400"
onClick={() => onToggle()}
outlined
disabled={disabled}
style={disabled ? { opacity: 0.4, cursor: 'not-allowed' } : undefined}
>
<Icon
size="400"
+4 -1
View File
@@ -6,6 +6,8 @@ import { ChatButton, ControlDivider, MicrophoneButton, SoundButton, VideoButton
import { useIsDirectRoom, useRoom } from '../../hooks/useRoom';
import { useCallEmbed, useCallJoined, useCallStart } from '../../hooks/useCallEmbed';
import { useCallPreferences } from '../../state/hooks/callPreferences';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
type MediaPermState = 'granted' | 'denied' | 'prompt' | 'unknown';
@@ -50,6 +52,7 @@ export function PrescreenControls({ canJoin }: PrescreenControlsProps) {
const { microphone, video, sound, toggleMicrophone, toggleVideo, toggleSound } =
useCallPreferences();
const [cameraOnJoin] = useSetting(settingsAtom, 'cameraOnJoin');
return (
<SequenceCard
@@ -67,7 +70,7 @@ export function PrescreenControls({ canJoin }: PrescreenControlsProps) {
</Box>
<ControlDivider />
<Box shrink="No" alignItems="Inherit" justifyContent="SpaceBetween" gap="200">
<VideoButton enabled={video} onToggle={toggleVideo} />
<VideoButton enabled={video} onToggle={toggleVideo} disabled={!cameraOnJoin} />
<ChatButton />
</Box>
<Box grow="Yes" direction="Column" gap="200">
+17 -3
View File
@@ -3,7 +3,9 @@ import React, {
FormEventHandler,
KeyboardEventHandler,
MouseEventHandler,
useCallback,
useEffect,
useRef,
useState,
} from 'react';
import dayjs from 'dayjs';
@@ -378,7 +380,7 @@ function Appearance() {
title="Lotus Terminal Mode"
description="LotusGuild Terminal Design System: Anduril Orange + Ice Cyan + Matrix Green, dot-grid background, CRT scanlines, and boot sequence animation."
after={
<Box direction="Row" gap="200" align="Center">
<Box direction="Row" gap="200" alignItems="Center">
{lotusTerminal && (
<button
type="button"
@@ -811,8 +813,18 @@ function Calls() {
const [pttMode, setPttMode] = useSetting(settingsAtom, 'pttMode');
const [pttKey, setPttKey] = useSetting(settingsAtom, 'pttKey');
const [listeningForKey, setListeningForKey] = useState(false);
const keyListenerRef = useRef<((e: KeyboardEvent) => void) | null>(null);
const handleKeyBind = () => {
useEffect(
() => () => {
if (keyListenerRef.current)
window.removeEventListener('keydown', keyListenerRef.current, true);
},
[]
);
const handleKeyBind = useCallback(() => {
if (listeningForKey) return;
setListeningForKey(true);
const onKey = (e: KeyboardEvent) => {
e.preventDefault();
@@ -823,9 +835,11 @@ function Calls() {
setListeningForKey(false);
}
window.removeEventListener('keydown', onKey, true);
keyListenerRef.current = null;
};
keyListenerRef.current = onKey;
window.addEventListener('keydown', onKey, true);
};
}, [listeningForKey, setPttKey]);
const keyLabel = (code: string) => code === 'Space' ? 'Space' : code.replace('Key', '').replace('Digit', '');