(fix): small ui and layout bug
This commit is contained in:
parent
6840e04118
commit
dd09ca943d
10 changed files with 279 additions and 171 deletions
|
|
@ -24,6 +24,7 @@ import {
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
Maximize,
|
Maximize,
|
||||||
Minimize,
|
Minimize,
|
||||||
|
ScreenShareOff,
|
||||||
SquareArrowOutDownLeft,
|
SquareArrowOutDownLeft,
|
||||||
SquareArrowOutUpRight,
|
SquareArrowOutUpRight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
@ -96,68 +97,56 @@ export default function Actions() {
|
||||||
</div>
|
</div>
|
||||||
<Card className="p-1.75">
|
<Card className="p-1.75">
|
||||||
<CardContent className="p-0! flex gap-1.75">
|
<CardContent className="p-0! flex gap-1.75">
|
||||||
<Tooltip>
|
<MuteButton
|
||||||
<TooltipTrigger
|
className={sharedClasses}
|
||||||
render={
|
iconSize={sharedIconSize}
|
||||||
<MuteButton
|
tooltip="Mute"
|
||||||
className={sharedClasses}
|
portalContainer={portalContainer}
|
||||||
iconSize={sharedIconSize}
|
/>
|
||||||
/>
|
<DeafButton
|
||||||
}
|
className={sharedClasses}
|
||||||
/>
|
iconSize={sharedIconSize}
|
||||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
tooltip="Deafen"
|
||||||
Mute
|
portalContainer={portalContainer}
|
||||||
</TooltipContent>
|
/>
|
||||||
</Tooltip>
|
<ScreenshareButton
|
||||||
<Tooltip>
|
className={sharedClasses}
|
||||||
<TooltipTrigger
|
iconSize={sharedIconSize}
|
||||||
render={
|
tooltip="Screenshare"
|
||||||
<DeafButton
|
/>
|
||||||
className={sharedClasses}
|
<InviteButton
|
||||||
iconSize={sharedIconSize}
|
className={sharedClasses}
|
||||||
/>
|
iconSize={sharedIconSize}
|
||||||
}
|
tooltip="Invite"
|
||||||
/>
|
/>
|
||||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
|
||||||
Deafen
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger
|
|
||||||
render={
|
|
||||||
<ScreenshareButton
|
|
||||||
className={sharedClasses}
|
|
||||||
iconSize={sharedIconSize}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
|
||||||
Screenshare
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger
|
|
||||||
render={
|
|
||||||
<InviteButton
|
|
||||||
className={sharedClasses}
|
|
||||||
iconSize={sharedIconSize}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
|
||||||
Invite
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
{isWatchingFocusedStream ? (
|
{isWatchingFocusedStream ? (
|
||||||
<Button
|
<Tooltip>
|
||||||
className="h-10"
|
<TooltipTrigger
|
||||||
variant="destructive"
|
render={
|
||||||
onClick={() => stopWatchingFocusedStream()}
|
<Button
|
||||||
>
|
className={sharedClasses}
|
||||||
Stop watching
|
variant="destructive"
|
||||||
</Button>
|
onClick={() => stopWatchingFocusedStream()}
|
||||||
|
>
|
||||||
|
<ScreenShareOff
|
||||||
|
style={{
|
||||||
|
scale: (sharedIconSize ? sharedIconSize + 100 : 100) + "%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
Stop watching
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
) : (
|
) : (
|
||||||
<LeaveButton className={sharedClasses} iconSize={sharedIconSize} />
|
<LeaveButton
|
||||||
|
className={sharedClasses}
|
||||||
|
iconSize={sharedIconSize}
|
||||||
|
tooltip="Leave"
|
||||||
|
portalContainer={portalContainer}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
import { Button } from "@tensamin/ui";
|
import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
|
||||||
import { toggleDeaf, useCall } from "../../store";
|
import { toggleDeaf, useCall } from "../../store";
|
||||||
import { HeadphoneOff, Headphones } from "lucide-react";
|
import { HeadphoneOff, Headphones } from "lucide-react";
|
||||||
|
|
||||||
export default function DeafButton({
|
export default function DeafButton({
|
||||||
className,
|
className,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
tooltip,
|
||||||
|
portalContainer,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
|
tooltip?: string;
|
||||||
|
portalContainer?: HTMLElement;
|
||||||
}) {
|
}) {
|
||||||
const deaf = useCall((state) => state.deaf);
|
const deaf = useCall((state) => state.deaf);
|
||||||
|
|
||||||
return (
|
const button = (
|
||||||
<Button
|
<Button
|
||||||
variant={deaf ? "destructive" : "default"}
|
variant={deaf ? "destructive" : "default"}
|
||||||
onClick={toggleDeaf}
|
onClick={toggleDeaf}
|
||||||
|
|
@ -28,4 +32,17 @@ export default function DeafButton({
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger render={button} />
|
||||||
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
{tooltip}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Button, Popover, PopoverContent, PopoverTrigger } from "@tensamin/ui";
|
import {
|
||||||
|
Button,
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@tensamin/ui";
|
||||||
import Wrapper from "@tensamin/user/wrapper";
|
import Wrapper from "@tensamin/user/wrapper";
|
||||||
import { Mail } from "lucide-react";
|
import { Mail } from "lucide-react";
|
||||||
import { sendCallInvite, useCall } from "../../store";
|
import { sendCallInvite, useCall } from "../../store";
|
||||||
|
|
@ -9,9 +17,11 @@ import { useSession } from "@tensamin/storage/session";
|
||||||
export default function InviteButton({
|
export default function InviteButton({
|
||||||
className,
|
className,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
tooltip,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
|
tooltip?: string;
|
||||||
}) {
|
}) {
|
||||||
const { contacts } = useSession();
|
const { contacts } = useSession();
|
||||||
const screenRef = useCall((state) => state.screenRef);
|
const screenRef = useCall((state) => state.screenRef);
|
||||||
|
|
@ -22,43 +32,64 @@ export default function InviteButton({
|
||||||
}, [screenRef]);
|
}, [screenRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<Tooltip>
|
||||||
<PopoverTrigger
|
<Popover>
|
||||||
render={
|
<PopoverTrigger
|
||||||
<Button className={className}>
|
render={
|
||||||
<Mail style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }} />
|
tooltip ? (
|
||||||
</Button>
|
<TooltipTrigger
|
||||||
}
|
render={
|
||||||
/>
|
<Button className={className}>
|
||||||
<PopoverContent
|
<Mail
|
||||||
className="flex w-40 flex-col gap-0.5 p-1!"
|
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||||
portalProps={{ container: portalContainer }}
|
/>
|
||||||
>
|
</Button>
|
||||||
{contacts.map((contact) => (
|
}
|
||||||
<Wrapper
|
/>
|
||||||
key={contact.user_id}
|
) : (
|
||||||
userId={contact.user_id}
|
<Button className={className}>
|
||||||
loading={<div>Loading...</div>}
|
<Mail
|
||||||
component={(user) => (
|
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||||
<Button
|
/>
|
||||||
className="w-full justify-start"
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => {
|
|
||||||
void sendCallInvite(contact.user_id).catch((err) => {
|
|
||||||
toast(
|
|
||||||
"error",
|
|
||||||
"Failed to send call invite. Check console for details.",
|
|
||||||
);
|
|
||||||
log(1, "call", "red", "Failed to send call invite", err);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{user.display}
|
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)
|
||||||
/>
|
}
|
||||||
))}
|
/>
|
||||||
</PopoverContent>
|
<PopoverContent
|
||||||
</Popover>
|
className="flex w-40 flex-col gap-0.5 p-1!"
|
||||||
|
portalProps={{ container: portalContainer }}
|
||||||
|
>
|
||||||
|
{contacts.map((contact) => (
|
||||||
|
<Wrapper
|
||||||
|
key={contact.user_id}
|
||||||
|
userId={contact.user_id}
|
||||||
|
loading={<div>Loading...</div>}
|
||||||
|
component={(user) => (
|
||||||
|
<Button
|
||||||
|
className="w-full justify-start"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
void sendCallInvite(contact.user_id).catch((err) => {
|
||||||
|
toast(
|
||||||
|
"error",
|
||||||
|
"Failed to send call invite. Check console for details.",
|
||||||
|
);
|
||||||
|
log(1, "call", "red", "Failed to send call invite", err);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{user.display}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
{tooltip && (
|
||||||
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
{tooltip}
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
import { LeaveIcon } from "@livekit/components-react";
|
import { LeaveIcon } from "@livekit/components-react";
|
||||||
import { Button } from "@tensamin/ui";
|
import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
|
||||||
import { disconnect, useCall } from "../../store";
|
import { disconnect, useCall } from "../../store";
|
||||||
|
|
||||||
export default function LeaveButton({
|
export default function LeaveButton({
|
||||||
className,
|
className,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
tooltip,
|
||||||
|
portalContainer,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
|
tooltip?: string;
|
||||||
|
portalContainer?: HTMLElement;
|
||||||
}) {
|
}) {
|
||||||
const state = useCall((store) => store.state);
|
const state = useCall((store) => store.state);
|
||||||
|
|
||||||
return (
|
const button = (
|
||||||
<Button
|
<Button
|
||||||
className={className}
|
className={className}
|
||||||
onClick={() => disconnect()}
|
onClick={() => disconnect()}
|
||||||
|
|
@ -21,4 +25,17 @@ export default function LeaveButton({
|
||||||
<LeaveIcon style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }} />
|
<LeaveIcon style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }} />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger render={button} />
|
||||||
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
{tooltip}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,21 @@
|
||||||
import { Button } from "@tensamin/ui";
|
import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
|
||||||
import { toggleMute, useCall } from "../../store";
|
import { toggleMute, useCall } from "../../store";
|
||||||
import { Mic, MicOff } from "lucide-react";
|
import { Mic, MicOff } from "lucide-react";
|
||||||
|
|
||||||
export default function MuteButton({
|
export default function MuteButton({
|
||||||
className,
|
className,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
tooltip,
|
||||||
|
portalContainer,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
|
tooltip?: string;
|
||||||
|
portalContainer?: HTMLElement;
|
||||||
}) {
|
}) {
|
||||||
const micEnabled = useCall((state) => state.micEnabled);
|
const micEnabled = useCall((state) => state.micEnabled);
|
||||||
|
|
||||||
return (
|
const button = (
|
||||||
<Button
|
<Button
|
||||||
variant={micEnabled ? "default" : "destructive"}
|
variant={micEnabled ? "default" : "destructive"}
|
||||||
className={className}
|
className={className}
|
||||||
|
|
@ -24,4 +28,17 @@ export default function MuteButton({
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger render={button} />
|
||||||
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
{tooltip}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Button, Popover, PopoverContent, PopoverTrigger } from "@tensamin/ui";
|
import {
|
||||||
|
Button,
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@tensamin/ui";
|
||||||
import { MonitorDot, ScreenShare } from "lucide-react";
|
import { MonitorDot, ScreenShare } from "lucide-react";
|
||||||
import { toast } from "@tensamin/shared/log";
|
import { toast } from "@tensamin/shared/log";
|
||||||
import { isTauri } from "@tauri-apps/api/core";
|
import { isTauri } from "@tauri-apps/api/core";
|
||||||
|
|
@ -9,9 +17,11 @@ import ScreenShareDialog from "../screenshareDialog";
|
||||||
export default function ScreenshareButton({
|
export default function ScreenshareButton({
|
||||||
className,
|
className,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
tooltip,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
iconSize?: number;
|
iconSize?: number;
|
||||||
|
tooltip?: string;
|
||||||
}) {
|
}) {
|
||||||
const isScreensharing = useCall((state) => state.screenShareEnabled);
|
const isScreensharing = useCall((state) => state.screenShareEnabled);
|
||||||
const screenRef = useCall((state) => state.screenRef);
|
const screenRef = useCall((state) => state.screenRef);
|
||||||
|
|
@ -53,57 +63,89 @@ export default function ScreenshareButton({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Popover onOpenChange={setMenuOpen} open={menuOpen}>
|
<Tooltip>
|
||||||
<PopoverTrigger
|
<Popover onOpenChange={setMenuOpen} open={menuOpen}>
|
||||||
render={
|
<PopoverTrigger
|
||||||
<Button
|
render={
|
||||||
variant={isScreensharing ? "subtleDefault" : "default"}
|
tooltip ? (
|
||||||
className={className}
|
<TooltipTrigger
|
||||||
>
|
render={
|
||||||
{isScreensharing ? (
|
<Button
|
||||||
<MonitorDot
|
variant={isScreensharing ? "subtleDefault" : "default"}
|
||||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
className={className}
|
||||||
|
>
|
||||||
|
{isScreensharing ? (
|
||||||
|
<MonitorDot
|
||||||
|
style={{
|
||||||
|
scale: (iconSize ? iconSize + 100 : 100) + "%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ScreenShare
|
||||||
|
style={{
|
||||||
|
scale: (iconSize ? iconSize + 100 : 100) + "%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ScreenShare
|
<Button
|
||||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
variant={isScreensharing ? "subtleDefault" : "default"}
|
||||||
/>
|
className={className}
|
||||||
)}
|
>
|
||||||
|
{isScreensharing ? (
|
||||||
|
<MonitorDot
|
||||||
|
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ScreenShare
|
||||||
|
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<PopoverContent
|
||||||
|
className="flex w-40 flex-col gap-2"
|
||||||
|
portalProps={{ container: portalContainer }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
disabled={isScreensharing}
|
||||||
|
onClick={() => {
|
||||||
|
setMenuOpen(false);
|
||||||
|
|
||||||
|
if (isTauri()) {
|
||||||
|
setDialogOpen(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startWebShare();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Start screenshare
|
||||||
</Button>
|
</Button>
|
||||||
}
|
<Button
|
||||||
/>
|
variant="destructive"
|
||||||
<PopoverContent
|
disabled={!isScreensharing}
|
||||||
className="flex w-40 flex-col gap-2"
|
onClick={() => {
|
||||||
portalProps={{ container: portalContainer }}
|
setMenuOpen(false);
|
||||||
>
|
void stopShare();
|
||||||
<Button
|
}}
|
||||||
disabled={isScreensharing}
|
>
|
||||||
onClick={() => {
|
Stop screenshare
|
||||||
setMenuOpen(false);
|
</Button>
|
||||||
|
<Button variant="outline">Change quality</Button>
|
||||||
if (isTauri()) {
|
</PopoverContent>
|
||||||
setDialogOpen(true);
|
</Popover>
|
||||||
return;
|
{tooltip && (
|
||||||
}
|
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||||
|
{tooltip}
|
||||||
void startWebShare();
|
</TooltipContent>
|
||||||
}}
|
)}
|
||||||
>
|
</Tooltip>
|
||||||
Start screenshare
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
disabled={!isScreensharing}
|
|
||||||
onClick={() => {
|
|
||||||
setMenuOpen(false);
|
|
||||||
void stopShare();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Stop screenshare
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline">Change quality</Button>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
{isTauri() && (
|
{isTauri() && (
|
||||||
<ScreenShareDialog
|
<ScreenShareDialog
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,7 @@ export default function SidebarBox() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConnectionBar({
|
function ConnectionBar({ portalContainer }: { portalContainer?: HTMLElement }) {
|
||||||
portalContainer,
|
|
||||||
}: {
|
|
||||||
portalContainer?: HTMLElement;
|
|
||||||
}) {
|
|
||||||
const state = useCall((store) => store.state);
|
const state = useCall((store) => store.state);
|
||||||
const isEncrypted = useCall((store) => store.isEncrypted);
|
const isEncrypted = useCall((store) => store.isEncrypted);
|
||||||
const callId = useCall((store) => store.callId);
|
const callId = useCall((store) => store.callId);
|
||||||
|
|
|
||||||
|
|
@ -509,9 +509,7 @@ export function setCallView(view: CallView) {
|
||||||
useCall.setState({ view });
|
useCall.setState({ view });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUsersInFocusedViewHidden(
|
export function setUsersInFocusedViewHidden(usersInFocusedViewHidden: boolean) {
|
||||||
usersInFocusedViewHidden: boolean,
|
|
||||||
) {
|
|
||||||
useCall.setState((state) => ({
|
useCall.setState((state) => ({
|
||||||
usersInFocusedViewHidden,
|
usersInFocusedViewHidden,
|
||||||
layoutVersion:
|
layoutVersion:
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,9 @@ export default function View() {
|
||||||
let frameId = 0;
|
let frameId = 0;
|
||||||
|
|
||||||
const syncTileLayout = () => {
|
const syncTileLayout = () => {
|
||||||
const containerWidth = Math.floor(container.getBoundingClientRect().width);
|
const containerWidth = Math.floor(
|
||||||
|
container.getBoundingClientRect().width,
|
||||||
|
);
|
||||||
const tileWidth = Math.floor(focusedTile.getBoundingClientRect().width);
|
const tileWidth = Math.floor(focusedTile.getBoundingClientRect().width);
|
||||||
|
|
||||||
setIsFocusedTileFlush(Math.abs(containerWidth - tileWidth) <= 1);
|
setIsFocusedTileFlush(Math.abs(containerWidth - tileWidth) <= 1);
|
||||||
|
|
@ -155,14 +157,10 @@ export default function View() {
|
||||||
const focusedParticipant = getParticipantById(focusedParticipantId);
|
const focusedParticipant = getParticipantById(focusedParticipantId);
|
||||||
const focusedParticipantHasActiveScreenShare =
|
const focusedParticipantHasActiveScreenShare =
|
||||||
activeScreenShareParticipantIdSet.has(focusedParticipantId);
|
activeScreenShareParticipantIdSet.has(focusedParticipantId);
|
||||||
const isImmersiveFocusedView =
|
const isImmersiveFocusedView = callIsFullscreen && usersInFocusedViewHidden;
|
||||||
callIsFullscreen && usersInFocusedViewHidden;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div ref={containerRef} className="flex h-full w-full overflow-hidden">
|
||||||
ref={containerRef}
|
|
||||||
className="flex h-full w-full overflow-hidden"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="flex h-full w-full flex-col items-center overflow-hidden"
|
className="flex h-full w-full flex-col items-center overflow-hidden"
|
||||||
style={{
|
style={{
|
||||||
|
|
@ -175,7 +173,7 @@ export default function View() {
|
||||||
className={
|
className={
|
||||||
isImmersiveFocusedView
|
isImmersiveFocusedView
|
||||||
? "h-full w-full overflow-hidden"
|
? "h-full w-full overflow-hidden"
|
||||||
: "h-full max-w-full aspect-video overflow-hidden"
|
: "h-full max-w-full aspect-video overflow-hidden flex items-center"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Base
|
<Base
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
const screenRef = useRef<HTMLDivElement>(null);
|
const screenRef = useRef<HTMLDivElement>(null);
|
||||||
const topBarRef = useRef<HTMLDivElement>(null);
|
const topBarRef = useRef<HTMLDivElement>(null);
|
||||||
const actionsRef = useRef<HTMLDivElement>(null);
|
const actionsRef = useRef<HTMLDivElement>(null);
|
||||||
const hideChromeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const hideChromeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
const [overlayInsets, setOverlayInsets] = useState({ top: 0, bottom: 0 });
|
const [overlayInsets, setOverlayInsets] = useState({ top: 0, bottom: 0 });
|
||||||
const [isImmersiveChromeVisible, setIsImmersiveChromeVisible] = useState(false);
|
const [isImmersiveChromeVisible, setIsImmersiveChromeVisible] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setScreenRef(screenRef);
|
setScreenRef(screenRef);
|
||||||
|
|
@ -102,7 +105,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
ref={screenRef}
|
ref={screenRef}
|
||||||
className={`relative w-full h-full flex flex-col ${
|
className={`relative w-full h-full flex flex-col ${
|
||||||
isImmersiveFocusedView && !immersiveChromeVisible ? "cursor-none" : ""
|
isImmersiveFocusedView && !immersiveChromeVisible ? "cursor-none" : ""
|
||||||
}`}
|
} ${callIsFullscreen ? "bg-background" : ""}`}
|
||||||
onMouseEnter={showImmersiveChrome}
|
onMouseEnter={showImmersiveChrome}
|
||||||
onMouseMove={showImmersiveChrome}
|
onMouseMove={showImmersiveChrome}
|
||||||
onMouseLeave={hideImmersiveChrome}
|
onMouseLeave={hideImmersiveChrome}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue