forked from github/cinny
Add own control buttons for element-call (#2744)
* add mutation observer hok * add hook to read speaking member by observing iframe content * display speaking member name in call status bar and improve layout * fix shrining * add joined call control bar * remove chat toggle from room header * change member speaking icon to mic * fix joined call control appear in other * show spinner on end call button * hide call statusbar for mobile view when room is selected * make call statusbar more mobile friendly * fix call status bar item align
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { Box, Chip, Icon, IconButton, Icons, Text, Tooltip, TooltipProvider } from 'folds';
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Chip, Icon, IconButton, Icons, Spinner, Text, Tooltip, TooltipProvider } from 'folds';
|
||||
import React, { useCallback } from 'react';
|
||||
import { StatusDivider } from './components';
|
||||
import { CallEmbed, useCallControlState } from '../../plugins/call';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
|
||||
type MicrophoneButtonProps = {
|
||||
enabled: boolean;
|
||||
@@ -104,9 +105,11 @@ function VideoButton({ enabled, onToggle }: VideoButtonProps) {
|
||||
);
|
||||
}
|
||||
|
||||
function ScreenShareButton() {
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
|
||||
type ScreenShareButtonProps = {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
};
|
||||
function ScreenShareButton({ enabled, onToggle }: ScreenShareButtonProps) {
|
||||
return (
|
||||
<TooltipProvider
|
||||
position="Top"
|
||||
@@ -123,7 +126,7 @@ function ScreenShareButton() {
|
||||
fill="Soft"
|
||||
radii="300"
|
||||
size="300"
|
||||
onClick={() => setEnabled(!enabled)}
|
||||
onClick={onToggle}
|
||||
outlined
|
||||
>
|
||||
<Icon size="100" src={Icons.ScreenShare} filled={enabled} />
|
||||
@@ -133,8 +136,14 @@ function ScreenShareButton() {
|
||||
);
|
||||
}
|
||||
|
||||
export function CallControl({ callEmbed }: { callEmbed: CallEmbed }) {
|
||||
const { microphone, video, sound } = useCallControlState(callEmbed.control);
|
||||
export function CallControl({ callEmbed, compact }: { callEmbed: CallEmbed; compact: boolean }) {
|
||||
const { microphone, video, sound, screenshare } = useCallControlState(callEmbed.control);
|
||||
|
||||
const [hangupState, hangup] = useAsyncCallback(
|
||||
useCallback(() => callEmbed.hangup(), [callEmbed])
|
||||
);
|
||||
const exiting =
|
||||
hangupState.status === AsyncStatus.Loading || hangupState.status === AsyncStatus.Success;
|
||||
|
||||
return (
|
||||
<Box shrink="No" alignItems="Center" gap="300">
|
||||
@@ -144,21 +153,36 @@ export function CallControl({ callEmbed }: { callEmbed: CallEmbed }) {
|
||||
onToggle={() => callEmbed.control.toggleMicrophone()}
|
||||
/>
|
||||
<SoundButton enabled={sound} onToggle={() => callEmbed.control.toggleSound()} />
|
||||
{!compact && <StatusDivider />}
|
||||
<VideoButton enabled={video} onToggle={() => callEmbed.control.toggleVideo()} />
|
||||
{false && <ScreenShareButton />}
|
||||
{!compact && (
|
||||
<ScreenShareButton
|
||||
enabled={screenshare}
|
||||
onToggle={() => callEmbed.control.toggleScreenshare()}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
<StatusDivider />
|
||||
<Chip
|
||||
variant="Critical"
|
||||
radii="300"
|
||||
radii="Pill"
|
||||
fill="Soft"
|
||||
before={<Icon size="50" src={Icons.PhoneDown} filled />}
|
||||
before={
|
||||
exiting ? (
|
||||
<Spinner variant="Critical" fill="Soft" size="50" />
|
||||
) : (
|
||||
<Icon size="50" src={Icons.PhoneDown} filled />
|
||||
)
|
||||
}
|
||||
disabled={exiting}
|
||||
outlined
|
||||
onClick={() => callEmbed.hangup()}
|
||||
onClick={hangup}
|
||||
>
|
||||
<Text as="span" size="L400">
|
||||
End
|
||||
</Text>
|
||||
{!compact && (
|
||||
<Text as="span" size="L400">
|
||||
End
|
||||
</Text>
|
||||
)}
|
||||
</Chip>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -47,18 +47,17 @@ export function CallStatus({ callEmbed }: CallStatusProps) {
|
||||
) : (
|
||||
<Spinner variant="Secondary" size="200" />
|
||||
)}
|
||||
<Box
|
||||
grow="Yes"
|
||||
alignItems="Center"
|
||||
gap="Inherit"
|
||||
justifyContent={compact ? 'Center' : undefined}
|
||||
>
|
||||
<CallRoomName room={room} />
|
||||
{speakers.size > 0 && !compact && (
|
||||
<Box grow="Yes" alignItems="Center" gap="Inherit">
|
||||
{!compact && (
|
||||
<>
|
||||
<StatusDivider />
|
||||
<span data-spacing-node />
|
||||
<MemberSpeaking room={room} speakers={speakers} />
|
||||
<CallRoomName room={room} />
|
||||
{speakers.size > 0 && (
|
||||
<>
|
||||
<StatusDivider />
|
||||
<span data-spacing-node />
|
||||
<MemberSpeaking room={room} speakers={speakers} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
@@ -69,8 +68,13 @@ export function CallStatus({ callEmbed }: CallStatusProps) {
|
||||
)}
|
||||
</Box>
|
||||
{memberVisible && !compact && <StatusDivider />}
|
||||
<Box shrink="No" alignItems="Center" justifyContent="Center" gap="Inherit">
|
||||
<CallControl callEmbed={callEmbed} />
|
||||
<Box shrink="No" alignItems="Center" gap="Inherit">
|
||||
{compact && (
|
||||
<Box grow="Yes">
|
||||
<CallRoomName room={room} />
|
||||
</Box>
|
||||
)}
|
||||
<CallControl compact={compact} callEmbed={callEmbed} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -128,7 +128,7 @@ export function LiveChip({ count, room, members }: LiveChipProps) {
|
||||
radii="Pill"
|
||||
onClick={handleOpenMenu}
|
||||
>
|
||||
<Text className={css.LiveChipText} as="span" size="L400">
|
||||
<Text className={css.LiveChipText} as="span" size="L400" truncate>
|
||||
{count} Live
|
||||
</Text>
|
||||
</Chip>
|
||||
|
||||
@@ -14,7 +14,7 @@ export function MemberSpeaking({ room, speakers }: MemberSpeakingProps) {
|
||||
);
|
||||
return (
|
||||
<Box alignItems="Center" gap="100">
|
||||
<Icon size="100" src={Icons.Phone} filled />
|
||||
<Icon size="100" src={Icons.Mic} filled />
|
||||
<Text size="T200" truncate>
|
||||
{speakingNames.length === 1 && (
|
||||
<>
|
||||
|
||||
203
src/app/features/call/CallControls.tsx
Normal file
203
src/app/features/call/CallControls.tsx
Normal file
@@ -0,0 +1,203 @@
|
||||
import React, { MouseEventHandler, useCallback, useRef, useState } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
config,
|
||||
Icon,
|
||||
IconButton,
|
||||
Icons,
|
||||
Menu,
|
||||
MenuItem,
|
||||
PopOut,
|
||||
RectCords,
|
||||
Spinner,
|
||||
Text,
|
||||
toRem,
|
||||
} from 'folds';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { SequenceCard } from '../../components/sequence-card';
|
||||
import * as css from './styles.css';
|
||||
import {
|
||||
ChatButton,
|
||||
ControlDivider,
|
||||
MicrophoneButton,
|
||||
ScreenShareButton,
|
||||
SoundButton,
|
||||
VideoButton,
|
||||
} from './Controls';
|
||||
import { CallEmbed, useCallControlState } from '../../plugins/call';
|
||||
import { useResizeObserver } from '../../hooks/useResizeObserver';
|
||||
import { stopPropagation } from '../../utils/keyboard';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
|
||||
type CallControlsProps = {
|
||||
callEmbed: CallEmbed;
|
||||
};
|
||||
export function CallControls({ callEmbed }: CallControlsProps) {
|
||||
const controlRef = useRef<HTMLDivElement>(null);
|
||||
const [compact, setCompact] = useState(document.body.clientWidth < 500);
|
||||
|
||||
useResizeObserver(
|
||||
useCallback(() => {
|
||||
const element = controlRef.current;
|
||||
if (!element) return;
|
||||
setCompact(element.clientWidth < 500);
|
||||
}, []),
|
||||
useCallback(() => controlRef.current, [])
|
||||
);
|
||||
|
||||
const { microphone, video, sound, screenshare, spotlight } = useCallControlState(
|
||||
callEmbed.control
|
||||
);
|
||||
|
||||
const [cords, setCords] = useState<RectCords>();
|
||||
|
||||
const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
setCords(evt.currentTarget.getBoundingClientRect());
|
||||
};
|
||||
|
||||
const handleSpotlightClick = () => {
|
||||
callEmbed.control.toggleSpotlight();
|
||||
setCords(undefined);
|
||||
};
|
||||
|
||||
const handleReactionsClick = () => {
|
||||
callEmbed.control.toggleReactions();
|
||||
setCords(undefined);
|
||||
};
|
||||
|
||||
const handleSettingsClick = () => {
|
||||
callEmbed.control.toggleSettings();
|
||||
setCords(undefined);
|
||||
};
|
||||
|
||||
const [hangupState, hangup] = useAsyncCallback(
|
||||
useCallback(() => callEmbed.hangup(), [callEmbed])
|
||||
);
|
||||
const exiting =
|
||||
hangupState.status === AsyncStatus.Loading || hangupState.status === AsyncStatus.Success;
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={controlRef}
|
||||
className={css.CallControlContainer}
|
||||
justifyContent="Center"
|
||||
alignItems="Center"
|
||||
>
|
||||
<SequenceCard
|
||||
className={css.ControlCard}
|
||||
variant="SurfaceVariant"
|
||||
gap="400"
|
||||
radii="500"
|
||||
alignItems="Center"
|
||||
justifyContent="SpaceBetween"
|
||||
>
|
||||
<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()}
|
||||
/>
|
||||
<SoundButton enabled={sound} onToggle={() => callEmbed.control.toggleSound()} />
|
||||
</Box>
|
||||
{!compact && <ControlDivider />}
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="Inherit" gap="200">
|
||||
<VideoButton enabled={video} onToggle={() => callEmbed.control.toggleVideo()} />
|
||||
<ScreenShareButton
|
||||
enabled={screenshare}
|
||||
onToggle={() => callEmbed.control.toggleScreenshare()}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
{!compact && <ControlDivider />}
|
||||
<Box alignItems="Center" gap="Inherit" grow="Yes" direction={compact ? 'Column' : 'Row'}>
|
||||
<Box shrink="No" alignItems="Inherit" justifyContent="Inherit" gap="200">
|
||||
<ChatButton />
|
||||
<PopOut
|
||||
anchor={cords}
|
||||
position="Top"
|
||||
align="Center"
|
||||
content={
|
||||
<FocusTrap
|
||||
focusTrapOptions={{
|
||||
initialFocus: false,
|
||||
onDeactivate: () => setCords(undefined),
|
||||
clickOutsideDeactivates: true,
|
||||
isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
|
||||
isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
|
||||
escapeDeactivates: stopPropagation,
|
||||
}}
|
||||
>
|
||||
<Menu>
|
||||
<Box direction="Column" style={{ padding: config.space.S100 }}>
|
||||
<MenuItem
|
||||
size="300"
|
||||
variant="Surface"
|
||||
radii="300"
|
||||
onClick={handleSpotlightClick}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
{spotlight ? 'Grid View' : 'Spotlight View'}
|
||||
</Text>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
size="300"
|
||||
variant="Surface"
|
||||
radii="300"
|
||||
onClick={handleReactionsClick}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
Reactions
|
||||
</Text>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
size="300"
|
||||
variant="Surface"
|
||||
radii="300"
|
||||
onClick={handleSettingsClick}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
Settings
|
||||
</Text>
|
||||
</MenuItem>
|
||||
</Box>
|
||||
</Menu>
|
||||
</FocusTrap>
|
||||
}
|
||||
>
|
||||
<IconButton
|
||||
variant="Surface"
|
||||
fill="Soft"
|
||||
radii="400"
|
||||
size="400"
|
||||
onClick={handleOpenMenu}
|
||||
outlined
|
||||
aria-pressed={!!cords}
|
||||
>
|
||||
<Icon size="400" src={Icons.VerticalDots} />
|
||||
</IconButton>
|
||||
</PopOut>
|
||||
</Box>
|
||||
<Box shrink="No" direction="Column">
|
||||
<Button
|
||||
style={{ minWidth: toRem(88) }}
|
||||
variant="Critical"
|
||||
fill="Solid"
|
||||
onClick={hangup}
|
||||
before={
|
||||
exiting ? (
|
||||
<Spinner variant="Critical" fill="Solid" size="200" />
|
||||
) : (
|
||||
<Icon src={Icons.PhoneDown} size="200" filled />
|
||||
)
|
||||
}
|
||||
disabled={exiting}
|
||||
>
|
||||
<Text size="B400">End</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</SequenceCard>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useRef } from 'react';
|
||||
import React, { RefObject, useRef } from 'react';
|
||||
import { Badge, Box, color, Header, Scroll, Text, toRem } from 'folds';
|
||||
import { useCallEmbed, useCallJoined, useCallEmbedPlacementSync } from '../../hooks/useCallEmbed';
|
||||
import { ContainerColor } from '../../styles/ContainerColor.css';
|
||||
@@ -12,6 +12,7 @@ import { StateEvent } from '../../../types/matrix/room';
|
||||
import { useCallMembers, useCallSession } from '../../hooks/useCall';
|
||||
import { CallMemberRenderer } from './CallMemberCard';
|
||||
import * as css from './styles.css';
|
||||
import { CallControls } from './CallControls';
|
||||
|
||||
function JoinMessage({ hasParticipant }: { hasParticipant?: boolean }) {
|
||||
if (hasParticipant) return null;
|
||||
@@ -39,13 +40,10 @@ function AlreadyInCallMessage() {
|
||||
);
|
||||
}
|
||||
|
||||
export function CallView() {
|
||||
function CallPrescreen() {
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
const callViewRef = useRef<HTMLDivElement>(null);
|
||||
useCallEmbedPlacementSync(callViewRef);
|
||||
|
||||
const powerLevels = usePowerLevelsContext();
|
||||
const creators = useRoomCreators(room);
|
||||
|
||||
@@ -57,49 +55,70 @@ export function CallView() {
|
||||
const hasParticipant = callMembers.length > 0;
|
||||
|
||||
const callEmbed = useCallEmbed();
|
||||
const callJoined = useCallJoined(callEmbed);
|
||||
const inOtherCall = callEmbed && callEmbed.roomId !== room.roomId;
|
||||
|
||||
return (
|
||||
<Scroll variant="Surface" hideTrack>
|
||||
<Box className={css.CallViewContent} alignItems="Center" justifyContent="Center">
|
||||
<Box style={{ maxWidth: toRem(382), width: '100%' }} direction="Column" gap="100">
|
||||
{hasParticipant && (
|
||||
<Header size="300">
|
||||
<Box grow="Yes" alignItems="Center">
|
||||
<Text size="L400">Participant</Text>
|
||||
</Box>
|
||||
<Badge variant="Critical" fill="Solid" size="400">
|
||||
<Text as="span" size="L400" truncate>
|
||||
{callMembers.length} Live
|
||||
</Text>
|
||||
</Badge>
|
||||
</Header>
|
||||
)}
|
||||
<CallMemberRenderer members={callMembers} />
|
||||
<PrescreenControls canJoin={canJoin} />
|
||||
<Header size="300">
|
||||
{!inOtherCall &&
|
||||
(canJoin ? <JoinMessage hasParticipant={hasParticipant} /> : <NoPermissionMessage />)}
|
||||
{inOtherCall && <AlreadyInCallMessage />}
|
||||
</Header>
|
||||
</Box>
|
||||
</Box>
|
||||
</Scroll>
|
||||
);
|
||||
}
|
||||
|
||||
type CallJoinedProps = {
|
||||
containerRef: RefObject<HTMLDivElement>;
|
||||
joined: boolean;
|
||||
};
|
||||
function CallJoined({ joined, containerRef }: CallJoinedProps) {
|
||||
const callEmbed = useCallEmbed();
|
||||
|
||||
return (
|
||||
<Box grow="Yes" direction="Column">
|
||||
<Box grow="Yes" ref={containerRef} />
|
||||
{callEmbed && joined && <CallControls callEmbed={callEmbed} />}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export function CallView() {
|
||||
const room = useRoom();
|
||||
const callContainerRef = useRef<HTMLDivElement>(null);
|
||||
useCallEmbedPlacementSync(callContainerRef);
|
||||
|
||||
const callEmbed = useCallEmbed();
|
||||
const callJoined = useCallJoined(callEmbed);
|
||||
|
||||
const currentJoined = callEmbed?.roomId === room.roomId && callJoined;
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={callViewRef}
|
||||
className={ContainerColor({ variant: 'Surface' })}
|
||||
style={{ minWidth: toRem(280) }}
|
||||
grow="Yes"
|
||||
>
|
||||
{!currentJoined && (
|
||||
<Scroll variant="Surface" hideTrack>
|
||||
<Box className={css.CallViewContent} alignItems="Center" justifyContent="Center">
|
||||
<Box style={{ maxWidth: toRem(382), width: '100%' }} direction="Column" gap="100">
|
||||
{hasParticipant && (
|
||||
<Header size="300">
|
||||
<Box grow="Yes" alignItems="Center">
|
||||
<Text size="L400">Participant</Text>
|
||||
</Box>
|
||||
<Badge variant="Critical" fill="Solid" size="400">
|
||||
<Text as="span" size="L400" truncate>
|
||||
{callMembers.length} Live
|
||||
</Text>
|
||||
</Badge>
|
||||
</Header>
|
||||
)}
|
||||
<CallMemberRenderer members={callMembers} />
|
||||
<PrescreenControls canJoin={canJoin} />
|
||||
<Header size="300">
|
||||
{!inOtherCall &&
|
||||
(canJoin ? (
|
||||
<JoinMessage hasParticipant={hasParticipant} />
|
||||
) : (
|
||||
<NoPermissionMessage />
|
||||
))}
|
||||
{inOtherCall && <AlreadyInCallMessage />}
|
||||
</Header>
|
||||
</Box>
|
||||
</Box>
|
||||
</Scroll>
|
||||
)}
|
||||
{!currentJoined && <CallPrescreen />}
|
||||
<CallJoined joined={currentJoined} containerRef={callContainerRef} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,38 @@ export function VideoButton({ enabled, onToggle }: VideoButtonProps) {
|
||||
);
|
||||
}
|
||||
|
||||
type ScreenShareButtonProps = {
|
||||
enabled: boolean;
|
||||
onToggle: () => void;
|
||||
};
|
||||
export function ScreenShareButton({ enabled, onToggle }: ScreenShareButtonProps) {
|
||||
return (
|
||||
<TooltipProvider
|
||||
position="Top"
|
||||
delay={500}
|
||||
tooltip={
|
||||
<Tooltip>
|
||||
<Text size="T200">{enabled ? 'Stop Screenshare' : 'Start Screenshare'}</Text>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
{(anchorRef) => (
|
||||
<IconButton
|
||||
ref={anchorRef}
|
||||
variant={enabled ? 'Success' : 'Surface'}
|
||||
fill="Soft"
|
||||
radii="400"
|
||||
size="400"
|
||||
onClick={() => onToggle()}
|
||||
outlined
|
||||
>
|
||||
<Icon size="400" src={Icons.ScreenShare} filled={enabled} />
|
||||
</IconButton>
|
||||
)}
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChatButton() {
|
||||
const [chat, setChat] = useAtom(callChatAtom);
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ 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 { CallControlState } from '../../plugins/call/CallControlState';
|
||||
|
||||
type PrescreenControlsProps = {
|
||||
canJoin?: boolean;
|
||||
@@ -50,7 +49,7 @@ export function PrescreenControls({ canJoin }: PrescreenControlsProps) {
|
||||
<Button
|
||||
variant={disabled ? 'Secondary' : 'Success'}
|
||||
fill={disabled ? 'Soft' : 'Solid'}
|
||||
onClick={() => startCall(room, new CallControlState(microphone, video, sound))}
|
||||
onClick={() => startCall(room, { microphone, video, sound })}
|
||||
disabled={disabled || joining}
|
||||
before={
|
||||
joining ? (
|
||||
|
||||
@@ -18,3 +18,7 @@ export const ControlDivider = style({
|
||||
export const CallMemberCard = style({
|
||||
padding: config.space.S300,
|
||||
});
|
||||
|
||||
export const CallControlContainer = style({
|
||||
padding: config.space.S400,
|
||||
});
|
||||
|
||||
@@ -57,7 +57,6 @@ import { useCallMembers, useCallSession } from '../../hooks/useCall';
|
||||
import { useCallEmbed, useCallStart } from '../../hooks/useCallEmbed';
|
||||
import { callChatAtom } from '../../state/callEmbed';
|
||||
import { useCallPreferencesAtom } from '../../state/hooks/callPreferences';
|
||||
import { CallControlState } from '../../plugins/call/CallControlState';
|
||||
|
||||
type RoomNavItemMenuProps = {
|
||||
room: Room;
|
||||
@@ -292,7 +291,7 @@ export function RoomNavItem({
|
||||
// Start call in second click
|
||||
if (selected) {
|
||||
evt.preventDefault();
|
||||
startCall(room, new CallControlState(callPref.microphone, callPref.video, callPref.sound));
|
||||
startCall(room, callPref);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
} from 'folds';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Room } from 'matrix-js-sdk';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useStateEvent } from '../../hooks/useStateEvent';
|
||||
import { PageHeader } from '../../components/page';
|
||||
import { RoomAvatar, RoomIcon } from '../../components/room-avatar';
|
||||
@@ -68,7 +67,6 @@ import { useRoomCreators } from '../../hooks/useRoomCreators';
|
||||
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
|
||||
import { InviteUserPrompt } from '../../components/invite-user-prompt';
|
||||
import { ContainerColor } from '../../styles/ContainerColor.css';
|
||||
import { callChatAtom } from '../../state/callEmbed';
|
||||
import { RoomSettingsPage } from '../../state/roomSettings';
|
||||
|
||||
type RoomMenuProps = {
|
||||
@@ -266,8 +264,6 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) {
|
||||
const [pinMenuAnchor, setPinMenuAnchor] = useState<RectCords>();
|
||||
const direct = useIsDirectRoom();
|
||||
|
||||
const [chat, setChat] = useAtom(callChatAtom);
|
||||
|
||||
const pinnedEvents = useRoomPinnedEvents(room);
|
||||
const encryptionEvent = useStateEvent(room, StateEvent.RoomEncryption);
|
||||
const encryptedRoom = !!encryptionEvent;
|
||||
@@ -476,24 +472,6 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) {
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
{callView && (
|
||||
<TooltipProvider
|
||||
position="Bottom"
|
||||
offset={4}
|
||||
tooltip={
|
||||
<Tooltip>
|
||||
<Text>Chat</Text>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
{(triggerRef) => (
|
||||
<IconButton fill="None" ref={triggerRef} onClick={() => setChat(!chat)}>
|
||||
<Icon size="400" src={Icons.Message} filled={chat} />
|
||||
</IconButton>
|
||||
)}
|
||||
</TooltipProvider>
|
||||
)}
|
||||
|
||||
<TooltipProvider
|
||||
position="Bottom"
|
||||
align="End"
|
||||
|
||||
Reference in New Issue
Block a user