(feat): move call context to zustand
(feat): add actions, basic call page
This commit is contained in:
parent
d01df7c02c
commit
413764f33e
17 changed files with 673 additions and 382 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { Lock, LockOpen } from "lucide-react";
|
||||
import { useCall } from "../context";
|
||||
import { openCallPage, useCall } from "../store";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
|
|
@ -10,16 +10,16 @@ import {
|
|||
TooltipTrigger,
|
||||
useIsMobile,
|
||||
} from "@tensamin/ui";
|
||||
import { LeaveIcon } from "@livekit/components-react";
|
||||
import ScreenshareButton from "./buttons/screenshare";
|
||||
import MuteButton from "./buttons/mute";
|
||||
import DeafButton from "./buttons/deaf";
|
||||
import { Room, Track } from "livekit-client";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ResponsiveContainer, AreaChart, Area } from "recharts";
|
||||
import LeaveButton from "./buttons/leave";
|
||||
|
||||
export default function SidebarBox() {
|
||||
const { state, disconnect } = useCall();
|
||||
const state = useCall((store) => store.state);
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return state === "closed" ? null : (
|
||||
|
|
@ -32,14 +32,7 @@ export default function SidebarBox() {
|
|||
<MuteButton className="w-9 h-9" />
|
||||
<DeafButton className="w-9 h-9" />
|
||||
<ScreenshareButton className="w-9 h-9" />
|
||||
<Button
|
||||
size="lg"
|
||||
className="w-9 h-9"
|
||||
onClick={() => disconnect()}
|
||||
variant="destructive"
|
||||
>
|
||||
<LeaveIcon />
|
||||
</Button>
|
||||
<LeaveButton className="w-9 h-9" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -47,9 +40,9 @@ export default function SidebarBox() {
|
|||
}
|
||||
|
||||
function ConnectionBar() {
|
||||
const { state, room, openCallPage, callId } = useCall();
|
||||
const encrypted =
|
||||
room.localParticipant.isE2EEEnabled && room.localParticipant.isEncrypted;
|
||||
const state = useCall((store) => store.state);
|
||||
const isEncrypted = useCall((store) => store.isEncrypted);
|
||||
const callId = useCall((store) => store.callId);
|
||||
|
||||
return (
|
||||
<Tooltip>
|
||||
|
|
@ -59,7 +52,7 @@ function ConnectionBar() {
|
|||
onClick={() => openCallPage(callId || "")}
|
||||
size="lg"
|
||||
variant={
|
||||
state === "open" && encrypted ? "subtleDefault" : "destructive"
|
||||
state === "open" && isEncrypted ? "subtleDefault" : "destructive"
|
||||
}
|
||||
className="flex justify-between items-center"
|
||||
>
|
||||
|
|
@ -71,7 +64,7 @@ function ConnectionBar() {
|
|||
|
||||
<TinyPingGraph />
|
||||
|
||||
{encrypted ? (
|
||||
{isEncrypted ? (
|
||||
<Lock color="var(--primary-foreground-alt)" />
|
||||
) : (
|
||||
<LockOpen color="var(--destructive)" />
|
||||
|
|
@ -85,11 +78,9 @@ function ConnectionBar() {
|
|||
}
|
||||
|
||||
export function TinyPingGraph() {
|
||||
const { room } = useCall();
|
||||
const room = useCall((store) => store.room);
|
||||
|
||||
const [mapData, setMapData] = useState<Map<number, number>>(
|
||||
() => new Map([[Date.now(), 0]]),
|
||||
);
|
||||
const [mapData, setMapData] = useState<Map<number, number>>(() => new Map());
|
||||
|
||||
const data = Array.from(mapData, ([time, ping]) => ({ time, ping }));
|
||||
|
||||
|
|
@ -102,7 +93,9 @@ export function TinyPingGraph() {
|
|||
setMapData((prev) => {
|
||||
const next = new Map(prev);
|
||||
|
||||
next.set(now, ping || 0);
|
||||
if (ping != null && ping > 0) {
|
||||
next.set(now, ping);
|
||||
}
|
||||
|
||||
for (const time of next.keys()) {
|
||||
if (time < cutoff) next.delete(time);
|
||||
|
|
@ -128,48 +121,52 @@ export function TinyPingGraph() {
|
|||
"linear-gradient(to right, transparent 0%, var(--primary) 15%, var(--primary) 85%, transparent 100%)",
|
||||
}}
|
||||
>
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart
|
||||
data={data}
|
||||
margin={{ top: 2, right: 0, bottom: 2, left: 0 }}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="pingGradient" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0.35}
|
||||
/>
|
||||
<stop
|
||||
offset="70%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0.08}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
{data.length > 1 && (
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart
|
||||
data={data}
|
||||
margin={{ top: 2, right: 0, bottom: 2, left: 0 }}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="pingGradient" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0.35}
|
||||
/>
|
||||
<stop
|
||||
offset="70%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0.08}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor="currentColor"
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="ping"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
fill="url(#pingGradient)"
|
||||
fillOpacity={1}
|
||||
dot={false}
|
||||
activeDot={false}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="ping"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
fill="url(#pingGradient)"
|
||||
fillOpacity={1}
|
||||
dot={false}
|
||||
activeDot={false}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<TooltipContent>{data.at(-1)?.ping} ms</TooltipContent>
|
||||
<TooltipContent>
|
||||
{data.length > 0 ? `${data.at(-1)?.ping} ms` : "Measuring ping..."}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
@ -197,5 +194,11 @@ async function getPing(room: Room): Promise<number | undefined> {
|
|||
}
|
||||
});
|
||||
|
||||
return Math.round(bestRtt || 0);
|
||||
if (bestRtt == null || bestRtt <= 0) return;
|
||||
|
||||
const roundedRtt = Math.round(bestRtt);
|
||||
|
||||
if (roundedRtt <= 0) return;
|
||||
|
||||
return roundedRtt;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue