Commit a59510bb authored by JC Brand's avatar JC Brand

Highlight relevant category when scrolling

parent 2c480966
...@@ -13,7 +13,7 @@ import BrowserStorage from "backbone.browserStorage"; ...@@ -13,7 +13,7 @@ import BrowserStorage from "backbone.browserStorage";
import bootstrap from "bootstrap.native"; import bootstrap from "bootstrap.native";
import tpl_emoji_button from "templates/emoji_button.html"; import tpl_emoji_button from "templates/emoji_button.html";
import tpl_emojis from "templates/emojis.html"; import tpl_emojis from "templates/emojis.html";
const { Backbone, _ } = converse.env; const { Backbone, sizzle, _ } = converse.env;
const u = converse.env.utils; const u = converse.env.utils;
...@@ -116,7 +116,6 @@ converse.plugins.add('converse-emoji-views', { ...@@ -116,7 +116,6 @@ converse.plugins.add('converse-emoji-views', {
this.createEmojiDropdown(); this.createEmojiDropdown();
this.emoji_dropdown.toggle(); this.emoji_dropdown.toggle();
await _converse.api.waitUntil('emojisInitialized'); await _converse.api.waitUntil('emojisInitialized');
this.emoji_picker_view.render();
this.emoji_picker_view.setScrollPosition(); this.emoji_picker_view.setScrollPosition();
} }
}, },
...@@ -141,14 +140,14 @@ converse.plugins.add('converse-emoji-views', { ...@@ -141,14 +140,14 @@ converse.plugins.add('converse-emoji-views', {
'keydown .emoji-search': 'onKeyDown' 'keydown .emoji-search': 'onKeyDown'
}, },
initialize () { async initialize () {
this.debouncedFilter = _.debounce(input => this.filter(input.value), 150); this.debouncedFilter = _.debounce(input => this.filter(input.value), 150);
this.model.on('change:query', this.render, this); this.model.on('change:query', this.render, this);
this.model.on('change:current_skintone', this.render, this); this.model.on('change:current_skintone', this.render, this);
this.model.on('change:current_category', () => { this.model.on('change:current_category', this.render, this);
await _converse.api.waitUntil('emojisInitialized');
this.render(); this.render();
this.setScrollPosition(); this.initIntersectionObserver();
});
_converse.api.trigger('emojiPickerViewInitialized'); _converse.api.trigger('emojiPickerViewInitialized');
}, },
...@@ -183,6 +182,38 @@ converse.plugins.add('converse-emoji-views', { ...@@ -183,6 +182,38 @@ converse.plugins.add('converse-emoji-views', {
} }
}, },
initIntersectionObserver () {
if (!window.IntersectionObserver) {
return;
}
const categories = sizzle('.emoji-picker__header .emoji-category', this.el);
const options = {
root: this.el.querySelector('.emoji-picker__lists'),
rootMargin: '0px',
threshold: [0.1, 0.25, 0.5]
}
const handler = _.debounce(ev => {
const current = ev.filter(e => e.isIntersecting).pop();
if (current) {
const category = current.target.getAttribute('data-category');
const old_category = this.model.get('current_category');
if (old_category !== category) {
// XXX: Manually set the classes, it's quicker than using the VDOM
this.model.set(
{'current_category': category},
{'silent': true}
);
const new_el = categories.filter(el => el.getAttribute('data-category') === category).pop();
const old_el = categories.filter(el => el.getAttribute('data-category') === old_category).pop();
new_el && u.addClass('picked', new_el);
old_el && u.removeClass('picked', old_el);
}
}
}, 100);
const observer = new IntersectionObserver(handler, options);
sizzle('.emoji-picker', this.el).forEach(a => observer.observe(a));
},
onKeyDown (ev) { onKeyDown (ev) {
if (ev.keyCode === _converse.keycodes.TAB) { if (ev.keyCode === _converse.keycodes.TAB) {
ev.preventDefault(); ev.preventDefault();
...@@ -256,13 +287,14 @@ converse.plugins.add('converse-emoji-views', { ...@@ -256,13 +287,14 @@ converse.plugins.add('converse-emoji-views', {
const input = this.el.querySelector('.emoji-search'); const input = this.el.querySelector('.emoji-search');
input.value = ''; input.value = '';
this.model.save({'current_category': category, 'query': undefined}); this.model.save({'current_category': category, 'query': undefined});
this.setScrollPosition();
}, },
setScrollPosition () { setScrollPosition () {
const category = this.model.get('current_category'); const category = this.model.get('current_category');
const el = this.el.querySelector('.emoji-picker__lists'); const el = this.el.querySelector('.emoji-picker__lists');
const heading = this.el.querySelector(`#emoji-picker-${category}`); const heading = this.el.querySelector(`#emoji-picker-${category}`);
el.scrollTop = heading.offsetTop - heading.offsetHeight*2; el.scrollTop = heading.offsetTop - heading.offsetHeight*3;
}, },
insertEmoji (ev) { insertEmoji (ev) {
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
</ul> </ul>
{[ } else { ]} {[ } else { ]}
{[ Object.keys(o.emoji_categories).forEach(function (category) { ]} {[ Object.keys(o.emoji_categories).forEach(function (category) { ]}
<a id="emoji-picker-{{{category}}}" class="emoji-category__heading">{{{o._converse.emoji_category_labels[category]}}}</a> <a id="emoji-picker-{{{category}}}" class="emoji-category__heading" data-category="{{{category}}}">{{{o._converse.emoji_category_labels[category]}}}</a>
<ul class="emoji-picker"> <ul class="emoji-picker" data-category="{{{category}}}">
{[ o.emojis_by_category[category].forEach(function (emoji) { ]} {[ o.emojis_by_category[category].forEach(function (emoji) { ]}
<li class="emoji insert-emoji {[ if (o.shouldBeHidden(emoji.sn)) { ]} hidden {[ }; ]}" <li class="emoji insert-emoji {[ if (o.shouldBeHidden(emoji.sn)) { ]} hidden {[ }; ]}"
data-emoji="{{{emoji.sn}}}" title="{{{emoji.sn}}}"> data-emoji="{{{emoji.sn}}}" title="{{{emoji.sn}}}">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment