* refactor: update api and client to reference humanIds * fix: prevent deletion of network member This may cause various side effects if there is data in other services which reference this member
96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
import { useNavigate } from "react-router-dom";
|
|
import { X, Mic } from "lucide-react";
|
|
import { useAutoplayStore } from "@/stores/autoplay-store";
|
|
import { useDownloadUrl } from "@/hooks/use-download-url";
|
|
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
|
import { Small } from "@/components/ui/typography";
|
|
import { getInitials } from "@/lib/utils";
|
|
import { useNetwork } from "@/hooks/use-networks";
|
|
|
|
interface AutoplayOverlayProps {
|
|
networkId: string;
|
|
}
|
|
|
|
export function AutoplayOverlay({ networkId }: AutoplayOverlayProps) {
|
|
const activeParticle = useAutoplayStore((s) => s.activeParticle);
|
|
const streamId = useAutoplayStore((s) => s.streamId);
|
|
const stop = useAutoplayStore((s) => s.stop);
|
|
const { data: url } = useDownloadUrl(activeParticle?.properties.object_id);
|
|
const navigate = useNavigate();
|
|
|
|
const network = useNetwork(networkId);
|
|
|
|
if (!activeParticle || !url) return null;
|
|
|
|
const isVideo = activeParticle.properties.mime_type?.startsWith("video/");
|
|
const creator = network?.humans?.find((h) => h.id === activeParticle.created_by_human_id);
|
|
const senderInitials = creator ? getInitials(creator.email) : activeParticle.created_by_human_id.slice(0, 2).toUpperCase();
|
|
const senderName = creator?.email_prefix ?? activeParticle.created_by_human_id;
|
|
|
|
const handleClick = () => {
|
|
stop();
|
|
if (streamId) {
|
|
navigate(`/${networkId}/${streamId}`);
|
|
}
|
|
};
|
|
|
|
const closeButton = (
|
|
<button
|
|
className="absolute top-1 right-1 z-10 rounded-full bg-black/50 p-0.5 text-white hover:bg-black/70"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
stop();
|
|
}}
|
|
>
|
|
<X className="size-3.5" />
|
|
</button>
|
|
);
|
|
|
|
const senderBar = (
|
|
<div className="flex items-center gap-2 px-3 py-2">
|
|
<Avatar size="sm">
|
|
<AvatarFallback className="bg-primary/10 text-primary text-[10px] font-medium">
|
|
{senderInitials}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<Small className="truncate text-muted-foreground">{senderName}</Small>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div
|
|
className="absolute bottom-4 right-4 z-40 w-52 cursor-pointer overflow-hidden rounded-xl bg-card text-card-foreground shadow-lg ring-1 ring-foreground/10"
|
|
onClick={handleClick}
|
|
>
|
|
{isVideo ? (
|
|
<div className="relative">
|
|
{closeButton}
|
|
<video
|
|
src={url}
|
|
autoPlay
|
|
playsInline
|
|
onEnded={stop}
|
|
className="w-full object-cover"
|
|
/>
|
|
{senderBar}
|
|
</div>
|
|
) : (
|
|
<div className="relative">
|
|
{closeButton}
|
|
<div className="flex items-center gap-2 px-3 py-3">
|
|
<Avatar size="sm">
|
|
<AvatarFallback className="bg-primary/10 text-primary text-[10px] font-medium">
|
|
{senderInitials}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<div className="min-w-0 flex-1">
|
|
<Small className="truncate font-medium">{senderName}</Small>
|
|
</div>
|
|
</div>
|
|
<audio src={url} autoPlay onEnded={stop} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|