Load visible emoji groups when scrolling

This commit is contained in:
Tusooa Zhu 2021-08-14 23:37:00 -04:00
parent 992d57ef69
commit ba1b006e05
No known key found for this signature in database
GPG Key ID: 7B467EDE43A08224
2 changed files with 75 additions and 30 deletions

View File

@ -57,7 +57,8 @@ const EmojiPicker = {
keepOpen: false, keepOpen: false,
customEmojiBufferSlice: LOAD_EMOJI_BY, customEmojiBufferSlice: LOAD_EMOJI_BY,
customEmojiTimeout: null, customEmojiTimeout: null,
customEmojiLoadAllConfirmed: false customEmojiLoadAllConfirmed: false,
groupLoadedCount: {}
} }
}, },
components: { components: {
@ -79,7 +80,9 @@ const EmojiPicker = {
const target = (e && e.target) || this.$refs['emoji-groups'] const target = (e && e.target) || this.$refs['emoji-groups']
this.updateScrolledClass(target) this.updateScrolledClass(target)
this.scrolledGroup(target) this.scrolledGroup(target)
this.$nextTick(() => {
this.triggerLoadMore(target) this.triggerLoadMore(target)
})
}, },
highlight (key) { highlight (key) {
const ref = this.$refs['group-' + key] const ref = this.$refs['group-' + key]
@ -88,6 +91,7 @@ const EmojiPicker = {
this.activeGroup = key this.activeGroup = key
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['emoji-groups'].scrollTop = top + 1 this.$refs['emoji-groups'].scrollTop = top + 1
this.loadEmoji(key)
}) })
}, },
updateScrolledClass (target) { updateScrolledClass (target) {
@ -100,10 +104,16 @@ const EmojiPicker = {
} }
}, },
triggerLoadMore (target) { triggerLoadMore (target) {
const ref = this.$refs[`group-end-${this.lastNonUnicodeGroupId}`][0] Object.keys(this.allCustomGroups)
if (!ref) return .map(groupId => {
const ref = this.$refs[`group-end-${groupId}`][0]
if (!ref) return undefined
const bottom = ref.offsetTop + ref.offsetHeight const bottom = ref.offsetTop + ref.offsetHeight
const group = this.$refs[`group-${groupId}`][0]
const top = group.offsetTop
const scrollerBottom = target.scrollTop + target.clientHeight const scrollerBottom = target.scrollTop + target.clientHeight
const scrollerTop = target.scrollTop const scrollerTop = target.scrollTop
const scrollerMax = target.scrollHeight const scrollerMax = target.scrollHeight
@ -111,17 +121,23 @@ const EmojiPicker = {
// Loads more emoji when they come into view // Loads more emoji when they come into view
const approachingBottom = bottom - scrollerBottom < LOAD_EMOJI_MARGIN const approachingBottom = bottom - scrollerBottom < LOAD_EMOJI_MARGIN
// Always load when at the very top in case there's no scroll space yet // Always load when at the very top in case there's no scroll space yet
const atTop = scrollerTop < 5 const atTop = scrollerTop < top + target.clientHeight / 2 && top < scrollerBottom
// Don't load when looking at unicode category or at the very bottom // Don't load when looking at unicode category or at the very bottom
const bottomAboveViewport = bottom < scrollerTop || scrollerBottom === scrollerMax const bottomAboveViewport = bottom < scrollerTop || scrollerBottom === scrollerMax
if (!bottomAboveViewport && (approachingBottom || atTop)) { if (!bottomAboveViewport && (approachingBottom || atTop)) {
this.loadEmoji() return groupId
} }
return undefined
})
.filter(k => k)
.map(k => {
this.loadEmoji(k)
})
}, },
scrolledGroup (target) { scrolledGroup (target) {
const top = target.scrollTop + 5 const top = target.scrollTop + 5
this.$nextTick(() => { this.$nextTick(() => {
this.emojisView.forEach(group => { this.allEmojiGroups.forEach(group => {
const ref = this.$refs['group-' + group.id] const ref = this.$refs['group-' + group.id]
if (ref.offsetTop <= top) { if (ref.offsetTop <= top) {
this.activeGroup = group.id this.activeGroup = group.id
@ -129,14 +145,21 @@ const EmojiPicker = {
}) })
}) })
}, },
loadEmoji () { loadEmoji (loadGroup) {
const allLoaded = this.customEmojiBuffer.length === this.filteredEmoji.length if (!this.allCustomGroups[loadGroup]) {
return
}
const allLoaded = this.loadedCount[loadGroup] >= this.allCustomGroups[loadGroup].emojis.length
if (allLoaded) { if (allLoaded) {
return return
} }
this.customEmojiBufferSlice += LOAD_EMOJI_BY this.groupLoadedCount = {
...this.groupLoadedCount,
[loadGroup]: this.loadedCount[loadGroup] + LOAD_EMOJI_BY
}
}, },
startEmojiLoad (forceUpdate = false) { startEmojiLoad (forceUpdate = false) {
if (!forceUpdate) { if (!forceUpdate) {
@ -157,6 +180,9 @@ const EmojiPicker = {
}, },
setShowStickers (value) { setShowStickers (value) {
this.showingStickers = value this.showingStickers = value
},
limitedEmojis (list, groupId) {
return list.slice(0, this.loadedCount[groupId])
} }
}, },
watch: { watch: {
@ -205,24 +231,36 @@ const EmojiPicker = {
return res return res
}, {}) }, {})
}, },
allEmojiGroups () { allCustomGroups () {
return this.allEmojis return this.filteredEmoji
.reduce((res, emoji) => { .reduce((res, emoji) => {
const packName = packOf(emoji) const packName = packOf(emoji)
const packId = `custom-${packName}` const packId = `custom-${packName}`
if (res.filter(k => k.id === packId).length === 0) { if (!res[packId]) {
res.push({ res[packId] = ({
id: packId, id: packId,
text: packName, text: packName,
image: emoji.imageUrl image: emoji.imageUrl,
emojis: []
}) })
} }
res[packId].emojis.push(emoji)
return res return res
}, []) }, {})
},
sensibleInitialAmountForAGroup () {
const groupCount = Object.keys(this.allCustomGroups).length
return Math.max(Math.floor(LOAD_EMOJI_BY / Math.max(groupCount, 1)), 1)
},
allEmojiGroups () {
const standardEmojis = this.$store.state.instance.emoji || []
return Object.entries(this.allCustomGroups)
.map(([_, v]) => v)
.concat({ .concat({
id: 'standard', id: 'standard',
text: this.$t('emoji.unicode'), text: this.$t('emoji.unicode'),
icon: 'box-open' icon: 'box-open',
emojis: filterByKeyword(standardEmojis, this.keyword)
}) })
}, },
emojis () { emojis () {
@ -241,6 +279,13 @@ const EmojiPicker = {
} }
] ]
}, },
loadedCount () {
return Object.keys(this.allCustomGroups)
.reduce((res, groupId) => {
res[groupId] = this.groupLoadedCount[groupId] || this.sensibleInitialAmountForAGroup
return res
}, {})
},
lastNonUnicodeGroupId () { lastNonUnicodeGroupId () {
return this.emojis[this.emojis.length - 2].id return this.emojis[this.emojis.length - 2].id
}, },

View File

@ -67,7 +67,7 @@
@scroll="onScroll" @scroll="onScroll"
> >
<div <div
v-for="group in emojisView" v-for="group in allEmojiGroups"
:key="group.id" :key="group.id"
class="emoji-group" class="emoji-group"
> >
@ -78,7 +78,7 @@
{{ group.text }} {{ group.text }}
</h6> </h6>
<span <span
v-for="emoji in group.emojis" v-for="emoji in limitedEmojis(group.emojis, group.id)"
:key="group.id + emoji.displayText" :key="group.id + emoji.displayText"
:title="emoji.displayText" :title="emoji.displayText"
class="emoji-item" class="emoji-item"