Merge pull request #348 from multica-ai/fix/unify-image-upload-flow

fix(editor): unify image upload flow for paste and button
This commit is contained in:
Naiyuan Qing 2026-04-02 18:05:11 +08:00 committed by GitHub
commit e6a1ff4354
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 88 additions and 109 deletions

View file

@ -228,14 +228,14 @@ function CommentRow({
defaultValue={entry.content ?? ""}
placeholder="Edit comment..."
onSubmit={saveEdit}
onUploadFile={(file) => uploadWithToast(file, { issueId })}
debounceMs={100}
/>
</div>
<div className="flex items-center justify-between mt-2">
<FileUploadButton
size="sm"
onUpload={(file) => uploadWithToast(file, { issueId })}
onInsert={(result, isImage) => editEditorRef.current?.insertFile(result.filename, result.link, isImage)}
onSelect={(file) => editEditorRef.current?.uploadFile(file)}
/>
<div className="flex items-center gap-2">
<Button size="sm" variant="ghost" onClick={cancelEdit}>Cancel</Button>
@ -441,8 +441,7 @@ function CommentCard({
<div className="flex items-center justify-between mt-2">
<FileUploadButton
size="sm"
onUpload={(file) => uploadWithToast(file, { issueId })}
onInsert={(result, isImage) => editEditorRef.current?.insertFile(result.filename, result.link, isImage)}
onSelect={(file) => editEditorRef.current?.uploadFile(file)}
/>
<div className="flex items-center gap-2">
<Button size="sm" variant="ghost" onClick={cancelEdit}>Cancel</Button>

View file

@ -14,15 +14,12 @@ interface CommentInputProps {
function CommentInput({ issueId, onSubmit }: CommentInputProps) {
const editorRef = useRef<RichTextEditorRef>(null);
const attachmentIdsRef = useRef<string[]>([]);
const [isEmpty, setIsEmpty] = useState(true);
const [submitting, setSubmitting] = useState(false);
const { uploadWithToast, uploading } = useFileUpload();
const { uploadWithToast } = useFileUpload();
const handleUpload = async (file: File) => {
const result = await uploadWithToast(file, { issueId });
if (result) attachmentIdsRef.current.push(result.id);
return result;
return await uploadWithToast(file, { issueId });
};
const handleSubmit = async () => {
@ -30,10 +27,8 @@ function CommentInput({ issueId, onSubmit }: CommentInputProps) {
if (!content || submitting) return;
setSubmitting(true);
try {
const ids = attachmentIdsRef.current.length > 0 ? [...attachmentIdsRef.current] : undefined;
await onSubmit(content, ids);
await onSubmit(content);
editorRef.current?.clearContent();
attachmentIdsRef.current = [];
setIsEmpty(true);
} finally {
setSubmitting(false);
@ -55,11 +50,7 @@ function CommentInput({ issueId, onSubmit }: CommentInputProps) {
<div className="absolute bottom-1 right-1.5 flex items-center gap-1">
<FileUploadButton
size="sm"
onUpload={handleUpload}
onInsert={(result, isImage) =>
editorRef.current?.insertFile(result.filename, result.link, isImage)
}
disabled={uploading}
onSelect={(file) => editorRef.current?.uploadFile(file)}
/>
<Button
size="icon-xs"

View file

@ -667,8 +667,7 @@ export function IssueDetail({ issueId, onDelete, defaultSidebarOpen = true, layo
)}
<FileUploadButton
size="sm"
onUpload={handleDescriptionUpload}
onInsert={(result, isImage) => descEditorRef.current?.insertFile(result.filename, result.link, isImage)}
onSelect={(file) => descEditorRef.current?.uploadFile(file)}
/>
</div>

View file

@ -35,11 +35,10 @@ function ReplyInput({
}: ReplyInputProps) {
const editorRef = useRef<RichTextEditorRef>(null);
const measureRef = useRef<HTMLDivElement>(null);
const attachmentIdsRef = useRef<string[]>([]);
const [isEmpty, setIsEmpty] = useState(true);
const [isExpanded, setIsExpanded] = useState(false);
const [submitting, setSubmitting] = useState(false);
const { uploadWithToast, uploading } = useFileUpload();
const { uploadWithToast } = useFileUpload();
useEffect(() => {
const el = measureRef.current;
@ -53,9 +52,7 @@ function ReplyInput({
}, []);
const handleUpload = async (file: File) => {
const result = await uploadWithToast(file, { issueId });
if (result) attachmentIdsRef.current.push(result.id);
return result;
return await uploadWithToast(file, { issueId });
};
const handleSubmit = async () => {
@ -63,10 +60,8 @@ function ReplyInput({
if (!content || submitting) return;
setSubmitting(true);
try {
const ids = attachmentIdsRef.current.length > 0 ? [...attachmentIdsRef.current] : undefined;
await onSubmit(content, ids);
await onSubmit(content);
editorRef.current?.clearContent();
attachmentIdsRef.current = [];
setIsEmpty(true);
} finally {
setSubmitting(false);
@ -105,11 +100,7 @@ function ReplyInput({
<div className="absolute bottom-0 right-0 flex items-center gap-1 text-muted-foreground transition-colors group-focus-within/editor:text-foreground">
<FileUploadButton
size="sm"
onUpload={handleUpload}
onInsert={(result, isImage) =>
editorRef.current?.insertFile(result.filename, result.link, isImage)
}
disabled={uploading}
onSelect={(file) => editorRef.current?.uploadFile(file)}
/>
<button
type="button"