Ensure emoji completion always takes effect
This commit is contained in:
parent
ff0794e08b
commit
fef8c5b2f1
2 changed files with 69 additions and 10 deletions
ts
|
@ -65,8 +65,26 @@ export class EmojiCompletion {
|
||||||
this.quill.keyboard.addBinding({ key: 38 }, changeIndex(-1)); // 38 = Up
|
this.quill.keyboard.addBinding({ key: 38 }, changeIndex(-1)); // 38 = Up
|
||||||
this.quill.keyboard.addBinding({ key: 39 }, clearResults); // 39 = Right
|
this.quill.keyboard.addBinding({ key: 39 }, clearResults); // 39 = Right
|
||||||
this.quill.keyboard.addBinding({ key: 40 }, changeIndex(1)); // 40 = Down
|
this.quill.keyboard.addBinding({ key: 40 }, changeIndex(1)); // 40 = Down
|
||||||
|
this.quill.keyboard.addBinding(
|
||||||
|
{
|
||||||
|
// 186 + Shift = Colon
|
||||||
|
key: 186,
|
||||||
|
shiftKey: true,
|
||||||
|
},
|
||||||
|
() => this.onTextChange(true)
|
||||||
|
);
|
||||||
|
this.quill.keyboard.addBinding(
|
||||||
|
{
|
||||||
|
// 58 = Also Colon
|
||||||
|
key: 58,
|
||||||
|
},
|
||||||
|
() => this.onTextChange(true)
|
||||||
|
);
|
||||||
|
|
||||||
this.quill.on('text-change', _.debounce(this.onTextChange.bind(this), 100));
|
this.quill.on(
|
||||||
|
'text-change',
|
||||||
|
_.debounce(() => this.onTextChange(), 100)
|
||||||
|
);
|
||||||
this.quill.on('selection-change', this.onSelectionChange.bind(this));
|
this.quill.on('selection-change', this.onSelectionChange.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +109,13 @@ export class EmojiCompletion {
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTextChange(): void {
|
onTextChange(justPressedColon = false): boolean {
|
||||||
|
const PASS_THROUGH = true;
|
||||||
|
const INTERCEPT = false;
|
||||||
|
|
||||||
const range = this.quill.getSelection();
|
const range = this.quill.getSelection();
|
||||||
|
|
||||||
if (!range) return;
|
if (!range) return PASS_THROUGH;
|
||||||
|
|
||||||
const [blot, index] = this.quill.getLeaf(range.index);
|
const [blot, index] = this.quill.getLeaf(range.index);
|
||||||
const [leftTokenTextMatch, rightTokenTextMatch] = matchBlotTextPartitions(
|
const [leftTokenTextMatch, rightTokenTextMatch] = matchBlotTextPartitions(
|
||||||
|
@ -107,24 +128,26 @@ export class EmojiCompletion {
|
||||||
if (leftTokenTextMatch) {
|
if (leftTokenTextMatch) {
|
||||||
const [, leftTokenText, isSelfClosing] = leftTokenTextMatch;
|
const [, leftTokenText, isSelfClosing] = leftTokenTextMatch;
|
||||||
|
|
||||||
if (isSelfClosing) {
|
if (isSelfClosing || justPressedColon) {
|
||||||
if (isShortName(leftTokenText)) {
|
if (isShortName(leftTokenText)) {
|
||||||
const emojiData = convertShortNameToData(
|
const emojiData = convertShortNameToData(
|
||||||
leftTokenText,
|
leftTokenText,
|
||||||
this.options.skinTone
|
this.options.skinTone
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const numberOfColons = isSelfClosing ? 2 : 1;
|
||||||
|
|
||||||
if (emojiData) {
|
if (emojiData) {
|
||||||
this.insertEmoji(
|
this.insertEmoji(
|
||||||
emojiData,
|
emojiData,
|
||||||
range.index - leftTokenText.length - 2,
|
range.index - leftTokenText.length - numberOfColons,
|
||||||
leftTokenText.length + 2
|
leftTokenText.length + numberOfColons
|
||||||
);
|
);
|
||||||
return;
|
return INTERCEPT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.reset();
|
this.reset();
|
||||||
return;
|
return PASS_THROUGH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,14 +167,14 @@ export class EmojiCompletion {
|
||||||
range.index - leftTokenText.length - 1,
|
range.index - leftTokenText.length - 1,
|
||||||
tokenText.length + 2
|
tokenText.length + 2
|
||||||
);
|
);
|
||||||
return;
|
return INTERCEPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftTokenText.length < 2) {
|
if (leftTokenText.length < 2) {
|
||||||
this.reset();
|
this.reset();
|
||||||
return;
|
return PASS_THROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
const showEmojiResults = search(leftTokenText, 10);
|
const showEmojiResults = search(leftTokenText, 10);
|
||||||
|
@ -165,6 +188,8 @@ export class EmojiCompletion {
|
||||||
} else if (this.results.length !== 0) {
|
} else if (this.results.length !== 0) {
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return PASS_THROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
completeEmoji(): void {
|
completeEmoji(): void {
|
||||||
|
|
|
@ -336,6 +336,40 @@ describe('emojiCompletion', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('given a completeable emoji and colon was just pressed', () => {
|
||||||
|
beforeEach(function beforeEach() {
|
||||||
|
mockQuill.getSelection.returns({
|
||||||
|
index: 6,
|
||||||
|
length: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and given it matches a short name', () => {
|
||||||
|
const text = ':smile';
|
||||||
|
|
||||||
|
beforeEach(function beforeEach() {
|
||||||
|
const blot = {
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
mockQuill.getLeaf.returns([blot, 6]);
|
||||||
|
|
||||||
|
emojiCompletion.onTextChange(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inserts the emoji at the current cursor position', () => {
|
||||||
|
const [emoji, index, range] = insertEmojiStub.args[0];
|
||||||
|
|
||||||
|
assert.equal(emoji.short_name, 'smile');
|
||||||
|
assert.equal(index, 0);
|
||||||
|
assert.equal(range, 6);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show results', () => {
|
||||||
|
assert.equal(emojiCompletion.results.length, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('completeEmoji', () => {
|
describe('completeEmoji', () => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue