diff --git a/public/locales/zh/common.json b/public/locales/zh/common.json index 049d9c2f..84b5c9cc 100644 --- a/public/locales/zh/common.json +++ b/public/locales/zh/common.json @@ -28,6 +28,9 @@ "Submit": "提交", "Reply": "回复", "Cancel Reply": "取消回复", + "Edit": "编辑", + "Cancel Edit": "取消编辑", + "Confirm Modification": "确认修改", "ago": "{{time}}前", "joined ago": "{{time}}前加入", "obtained ago": "{{time}}前获得", diff --git a/src/components/common/CommentInput.tsx b/src/components/common/CommentInput.tsx index f3c32273..10d4fc04 100644 --- a/src/components/common/CommentInput.tsx +++ b/src/components/common/CommentInput.tsx @@ -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(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 (
@@ -104,12 +120,18 @@ export const CommentInput: React.FC<{ )} + {comment.characterId === account?.characterId && ( + + )}
{replyOpen && (
@@ -115,6 +130,16 @@ export const CommentItem: React.FC<{ />
)} + {editOpen && ( +
+ setEditOpen(false)} + comment={comment} + /> +
+ )} {(comment as any)?.fromNotes?.list?.length > 0 && ( diff --git a/src/models/page.model.ts b/src/models/page.model.ts index 867ff922..2271083b 100644 --- a/src/models/page.model.ts +++ b/src/models/page.model.ts @@ -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) diff --git a/src/queries/page.ts b/src/queries/page.ts index a364170d..3b820fc3 100644 --- a/src/queries/page.ts +++ b/src/queries/page.ts @@ -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[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],