Performance fixes

This commit is contained in:
wvffle 2022-07-24 23:43:40 +00:00 committed by Georg Krause
parent 29afac3101
commit d1b8190dca
5 changed files with 68 additions and 48 deletions

View File

@ -44,6 +44,7 @@
"vue-router": "4.1.2", "vue-router": "4.1.2",
"vue-tsc": "0.38.9", "vue-tsc": "0.38.9",
"vue-upload-component": "3.1.2", "vue-upload-component": "3.1.2",
"vue-virtual-scroller": "^2.0.0-alpha.1",
"vue3-gettext": "2.3.0", "vue3-gettext": "2.3.0",
"vue3-lazyload": "0.3.5", "vue3-lazyload": "0.3.5",
"vue3-virtual-scroll-list": "0.2.0", "vue3-virtual-scroll-list": "0.2.0",
@ -61,6 +62,7 @@
"@types/qs": "6.9.7", "@types/qs": "6.9.7",
"@types/semantic-ui": "2.2.7", "@types/semantic-ui": "2.2.7",
"@types/showdown": "2.0.0", "@types/showdown": "2.0.0",
"@types/vue-virtual-scroller": "npm:@earltp/vue-virtual-scroller",
"@typescript-eslint/eslint-plugin": "5.30.7", "@typescript-eslint/eslint-plugin": "5.30.7",
"@vitejs/plugin-vue": "3.0.1", "@vitejs/plugin-vue": "3.0.1",
"@vue/compiler-sfc": "3.2.37", "@vue/compiler-sfc": "3.2.37",

View File

@ -387,12 +387,19 @@ const reorderTracks = async (from: number, to: number) => {
:list="queueItems" :list="queueItems"
:component="QueueItem" :component="QueueItem"
:size="50" :size="50"
:item-class="(index: number) => currentIndex === index ? 'active': ''"
data-key="id"
@play="play"
@remove="removeTrack"
@reorder="reorderTracks" @reorder="reorderTracks"
/> >
<template #default="{ index, item, classList }">
<queue-item
:data-index="index"
:index="index"
:source="item"
:class="[...classList, currentIndex === index && 'active']"
@play="play"
@remove="removeTrack"
/>
</template>
</virtual-list>
<div <div
v-if="$store.state.radios.running" v-if="$store.state.radios.running"
class="ui info message" class="ui info message"

View File

@ -4,7 +4,6 @@ import type { QueueItemSource } from '~/types'
interface Props { interface Props {
source: QueueItemSource source: QueueItemSource
index: number index: number
itemClass: (index: number) => string
} }
interface Emits { interface Emits {
@ -18,7 +17,6 @@ defineEmits<Emits>()
<template> <template>
<div <div
:class="itemClass(index)"
class="queue-item" class="queue-item"
tabindex="0" tabindex="0"
> >

View File

@ -4,9 +4,10 @@ import type { MaybeElementRef, MaybeElement } from '@vueuse/core'
import { useMouse, useCurrentElement, useResizeObserver, useRafFn, useElementByPoint } from '@vueuse/core' import { useMouse, useCurrentElement, useResizeObserver, useRafFn, useElementByPoint } from '@vueuse/core'
import { ref, watchEffect, reactive } from 'vue' import { ref, watchEffect, reactive } from 'vue'
import VirtualItem from './VirtualItem.vue'
// @ts-expect-error no typings // @ts-expect-error no typings
import VirtualList from 'vue3-virtual-scroll-list' // import VirtualList from 'vue3-virtual-scroll-list'
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
interface Emits { interface Emits {
(e: 'reorder', from: number, to: number): void (e: 'reorder', from: number, to: number): void
@ -15,7 +16,6 @@ interface Emits {
interface Props { interface Props {
list: object[] list: object[]
size: number size: number
dataKey: string
} }
const emit = defineEmits<Emits>() const emit = defineEmits<Emits>()
@ -31,7 +31,7 @@ const getIndex = (element: HTMLElement) => +(element?.getAttribute('data-index')
const isTouch = ref(false) const isTouch = ref(false)
const onMousedown = (event: MouseEvent | TouchEvent) => { const onMousedown = (event: MouseEvent | TouchEvent) => {
const element = event.target as HTMLElement const element = event.target as HTMLElement
const dragItem = element.closest('.drag-item')?.children[0] as HTMLElement const dragItem = element.closest('.drag-item') as HTMLElement
if (!dragItem || !element.classList.contains('handle')) return if (!dragItem || !element.classList.contains('handle')) return
// Touch devices stop emitting touch events while container is scrolled // Touch devices stop emitting touch events while container is scrolled
@ -68,10 +68,7 @@ document.addEventListener('touchcancel', (event: TouchEvent) => {
}) })
const reorder = (event: MouseEvent | TouchEvent) => { const reorder = (event: MouseEvent | TouchEvent) => {
const element = event.target as HTMLElement if (draggedItem.value) {
const dragItem = element.closest('.drag-item')?.children[0]
if (dragItem && draggedItem.value) {
const from = draggedItem.value.index const from = draggedItem.value.index
let to = hoveredIndex.value let to = hoveredIndex.value
@ -98,10 +95,6 @@ const cleanup = () => {
scrollDirection.value = undefined scrollDirection.value = undefined
} }
const dragClassHandler = (index: number) => draggedItem.value && hoveredIndex.value === index
? `drop-${position.value}`
: ''
const scrollDirection = ref() const scrollDirection = ref()
const containerSize = reactive({ bottom: 0, top: 0 }) const containerSize = reactive({ bottom: 0, top: 0 })
const { x, y: screenY } = useMouse({ type: 'client' }) const { x, y: screenY } = useMouse({ type: 'client' })
@ -109,12 +102,14 @@ const { element: hoveredElement } = useElementByPoint({ x, y: screenY })
// Find current index and position on both desktop and mobile devices // Find current index and position on both desktop and mobile devices
watchEffect(() => { watchEffect(() => {
const dragItem = (hoveredElement.value as HTMLElement)?.closest('.drag-item')?.children[0] as HTMLElement if (draggedItem.value) {
if (!dragItem) return const dragItem = (hoveredElement.value as HTMLElement)?.closest('.drag-item') as HTMLElement
if (!dragItem) return
hoveredIndex.value = getIndex(dragItem) hoveredIndex.value = getIndex(dragItem)
const { y } = dragItem.getBoundingClientRect() const { y } = dragItem.getBoundingClientRect()
position.value = screenY.value - y < props.size / 2 ? 'before' : 'after' position.value = screenY.value - y < props.size / 2 ? 'before' : 'after'
}
}) })
// Automatically scroll when on the edge // Automatically scroll when on the edge
@ -137,7 +132,6 @@ watchEffect(() => {
scrollDirection.value = undefined scrollDirection.value = undefined
}) })
const keeps = ref(30)
const el = useCurrentElement() const el = useCurrentElement()
useResizeObserver(el as unknown as MaybeElementRef<MaybeElement>, ([entry]) => { useResizeObserver(el as unknown as MaybeElementRef<MaybeElement>, ([entry]) => {
const height = entry.borderBoxSize?.[0]?.blockSize ?? 0 const height = entry.borderBoxSize?.[0]?.blockSize ?? 0
@ -145,7 +139,6 @@ useResizeObserver(el as unknown as MaybeElementRef<MaybeElement>, ([entry]) => {
if (height !== 0) { if (height !== 0) {
containerSize.top = (entry.target as HTMLElement).offsetTop containerSize.top = (entry.target as HTMLElement).offsetTop
containerSize.bottom = height + containerSize.top containerSize.bottom = height + containerSize.top
keeps.value = (containerSize.bottom - containerSize.top) / props.size * 2 | 0
} }
}) })
@ -164,38 +157,29 @@ const { resume, pause } = useRafFn(() => {
const virtualList = ref() const virtualList = ref()
defineExpose({ defineExpose({
scrollToIndex: (index: number) => virtualList.value?.scrollToIndex(index), scrollToIndex: (index: number) => virtualList.value?.scrollToItem(index),
cleanup cleanup
}) })
</script> </script>
<script lang="ts">
export default {
inheritAttrs: false
}
</script>
<template> <template>
<div> <div>
<component <recycle-scroller
:is="VirtualList"
ref="virtualList" ref="virtualList"
class="virtual-list" v-slot="{ item, index }"
wrap-class="drag-container" class="virtual-list drag-container"
item-class="drag-item" :items="list"
:keeps="keeps" :item-size="size"
:data-key="dataKey"
:data-sources="list"
:data-component="VirtualItem"
:estimate-size="size"
:extra-props="{
dragClassHandler,
...$attrs
}"
@mousedown="onMousedown" @mousedown="onMousedown"
@touchstart="onMousedown" @touchstart="onMousedown"
@touchmove="onTouchmove" @touchmove="onTouchmove"
/> >
<slot
:class-list="[draggedItem && hoveredIndex === index && `drop-${position}`, 'drag-item']"
:item="item"
:index="index"
/>
</recycle-scroller>
<div <div
ref="ghostContainer" ref="ghostContainer"

View File

@ -1689,6 +1689,11 @@
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
"@types/vue-virtual-scroller@npm:@earltp/vue-virtual-scroller":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@earltp/vue-virtual-scroller/-/vue-virtual-scroller-1.0.1.tgz#75116ef9b091457a654d92ff0688e991b3cd9e8a"
integrity sha512-7UsmP2JALnkfWlheuWRDywuBUTLJcVPE86X5ogA3djUmYFybE6qximgQ7OgyJnrKLteWR7+1Cp0GUXHhdDKaDQ==
"@types/web-bluetooth@^0.0.14": "@types/web-bluetooth@^0.0.14":
version "0.0.14" version "0.0.14"
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5" resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5"
@ -5076,6 +5081,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
mitt@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==
moment@2.29.4: moment@2.29.4:
version "2.29.4" version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
@ -6479,6 +6489,11 @@ vue-jest@3.0.7:
tsconfig "^7.0.0" tsconfig "^7.0.0"
vue-template-es2015-compiler "^1.6.0" vue-template-es2015-compiler "^1.6.0"
vue-observe-visibility@^2.0.0-alpha.1:
version "2.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/vue-observe-visibility/-/vue-observe-visibility-2.0.0-alpha.1.tgz#1e4eda7b12562161d58984b7e0dea676d83bdb13"
integrity sha512-flFbp/gs9pZniXR6fans8smv1kDScJ8RS7rEpMjhVabiKeq7Qz3D9+eGsypncjfIyyU84saU88XZ0zjbD6Gq/g==
vue-plyr@7.0.0: vue-plyr@7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/vue-plyr/-/vue-plyr-7.0.0.tgz#938257e2a4def4582b5803a16087371a8e96209e" resolved "https://registry.yarnpkg.com/vue-plyr/-/vue-plyr-7.0.0.tgz#938257e2a4def4582b5803a16087371a8e96209e"
@ -6487,6 +6502,11 @@ vue-plyr@7.0.0:
plyr "github:sampotts/plyr#develop" plyr "github:sampotts/plyr#develop"
vue "^2.6.12" vue "^2.6.12"
vue-resize@^2.0.0-alpha.1:
version "2.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz#43eeb79e74febe932b9b20c5c57e0ebc14e2df3a"
integrity sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==
vue-router@4.1.2: vue-router@4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.1.2.tgz#ae08f63c9610afa6bff6743e8f128b7054d4c9f5" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.1.2.tgz#ae08f63c9610afa6bff6743e8f128b7054d4c9f5"
@ -6511,6 +6531,15 @@ vue-upload-component@3.1.2:
resolved "https://registry.yarnpkg.com/vue-upload-component/-/vue-upload-component-3.1.2.tgz#9ba050f408781b008a16cb8bfaadbcf07eab68fa" resolved "https://registry.yarnpkg.com/vue-upload-component/-/vue-upload-component-3.1.2.tgz#9ba050f408781b008a16cb8bfaadbcf07eab68fa"
integrity sha512-z7/98xhNbLecTf09ZyJp0QKH6RMoVH3ojBrWYonPPHQ6qodQf0qVV81+vnB94cFVWpR/mb+F+dMN2p04K14ouw== integrity sha512-z7/98xhNbLecTf09ZyJp0QKH6RMoVH3ojBrWYonPPHQ6qodQf0qVV81+vnB94cFVWpR/mb+F+dMN2p04K14ouw==
vue-virtual-scroller@^2.0.0-alpha.1:
version "2.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/vue-virtual-scroller/-/vue-virtual-scroller-2.0.0-alpha.1.tgz#5b5410105b8e60ca57bbd5f2faf5ad1d8108d046"
integrity sha512-Mn5w3Qe06t7c3Imm2RHD43RACab1CCWplpdgzq+/FWJcpQtcGKd5vDep8i+nIwFtzFLsWAqEK0RzM7KrfAcBng==
dependencies:
mitt "^2.1.0"
vue-observe-visibility "^2.0.0-alpha.1"
vue-resize "^2.0.0-alpha.1"
vue3-gettext@2.3.0: vue3-gettext@2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/vue3-gettext/-/vue3-gettext-2.3.0.tgz#5825949e3978aa576e035128de46c97e59b65a5b" resolved "https://registry.yarnpkg.com/vue3-gettext/-/vue3-gettext-2.3.0.tgz#5825949e3978aa576e035128de46c97e59b65a5b"