diff --git a/ts/quill/auto-substitute-ascii-emojis/index.tsx b/ts/quill/auto-substitute-ascii-emojis/index.tsx index 835ee5303e..c5eb77def0 100644 --- a/ts/quill/auto-substitute-ascii-emojis/index.tsx +++ b/ts/quill/auto-substitute-ascii-emojis/index.tsx @@ -66,7 +66,7 @@ export class AutoSubstituteAsciiEmojis { } onTextChange(): void { - if (!window.storage.get('autoConvertEmoji', false)) { + if (!window.storage.get('autoConvertEmoji', true)) { return; } diff --git a/ts/quill/emoji/completion.tsx b/ts/quill/emoji/completion.tsx index d16f7d86e0..cf4c9a078c 100644 --- a/ts/quill/emoji/completion.tsx +++ b/ts/quill/emoji/completion.tsx @@ -27,6 +27,14 @@ type EmojiPickerOptions = { search: SearchFnType; }; +export type InsertEmojiOptionsType = Readonly<{ + shortName: string; + index: number; + range: number; + withTrailingSpace?: boolean; + justPressedColon?: boolean; +}>; + export class EmojiCompletion { results: Array; @@ -84,10 +92,13 @@ export class EmojiCompletion { () => this.onTextChange(true) ); - this.quill.on( - 'text-change', - _.debounce(() => this.onTextChange(), 100) - ); + const debouncedOnTextChange = _.debounce(() => this.onTextChange(), 100); + + this.quill.on('text-change', (_now, _before, source) => { + if (source === 'user') { + debouncedOnTextChange(); + } + }); this.quill.on('selection-change', this.onSelectionChange.bind(this)); } @@ -139,11 +150,12 @@ export class EmojiCompletion { if (isShortName(leftTokenText)) { const numberOfColons = isSelfClosing ? 2 : 1; - this.insertEmoji( - leftTokenText, - range.index - leftTokenText.length - numberOfColons, - leftTokenText.length + numberOfColons - ); + this.insertEmoji({ + shortName: leftTokenText, + index: range.index - leftTokenText.length - numberOfColons, + range: leftTokenText.length + numberOfColons, + justPressedColon, + }); return INTERCEPT; } this.reset(); @@ -155,11 +167,12 @@ export class EmojiCompletion { const tokenText = leftTokenText + rightTokenText; if (isShortName(tokenText)) { - this.insertEmoji( - tokenText, - range.index - leftTokenText.length - 1, - tokenText.length + 2 - ); + this.insertEmoji({ + shortName: tokenText, + index: range.index - leftTokenText.length - 1, + range: tokenText.length + 2, + justPressedColon, + }); return INTERCEPT; } } @@ -212,27 +225,33 @@ export class EmojiCompletion { const [, tokenText] = tokenTextMatch; - this.insertEmoji( - emoji, - range.index - tokenText.length - 1, - tokenText.length + 1, - true - ); + this.insertEmoji({ + shortName: emoji, + index: range.index - tokenText.length - 1, + range: tokenText.length + 1, + withTrailingSpace: true, + }); } - insertEmoji( - shortName: string, - index: number, - range: number, - withTrailingSpace = false - ): void { + insertEmoji({ + shortName, + index, + range, + withTrailingSpace = false, + justPressedColon = false, + }: InsertEmojiOptionsType): void { const emoji = convertShortName(shortName, this.options.skinTone); + let source = this.quill.getText(index, range); + if (justPressedColon) { + source += ':'; + } + const delta = new Delta() .retain(index) .delete(range) .insert({ - emoji: { value: emoji }, + emoji: { value: emoji, source }, }); if (withTrailingSpace) { diff --git a/ts/test-electron/quill/emoji/completion_test.tsx b/ts/test-electron/quill/emoji/completion_test.tsx index 1f1639153c..52b9206e5a 100644 --- a/ts/test-electron/quill/emoji/completion_test.tsx +++ b/ts/test-electron/quill/emoji/completion_test.tsx @@ -5,6 +5,7 @@ import { assert } from 'chai'; import sinon from 'sinon'; import { EmojiCompletion } from '../../../quill/emoji/completion'; +import type { InsertEmojiOptionsType } from '../../../quill/emoji/completion'; import { createSearch } from '../../../components/emoji/lib'; describe('emojiCompletion', () => { @@ -15,6 +16,7 @@ describe('emojiCompletion', () => { beforeEach(function (this: Mocha.Context) { mockQuill = { getLeaf: sinon.stub(), + getText: sinon.stub(), getSelection: sinon.stub(), keyboard: { addBinding: sinon.stub(), @@ -55,10 +57,7 @@ describe('emojiCompletion', () => { }); describe('onTextChange', () => { - let insertEmojiStub: sinon.SinonStub< - [string, number, number, (boolean | undefined)?], - void - >; + let insertEmojiStub: sinon.SinonStub<[InsertEmojiOptionsType], void>; beforeEach(() => { emojiCompletion.results = ['joy']; @@ -194,9 +193,9 @@ describe('emojiCompletion', () => { }); it('inserts the emoji at the current cursor position', () => { - const [emoji, index, range] = insertEmojiStub.args[0]; + const [{ shortName, index, range }] = insertEmojiStub.args[0]; - assert.equal(emoji, 'smile'); + assert.equal(shortName, 'smile'); assert.equal(index, 0); assert.equal(range, 7); }); @@ -223,9 +222,9 @@ describe('emojiCompletion', () => { }); it('inserts the emoji at the current cursor position', () => { - const [emoji, index, range] = insertEmojiStub.args[0]; + const [{ shortName, index, range }] = insertEmojiStub.args[0]; - assert.equal(emoji, 'smile'); + assert.equal(shortName, 'smile'); assert.equal(index, 7); assert.equal(range, 7); }); @@ -283,9 +282,9 @@ describe('emojiCompletion', () => { }); it('inserts the emoji at the current cursor position', () => { - const [emoji, index, range] = insertEmojiStub.args[0]; + const [{ shortName, index, range }] = insertEmojiStub.args[0]; - assert.equal(emoji, 'smile'); + assert.equal(shortName, 'smile'); assert.equal(index, 0); assert.equal(range, validEmoji.length); }); @@ -332,9 +331,9 @@ describe('emojiCompletion', () => { }); it('inserts the emoji at the current cursor position', () => { - const [emoji, index, range] = insertEmojiStub.args[0]; + const [{ shortName, index, range }] = insertEmojiStub.args[0]; - assert.equal(emoji, 'smile'); + assert.equal(shortName, 'smile'); assert.equal(index, 0); assert.equal(range, 6); }); @@ -347,10 +346,7 @@ describe('emojiCompletion', () => { }); describe('completeEmoji', () => { - let insertEmojiStub: sinon.SinonStub< - [string, number, number, (boolean | undefined)?], - void - >; + let insertEmojiStub: sinon.SinonStub<[InsertEmojiOptionsType], void>; beforeEach(() => { emojiCompletion.results = ['smile', 'smile_cat']; @@ -377,9 +373,10 @@ describe('emojiCompletion', () => { }); it('inserts the currently selected emoji at the current cursor position', () => { - const [emoji, insertIndex, range] = insertEmojiStub.args[0]; + const [{ shortName, index: insertIndex, range }] = + insertEmojiStub.args[0]; - assert.equal(emoji, 'smile_cat'); + assert.equal(shortName, 'smile_cat'); assert.equal(insertIndex, 0); assert.equal(range, text.length); });