feat: support editing comment content
This commit is contained in:
parent
8f4adbd2bc
commit
556c20ba68
|
|
@ -28,6 +28,9 @@
|
|||
"Submit": "提交",
|
||||
"Reply": "回复",
|
||||
"Cancel Reply": "取消回复",
|
||||
"Edit": "编辑",
|
||||
"Cancel Edit": "取消编辑",
|
||||
"Confirm Modification": "确认修改",
|
||||
"ago": "{{time}}前",
|
||||
"joined ago": "{{time}}前加入",
|
||||
"obtained ago": "{{time}}前获得",
|
||||
|
|
|
|||
|
|
@ -6,20 +6,25 @@ import { Button } from "~/components/ui/Button"
|
|||
import { useForm } from "react-hook-form"
|
||||
import { useAccountState } from "@crossbell/connect-kit"
|
||||
import { useState, useEffect } from "react"
|
||||
import { useCommentPage } from "~/queries/page"
|
||||
import { useCommentPage, useUpdateComment } from "~/queries/page"
|
||||
import { useRouter } from "next/router"
|
||||
import { EmojiPicker } from "./EmojiPicker"
|
||||
import { Popover } from "@headlessui/react"
|
||||
import { useTranslation } from "next-i18next"
|
||||
import { NoteEntity, CharacterEntity } from "crossbell.js"
|
||||
|
||||
export const CommentInput: React.FC<{
|
||||
pageId?: string
|
||||
originalId?: string
|
||||
onSubmitted?: () => void
|
||||
}> = ({ pageId, originalId, onSubmitted }) => {
|
||||
comment?: NoteEntity & {
|
||||
character?: CharacterEntity | null
|
||||
}
|
||||
}> = ({ pageId, originalId, onSubmitted, comment }) => {
|
||||
const account = useAccountState((s) => s.computed.account)
|
||||
const userSites = useAccountSites()
|
||||
const commentPage = useCommentPage()
|
||||
const updateComment = useUpdateComment()
|
||||
const router = useRouter()
|
||||
const [viewer, setViewer] = useState<Profile | null>(null)
|
||||
const { t } = useTranslation(["common", "site"])
|
||||
|
|
@ -32,27 +37,38 @@ export const CommentInput: React.FC<{
|
|||
|
||||
const form = useForm({
|
||||
defaultValues: {
|
||||
content: "",
|
||||
content: comment?.metadata?.content?.content || "",
|
||||
},
|
||||
})
|
||||
|
||||
const handleSubmit = form.handleSubmit(async (values) => {
|
||||
if (pageId) {
|
||||
commentPage.mutate({
|
||||
pageId: pageId,
|
||||
content: values.content,
|
||||
externalUrl: window.location.href,
|
||||
originalId: originalId,
|
||||
})
|
||||
if (pageId && values.content) {
|
||||
if (comment) {
|
||||
updateComment.mutate({
|
||||
pageId,
|
||||
content: values.content,
|
||||
externalUrl: window.location.href,
|
||||
originalId,
|
||||
characterId: comment.characterId,
|
||||
noteId: comment.noteId,
|
||||
})
|
||||
} else {
|
||||
commentPage.mutate({
|
||||
pageId,
|
||||
content: values.content,
|
||||
externalUrl: window.location.href,
|
||||
originalId,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (commentPage.isSuccess) {
|
||||
if (commentPage.isSuccess || updateComment.isSuccess) {
|
||||
form.reset()
|
||||
onSubmitted?.()
|
||||
}
|
||||
}, [commentPage.isSuccess, form, onSubmitted])
|
||||
}, [commentPage.isSuccess, updateComment.isSuccess, form, onSubmitted])
|
||||
|
||||
return (
|
||||
<div className="xlog-comment-input flex">
|
||||
|
|
@ -104,12 +120,18 @@ export const CommentInput: React.FC<{
|
|||
</Popover>
|
||||
<Button
|
||||
type="submit"
|
||||
isLoading={userSites.isLoading || commentPage.isLoading}
|
||||
isLoading={
|
||||
userSites.isLoading ||
|
||||
commentPage.isLoading ||
|
||||
updateComment.isLoading
|
||||
}
|
||||
>
|
||||
{t(
|
||||
account
|
||||
? userSites.isSuccess && !userSites.data?.length
|
||||
? "Create Character"
|
||||
: comment
|
||||
? "Confirm Modification"
|
||||
: "Submit"
|
||||
: "Connect",
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { CommentInput } from "~/components/common/CommentInput"
|
|||
import { CharacterFloatCard } from "~/components/common/CharacterFloatCard"
|
||||
import { useTranslation } from "next-i18next"
|
||||
import { useDate } from "~/hooks/useDate"
|
||||
import { useAccountState } from "@crossbell/connect-kit"
|
||||
|
||||
export const CommentItem: React.FC<{
|
||||
comment: NoteEntity & {
|
||||
|
|
@ -21,9 +22,13 @@ export const CommentItem: React.FC<{
|
|||
depth: number
|
||||
}> = ({ comment, originalId, depth }) => {
|
||||
const [replyOpen, setReplyOpen] = useState(false)
|
||||
const [editOpen, setEditOpen] = useState(false)
|
||||
|
||||
const { t } = useTranslation("common")
|
||||
const date = useDate()
|
||||
|
||||
const account = useAccountState(({ computed }) => computed.account)
|
||||
|
||||
if (!comment.metadata?.content?.content) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -95,7 +100,7 @@ export const CommentItem: React.FC<{
|
|||
/>
|
||||
{depth < 2 && (
|
||||
<Button
|
||||
className="text-gray-500 text-[13px] ml-2 mt-[-1px]"
|
||||
className="text-gray-500 text-[13px] ml-1 mt-[-1px]"
|
||||
variant="text"
|
||||
onClick={() => setReplyOpen(!replyOpen)}
|
||||
>
|
||||
|
|
@ -105,6 +110,16 @@ export const CommentItem: React.FC<{
|
|||
</span>
|
||||
</Button>
|
||||
)}
|
||||
{comment.characterId === account?.characterId && (
|
||||
<Button
|
||||
className="text-gray-500 text-[13px] mt-[-1px]"
|
||||
variant="text"
|
||||
onClick={() => setEditOpen(!editOpen)}
|
||||
>
|
||||
<i className="i-mingcute:edit-line mx-1" />{" "}
|
||||
{t(`${editOpen ? "Cancel " : ""}Edit`)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{replyOpen && (
|
||||
<div className="pt-6">
|
||||
|
|
@ -115,6 +130,16 @@ export const CommentItem: React.FC<{
|
|||
/>
|
||||
</div>
|
||||
)}
|
||||
{editOpen && (
|
||||
<div className="pt-6">
|
||||
<CommentInput
|
||||
originalId={originalId}
|
||||
pageId={`${comment.characterId}-${comment.noteId}`}
|
||||
onSubmitted={() => setEditOpen(false)}
|
||||
comment={comment}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{(comment as any)?.fromNotes?.list?.length > 0 && (
|
||||
|
|
|
|||
|
|
@ -567,6 +567,32 @@ export async function getComments({
|
|||
return res
|
||||
}
|
||||
|
||||
export async function updateComment(
|
||||
{
|
||||
pageId,
|
||||
content,
|
||||
externalUrl,
|
||||
originalId,
|
||||
characterId,
|
||||
noteId,
|
||||
}: {
|
||||
pageId: string
|
||||
content: string
|
||||
externalUrl: string
|
||||
originalId?: string
|
||||
characterId: number
|
||||
noteId: number
|
||||
},
|
||||
contract: Contract,
|
||||
) {
|
||||
return contract.setNoteMetadata(characterId, noteId, {
|
||||
content,
|
||||
external_urls: [externalUrl],
|
||||
tags: ["comment"],
|
||||
sources: ["xlog"],
|
||||
})
|
||||
}
|
||||
|
||||
export function parsePageId(pageId: string) {
|
||||
const [characterId, noteId] = pageId.split("-").map(Number)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from "@crossbell/connect-kit"
|
||||
import { useRefCallback } from "@crossbell/util-hooks"
|
||||
import { useContract } from "@crossbell/contract"
|
||||
import { NoteEntity } from "crossbell.js"
|
||||
|
||||
import * as pageModel from "~/models/page.model"
|
||||
|
||||
|
|
@ -233,6 +234,25 @@ export function useCommentPage() {
|
|||
}
|
||||
}
|
||||
|
||||
export function useUpdateComment() {
|
||||
const queryClient = useQueryClient()
|
||||
const contract = useContract()
|
||||
|
||||
return useMutation(
|
||||
async (payload: Parameters<typeof pageModel.updateComment>[0]) => {
|
||||
return pageModel.updateComment(payload, contract)
|
||||
},
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries([
|
||||
"getComments",
|
||||
variables.originalId || variables.pageId,
|
||||
])
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export function useGetComments(input: { pageId?: string }) {
|
||||
return useInfiniteQuery({
|
||||
queryKey: ["getComments", input.pageId],
|
||||
|
|
|
|||
Loading…
Reference in New Issue