(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,
|
||||
Maximize,
|
||||
Minimize,
|
||||
ScreenShareOff,
|
||||
SquareArrowOutDownLeft,
|
||||
SquareArrowOutUpRight,
|
||||
} from "lucide-react";
|
||||
|
|
@ -96,68 +97,56 @@ export default function Actions() {
|
|||
</div>
|
||||
<Card className="p-1.75">
|
||||
<CardContent className="p-0! flex gap-1.75">
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<MuteButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||
Mute
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<DeafButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<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>
|
||||
<MuteButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
tooltip="Mute"
|
||||
portalContainer={portalContainer}
|
||||
/>
|
||||
<DeafButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
tooltip="Deafen"
|
||||
portalContainer={portalContainer}
|
||||
/>
|
||||
<ScreenshareButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
tooltip="Screenshare"
|
||||
/>
|
||||
<InviteButton
|
||||
className={sharedClasses}
|
||||
iconSize={sharedIconSize}
|
||||
tooltip="Invite"
|
||||
/>
|
||||
{isWatchingFocusedStream ? (
|
||||
<Button
|
||||
className="h-10"
|
||||
variant="destructive"
|
||||
onClick={() => stopWatchingFocusedStream()}
|
||||
>
|
||||
Stop watching
|
||||
</Button>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<Button
|
||||
className={sharedClasses}
|
||||
variant="destructive"
|
||||
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>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
import { Button } from "@tensamin/ui";
|
||||
import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
|
||||
import { toggleDeaf, useCall } from "../../store";
|
||||
import { HeadphoneOff, Headphones } from "lucide-react";
|
||||
|
||||
export default function DeafButton({
|
||||
className,
|
||||
iconSize,
|
||||
tooltip,
|
||||
portalContainer,
|
||||
}: {
|
||||
className?: string;
|
||||
iconSize?: number;
|
||||
tooltip?: string;
|
||||
portalContainer?: HTMLElement;
|
||||
}) {
|
||||
const deaf = useCall((state) => state.deaf);
|
||||
|
||||
return (
|
||||
const button = (
|
||||
<Button
|
||||
variant={deaf ? "destructive" : "default"}
|
||||
onClick={toggleDeaf}
|
||||
|
|
@ -28,4 +32,17 @@ export default function DeafButton({
|
|||
)}
|
||||
</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 { 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 { Mail } from "lucide-react";
|
||||
import { sendCallInvite, useCall } from "../../store";
|
||||
|
|
@ -9,9 +17,11 @@ import { useSession } from "@tensamin/storage/session";
|
|||
export default function InviteButton({
|
||||
className,
|
||||
iconSize,
|
||||
tooltip,
|
||||
}: {
|
||||
className?: string;
|
||||
iconSize?: number;
|
||||
tooltip?: string;
|
||||
}) {
|
||||
const { contacts } = useSession();
|
||||
const screenRef = useCall((state) => state.screenRef);
|
||||
|
|
@ -22,43 +32,64 @@ export default function InviteButton({
|
|||
}, [screenRef]);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
<Button className={className}>
|
||||
<Mail style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }} />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<PopoverContent
|
||||
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}
|
||||
<Tooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
tooltip ? (
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<Button className={className}>
|
||||
<Mail
|
||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||
/>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Button className={className}>
|
||||
<Mail
|
||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
/>
|
||||
<PopoverContent
|
||||
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 { Button } from "@tensamin/ui";
|
||||
import { Button, Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui";
|
||||
import { disconnect, useCall } from "../../store";
|
||||
|
||||
export default function LeaveButton({
|
||||
className,
|
||||
iconSize,
|
||||
tooltip,
|
||||
portalContainer,
|
||||
}: {
|
||||
className?: string;
|
||||
iconSize?: number;
|
||||
tooltip?: string;
|
||||
portalContainer?: HTMLElement;
|
||||
}) {
|
||||
const state = useCall((store) => store.state);
|
||||
|
||||
return (
|
||||
const button = (
|
||||
<Button
|
||||
className={className}
|
||||
onClick={() => disconnect()}
|
||||
|
|
@ -21,4 +25,17 @@ export default function LeaveButton({
|
|||
<LeaveIcon style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }} />
|
||||
</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 { Mic, MicOff } from "lucide-react";
|
||||
|
||||
export default function MuteButton({
|
||||
className,
|
||||
iconSize,
|
||||
tooltip,
|
||||
portalContainer,
|
||||
}: {
|
||||
className?: string;
|
||||
iconSize?: number;
|
||||
tooltip?: string;
|
||||
portalContainer?: HTMLElement;
|
||||
}) {
|
||||
const micEnabled = useCall((state) => state.micEnabled);
|
||||
|
||||
return (
|
||||
const button = (
|
||||
<Button
|
||||
variant={micEnabled ? "default" : "destructive"}
|
||||
className={className}
|
||||
|
|
@ -24,4 +28,17 @@ export default function MuteButton({
|
|||
)}
|
||||
</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 { 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 { toast } from "@tensamin/shared/log";
|
||||
import { isTauri } from "@tauri-apps/api/core";
|
||||
|
|
@ -9,9 +17,11 @@ import ScreenShareDialog from "../screenshareDialog";
|
|||
export default function ScreenshareButton({
|
||||
className,
|
||||
iconSize,
|
||||
tooltip,
|
||||
}: {
|
||||
className?: string;
|
||||
iconSize?: number;
|
||||
tooltip?: string;
|
||||
}) {
|
||||
const isScreensharing = useCall((state) => state.screenShareEnabled);
|
||||
const screenRef = useCall((state) => state.screenRef);
|
||||
|
|
@ -53,57 +63,89 @@ export default function ScreenshareButton({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Popover onOpenChange={setMenuOpen} open={menuOpen}>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
<Button
|
||||
variant={isScreensharing ? "subtleDefault" : "default"}
|
||||
className={className}
|
||||
>
|
||||
{isScreensharing ? (
|
||||
<MonitorDot
|
||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||
<Tooltip>
|
||||
<Popover onOpenChange={setMenuOpen} open={menuOpen}>
|
||||
<PopoverTrigger
|
||||
render={
|
||||
tooltip ? (
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<Button
|
||||
variant={isScreensharing ? "subtleDefault" : "default"}
|
||||
className={className}
|
||||
>
|
||||
{isScreensharing ? (
|
||||
<MonitorDot
|
||||
style={{
|
||||
scale: (iconSize ? iconSize + 100 : 100) + "%",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ScreenShare
|
||||
style={{
|
||||
scale: (iconSize ? iconSize + 100 : 100) + "%",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<ScreenShare
|
||||
style={{ scale: (iconSize ? iconSize + 100 : 100) + "%" }}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
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>
|
||||
}
|
||||
/>
|
||||
<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
|
||||
variant="destructive"
|
||||
disabled={!isScreensharing}
|
||||
onClick={() => {
|
||||
setMenuOpen(false);
|
||||
void stopShare();
|
||||
}}
|
||||
>
|
||||
Stop screenshare
|
||||
</Button>
|
||||
<Button variant="outline">Change quality</Button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<Button
|
||||
variant="destructive"
|
||||
disabled={!isScreensharing}
|
||||
onClick={() => {
|
||||
setMenuOpen(false);
|
||||
void stopShare();
|
||||
}}
|
||||
>
|
||||
Stop screenshare
|
||||
</Button>
|
||||
<Button variant="outline">Change quality</Button>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{tooltip && (
|
||||
<TooltipContent portalProps={{ container: portalContainer }}>
|
||||
{tooltip}
|
||||
</TooltipContent>
|
||||
)}
|
||||
</Tooltip>
|
||||
|
||||
{isTauri() && (
|
||||
<ScreenShareDialog
|
||||
|
|
|
|||
|
|
@ -45,11 +45,7 @@ export default function SidebarBox() {
|
|||
);
|
||||
}
|
||||
|
||||
function ConnectionBar({
|
||||
portalContainer,
|
||||
}: {
|
||||
portalContainer?: HTMLElement;
|
||||
}) {
|
||||
function ConnectionBar({ portalContainer }: { portalContainer?: HTMLElement }) {
|
||||
const state = useCall((store) => store.state);
|
||||
const isEncrypted = useCall((store) => store.isEncrypted);
|
||||
const callId = useCall((store) => store.callId);
|
||||
|
|
|
|||
Loading…
Reference in a new issue