FIX: improves efficiency

This commit is contained in:
Joffrey JAFFEUX 2017-07-24 12:41:39 +02:00
parent d9c3ebe299
commit 995d253030
1 changed files with 63 additions and 77 deletions

View File

@ -8,19 +8,17 @@ import { extendedEmojiList, isSkinTonableEmoji } from "pretty-text/emoji";
const keyValueStore = new KeyValueStore("discourse_emojis_"); const keyValueStore = new KeyValueStore("discourse_emojis_");
const EMOJI_USAGE = "emojiUsage"; const EMOJI_USAGE = "emojiUsage";
const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity"; const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
const EMOJI_CACHED_SECTIONS = "emojiCachedSections";
const PER_ROW = 11; const PER_ROW = 11;
const customEmojis = _.map(_.keys(extendedEmojiList()), code => { const customEmojis = _.map(_.keys(extendedEmojiList()), code => {
return { code, src: emojiUrlFor(code) }; return { code, src: emojiUrlFor(code) };
}); });
export function resetCache() { export function resetCache() {
keyValueStore.setObject({ key: EMOJI_CACHED_SECTIONS, value: [] });
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] }); keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
keyValueStore.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: 1 }); keyValueStore.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: 1 });
} }
let $picker, $filter, $results, $list, scrollPosition; let $picker, $filter, $results, $list, scrollPosition, $visibleSections;
export default Ember.Component.extend({ export default Ember.Component.extend({
willDestroyElement() { willDestroyElement() {
@ -30,12 +28,6 @@ export default Ember.Component.extend({
this.appEvents.off("emoji-picker:close"); this.appEvents.off("emoji-picker:close");
}, },
didDestroyElement() {
this._super();
$picker = null;
},
didInsertElement() { didInsertElement() {
this._super(); this._super();
@ -43,10 +35,6 @@ export default Ember.Component.extend({
$picker = this.$(".emoji-picker"); $picker = this.$(".emoji-picker");
if (!keyValueStore.getObject(EMOJI_CACHED_SECTIONS)) {
keyValueStore.setObject({ key: EMOJI_CACHED_SECTIONS, value: [] });
}
if (!keyValueStore.getObject(EMOJI_USAGE)) { if (!keyValueStore.getObject(EMOJI_USAGE)) {
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] }); keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
} else if(_.isPlainObject(keyValueStore.getObject(EMOJI_USAGE))) { } else if(_.isPlainObject(keyValueStore.getObject(EMOJI_USAGE))) {
@ -77,20 +65,28 @@ export default Ember.Component.extend({
selectedDiversityChanged() { selectedDiversityChanged() {
keyValueStore.setObject({key: EMOJI_SELECTED_DIVERSITY, value: this.get("selectedDiversity")}); keyValueStore.setObject({key: EMOJI_SELECTED_DIVERSITY, value: this.get("selectedDiversity")});
$.each($list.find(".emoji.diversity"), (_, button) => this._setButtonBackground(button, true) ); $.each($list.find(".emoji[data-loaded='1'].diversity"), (_, button) => this._setButtonBackground(button, true) );
if(this.get("filter") !== "") { if(this.get("filter") !== "") {
$.each($results.find(".emoji.diversity"), (_, button) => this._setButtonBackground(button, true) ); $.each($results.find(".emoji.diversity"), (_, button) => this._setButtonBackground(button, true) );
} }
$picker
.find(".diversity-picker .diversity-scale")
.removeClass("selected");
$picker
.find(`.diversity-picker .diversity-scale[data-level="${this.get("selectedDiversity")}"]`)
.addClass("selected");
}, },
@observes("recentEmojis") @observes("recentEmojis")
recentEmojisChanged() { recentEmojisChanged() {
const previousScrollTop = $list.scrollTop(); const previousScrollTop = scrollPosition;
const $recentSection = $list.find(".section[data-section='recent']"); const $recentSection = $list.find(".section[data-section='recent']");
const $recentSectionGroup = $recentSection.find(".section-group"); const $recentSectionGroup = $recentSection.find(".section-group");
const $recentCategory = $picker.find(".category-icon button[data-section='recent']").parent(); const $recentCategory = $picker.find(".category-icon button[data-section='recent']").parent();
let persistScrollPosition = !$recentCategory.is(':visible') ? true : false; let persistScrollPosition = !$recentCategory.is(":visible") ? true : false;
// we set height to 0 to avoid it being taken into account for scroll position // we set height to 0 to avoid it being taken into account for scroll position
if(_.isEmpty(this.get("recentEmojis"))) { if(_.isEmpty(this.get("recentEmojis"))) {
@ -122,10 +118,12 @@ export default Ember.Component.extend({
this.$().find(".emoji-picker-modal").remove(); this.$().find(".emoji-picker-modal").remove();
this._unbindEvents(); this._unbindEvents();
this._unbindSectionLoadingCheck();
}, },
show() { show() {
const template = findRawTemplate("emoji-picker")({ customEmojis }); const template = findRawTemplate("emoji-picker")({customEmojis});
$picker.html(template); $picker.html(template);
this.$().append("<div class='emoji-picker-modal'></div>"); this.$().append("<div class='emoji-picker-modal'></div>");
@ -140,12 +138,24 @@ export default Ember.Component.extend({
Ember.run.scheduleOnce("afterRender", this, function() { Ember.run.scheduleOnce("afterRender", this, function() {
this._loadCategoriesEmojis(); this._loadCategoriesEmojis();
this._setDiversity();
this._positionPicker(); this._positionPicker();
this._scrollTo(); this._scrollTo();
this._sectionLoadingCheck();
}); });
}, },
_unbindSectionLoadingCheck() {
Ember.run.cancel(this.get("nextSectionloadingCheck"));
},
_sectionLoadingCheck() {
const nextSectionloadingCheck = Ember.run.later(this, function() {
Ember.run.throttle(this, this._checkVisibleSection, 100);
this._sectionLoadingCheck();
}, 500);
this.set("nextSectionloadingCheck", nextSectionloadingCheck);
},
_loadCategoriesEmojis() { _loadCategoriesEmojis() {
$.each($picker.find(".categories-column button.emoji"), (_, button) => { $.each($picker.find(".categories-column button.emoji"), (_, button) => {
const $button = $(button); const $button = $(button);
@ -313,8 +323,8 @@ export default Ember.Component.extend({
_bindSectionsScroll() { _bindSectionsScroll() {
$list.on("scroll", () => { $list.on("scroll", () => {
Ember.run.debounce(this, this._checkVisibleSection, 150);
scrollPosition = $list.scrollTop(); scrollPosition = $list.scrollTop();
Ember.run.throttle(this, this._checkVisibleSection, 150);
}); });
}, },
@ -325,68 +335,60 @@ export default Ember.Component.extend({
} }
const $sections = $list.find(".section"); const $sections = $list.find(".section");
const sections = []; const listHeight = $list.innerHeight();
let cumulatedHeight = 0; let $selectedSection;
$.each($sections, (_, section) => { $visibleSections = _.filter($sections, section => {
const $section = $(section); const $section = $(section);
sections.push({$section, cumulatedHeight}); const sectionTop = $section.position().top;
cumulatedHeight += $section.innerHeight(); return sectionTop + $section.height() > 0 && sectionTop < listHeight;
}); });
let selectedSection; if (!_.isEmpty(this.get("recentEmojis")) && scrollPosition === 0) {
const currentScrollTop = $list.scrollTop(); $selectedSection = $(_.first($visibleSections));
if (!_.isEmpty(this.get("recentEmojis")) && currentScrollTop === 0) {
selectedSection = _.first(sections);
} else if (!_.isEmpty(customEmojis) &&
currentScrollTop === $list[0].scrollHeight - $list.innerHeight())
{
selectedSection = _.last(sections);
} else { } else {
selectedSection = _.last(_.reject(sections, (section) => { $selectedSection = $(_.last($visibleSections));
return section.cumulatedHeight > currentScrollTop;
}));
} }
if(selectedSection) { if($selectedSection) {
const sectionTitle = selectedSection.$section.data("section");
$picker.find(".category-icon").removeClass("current"); $picker.find(".category-icon").removeClass("current");
$picker.find(`.category-icon button[data-section='${sectionTitle}']`) $picker.find(`.category-icon button[data-section='${$selectedSection.data("section")}']`)
.parent() .parent()
.addClass("current"); .addClass("current");
if(!selectedSection.$section.hasClass("loaded")) { this._loadVisibleSections();
selectedSection.$section.addClass("loaded"); }
this._loadSection(selectedSection.$section); },
_loadVisibleSections() {
if(!$visibleSections) {
return;
} }
//preload surrounding sections const listHeight = $list.innerHeight();
const selectedSectionIndex = sections.indexOf(selectedSection); $visibleSections.forEach(visibleSection => {
const preloadedSection = sections[selectedSectionIndex + 1] || sections[selectedSectionIndex - 1]; const $unloadedEmojis = $(visibleSection).find("button.emoji[data-loaded!='1']");
if(preloadedSection && !preloadedSection.$section.hasClass("loaded")) { $.each($unloadedEmojis, (_, button) => {
preloadedSection.$section.addClass("loaded"); const $button = $(button);
this._loadSection(preloadedSection.$section); const buttonTop = $button.position().top;
} const buttonHeight = $button.height();
if(buttonTop + buttonHeight > 0 && buttonTop - buttonHeight < listHeight) {
this._setButtonBackground($button);
} }
});
});
}, },
_bindDiversityClick() { _bindDiversityClick() {
const $diversityScales = $picker.find(".diversity-picker .diversity-scale"); const $diversityScales = $picker.find(".diversity-picker .diversity-scale");
$diversityScales.on("click", (event) => { $diversityScales.on("click", (event) => {
const $selectedDiversity = $(event.currentTarget); const $selectedDiversity = $(event.currentTarget);
$diversityScales.removeClass("selected");
$selectedDiversity.addClass("selected");
this.set("selectedDiversity", parseInt($selectedDiversity.data("level"))); this.set("selectedDiversity", parseInt($selectedDiversity.data("level")));
return false; return false;
}); });
}, },
_setDiversity() {
$picker
.find(`.diversity-picker .diversity-scale[data-level="${this.get("selectedDiversity")}"]`)
.addClass("selected");
},
_isReplyControlExpanded() { _isReplyControlExpanded() {
const verticalSpace = this.$(window).height() - const verticalSpace = this.$(window).height() -
Ember.$(".d-header").height() - Ember.$(".d-header").height() -
@ -490,24 +492,6 @@ export default Ember.Component.extend({
$picker.find(".info").css("max-width", infoMaxWidth); $picker.find(".info").css("max-width", infoMaxWidth);
}, },
_loadSection($section) {
const sectionName = $section.data("section");
if(keyValueStore.getObject(EMOJI_CACHED_SECTIONS).indexOf(sectionName) > -1) {
$.each($section.find(".emoji"), (_, button) => this._setButtonBackground(button) );
} else {
Ember.run.later(
this, () => {
keyValueStore.setObject({
key: EMOJI_CACHED_SECTIONS,
value: keyValueStore.getObject(EMOJI_CACHED_SECTIONS).concat(sectionName)
});
$.each($section.find(".emoji"), (_, button) => this._setButtonBackground(button) );
},
1500
);
}
},
_codeWithDiversity(code, diversity) { _codeWithDiversity(code, diversity) {
if(diversity && this.get("selectedDiversity") !== 1) { if(diversity && this.get("selectedDiversity") !== 1) {
return `${code}:t${this.get("selectedDiversity")}`; return `${code}:t${this.get("selectedDiversity")}`;
@ -553,6 +537,8 @@ export default Ember.Component.extend({
$button.css("background-image", ""); $button.css("background-image", "");
} }
$button.css("background-image", `url("${emojiUrlFor(code)}")`); $button
.attr("data-loaded", 1)
.css("background-image", `url("${emojiUrlFor(code)}")`);
}, },
}); });