Merge upstream v4.12.3 (Element Call 0.20.1) into lotus
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -129,6 +129,12 @@ export function CallControls({ callEmbed }: CallControlsProps) {
|
||||
setCords(undefined);
|
||||
};
|
||||
|
||||
const handleMicrophoneToggle = useCallback(
|
||||
() => callEmbed.control.toggleMicrophone(),
|
||||
[callEmbed],
|
||||
);
|
||||
const handleVideoToggle = useCallback(() => callEmbed.control.toggleVideo(), [callEmbed]);
|
||||
|
||||
const pttActiveRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -368,10 +374,7 @@ export function CallControls({ callEmbed }: CallControlsProps) {
|
||||
>
|
||||
<Box alignItems="Center" gap="Inherit" grow="Yes" direction={compact ? 'Column' : 'Row'}>
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="Inherit" gap="200">
|
||||
<MicrophoneButton
|
||||
enabled={microphone}
|
||||
onToggle={() => callEmbed.control.toggleMicrophone()}
|
||||
/>
|
||||
<MicrophoneButton enabled={microphone} onToggle={handleMicrophoneToggle} />
|
||||
<SoundButton enabled={sound} onToggle={() => callEmbed.control.toggleSound()} />
|
||||
<ScreenshareAudioButton
|
||||
muted={screenshareAudioMuted}
|
||||
@@ -380,7 +383,7 @@ export function CallControls({ callEmbed }: CallControlsProps) {
|
||||
</Box>
|
||||
{!compact && <ControlDivider />}
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="Inherit" gap="200">
|
||||
<VideoButton enabled={video} onToggle={() => callEmbed.control.toggleVideo()} />
|
||||
<VideoButton enabled={video} onToggle={handleVideoToggle} />
|
||||
<ScreenShareButton
|
||||
enabled={screenshare}
|
||||
onToggle={() =>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Icon, IconButton, Icons, Line, Text, Tooltip, TooltipProvider } from 'f
|
||||
import { useAtom } from 'jotai';
|
||||
import * as css from './styles.css';
|
||||
import { callChatAtom } from '../../state/callEmbed';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
|
||||
export function ControlDivider() {
|
||||
return (
|
||||
@@ -12,9 +13,12 @@ export function ControlDivider() {
|
||||
|
||||
type MicrophoneButtonProps = {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
onToggle: () => Promise<unknown>;
|
||||
};
|
||||
export function MicrophoneButton({ enabled, onToggle }: MicrophoneButtonProps) {
|
||||
const [micState, toggleMic] = useAsyncCallback(onToggle);
|
||||
const loading = micState.status === AsyncStatus.Loading;
|
||||
|
||||
return (
|
||||
<TooltipProvider
|
||||
position="Top"
|
||||
@@ -32,9 +36,10 @@ export function MicrophoneButton({ enabled, onToggle }: MicrophoneButtonProps) {
|
||||
fill="Soft"
|
||||
radii="400"
|
||||
size="400"
|
||||
onClick={() => onToggle()}
|
||||
onClick={toggleMic}
|
||||
aria-label={enabled ? 'Turn Off Microphone' : 'Turn On Microphone'}
|
||||
outlined
|
||||
disabled={loading}
|
||||
>
|
||||
<Icon size="400" src={enabled ? Icons.Mic : Icons.MicMute} filled={!enabled} />
|
||||
</IconButton>
|
||||
@@ -82,10 +87,13 @@ export function SoundButton({ enabled, onToggle }: SoundButtonProps) {
|
||||
|
||||
type VideoButtonProps = {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
onToggle: () => Promise<unknown>;
|
||||
disabled?: boolean;
|
||||
};
|
||||
export function VideoButton({ enabled, onToggle, disabled }: VideoButtonProps) {
|
||||
const [videoState, toggleVideo] = useAsyncCallback(onToggle);
|
||||
const loading = videoState.status === AsyncStatus.Loading;
|
||||
|
||||
return (
|
||||
<TooltipProvider
|
||||
position="Top"
|
||||
@@ -105,9 +113,9 @@ export function VideoButton({ enabled, onToggle, disabled }: VideoButtonProps) {
|
||||
fill="Soft"
|
||||
radii="400"
|
||||
size="400"
|
||||
onClick={() => onToggle()}
|
||||
onClick={toggleVideo}
|
||||
outlined
|
||||
disabled={disabled}
|
||||
disabled={disabled || loading}
|
||||
aria-label={
|
||||
disabled ? 'Camera disabled in settings' : enabled ? 'Stop camera' : 'Start camera'
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Box, Button, Icon, Icons, Spinner, Text } from 'folds';
|
||||
import { SequenceCard } from '../../components/sequence-card';
|
||||
import * as css from './styles.css';
|
||||
@@ -54,6 +54,9 @@ export function PrescreenControls({ canJoin }: PrescreenControlsProps) {
|
||||
useCallPreferences();
|
||||
const [cameraOnJoin] = useSetting(settingsAtom, 'cameraOnJoin');
|
||||
|
||||
const handleMicrophoneToggle = useCallback(async () => toggleMicrophone(), [toggleMicrophone]);
|
||||
const handleVideoToggle = useCallback(async () => toggleVideo(), [toggleVideo]);
|
||||
|
||||
return (
|
||||
<SequenceCard
|
||||
className={css.ControlCard}
|
||||
@@ -65,12 +68,12 @@ export function PrescreenControls({ canJoin }: PrescreenControlsProps) {
|
||||
wrap="Wrap"
|
||||
>
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="SpaceBetween" gap="200">
|
||||
<MicrophoneButton enabled={microphone} onToggle={toggleMicrophone} />
|
||||
<MicrophoneButton enabled={microphone} onToggle={handleMicrophoneToggle} />
|
||||
<SoundButton enabled={sound} onToggle={toggleSound} />
|
||||
</Box>
|
||||
<ControlDivider />
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="SpaceBetween" gap="200">
|
||||
<VideoButton enabled={video} onToggle={toggleVideo} disabled={!cameraOnJoin} />
|
||||
<VideoButton enabled={video} onToggle={handleVideoToggle} disabled={!cameraOnJoin} />
|
||||
<ChatButton />
|
||||
</Box>
|
||||
<Box grow="Yes" direction="Column" gap="200">
|
||||
|
||||
Reference in New Issue
Block a user