fix(core): should not be able to commit comments when uploading images (#13108)
#### PR Dependency Tree * **PR #13108** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * The commit button in the comment editor is now properly disabled while attachments are uploading or when the editor is empty without attachments, preventing accidental or premature submissions. * **New Features** * Attachment delete button now shows a loading state during uploads for clearer user feedback. * **Style** * Updated comment editor attachment button styles for a cleaner and more consistent appearance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -47,3 +47,7 @@ export const NullCommentInlineSpecExtension =
|
|||||||
match: () => false,
|
match: () => false,
|
||||||
renderer: () => html``,
|
renderer: () => html``,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// reuse the same identifier
|
||||||
|
NullCommentInlineSpecExtension.identifier =
|
||||||
|
CommentInlineSpecExtension.identifier;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IconButton, Loading } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import { LitDocEditor, type PageEditor } from '@affine/core/blocksuite/editors';
|
import { LitDocEditor, type PageEditor } from '@affine/core/blocksuite/editors';
|
||||||
import { SnapshotHelper } from '@affine/core/modules/comment/services/snapshot-helper';
|
import { SnapshotHelper } from '@affine/core/modules/comment/services/snapshot-helper';
|
||||||
import type { CommentAttachment } from '@affine/core/modules/comment/types';
|
import type { CommentAttachment } from '@affine/core/modules/comment/types';
|
||||||
@@ -144,6 +144,11 @@ export const CommentEditor = forwardRef<CommentEditorRef, CommentEditorProps>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isImageUploadDisabled = (attachments?.length ?? 0) >= MAX_IMAGE_COUNT;
|
const isImageUploadDisabled = (attachments?.length ?? 0) >= MAX_IMAGE_COUNT;
|
||||||
|
const uploadingAttachments = attachments?.some(
|
||||||
|
att => att.status === 'uploading'
|
||||||
|
);
|
||||||
|
const commitDisabled =
|
||||||
|
(empty && (attachments?.length ?? 0) === 0) || uploadingAttachments;
|
||||||
|
|
||||||
const addImages = useAsyncCallback(
|
const addImages = useAsyncCallback(
|
||||||
async (files: File[]) => {
|
async (files: File[]) => {
|
||||||
@@ -296,13 +301,13 @@ export const CommentEditor = forwardRef<CommentEditorRef, CommentEditorProps>(
|
|||||||
|
|
||||||
// upload attachments and call original onCommit
|
// upload attachments and call original onCommit
|
||||||
const handleCommit = useAsyncCallback(async () => {
|
const handleCommit = useAsyncCallback(async () => {
|
||||||
if (readonly) return;
|
if (readonly || commitDisabled) return;
|
||||||
onCommit?.();
|
onCommit?.();
|
||||||
setAttachments(prev => {
|
setAttachments(prev => {
|
||||||
prev.forEach(att => att.localUrl && URL.revokeObjectURL(att.localUrl));
|
prev.forEach(att => att.localUrl && URL.revokeObjectURL(att.localUrl));
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
}, [readonly, onCommit, setAttachments]);
|
}, [readonly, commitDisabled, onCommit, setAttachments]);
|
||||||
|
|
||||||
const focusEditor = useAsyncCallback(async () => {
|
const focusEditor = useAsyncCallback(async () => {
|
||||||
if (editorRef.current) {
|
if (editorRef.current) {
|
||||||
@@ -447,20 +452,17 @@ export const CommentEditor = forwardRef<CommentEditorRef, CommentEditorProps>(
|
|||||||
onClick={e => handleImageClick(e, index)}
|
onClick={e => handleImageClick(e, index)}
|
||||||
>
|
>
|
||||||
{!readonly && (
|
{!readonly && (
|
||||||
<div
|
<IconButton
|
||||||
className={styles.deleteBtn}
|
size={12}
|
||||||
|
className={styles.attachmentButton}
|
||||||
|
loading={att.status === 'uploading'}
|
||||||
|
variant="danger"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleImageRemove(att.id);
|
handleImageRemove(att.id);
|
||||||
}}
|
}}
|
||||||
>
|
icon={<CloseIcon />}
|
||||||
<CloseIcon width={12} height={12} />
|
/>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{att.status === 'uploading' && (
|
|
||||||
<div className={styles.spinnerWrapper}>
|
|
||||||
<Loading size={16} />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -480,7 +482,7 @@ export const CommentEditor = forwardRef<CommentEditorRef, CommentEditorProps>(
|
|||||||
<button
|
<button
|
||||||
onClick={handleCommit}
|
onClick={handleCommit}
|
||||||
className={styles.commitButton}
|
className={styles.commitButton}
|
||||||
disabled={empty && (attachments?.length ?? 0) === 0}
|
disabled={commitDisabled}
|
||||||
>
|
>
|
||||||
<ArrowUpBigIcon />
|
<ArrowUpBigIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -91,36 +91,18 @@ export const previewBox = style({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteBtn = style({
|
export const attachmentButton = style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: -6,
|
top: -6,
|
||||||
right: -6,
|
right: -6,
|
||||||
width: 16,
|
background: cssVarV2('layer/background/primary'),
|
||||||
height: 16,
|
border: '1px solid',
|
||||||
borderRadius: 4,
|
borderColor: cssVarV2('layer/insideBorder/border'),
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
border: `0.5px solid ${cssVarV2('layer/insideBorder/border')}`,
|
|
||||||
backgroundColor: cssVarV2('layer/background/primary'),
|
|
||||||
cursor: 'pointer',
|
|
||||||
selectors: {
|
selectors: {
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: cssVarV2('layer/background/error'),
|
background: cssVarV2('layer/background/error'),
|
||||||
borderColor: cssVarV2('button/error'),
|
borderColor: cssVarV2('button/error'),
|
||||||
color: cssVarV2('button/error'),
|
color: cssVarV2('button/error'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const spinnerWrapper = style({
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
backgroundColor: 'rgba(255,255,255,0.6)',
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user