feat: show nice video thumbnail in listview
This commit is contained in:
@@ -28,8 +28,38 @@ import { isParticleDeleted, type Particle, type StreamProperties } from "@/api/t
|
||||
import type { StreamParticle } from "@/hooks/use-stream-particles";
|
||||
import { useNetwork } from "@/hooks/use-networks";
|
||||
import { useStreamAutoplay } from "@/hooks/use-stream-autoplay";
|
||||
import { useDownloadUrl } from "@/hooks/use-download-url";
|
||||
import { StreamContextMenu } from "@/features/particles/stream-context-menu";
|
||||
|
||||
function VideoThumbnail({
|
||||
objectId,
|
||||
isUnseen,
|
||||
}: {
|
||||
objectId: string;
|
||||
isUnseen: boolean;
|
||||
}) {
|
||||
const { data: url } = useDownloadUrl(objectId);
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"size-8 shrink-0 overflow-hidden rounded-md bg-muted",
|
||||
isUnseen && "ring-2 ring-primary",
|
||||
)}
|
||||
>
|
||||
{url && (
|
||||
<video
|
||||
// Seek ~15 frames in so we skip any initial black/fade-in frames
|
||||
src={`${url}#t=0.5`}
|
||||
muted
|
||||
playsInline
|
||||
preload="metadata"
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getParticleTypeIcon(particle: Particle): LucideIcon {
|
||||
if (isParticleDeleted(particle)) return Trash2;
|
||||
switch (particle.type) {
|
||||
@@ -156,6 +186,14 @@ const StreamRow = memo(function StreamRow({
|
||||
|
||||
const TypeIcon = latestChild ? getParticleTypeIcon(latestChild) : Radio;
|
||||
|
||||
const videoThumbObjectId =
|
||||
latestChild &&
|
||||
!isParticleDeleted(latestChild) &&
|
||||
latestChild.type === "media" &&
|
||||
latestChild.properties.mime_type.startsWith("video/")
|
||||
? latestChild.properties.object_id
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div
|
||||
role="button"
|
||||
@@ -173,13 +211,15 @@ const StreamRow = memo(function StreamRow({
|
||||
{shortcutKey}
|
||||
</kbd>
|
||||
)}
|
||||
<Avatar
|
||||
className={cn(isUnseen && "ring-2 ring-primary")}
|
||||
>
|
||||
<AvatarFallback className="bg-primary/10 text-primary font-medium">
|
||||
{initials}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
{videoThumbObjectId ? (
|
||||
<VideoThumbnail objectId={videoThumbObjectId} isUnseen={!!isUnseen} />
|
||||
) : (
|
||||
<Avatar className={cn(isUnseen && "ring-2 ring-primary")}>
|
||||
<AvatarFallback className="bg-primary/10 text-primary font-medium">
|
||||
{initials}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
)}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p
|
||||
|
||||
Reference in New Issue
Block a user