1
0
Fork 0
panel/components/cards/MessageContextCard.tsx

146 lines
4.4 KiB
TypeScript

import { Message, SnapshotContent, User } from "revolt-api";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "../ui/card";
import { fetchUsersById } from "@/lib/db";
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Image as ImageIcon } from "lucide-react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "../ui/alert-dialog";
function Message({
message,
users,
}: {
message: Message;
users?: Record<string, User>;
}) {
const user = users?.[message.author];
return (
<AlertDialog>
<AlertDialogTrigger className="w-full">
<div className="flex gap-2">
<div className="flex-1 min-w-0 overflow-ellipsis overflow-hidden text-right">
{user?.avatar && (
<Avatar className="w-4 h-4 inline-block align-middle mr-1">
<AvatarImage
src={`https://autumn.revolt.chat/avatars/${user.avatar._id}`}
/>
</Avatar>
)}
{user?.username}
</div>
<div className="flex-[2] min-w-0 overflow-ellipsis overflow-hidden text-left">
{(message.attachments || message.embeds) && (
<ImageIcon size={16} className="inline align-middle" />
)}{" "}
{message.content ?? <span className="text-gray-500">No text.</span>}
</div>
</div>
</AlertDialogTrigger>
<AlertDialogContent className="max-h-[100vh] overflow-y-auto">
<AlertDialogHeader className="min-w-0">
<AlertDialogTitle>
{user?.avatar && (
<Avatar className="inline-block align-middle mr-1">
<AvatarImage
src={`https://autumn.revolt.chat/avatars/${user.avatar._id}`}
/>
</Avatar>
)}
{user?.username}
</AlertDialogTitle>
<AlertDialogDescription className="flex flex-col gap-2 max-w-full">
{message.content && <span>{message.content}</span>}
{message.attachments?.map((attachment) =>
attachment.metadata.type === "Image" ? (
<a
target="_blank"
className="w-fit"
key={attachment._id}
href={`https://autumn.revolt.chat/attachments/${attachment._id}`}
>
<img
className="max-h-[240px] object-contain"
src={`https://autumn.revolt.chat/attachments/${attachment._id}`}
/>
</a>
) : (
"unsupported"
)
)}
{message.embeds?.map((embed, index) => (
<pre key={index} className="overflow-auto max-w-full">
<code>{JSON.stringify(embed, null, 2)}</code>
</pre>
))}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Delete</AlertDialogCancel>
<AlertDialogAction>Close</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
export async function MessageContextCard({
snapshot,
}: {
snapshot: SnapshotContent & { _type: "Message" };
}) {
const userIds = [
...new Set(
[
...(snapshot._leading_context ?? []),
...(snapshot._prior_context ?? []),
snapshot,
].map((x) => x.author)
),
];
const users = await fetchUsersById(userIds).then((users) =>
users.reduce((prev, next) => {
prev[next._id] = next;
return prev;
}, {} as Record<string, any>)
);
return (
<Card>
<CardHeader>
<CardTitle>Message(s)</CardTitle>
<CardDescription>Reported Content</CardDescription>
</CardHeader>
<CardContent>
<div className="opacity-40">
{[...(snapshot._prior_context ?? [])].reverse()?.map((message) => (
<Message key={message._id} message={message} users={users} />
))}
</div>
<Message message={snapshot} users={users} />
<div className="opacity-40">
{snapshot._leading_context?.map((message) => (
<Message key={message._id} message={message} users={users} />
))}
</div>
</CardContent>
</Card>
);
}