mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
add comment composer keyboard submit shortcut (#2941)
Co-authored-by: Siri-Ray <2667192167@qq.com>
This commit is contained in:
parent
0bd07b2a3d
commit
cdf34897ba
2 changed files with 109 additions and 1 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import type { CSSProperties } from 'react';
|
||||
import { useRef } from 'react';
|
||||
|
||||
import type { PreviewCommentSnapshot } from '../comments';
|
||||
import type { Dict } from '../i18n/types';
|
||||
import type { PreviewComment, PreviewCommentMember } from '../types';
|
||||
import { isImeComposing } from '../utils/imeComposing';
|
||||
|
||||
import { Icon } from './Icon';
|
||||
|
||||
|
|
@ -262,6 +264,8 @@ export function BoardComposerPopover({
|
|||
const pendingCount = notes.length + (draft.trim() ? 1 : 0);
|
||||
const hasCommentChange = !existing || draft.trim() !== existing.note.trim();
|
||||
const podMembers = target.podMembers ?? [];
|
||||
const composingRef = useRef(false);
|
||||
const sendDisabled = pendingCount === 0 || sending;
|
||||
return (
|
||||
<div
|
||||
className={`comment-popover${docked ? ' comment-popover-docked' : ''}`}
|
||||
|
|
@ -335,6 +339,25 @@ export function BoardComposerPopover({
|
|||
aria-label={t('chat.comments.placeholder')}
|
||||
placeholder={t('chat.comments.placeholder')}
|
||||
onChange={(event) => onDraft(event.target.value)}
|
||||
onCompositionStart={() => {
|
||||
composingRef.current = true;
|
||||
}}
|
||||
onCompositionEnd={() => {
|
||||
composingRef.current = false;
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (isImeComposing(event, composingRef.current)) return;
|
||||
if (
|
||||
event.key === 'Enter' &&
|
||||
!event.shiftKey &&
|
||||
!event.altKey &&
|
||||
(event.metaKey || event.ctrlKey)
|
||||
) {
|
||||
event.preventDefault();
|
||||
if (sendDisabled) return;
|
||||
void onSendBatch();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="comment-popover-actions">
|
||||
<div className="comment-popover-actions-start">
|
||||
|
|
@ -386,7 +409,7 @@ export function BoardComposerPopover({
|
|||
type="button"
|
||||
className="primary"
|
||||
data-testid="comment-add-send"
|
||||
disabled={pendingCount === 0 || sending}
|
||||
disabled={sendDisabled}
|
||||
onClick={() => void onSendBatch()}
|
||||
>
|
||||
{sending ? t('chat.comments.sending') : t('chat.comments.sendToChat')}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// @vitest-environment jsdom
|
||||
|
||||
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { BoardComposerPopover } from '../../src/components/BoardComposerPopover';
|
||||
import type { PreviewCommentSnapshot } from '../../src/comments';
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
const target: PreviewCommentSnapshot = {
|
||||
filePath: 'index.html',
|
||||
elementId: 'hero-title',
|
||||
selector: '#hero-title',
|
||||
label: 'Hero title',
|
||||
text: '',
|
||||
position: { x: 0, y: 0, width: 100, height: 24 },
|
||||
htmlHint: '',
|
||||
selectionKind: 'element',
|
||||
};
|
||||
|
||||
function renderPopover(onSendBatch: () => void, sending = false) {
|
||||
return render(
|
||||
<BoardComposerPopover
|
||||
target={target}
|
||||
existing={null}
|
||||
draft="Tighten this heading"
|
||||
notes={[]}
|
||||
onDraft={() => {}}
|
||||
onAddDraft={() => {}}
|
||||
onRemoveQueuedNote={() => {}}
|
||||
onClose={() => {}}
|
||||
onSaveComment={() => {}}
|
||||
onSendBatch={onSendBatch}
|
||||
onRemoveMember={() => {}}
|
||||
sending={sending}
|
||||
t={((key: string) => String(key)) as never}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
describe('BoardComposerPopover keyboard submit', () => {
|
||||
it('sends the drafted comment with the primary Enter shortcut', () => {
|
||||
const onSendBatch = vi.fn();
|
||||
renderPopover(onSendBatch);
|
||||
|
||||
fireEvent.keyDown(screen.getByTestId('comment-popover-input'), { key: 'Enter', metaKey: true });
|
||||
|
||||
expect(onSendBatch).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not send while disabled or while IME text is composing', () => {
|
||||
const onSendBatch = vi.fn();
|
||||
const { rerender } = renderPopover(onSendBatch, true);
|
||||
const input = screen.getByTestId('comment-popover-input');
|
||||
|
||||
fireEvent.keyDown(input, { key: 'Enter', metaKey: true });
|
||||
expect(onSendBatch).not.toHaveBeenCalled();
|
||||
|
||||
rerender(
|
||||
<BoardComposerPopover
|
||||
target={target}
|
||||
existing={null}
|
||||
draft="Tighten this heading"
|
||||
notes={[]}
|
||||
onDraft={() => {}}
|
||||
onAddDraft={() => {}}
|
||||
onRemoveQueuedNote={() => {}}
|
||||
onClose={() => {}}
|
||||
onSaveComment={() => {}}
|
||||
onSendBatch={onSendBatch}
|
||||
onRemoveMember={() => {}}
|
||||
sending={false}
|
||||
t={((key: string) => String(key)) as never}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.compositionStart(input);
|
||||
fireEvent.keyDown(input, { key: 'Enter', metaKey: true });
|
||||
|
||||
expect(onSendBatch).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue