({type})
| 129 | } |
| 130 | |
| 131 | export default function AddModifyPost({type}) { |
| 132 | const mode = type === "new" ? "添加" : "编辑"; |
| 133 | const navigate = useNavigate(); |
| 134 | const submit = useSubmit(); |
| 135 | const loaderData = useLoaderData(); |
| 136 | const postObj = loaderData?.postObj; |
| 137 | const preparedPostContent = useMemo( |
| 138 | () => preparePostContentForEditing(postObj?.content ?? ""), |
| 139 | [postObj?.content] |
| 140 | ); |
| 141 | const [title, setTitle] = useState(postObj?.title ?? ""); |
| 142 | const [content, setContent] = useState(preparedPostContent.content); |
| 143 | const [attachments, setAttachments] = useState(preparedPostContent.attachments); |
| 144 | const [contentError, setContentError] = useState(""); |
| 145 | const [submitting, setSubmitting] = useState(false); |
| 146 | const attachmentsRef = useRef(attachments); |
| 147 | const theme = useTheme(); |
| 148 | const darkMode = theme.palette.mode === 'dark'; |
| 149 | const contentBytes = estimateFinalPostContentBytes(content, attachments); |
| 150 | const contentTooLarge = contentBytes > POST_CONTENT_MAX_BYTES; |
| 151 | const postContentMessage = contentTooLarge |
| 152 | ? `文章内容不能超过 ${formatPostContentSize(POST_CONTENT_MAX_BYTES)},当前 ${formatPostContentSize(contentBytes)}。` |
| 153 | : contentError; |
| 154 | useEffect(() => { |
| 155 | attachmentsRef.current = attachments; |
| 156 | }, [attachments]); |
| 157 | |
| 158 | const handleAttachmentPrepared = useCallback((file) => { |
| 159 | const attachment = createPostAttachmentFromFile(file); |
| 160 | const nextAttachments = new Map(attachmentsRef.current); |
| 161 | nextAttachments.set(attachment.token, attachment); |
| 162 | attachmentsRef.current = nextAttachments; |
| 163 | setAttachments(nextAttachments); |
| 164 | return attachment.token; |
| 165 | }, []); |
| 166 | const resolveAttachmentPreview = useCallback( |
| 167 | (src) => getPostAttachmentPreviewUrl(src, attachmentsRef.current), |
| 168 | [] |
| 169 | ); |
| 170 | |
| 171 | async function handleSubmit(event) { |
| 172 | event.preventDefault(); |
| 173 | if (contentTooLarge || submitting) { |
| 174 | return; |
| 175 | } |
| 176 | const form = event.currentTarget; |
| 177 | const submitter = event.nativeEvent.submitter; |
| 178 | setSubmitting(true); |
| 179 | try { |
| 180 | const finalizedContent = await finalizePostContentAttachments(content, attachmentsRef.current); |
| 181 | const finalizedContentBytes = getUtf8ByteLength(finalizedContent); |
| 182 | if (finalizedContentBytes > POST_CONTENT_MAX_BYTES) { |
| 183 | setContentError(`文章内容不能超过 ${formatPostContentSize(POST_CONTENT_MAX_BYTES)},当前 ${formatPostContentSize(finalizedContentBytes)}。`); |
| 184 | return; |
| 185 | } |
| 186 | const formData = new FormData(form); |
| 187 | if (submitter?.name) { |
| 188 | formData.set(submitter.name, submitter.value); |
nothing calls this directly
no test coverage detected