import { SELECTED_SURFACE } from "~/ui/tones"; import { useState } from "react"; import { editDiscussionComment, markDiscussionAnswer, replyToDiscussion, toggleDiscussionVote, } from "~/fns/discussions"; import { useAction } from "~/hooks/use-action"; import type { getDiscussion } from "~/fns/discussions"; import { MarkdownEditor } from "./MarkdownEditor"; import { ReactionBar } from "./ReactionBar"; import { Avatar } from "~/ui/Avatar"; import { Badge } from "~/ui/Badge"; import { Markdown } from "~/ui/Markdown"; import { RelativeTime } from "~/ui/RelativeTime"; import { Button } from "~/ui/Button"; import { cn } from "~/utils/cn"; import { ReportLink } from "./ReportLink"; type Data = Awaited>; type Thread = Data["threads"][number]; type Comment = Thread["replies"][number]; type Context = { owner: string; repo: string; number: number; signedIn: boolean }; export function UpvoteButton({ context, subjectId, count, voted, }: { context: Context; subjectId: string; count: number; voted: boolean; }) { const vote = useAction(toggleDiscussionVote); return ( ); } function CommentBody({ context, comment, reply }: { context: Context; comment: Comment; reply: boolean }) { const [editing, setEditing] = useState(false); const [draft, setDraft] = useState(comment.body); const edit = useAction(editDiscussionComment); const ref = { owner: context.owner, repo: context.repo }; return (
{comment.author} {comment.edited && " · edited"} {comment.canEdit && !editing && (
)}
{editing ? (
) : ( )}
); } function ReplyBox({ context, parentId }: { context: Context; parentId: string | null }) { const [body, setBody] = useState(""); const [open, setOpen] = useState(parentId === null); const reply = useAction(replyToDiscussion); if (!open) return ( ); return (
{reply.error &&

{reply.error}

}
{parentId && ( )}
); } /** Threaded discussion comments with upvotes, replies and answer marking. */ export function DiscussionThreads({ data, context }: { data: Data; context: Context }) { const answer = useAction(markDiscussionAnswer); const { discussion } = data; const threads = [...data.threads].sort((left, right) => Number(right.isAnswer) - Number(left.isAnswer)); return (

{data.threads.length} comments

{answer.error &&

{answer.error}

} {threads.map((thread) => (
{thread.isAnswer && ✓ Marked as answer} {discussion.answerable && data.canAnswer && ( )}
{(thread.replies.length > 0 || data.canComment) && (
{thread.replies.map((reply) => (
))} {data.canComment && }
)}
))} {data.canComment ? ( ) : (

{context.signedIn ? "This discussion is locked." : "Sign in to join the discussion."}

)}
); }