forked from administration/panel
146 lines
4.4 KiB
TypeScript
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>
|
|
);
|
|
}
|