From 92c39d38b1b853bce1d060477ca29b57ea8fee56 Mon Sep 17 00:00:00 2001 From: Alois Date: Tue, 28 Apr 2026 15:04:49 +0200 Subject: [PATCH] Updated sidebar & ui --- bun.lock | 4 +- package.json | 2 +- packages/call/src/components/sidebarBox.tsx | 93 ++++++++++++++++- packages/call/src/context.tsx | 110 ++++++++------------ 4 files changed, 140 insertions(+), 69 deletions(-) diff --git a/bun.lock b/bun.lock index 28857ea..e634e7c 100644 --- a/bun.lock +++ b/bun.lock @@ -242,7 +242,7 @@ }, "overrides": { "@tensamin/ttp-core": "https://git.methanium.net/tensamin/ttp/archive/0.0.12.tar.gz", - "@tensamin/ui": "https://git.methanium.net/tensamin/ui/archive/0.0.26.tar.gz", + "@tensamin/ui": "https://git.methanium.net/tensamin/ui/archive/0.0.29.tar.gz", }, "packages": { "@antfu/ni": ["@antfu/ni@25.0.0", "", { "dependencies": { "ansis": "^4.0.0", "fzf": "^0.5.2", "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" }, "bin": { "na": "bin/na.mjs", "ni": "bin/ni.mjs", "nr": "bin/nr.mjs", "nci": "bin/nci.mjs", "nlx": "bin/nlx.mjs", "nun": "bin/nun.mjs", "nup": "bin/nup.mjs" } }, "sha512-9q/yCljni37pkMr4sPrI3G4jqdIk074+iukc5aFJl7kmDCCsiJrbZ6zKxnES1Gwg+i9RcDZwvktl23puGslmvA=="], @@ -695,7 +695,7 @@ "@tensamin/ttp-core": ["@tensamin/ttp-core@https://git.methanium.net/tensamin/ttp/archive/0.0.12.tar.gz", { "dependencies": { "@eslint/js": "^10.0.1", "@typescript-eslint/parser": "^8.58.1", "@webtransport-bun/webtransport": "^0.3.0", "globals": "^17.5.0", "typescript": "^6.0.2", "typescript-eslint": "^8.58.1", "zod": "^4.3.6" } }, "sha512-YdwOocPnNMoE0N/yqksJM9JizkhmNv7q8sc7JMI/TOKM/0wDlQqHLqJBMd7fAGkGLCSx+DKx5z8SJbrA9YlzVg=="], - "@tensamin/ui": ["@tensamin/ui@https://git.methanium.net/tensamin/ui/archive/0.0.26.tar.gz", { "dependencies": { "@base-ui/react": "^1.3.0", "@fontsource-variable/inter": "^5.2.6", "@tauri-apps/api": "^2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "lucide-react": "^1.8.0", "next-themes": "^0.4.6", "react-day-picker": "^9.14.0", "react-resizable-panels": "^4.10.0", "recharts": "3.8.0", "shadcn": "^3.5.0", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "tw-animate-css": "^1.3.0", "vaul": "^1.1.2" }, "peerDependencies": { "react": "^19.2.0", "react-dom": "^19.2.0" } }, "sha512-SH+voNvmg2TtTjZH561NZC4ekY0ypFQpPvC0u0s5Jt1nGG243TR3ybX3T3WI83Z59ayC+t7YPZOmQPHTHI9+Mw=="], + "@tensamin/ui": ["@tensamin/ui@https://git.methanium.net/tensamin/ui/archive/0.0.29.tar.gz", { "dependencies": { "@base-ui/react": "^1.3.0", "@fontsource-variable/inter": "^5.2.6", "@tauri-apps/api": "^2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "lucide-react": "^1.8.0", "next-themes": "^0.4.6", "react-day-picker": "^9.14.0", "react-resizable-panels": "^4.10.0", "recharts": "3.8.0", "shadcn": "^3.5.0", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "tw-animate-css": "^1.3.0", "vaul": "^1.1.2" }, "peerDependencies": { "react": "^19.2.0", "react-dom": "^19.2.0" } }, "sha512-z83adnQtOLCr8ceVaUXZ7F7Hn/TrqsyqJM8hivhQxOX4OUNFaCBrbmfDpIK6OmtjRF/AnjqBNRua8FXAhJN35A=="], "@tensamin/user": ["@tensamin/user@workspace:packages/user"], diff --git a/package.json b/package.json index afcc5ae..045b428 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "jsonc-parser": "^3.3.1" }, "overrides": { - "@tensamin/ui": "https://git.methanium.net/tensamin/ui/archive/0.0.26.tar.gz", + "@tensamin/ui": "https://git.methanium.net/tensamin/ui/archive/0.0.29.tar.gz", "@tensamin/ttp-core": "https://git.methanium.net/tensamin/ttp/archive/0.0.12.tar.gz" }, "dependencies": { diff --git a/packages/call/src/components/sidebarBox.tsx b/packages/call/src/components/sidebarBox.tsx index 9e3d9fd..fd14c09 100644 --- a/packages/call/src/components/sidebarBox.tsx +++ b/packages/call/src/components/sidebarBox.tsx @@ -1,7 +1,96 @@ +import { Lock, LockOpen } from "lucide-react"; import { useCall } from "../context"; +import { + Button, + Card, + CardContent, + CardHeader, + Popover, + PopoverContent, + PopoverTrigger, + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@tensamin/ui"; +import { LeaveIcon } from "@livekit/components-react"; export default function SidebarBox() { - const { state } = useCall(); + const { state, room, disconnect } = useCall(); - return state === "closed" ? null :
Sidebar {state}
; + return state === "closed" ? null : ( + + + + + + + + + ); +} + +function ConnectionBar({ + state, + encrypted, +}: { + state: "closed" | "closing" | "connecting" | "open" | "encrypting"; + encrypted: boolean; +}) { + return ( + + + {state === "connecting" && "Connecting..."} + {state === "open" && "Connected"} + {state === "closed" && "Closed"} + {state === "closing" && "Closing"} + + + + ) : ( + + ) + } + /> + + {encrypted ? "Encrypted" : "Unencrypted"} + + + + } + /> + Test stuff + + ); } diff --git a/packages/call/src/context.tsx b/packages/call/src/context.tsx index c486608..85c68e7 100644 --- a/packages/call/src/context.tsx +++ b/packages/call/src/context.tsx @@ -7,7 +7,7 @@ import { ttp } from "@tensamin/shared/data"; import { LiveKitRoom, useLocalParticipant } from "@livekit/components-react"; import { DeepFilterNoiseFilterProcessor } from "deepfilternet3-noise-filter"; -import { LocalAudioTrack } from "livekit-client"; +import { ExternalE2EEKeyProvider, LocalAudioTrack, Room } from "livekit-client"; import { useCrypto } from "@tensamin/crypto/context"; import { useStorage } from "@tensamin/storage/context"; import { useUser } from "@tensamin/user/context"; @@ -17,12 +17,12 @@ export const context = createContext(undefined); export default function Provider(props: { children: React.ReactNode }) { const navigate = useNavigate(); const { send } = useTTP(); - const { encrypt, decrypt, getSharedSecret, decryptText } = useCrypto(); + const { getSharedSecret, decryptText } = useCrypto(); const { load } = useStorage(); const { get } = useUser(); const [state, setState] = useState< - "closed" | "closing" | "connecting" | "open" + "closed" | "closing" | "connecting" | "open" | "encrypting" >("closed"); const [callId, setCallId] = useState(null); @@ -53,6 +53,8 @@ export default function Provider(props: { children: React.ReactNode }) { setCallId(null); setCallSecret(null); setLivekitToken(null); + room.disconnect(); + e2eeWorker.terminate(); } // Utils @@ -124,12 +126,37 @@ export default function Provider(props: { children: React.ReactNode }) { }); }, [callId, send, view]); + // Room & Encryption + const [keyProvider] = useState(() => new ExternalE2EEKeyProvider()); + const [e2eeWorker] = useState( + () => new Worker(new URL("livekit-client/e2ee-worker", import.meta.url)), + ); + const [room] = useState( + () => + new Room({ + encryption: { + keyProvider, + worker: e2eeWorker, + }, + loggerName: "call", + }), + ); + + useEffect(() => { + async function enableStuff() { + await keyProvider.setKey(callSecret || ""); + await room.setE2EEEnabled(true); + } + enableStuff(); + }, [callSecret, keyProvider, room]); + return ( { - void room; - }, - setupEngine: async (engine) => { - void engine; - }, - setParticipantCryptorEnabled: async ( - enabled: boolean, - participantIdentity: string, - ) => { - console.log( - `Set participant ${participantIdentity} cryptor enabled: ${enabled}`, - ); - }, - setSifTrailer: async (trailer: Uint8Array) => { - void trailer; - }, - - // Encryption - encryptData: async (data: Uint8Array) => { - const encrypted = await encrypt(callSecret || "", data); - return { - uuid: "", - payload: encrypted, - iv: new Uint8Array(), - keyIndex: 0, - }; - }, - handleEncryptedData: async ( - payload: Uint8Array, - iv: Uint8Array, - participantIdentity: string, - keyIndex: number, - ) => { - void iv; - void participantIdentity; - void keyIndex; - - const decrypted = await decrypt(callSecret || "", payload); - - return { - uuid: "", - payload: decrypted, - }; - }, - }, - }, - loggerName: "call", + room={room} + onConnected={() => { + setState("open"); + log(2, "call", "purple", "Connected to call", { + callId, + callSecret, + }); + }} + onDisconnected={() => { + setState("closed"); + log(2, "call", "purple", "Disconnected from call", { + callId, + callSecret, + }); }} - onConnected={() => setState("open")} - onDisconnected={() => setState("closed")} onError={(error) => { log(1, "call", "red", error.message); toast("error", error.message); @@ -255,13 +236,14 @@ function NoiseFilter() { } type contextType = { - state: "closed" | "closing" | "connecting" | "open"; + state: "closed" | "closing" | "connecting" | "open" | "encrypting"; view: "preview" | "focused" | "grid"; setView: (view: "preview" | "focused" | "grid") => void; connect: (callId: string, callSecret: string) => void; disconnect: () => void; joinCall: (userId: number, callSecret?: string, callId?: string) => void; currentCallData: z.infer | null; + room: Room; }; export function useCall(): contextType {