mirror of
https://github.com/flarum/core.git
synced 2025-08-04 23:47:32 +02:00
feat: improve emoji autocomplete (#3923)
* feat: improve emoji autocomplete * chore: improve dropdown header
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 150,
|
|
||||||
"singleQuote": true,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"trailingComma": "es5"
|
|
||||||
}
|
|
@@ -1,6 +1,7 @@
|
|||||||
import { extend } from 'flarum/common/extend';
|
import { extend } from 'flarum/common/extend';
|
||||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||||
|
import Tooltip from 'flarum/common/components/Tooltip';
|
||||||
|
|
||||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||||
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||||
@@ -11,6 +12,13 @@ export default function addComposerAutocomplete() {
|
|||||||
|
|
||||||
extend('flarum/common/components/TextEditor', 'oninit', function () {
|
extend('flarum/common/components/TextEditor', 'oninit', function () {
|
||||||
this._loaders.push(async () => await import('./emojiMap').then((m) => (emojiMap = m.default)));
|
this._loaders.push(async () => await import('./emojiMap').then((m) => (emojiMap = m.default)));
|
||||||
|
// prettier-ignore
|
||||||
|
this.commonEmoji = [
|
||||||
|
'😀', '😁', '😂', '😃', '😄', '😅', '😆', '😇', '😈', '😉', '😊', '😋', '😌', '😍', '😎', '😏', '😐️', '😑', '😒',
|
||||||
|
'😓', '😔', '😕', '😖', '😗', '😘', '😙', '😚', '😛', '😜', '😝', '😞', '😟', '😠', '😡', '😢', '😣', '😤', '😥',
|
||||||
|
'😦', '😧', '😨', '😩', '😪', '😫', '😬', '😭', '😮', '😮💨', '😯', '😰', '😱', '😲', '😳', '😴', '😵', '😵💫',
|
||||||
|
'😶', '😶🌫️', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙁', '🙂', '🙃', '🙄',
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
extend('flarum/common/components/TextEditor', 'onbuild', function () {
|
extend('flarum/common/components/TextEditor', 'onbuild', function () {
|
||||||
@@ -75,6 +83,7 @@ export default function addComposerAutocomplete() {
|
|||||||
|
|
||||||
const makeSuggestion = function ({ emoji, name, code }) {
|
const makeSuggestion = function ({ emoji, name, code }) {
|
||||||
return (
|
return (
|
||||||
|
<Tooltip text={name}>
|
||||||
<button
|
<button
|
||||||
key={emoji}
|
key={emoji}
|
||||||
onclick={() => applySuggestion(emoji)}
|
onclick={() => applySuggestion(emoji)}
|
||||||
@@ -82,9 +91,9 @@ export default function addComposerAutocomplete() {
|
|||||||
this.emojiDropdown.setIndex($(this).parent().index() - 1);
|
this.emojiDropdown.setIndex($(this).parent().index() - 1);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img alt={emoji} className="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
<img alt={emoji} className="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} title={name} />
|
||||||
{name}
|
|
||||||
</button>
|
</button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,7 +107,7 @@ export default function addComposerAutocomplete() {
|
|||||||
};
|
};
|
||||||
const regTyped = fuzzyRegexp(typed);
|
const regTyped = fuzzyRegexp(typed);
|
||||||
|
|
||||||
let maxSuggestions = 7;
|
let maxSuggestions = 40;
|
||||||
|
|
||||||
const findMatchingEmojis = (matcher) => {
|
const findMatchingEmojis = (matcher) => {
|
||||||
for (let i = 0; i < emojiKeys.length && maxSuggestions > 0; i++) {
|
for (let i = 0; i < emojiKeys.length && maxSuggestions > 0; i++) {
|
||||||
@@ -107,7 +116,7 @@ export default function addComposerAutocomplete() {
|
|||||||
if (similarEmoji.indexOf(curEmoji) === -1) {
|
if (similarEmoji.indexOf(curEmoji) === -1) {
|
||||||
const names = emojiMap[curEmoji];
|
const names = emojiMap[curEmoji];
|
||||||
for (let name of names) {
|
for (let name of names) {
|
||||||
if (matcher(name)) {
|
if (matcher(name, curEmoji)) {
|
||||||
--maxSuggestions;
|
--maxSuggestions;
|
||||||
similarEmoji.push(curEmoji);
|
similarEmoji.push(curEmoji);
|
||||||
break;
|
break;
|
||||||
@@ -118,10 +127,17 @@ export default function addComposerAutocomplete() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// First, try to find all emojis starting with the given string
|
// First, try to find all emojis starting with the given string
|
||||||
findMatchingEmojis((emoji) => emoji.indexOf(typed) === 0);
|
findMatchingEmojis((emojiName, emoji) => {
|
||||||
|
// If no input is provided yet, match the most common emojis.
|
||||||
|
if (!typed) {
|
||||||
|
return this.commonEmoji?.includes(emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
return emojiName.indexOf(typed) === 0;
|
||||||
|
});
|
||||||
|
|
||||||
// If there are still suggestions left, try for some fuzzy matches
|
// If there are still suggestions left, try for some fuzzy matches
|
||||||
findMatchingEmojis((emoji) => regTyped.test(emoji));
|
findMatchingEmojis((emojiName) => regTyped.test(emojiName));
|
||||||
|
|
||||||
const suggestions = similarEmoji
|
const suggestions = similarEmoji
|
||||||
.map((emoji) => ({
|
.map((emoji) => ({
|
||||||
|
@@ -7,29 +7,28 @@ img.emoji {
|
|||||||
.EmojiDropdown {
|
.EmojiDropdown {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
overflow: auto;
|
overflow: visible;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin: 5px 0 !important;
|
padding: 8px;
|
||||||
|
|
||||||
> li > button {
|
> li {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
> button {
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-top: 6px;
|
padding: 8px;
|
||||||
padding-bottom: 6px;
|
border-radius: var(--border-radius);
|
||||||
padding-left: 45px;
|
|
||||||
|
|
||||||
.emoji {
|
|
||||||
float: left;
|
|
||||||
margin-left: -30px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Dropdown-header {
|
> .Dropdown-header {
|
||||||
|
display: block;
|
||||||
color: var(--muted-more-color);
|
color: var(--muted-more-color);
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
padding-bottom: 5px;
|
padding: 4px 8px;
|
||||||
font-size: 11px;
|
margin: 0 0 4px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user