aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot/after_store.js3
-rw-r--r--src/components/emoji_picker/emoji_picker.js33
-rw-r--r--src/components/emoji_picker/emoji_picker.scss1
-rw-r--r--src/components/emoji_picker/emoji_picker.vue79
4 files changed, 58 insertions, 58 deletions
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 7a4672b6..1fa9dd2a 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -1,6 +1,8 @@
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import vClickOutside from 'click-outside-vue3'
+import VueVirtualScroller from 'vue-virtual-scroller'
+import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
@@ -397,6 +399,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
app.use(vClickOutside)
app.use(VBodyScrollLock)
+ app.use(VueVirtualScroller)
app.component('FAIcon', FontAwesomeIcon)
app.component('FALayers', FontAwesomeLayers)
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 68240fd8..c87dea7e 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -143,22 +143,13 @@ const EmojiPicker = {
}
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
},
- onScroll (e) {
- const target = (e && e.target) || this.$refs['emoji-groups']
- this.updateScrolledClass(target)
- this.scrolledGroup(target)
+ onScroll (startIndex, endIndex, visibleStartIndex, visibleEndIndex) {
+ const current = this.filteredEmojiGroups[visibleStartIndex].id
+ this.scrolledGroup(current)
},
- scrolledGroup (target) {
- const top = target.scrollTop + 5
- this.$nextTick(() => {
- this.allEmojiGroups.forEach(group => {
- const ref = this.groupRefs['group-' + group.id]
- if (ref && ref.offsetTop <= top) {
- this.activeGroup = group.id
- }
- })
- this.scrollHeader()
- })
+ scrolledGroup (groupId) {
+ this.activeGroup = groupId
+ this.scrollHeader()
},
scrollHeader () {
// Scroll the active tab's header into view
@@ -177,14 +168,9 @@ const EmojiPicker = {
setScroll(right + margin - headerCont.clientWidth)
}
},
- highlight (key) {
- const ref = this.groupRefs['group-' + key]
- const top = ref.offsetTop
+ highlight (index) {
this.setShowStickers(false)
- this.activeGroup = key
- this.$nextTick(() => {
- this.$refs['emoji-groups'].scrollTop = top + 1
- })
+ this.$refs['emoji-groups'].scrollToItem(index)
},
updateScrolledClass (target) {
if (target.scrollTop <= 5) {
@@ -238,6 +224,9 @@ const EmojiPicker = {
}
},
computed: {
+ minItemSize () {
+ return 32
+ },
activeGroupView () {
return this.showingStickers ? '' : this.activeGroup
},
diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index 53363ec1..dda12197 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -74,6 +74,7 @@ $emoji-picker-emoji-size: 32px;
}
.emoji-groups {
+ height: 100%;
min-height: 200px;
}
diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue
index d0b7fe8f..15cdb704 100644
--- a/src/components/emoji_picker/emoji_picker.vue
+++ b/src/components/emoji_picker/emoji_picker.vue
@@ -13,7 +13,7 @@
class="emoji-tabs"
>
<span
- v-for="group in filteredEmojiGroups"
+ v-for="(group, index) in filteredEmojiGroups"
:ref="setGroupRef('group-header-' + group.id)"
:key="group.id"
class="emoji-tabs-item"
@@ -21,7 +21,7 @@
active: activeGroupView === group.id
}"
:title="group.text"
- @click.prevent="highlight(group.id)"
+ @click.prevent="highlight(index)"
>
<span
v-if="group.image"
@@ -74,45 +74,52 @@
@input="$event.target.composing = false"
>
</div>
- <div
+ <DynamicScroller
ref="emoji-groups"
class="emoji-groups"
:class="groupsScrolledClass"
- @scroll="onScroll"
+ :min-item-size="minItemSize"
+ :items="filteredEmojiGroups"
+ @update="onScroll"
>
- <div
- v-for="group in filteredEmojiGroups"
- :key="group.id"
- class="emoji-group"
- >
- <h6
- :ref="setGroupRef('group-' + group.id)"
- class="emoji-group-title"
- >
- {{ group.text }}
- </h6>
- <span
- v-for="emoji in group.emojis"
- :key="group.id + emoji.displayText"
- :title="maybeLocalizedEmojiName(emoji)"
- class="emoji-item"
- @click.stop.prevent="onEmoji(emoji)"
+ <template #default="{ item: group, index, active }">
+ <DynamicScrollerItem
+ :item="group"
+ :active="active"
+ :data-index="index"
+ :size-dependencies="[group.emojis.length]"
>
- <span
- v-if="!emoji.imageUrl"
- class="emoji-picker-emoji -unicode"
- >{{ emoji.replacement }}</span>
- <still-image
- v-else
- class="emoji-picker-emoji -custom"
- loading="lazy"
- :src="emoji.imageUrl"
- :data-emoji-name="group.id + emoji.displayText"
- />
- </span>
- <span :ref="setGroupRef('group-end-' + group.id)" />
- </div>
- </div>
+ <div
+ class="emoji-group"
+ >
+ <h6
+ class="emoji-group-title"
+ >
+ {{ group.text }}
+ </h6>
+ <span
+ v-for="emoji in group.emojis"
+ :key="group.id + emoji.displayText"
+ :title="maybeLocalizedEmojiName(emoji)"
+ class="emoji-item"
+ @click.stop.prevent="onEmoji(emoji)"
+ >
+ <span
+ v-if="!emoji.imageUrl"
+ class="emoji-picker-emoji -unicode"
+ >{{ emoji.replacement }}</span>
+ <still-image
+ v-else
+ class="emoji-picker-emoji -custom"
+ loading="lazy"
+ :src="emoji.imageUrl"
+ :data-emoji-name="group.id + emoji.displayText"
+ />
+ </span>
+ </div>
+ </DynamicScrollerItem>
+ </template>
+ </DynamicScroller>
<div class="keep-open">
<Checkbox v-model="keepOpen">
{{ $t('emoji.keep_open') }}