Updated a lot of stuff, trying out radix ui

This commit is contained in:
Alois 2026-04-01 21:22:13 +02:00
commit 2862060439
24 changed files with 525 additions and 437 deletions

View file

@ -7,11 +7,12 @@ import { Skeleton } from "@tensamin/ui/cmp/skeleton";
import { useConversation } from "@/features/conversation/context";
import {
Select,
SelectTrigger,
SelectContent,
SelectItem,
SelectTrigger,
} from "@tensamin/ui/cmp/select";
import { displayCallId } from "@tensamin/call/utils";
import { useState } from "react";
export default function Navbar() {
const navigate = useNavigate();
@ -22,6 +23,9 @@ export default function Navbar() {
const { id } = useSearch({ strict: false });
const currentCalls = id ? conversations?.[id]?.calls || [] : [];
//const currentCalls = ["leck", "schleck", "und", "eck"];
const [selectOpen, setSelectOpen] = useState(false);
return (
<div className="w-full h-13.5 flex items-center justify-center">
@ -32,7 +36,7 @@ export default function Navbar() {
>
<House className="size-4.5" />
</Button>
{pathname === "/app/chat" && (
{pathname === "/chat" && (
<Wrapper
userId={id}
component={(user) => (
@ -42,9 +46,9 @@ export default function Navbar() {
/>
)}
<div className="w-full" />
{pathname === "/app/chat" && id && (
{pathname === "/chat" && id && (
<>
{currentCalls.length > 0 ? (
{currentCalls.length === 0 ? (
<Button
disabled={state !== "closed"}
onClick={() => {
@ -66,27 +70,30 @@ export default function Navbar() {
<Phone />
</Button>
) : (
<Select>
<SelectTrigger
render={
<Button className="w-9 h-9 aspect-square rounded-lg mr-2">
<Phone />
</Button>
}
/>
<SelectContent>
{currentCalls.map((callId) => (
<SelectItem
key={callId}
onSelect={() => {
joinCall(id, callId);
}}
>
{displayCallId(callId)}
</SelectItem>
))}
</SelectContent>
</Select>
<>
<Button
onClick={() => setSelectOpen((prev) => !prev)}
className="w-9! h-9! aspect-square rounded-lg mr-2"
>
<Phone />
</Button>
<Select onOpenChange={setSelectOpen} open={selectOpen}>
<SelectTrigger hidden />
<SelectContent>
{currentCalls.map((callId) => (
<SelectItem
value={callId}
key={callId}
onSelect={() => {
joinCall(id, callId);
}}
>
{displayCallId(callId)}
</SelectItem>
))}
</SelectContent>
</Select>
</>
)}
</>
)}

View file

@ -1,5 +1,11 @@
import * as React from "react";
import { useSocket } from "@tensamin/ttp/context";
import {
createContext,
useContext,
useEffect,
useState,
type ReactNode,
} from "react";
import { toast } from "@tensamin/shared/log";
import type {
@ -12,28 +18,22 @@ interface contextValue {
communities: Community[] | null;
}
const ConversationContext = React.createContext<contextValue | undefined>(
undefined,
);
const ConversationContext = createContext<contextValue | undefined>(undefined);
/**
* Executes ConversationProvider.
* @param props Parameter props.
* @returns unknown.
*/
export default function ConversationProvider(props: {
children: React.ReactNode;
}) {
const [conversations, setConversations] = React.useState<
Conversation[] | null
>(null);
const [communities, setCommunities] = React.useState<Community[] | null>(
export default function ConversationProvider(props: { children: ReactNode }) {
const [conversations, setConversations] = useState<Conversation[] | null>(
null,
);
const [communities, setCommunities] = useState<Community[] | null>(null);
const { send } = useSocket();
React.useEffect(() => {
useEffect(() => {
let active = true;
send("get_conversations", {})
@ -92,7 +92,7 @@ export default function ConversationProvider(props: {
* @returns contextValue.
*/
export function useConversation(): contextValue {
const context = React.useContext(ConversationContext);
const context = useContext(ConversationContext);
if (!context) {
throw new Error(
"useConversation must be used within a ConversationProvider",

View file

@ -38,21 +38,20 @@ export default function List() {
id="conversation-list"
className="overflow-y-auto flex-1 h-full"
>
{communities === null || conversations === null ? (
<div className="flex items-center justify-center pt-5">
<p className="text-foreground/45 flex gap-1 items-center justify-center">
<Loader2 size={18} className="animate-spin" />
Loading...
</p>
</div>
) : null}
<div
className="relative w-full flex flex-col"
style={{
height: `${virtualizer.getTotalSize()}px`,
}}
>
{communities === null || conversations === null ? (
<div className="flex items-center justify-center h-full pt-5">
<p className="text-foreground/45 flex gap-1 items-center justify-center">
<Loader2 size={18} className="animate-spin" />
Loading...
</p>
</div>
) : null}
{communities &&
conversations &&
virtualizer.getVirtualItems().map((virtualItem) => {

View file

@ -14,20 +14,18 @@ export default function ConversationModal({ userId }: { userId: number }) {
return (
<ContextMenu>
<ContextMenuTrigger
render={
<div
className="select-none cursor-pointer"
onClick={() => navigate({ to: "/chat", search: { id: userId } })}
>
<Wrapper
loading={<Loading />}
userId={userId}
component={(user) => <Basic user={user} />}
/>
</div>
}
></ContextMenuTrigger>
<ContextMenuTrigger asChild>
<div
className="select-none cursor-pointer"
onClick={() => navigate({ to: "/chat", search: { id: userId } })}
>
<Wrapper
loading={<Loading />}
userId={userId}
component={(user) => <Basic user={user} />}
/>
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuItem>Test</ContextMenuItem>

View file

@ -70,7 +70,9 @@ function AddConversationButton() {
return (
<Dialog>
<DialogTrigger render={<Button>Add Conversation</Button>} />
<DialogTrigger asChild>
<Button>Add Conversation</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>New Conversation</DialogTitle>
@ -96,7 +98,9 @@ function AddConversationButton() {
placeholder="Enter username..."
/>
<div className="flex w-full justify-end gap-1">
<DialogClose render={<Button variant="outline">Cancel</Button>} />
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button disabled={loading} type="submit">
{loading && <Loader2 className="animate-spin" />} Continue
</Button>