Improve emoji autocomplete dropdown

- Add a key to each list item so that Mithril's diffing algorithm is used correctly. This prevents the emoji images from remaining for half a second before they update to a new suggestion.
- Clean up styles. The `PostPreview` doesn't really belong here.
This commit is contained in:
Toby Zerner 2016-02-07 11:47:49 +10:30
parent 7359407b54
commit 50d88d4547
4 changed files with 17 additions and 31 deletions

View File

@ -202,19 +202,16 @@ System.register('flarum/emoji/addComposerAutocomplete', ['flarum/extend', 'flaru
var imageName = (emojiMap[key].indexOf('-20e3') != -1 || emojiMap[key] == 'a9' || emojiMap[key] == 'ae' ? '00' : '') + emojiMap[key]; var imageName = (emojiMap[key].indexOf('-20e3') != -1 || emojiMap[key] == 'a9' || emojiMap[key] == 'ae' ? '00' : '') + emojiMap[key];
return m( return m(
'button', 'button',
{ className: 'PostPreview', {
key: key,
onclick: function () { onclick: function () {
return applySuggestion(code); return applySuggestion(code);
}, },
onmouseenter: function () { onmouseenter: function () {
dropdown.setIndex($(this).parent().index()); dropdown.setIndex($(this).parent().index());
} }, } },
m(
'span',
{ className: 'PostPreview-content' },
m('img', { alt: code, 'class': 'emoji', draggable: 'false', src: '//cdn.jsdelivr.net/emojione/assets/png/' + imageName + '.png' }), m('img', { alt: code, 'class': 'emoji', draggable: 'false', src: '//cdn.jsdelivr.net/emojione/assets/png/' + imageName + '.png' }),
key key
)
); );
}; };
@ -340,7 +337,7 @@ System.register('flarum/emoji/components/AutocompleteDropdown', ['flarum/Compone
this.props.items.map(function (item) { this.props.items.map(function (item) {
return m( return m(
'li', 'li',
null, { key: item.attrs.key },
item item
); );
}) })

View File

@ -68,15 +68,14 @@ export default function addComposerAutocomplete() {
const code = ':' + key + ':'; const code = ':' + key + ':';
const imageName = (emojiMap[key].indexOf('-20e3') != -1 || emojiMap[key] == 'a9' || emojiMap[key] == 'ae' ? '00' : '') + emojiMap[key]; const imageName = (emojiMap[key].indexOf('-20e3') != -1 || emojiMap[key] == 'a9' || emojiMap[key] == 'ae' ? '00' : '') + emojiMap[key];
return ( return (
<button className={'PostPreview'} <button
key={key}
onclick={() => applySuggestion(code)} onclick={() => applySuggestion(code)}
onmouseenter={function() { onmouseenter={function() {
dropdown.setIndex($(this).parent().index()); dropdown.setIndex($(this).parent().index());
}}> }}>
<span className="PostPreview-content"> <img alt={code} class="emoji" draggable="false" src={'//cdn.jsdelivr.net/emojione/assets/png/' + imageName + '.png'}/>
<img alt={code} class="emoji" draggable="false" src={'//cdn.jsdelivr.net/emojione/assets/png/' + imageName + '.png'}></img>
{key} {key}
</span>
</button> </button>
); );
}; };
@ -88,7 +87,7 @@ export default function addComposerAutocomplete() {
const fuzzyRegexp = function(str) { const fuzzyRegexp = function(str) {
const reEscape = new RegExp('\\(([' + ('+.*?[]{}()^$|\\'.replace(/(.)/g, '\\$1')) + '])\\)', 'g'); const reEscape = new RegExp('\\(([' + ('+.*?[]{}()^$|\\'.replace(/(.)/g, '\\$1')) + '])\\)', 'g');
return new RegExp('(.*)' + (str.toLowerCase().replace(/(.)/g, '($1)(.*?)')).replace(reEscape, '(\\$1)') + '$', 'i'); return new RegExp('(.*)' + (str.toLowerCase().replace(/(.)/g, '($1)(.*?)')).replace(reEscape, '(\\$1)') + '$', 'i');
} };
const regTyped = fuzzyRegexp(typed); const regTyped = fuzzyRegexp(typed);
for (var i=0, maxSuggestions = 7; i < emojiKeys.length && maxSuggestions > 0; i++) { for (var i=0, maxSuggestions = 7; i < emojiKeys.length && maxSuggestions > 0; i++) {

View File

@ -10,7 +10,7 @@ export default class AutocompleteDropdown extends Component {
view() { view() {
return ( return (
<ul className="Dropdown-menu EmojiDropdown"> <ul className="Dropdown-menu EmojiDropdown">
{this.props.items.map(item => <li>{item}</li>)} {this.props.items.map(item => <li key={item.attrs.key}>{item}</li>)}
</ul> </ul>
); );
} }

View File

@ -11,28 +11,18 @@ img.emoji {
position: absolute; position: absolute;
margin: 5px 0 !important; margin: 5px 0 !important;
> li > a { > li > button {
white-space: normal;
border-bottom: 0;
}
> li > a:hover {
background: none;
}
.PostPreview {
color: @text-color; color: @text-color;
font-weight: bold; font-weight: bold;
padding-top: 6px;
padding-bottom: 6px;
padding-left: 45px;
.emoji { .emoji {
margin-right: 5px; float: left;
margin-left: -30px;
} }
} }
.PostPreview-content {
overflow: hidden;
line-height: 1.7em;
display: block;
}
} }
.ComposerBody-emojiWrapper { .ComposerBody-emojiWrapper {