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:
commit
d6a7f46480
13 changed files with 211 additions and 73 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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%;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue