2021-03-24 11:59:09 +01:00
|
|
|
import { CustomElement } from 'shared/components/element.js';
|
2020-12-03 13:40:30 +01:00
|
|
|
import { _converse, converse, api } from "@converse/headless/core";
|
2021-04-14 22:56:59 +02:00
|
|
|
import { html } from "lit";
|
2023-02-15 14:19:48 +01:00
|
|
|
import { tplAllEmojis, tplSearchResults } from "./templates/emoji-picker.js";
|
2022-04-06 11:18:12 +02:00
|
|
|
import { getTonedEmojis } from './utils.js';
|
2020-07-01 21:45:18 +02:00
|
|
|
|
2020-12-10 16:39:27 +01:00
|
|
|
const { sizzle } = converse.env;
|
|
|
|
|
2020-07-01 21:45:18 +02:00
|
|
|
|
|
|
|
export default class EmojiPickerContent extends CustomElement {
|
|
|
|
static get properties () {
|
|
|
|
return {
|
|
|
|
'chatview': { type: Object },
|
|
|
|
'search_results': { type: Array },
|
|
|
|
'current_skintone': { type: String },
|
|
|
|
'model': { type: Object },
|
|
|
|
'query': { type: String },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
|
|
|
const props = {
|
|
|
|
'current_skintone': this.current_skintone,
|
|
|
|
'insertEmoji': ev => this.insertEmoji(ev),
|
|
|
|
'query': this.query,
|
|
|
|
'search_results': this.search_results,
|
|
|
|
'shouldBeHidden': shortname => this.shouldBeHidden(shortname),
|
|
|
|
}
|
|
|
|
return html`
|
|
|
|
<div class="emoji-picker__lists">
|
2023-02-15 14:19:48 +01:00
|
|
|
${tplSearchResults(props)}
|
|
|
|
${tplAllEmojis(props)}
|
2020-07-01 21:45:18 +02:00
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
|
|
|
firstUpdated () {
|
|
|
|
this.initIntersectionObserver();
|
|
|
|
}
|
|
|
|
|
|
|
|
initIntersectionObserver () {
|
|
|
|
if (!window.IntersectionObserver) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this.observer) {
|
|
|
|
this.observer.disconnect();
|
|
|
|
} else {
|
|
|
|
const options = {
|
|
|
|
root: this.querySelector('.emoji-picker__lists'),
|
|
|
|
threshold: [0.1]
|
|
|
|
}
|
|
|
|
const handler = ev => this.setCategoryOnVisibilityChange(ev);
|
|
|
|
this.observer = new IntersectionObserver(handler, options);
|
|
|
|
}
|
|
|
|
sizzle('.emoji-picker', this).forEach(a => this.observer.observe(a));
|
|
|
|
}
|
|
|
|
|
2021-06-03 16:29:31 +02:00
|
|
|
setCategoryOnVisibilityChange (entries) {
|
2020-07-01 21:45:18 +02:00
|
|
|
const selected = this.parentElement.navigator.selected;
|
2021-06-03 16:29:31 +02:00
|
|
|
const intersection_with_selected = entries.filter(i => i.target.contains(selected)).pop();
|
2020-07-01 21:45:18 +02:00
|
|
|
let current;
|
|
|
|
// Choose the intersection that contains the currently selected
|
|
|
|
// element, or otherwise the one with the largest ratio.
|
|
|
|
if (intersection_with_selected) {
|
|
|
|
current = intersection_with_selected;
|
|
|
|
} else {
|
2021-06-03 16:29:31 +02:00
|
|
|
current = entries.reduce((p, c) => c.intersectionRatio >= (p?.intersectionRatio || 0) ? c : p, null);
|
2020-07-01 21:45:18 +02:00
|
|
|
}
|
|
|
|
if (current && current.isIntersecting) {
|
|
|
|
const category = current.target.getAttribute('data-category');
|
|
|
|
if (category !== this.model.get('current_category')) {
|
|
|
|
this.parentElement.preserve_scroll = true;
|
|
|
|
this.model.save({'current_category': category});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
insertEmoji (ev) {
|
|
|
|
ev.preventDefault();
|
|
|
|
ev.stopPropagation();
|
|
|
|
const target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
|
2020-07-13 10:10:58 +02:00
|
|
|
this.parentElement.insertIntoTextArea(target.getAttribute('data-emoji'));
|
2020-07-01 21:45:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
shouldBeHidden (shortname) {
|
|
|
|
// Helper method for the template which decides whether an
|
|
|
|
// emoji should be hidden, based on which skin tone is
|
|
|
|
// currently being applied.
|
|
|
|
if (shortname.includes('_tone')) {
|
|
|
|
if (!this.current_skintone || !shortname.includes(this.current_skintone)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
2022-04-06 11:18:12 +02:00
|
|
|
if (this.current_skintone && getTonedEmojis().includes(shortname)) {
|
2020-07-01 21:45:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (this.query && !_converse.FILTER_CONTAINS(shortname, this.query)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
api.elements.define('converse-emoji-picker-content', EmojiPickerContent);
|