Skip to content

Commit 3a07006

Browse files
committed
fix: prevent emitting new TextComposer state with the same values
1 parent fdb0576 commit 3a07006

2 files changed

Lines changed: 93 additions & 2 deletions

File tree

src/messageComposer/textComposer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,14 @@ export class TextComposer {
151151
};
152152

153153
setText = (text: string) => {
154-
if (!this.enabled) return;
154+
if (!this.enabled || text === this.text) return;
155155
this.state.partialNext({ text });
156156
};
157157

158158
setSelection = (selection: TextSelection) => {
159-
if (!this.enabled) return;
159+
const selectionChanged =
160+
selection.start !== this.selection.start || selection.end !== this.selection.end;
161+
if (!this.enabled || !selectionChanged) return;
160162
this.state.partialNext({ selection });
161163
};
162164

test/unit/MessageComposer/textComposer.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { textIsEmpty } from '../../../src/messageComposer/textComposer';
88
import { DraftResponse, LocalMessage } from '../../../src/types';
99
import { logChatPromiseExecution } from '../../../src/utils';
1010
import { TextComposerConfig } from '../../../src/messageComposer/configuration';
11+
import { TextComposerState } from '../../../src';
1112

1213
const textComposerMiddlewareExecuteOutput = {
1314
state: {
@@ -393,6 +394,94 @@ describe('TextComposer', () => {
393394
textComposer.setText('New text');
394395
expect(textComposer.text).toBe(message.text);
395396
});
397+
it('should not update the text when setting the same value', () => {
398+
const message: LocalMessage = {
399+
id: 'test-message',
400+
type: 'regular',
401+
text: 'Hello world',
402+
};
403+
const {
404+
messageComposer: { textComposer },
405+
} = setup({ composition: message, config: { enabled: false } });
406+
const subscriber = vi.fn();
407+
const originalText = textComposer.text;
408+
textComposer.state.subscribeWithSelector(({ text }) => ({ text }), subscriber);
409+
expect(subscriber).toHaveBeenCalledWith({ text: originalText }, undefined);
410+
textComposer.setText(originalText);
411+
expect(textComposer.text).toBe(originalText);
412+
expect(subscriber).toHaveBeenCalledTimes(1);
413+
});
414+
});
415+
416+
describe('setSelection', () => {
417+
const message: LocalMessage = {
418+
id: 'test-message',
419+
type: 'regular',
420+
text: 'Hello world',
421+
};
422+
it('should update the selection', () => {
423+
const {
424+
messageComposer: { textComposer },
425+
} = setup({ composition: message });
426+
const subscriber = vi.fn();
427+
textComposer.state.subscribeWithSelector(
428+
({ selection }) => ({ selection }),
429+
subscriber,
430+
);
431+
expect(subscriber).toHaveBeenCalledWith(
432+
{ selection: { end: message.text!.length, start: message.text!.length } },
433+
undefined,
434+
);
435+
expect(textComposer.selection).toEqual({
436+
end: message.text!.length,
437+
start: message.text!.length,
438+
});
439+
textComposer.setSelection({ end: 2, start: 2 });
440+
expect(textComposer.selection).toEqual({ end: 2, start: 2 });
441+
expect(subscriber).toHaveBeenCalledWith(
442+
{ selection: { end: 2, start: 2 } },
443+
{ selection: { end: message.text!.length, start: message.text!.length } },
444+
);
445+
expect(subscriber).toHaveBeenCalledTimes(2);
446+
});
447+
448+
it('should not update the selection with the same value', () => {
449+
const {
450+
messageComposer: { textComposer },
451+
} = setup({ composition: message });
452+
const originalSelection = textComposer.selection;
453+
const subscriber = vi.fn();
454+
textComposer.state.subscribeWithSelector(
455+
({ selection }) => ({ ...selection }),
456+
subscriber,
457+
);
458+
expect(subscriber).toHaveBeenCalledWith(originalSelection, undefined);
459+
expect(textComposer.selection).toEqual(originalSelection);
460+
textComposer.setSelection(originalSelection);
461+
expect(textComposer.selection).toEqual(originalSelection);
462+
expect(subscriber).toHaveBeenCalledTimes(1);
463+
});
464+
465+
it('should not update the selection when text composer disabled', () => {
466+
const {
467+
messageComposer: { textComposer },
468+
} = setup({ composition: message, config: { enabled: false } });
469+
const originalSelection = textComposer.selection;
470+
const subscriber = vi.fn();
471+
textComposer.state.subscribeWithSelector(
472+
({ selection }) => ({ selection }),
473+
subscriber,
474+
);
475+
expect(subscriber).toHaveBeenCalledWith(
476+
{ selection: { end: message.text!.length, start: message.text!.length } },
477+
undefined,
478+
);
479+
480+
expect(textComposer.selection).toEqual(originalSelection);
481+
textComposer.setSelection({ end: 2, start: 2 });
482+
expect(textComposer.selection).toEqual(originalSelection);
483+
expect(subscriber).toHaveBeenCalledTimes(1);
484+
});
396485
});
397486

398487
describe('insertText', () => {

0 commit comments

Comments
 (0)