Merge branch 'emoji-optimizations' into shigusegubu

* emoji-optimizations:
  eslint
  fixed emoji picker showing up beyond viewport
  start loading emoji when picker is open
  remove the "textbox grows the 'wrong' way" behavior, replace it with more conditions to scroll to bottom
  arbitrary limit with option to overcome it
  emoji picker gradual render
  moved emoji stuff away from after-store and into users module since we only need emoji after login
This commit is contained in:
Henry Jameson 2019-10-08 21:41:45 +03:00
commit d6a7f46480
13 changed files with 211 additions and 73 deletions

View file

@ -1,4 +1,9 @@
import Checkbox from '../checkbox/checkbox.vue'
import { set } from 'vue'
const LOAD_EMOJI_BY = 50
const LOAD_EMOJI_INTERVAL = 100
const LOAD_EMOJI_SANE_AMOUNT = 500
const filterByKeyword = (list, keyword = '') => {
return list.filter(x => x.displayText.includes(keyword))
@ -18,7 +23,11 @@ const EmojiPicker = {
activeGroup: 'custom',
showingStickers: false,
groupsScrolledClass: 'scrolled-top',
keepOpen: false
keepOpen: false,
customEmojiBuffer: [],
customEmojiTimeout: null,
customEmojiCounter: 0,
customEmojiLoadAllConfirmed: false
}
},
components: {
@ -58,6 +67,40 @@ const EmojiPicker = {
})
})
},
loadEmojiInsane () {
this.customEmojiLoadAllConfirmed = true
this.continueEmojiLoad()
},
loadEmoji () {
const allLoaded = this.customEmojiBuffer.length === this.filteredEmoji.length
const saneLoaded = this.customEmojiBuffer.length >= LOAD_EMOJI_SANE_AMOUNT &&
!this.customEmojiLoadAllConfirmed
if (allLoaded || saneLoaded) {
return
}
this.customEmojiBuffer.push(
...this.filteredEmoji.slice(
this.customEmojiCounter,
this.customEmojiCounter + LOAD_EMOJI_BY
)
)
this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
this.customEmojiCounter += LOAD_EMOJI_BY
},
startEmojiLoad () {
if (this.customEmojiTimeout) {
window.clearTimeout(this.customEmojiTimeout)
}
set(this, 'customEmojiBuffer', [])
this.customEmojiCounter = 0
this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
},
continueEmojiLoad () {
this.customEmojiTimeout = window.setTimeout(this.loadEmoji, LOAD_EMOJI_INTERVAL)
},
toggleStickers () {
this.showingStickers = !this.showingStickers
},
@ -74,6 +117,7 @@ const EmojiPicker = {
watch: {
keyword () {
this.scrolledGroup()
this.startEmojiLoad()
}
},
computed: {
@ -86,15 +130,30 @@ const EmojiPicker = {
}
return 0
},
saneAmount () {
// for UI
return LOAD_EMOJI_SANE_AMOUNT
},
filteredEmoji () {
return filterByKeyword(
this.$store.state.instance.customEmoji || [],
this.keyword
)
},
askForSanity () {
return this.customEmojiBuffer.length >= LOAD_EMOJI_SANE_AMOUNT &&
!this.customEmojiLoadAllConfirmed
},
emojis () {
const standardEmojis = this.$store.state.instance.emoji || []
const customEmojis = this.$store.state.instance.customEmoji || []
const customEmojis = this.customEmojiBuffer
return [
{
id: 'custom',
text: this.$t('emoji.custom'),
icon: 'icon-smile',
emojis: filterByKeyword(customEmojis, this.keyword)
emojis: customEmojis
},
{
id: 'standard',

View file

@ -6,15 +6,25 @@
position: absolute;
right: 0;
left: 0;
height: 320px;
margin: 0 !important;
z-index: 1;
.keep-open {
.keep-open,
.too-many-emoji {
padding: 7px;
line-height: normal;
}
.too-many-emoji {
display: flex;
flex-direction: column;
}
.keep-open-label {
padding: 0 7px;
display: flex;
}
.heading {
display: flex;
height: 32px;
@ -24,7 +34,7 @@
.content {
display: flex;
flex-direction: column;
flex: 1 1 0;
flex: 1 1 auto;
min-height: 0px;
}
@ -32,12 +42,16 @@
flex-grow: 1;
}
.emoji-groups {
min-height: 200px;
}
.additional-tabs {
border-left: 1px solid;
border-left-color: $fallback--icon;
border-left-color: var(--icon, $fallback--icon);
padding-left: 7px;
flex: 0 0 0;
flex: 0 0 auto;
}
.additional-tabs,
@ -68,7 +82,7 @@
}
.sticker-picker {
flex: 1 1 0
flex: 1 1 auto
}
.stickers,
@ -76,7 +90,7 @@
&-content {
display: flex;
flex-direction: column;
flex: 1 1 0;
flex: 1 1 auto;
min-height: 0;
&.hidden {
@ -90,7 +104,7 @@
.emoji {
&-search {
padding: 5px;
flex: 0 0 0;
flex: 0 0 auto;
input {
width: 100%;

View file

@ -80,6 +80,20 @@
{{ $t('emoji.keep_open') }}
</Checkbox>
</div>
<div
v-if="askForSanity"
class="too-many-emoji"
>
<div class="alert warning hint">
{{ $t('emoji.load_all_hint', { saneAmount } ) }}
</div>
<button
class="btn btn-default"
@click="loadEmojiInsane"
>
{{ $t('emoji.load_all', { emojiAmount: filteredEmoji.length } ) }}
</button>
</div>
</div>
<div
v-if="showingStickers"