1
0
mirror of https://github.com/amir20/dozzle.git synced 2026-01-02 19:17:37 +01:00

Uses useScroll instead of handling the scroll event myself (#1642)

* Tries to use-scroll instead of scroll listener

* Moves observer to scrollable content only

* Fixes bugs
This commit is contained in:
Amir Raminfar
2022-01-20 14:23:43 -08:00
committed by GitHub
parent bb7beef6c9
commit 6cfb42412c
5 changed files with 49 additions and 57 deletions

View File

@@ -4,6 +4,8 @@
declare module 'vue' {
export interface GlobalComponents {
CarbonCaretDown: typeof import('~icons/carbon/caret-down')['default']
CilColumns: typeof import('~icons/cil/columns')['default']
ContainerStat: typeof import('./components/ContainerStat.vue')['default']
ContainerTitle: typeof import('./components/ContainerTitle.vue')['default']
FuzzySearchModal: typeof import('./components/FuzzySearchModal.vue')['default']
@@ -13,7 +15,16 @@ declare module 'vue' {
LogEventSource: typeof import('./components/LogEventSource.vue')['default']
LogViewer: typeof import('./components/LogViewer.vue')['default']
LogViewerWithSource: typeof import('./components/LogViewerWithSource.vue')['default']
MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default']
MdiLightChevronDoubleDown: typeof import('~icons/mdi-light/chevron-double-down')['default']
MdiLightChevronLeft: typeof import('~icons/mdi-light/chevron-left')['default']
MdiLightChevronRight: typeof import('~icons/mdi-light/chevron-right')['default']
MdiLightCog: typeof import('~icons/mdi-light/cog')['default']
MdiLightMagnify: typeof import('~icons/mdi-light/magnify')['default']
MobileMenu: typeof import('./components/MobileMenu.vue')['default']
OcticonContainer24: typeof import('~icons/octicon/container24')['default']
OcticonDownload24: typeof import('~icons/octicon/download24')['default']
OcticonTrash24: typeof import('~icons/octicon/trash24')['default']
PastTime: typeof import('./components/PastTime.vue')['default']
RelativeTime: typeof import('./components/RelativeTime.vue')['default']
ScrollableView: typeof import('./components/ScrollableView.vue')['default']

View File

@@ -19,9 +19,9 @@
<script lang="ts" setup>
import { useContainerStore } from "@/stores/container";
import throttle from "lodash.throttle";
import { useScroll } from "@vueuse/core";
import { storeToRefs } from "pinia";
import { onMounted, onUnmounted, ref, watchPostEffect } from "vue";
import { onMounted, ref, watch, watchPostEffect } from "vue";
const props = defineProps({
indeterminate: {
@@ -36,15 +36,28 @@ const props = defineProps({
const scrollProgress = ref(0);
const animation = ref({ cancel: () => {} });
const parentElement = ref<Node>(document);
const root = ref<HTMLElement>();
const store = useContainerStore();
const { activeContainers } = storeToRefs(store);
const onScrollThrottled = throttle(onScroll, 150);
const scrollElement = ref<HTMLElement | Document>((root.value?.closest("[data-scrolling]") as HTMLElement) ?? document);
const { y: scrollY } = useScroll(scrollElement, { throttle: 100 });
function onScroll() {
const parent = parentElement.value == document ? document.documentElement : (parentElement.value as HTMLElement);
scrollProgress.value = parent.scrollTop / (parent.scrollHeight - parent.clientHeight);
onMounted(() => {
watch(
activeContainers,
() => {
scrollElement.value = (root.value?.closest("[data-scrolling]") as HTMLElement) ?? document;
},
{ immediate: true, flush: "post" }
);
});
watchPostEffect(() => {
const parent =
scrollElement.value === document
? (scrollElement.value as Document).documentElement
: (scrollElement.value as HTMLElement);
scrollProgress.value = scrollY.value / (parent.scrollHeight - parent.clientHeight);
animation.value.cancel();
if (props.autoHide && root.value) {
animation.value = root.value.animate(
@@ -57,29 +70,6 @@ function onScroll() {
}
);
}
}
function attachEvents() {
parentElement.value = root.value?.closest("[data-scrolling]") || document;
parentElement.value.addEventListener("scroll", onScrollThrottled);
}
function detachEvents() {
parentElement.value.removeEventListener("scroll", onScrollThrottled);
}
onMounted(() => {
attachEvents();
});
onUnmounted(() => {
detachEvents();
});
watchPostEffect(() => {
activeContainers.value.length;
detachEvents();
attachEvents();
});
</script>
<style scoped lang="scss">

View File

@@ -3,11 +3,14 @@
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<main ref="content" :data-scrolling="scrollable ? true : undefined">
<main :data-scrolling="scrollable ? true : undefined">
<div class="is-scrollbar-progress is-hidden-mobile">
<scroll-progress v-show="paused" :indeterminate="loading" :auto-hide="!loading"></scroll-progress>
</div>
<slot :setLoading="setLoading"></slot>
<div ref="scrollableContent">
<slot :setLoading="setLoading"></slot>
</div>
<div ref="scrollObserver" class="is-scroll-observer"></div>
</main>
@@ -41,7 +44,7 @@ export default {
};
},
mounted() {
const { content } = this.$refs;
const { scrollableContent } = this.$refs;
this.mutationObserver = new MutationObserver((e) => {
if (!this.paused) {
this.scrollToBottom("instant");
@@ -54,7 +57,7 @@ export default {
}
}
});
this.mutationObserver.observe(content, { childList: true, subtree: true });
this.mutationObserver.observe(scrollableContent, { childList: true, subtree: true });
this.intersectionObserver = new IntersectionObserver(
(entries) => (this.paused = entries[0].intersectionRatio == 0),

View File

@@ -38,7 +38,6 @@
"fuzzysort": "^1.1.4",
"hotkeys-js": "^3.8.7",
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1",
"pinia": "^2.0.9",
"sass": "^1.48.0",
"semver": "^7.3.5",
@@ -55,7 +54,7 @@
"@pinia/testing": "^0.0.9",
"@types/jest": "^27.4.0",
"@types/lodash.debounce": "^4.0.6",
"@types/lodash.throttle": "^4.1.6",
"@types/node": "^17.0.10",
"@types/semver": "^7.3.9",
"@vue/test-utils": "^2.0.0-rc.18",
"eventsourcemock": "^2.0.0",

31
pnpm-lock.yaml generated
View File

@@ -11,7 +11,7 @@ specifiers:
'@pinia/testing': ^0.0.9
'@types/jest': ^27.4.0
'@types/lodash.debounce': ^4.0.6
'@types/lodash.throttle': ^4.1.6
'@types/node': ^17.0.10
'@types/semver': ^7.3.9
'@vitejs/plugin-vue': ^2.0.1
'@vue/compiler-sfc': ^3.2.27
@@ -28,7 +28,6 @@ specifiers:
jsdom: ^19.0.0
lint-staged: ^12.1.7
lodash.debounce: ^4.0.8
lodash.throttle: ^4.1.1
npm-run-all: ^4.1.5
pinia: ^2.0.9
prettier: ^2.5.1
@@ -63,7 +62,6 @@ dependencies:
fuzzysort: 1.1.4
hotkeys-js: 3.8.7
lodash.debounce: 4.0.8
lodash.throttle: 4.1.1
pinia: 2.0.9_typescript@4.5.4+vue@3.2.26
sass: 1.48.0
semver: 7.3.5
@@ -80,7 +78,7 @@ devDependencies:
'@pinia/testing': 0.0.9_pinia@2.0.9+vue@3.2.26
'@types/jest': 27.4.0
'@types/lodash.debounce': 4.0.6
'@types/lodash.throttle': 4.1.6
'@types/node': 17.0.10
'@types/semver': 7.3.9
'@vue/test-utils': 2.0.0-rc.18_vue@3.2.26
eventsourcemock: 2.0.0
@@ -91,7 +89,7 @@ devDependencies:
npm-run-all: 4.1.5
prettier: 2.5.1
release-it: 14.12.3
ts-node: 10.4.0_typescript@4.5.4
ts-node: 10.4.0_82b55006877de54992e74492b614ace9
vitest: 0.1.19_jsdom@19.0.0+sass@1.48.0
packages:
@@ -414,7 +412,7 @@ packages:
dependencies:
'@types/http-cache-semantics': 4.0.1
'@types/keyv': 3.1.3
'@types/node': 17.0.9
'@types/node': 17.0.10
'@types/responselike': 1.0.0
dev: true
@@ -442,7 +440,7 @@ packages:
/@types/keyv/3.1.3:
resolution: {integrity: sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==}
dependencies:
'@types/node': 17.0.9
'@types/node': 17.0.10
dev: true
/@types/lodash.debounce/4.0.6:
@@ -451,18 +449,12 @@ packages:
'@types/lodash': 4.14.178
dev: true
/@types/lodash.throttle/4.1.6:
resolution: {integrity: sha512-/UIH96i/sIRYGC60NoY72jGkCJtFN5KVPhEMMMTjol65effe1gPn0tycJqV5tlSwMTzX8FqzB5yAj0rfGHTPNg==}
dependencies:
'@types/lodash': 4.14.178
dev: true
/@types/lodash/4.14.178:
resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==}
dev: true
/@types/node/17.0.9:
resolution: {integrity: sha512-5dNBXu/FOER+EXnyah7rn8xlNrfMOQb/qXnw4NQgLkCygKBKhdmF/CA5oXVOKZLBEahw8s2WP9LxIcN/oDDRgQ==}
/@types/node/17.0.10:
resolution: {integrity: sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==}
dev: true
/@types/parse-json/4.0.0:
@@ -472,7 +464,7 @@ packages:
/@types/responselike/1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
'@types/node': 17.0.9
'@types/node': 17.0.10
dev: true
/@types/semver/7.3.9:
@@ -2473,10 +2465,6 @@ packages:
resolution: {integrity: sha1-gteb/zCmfEAF/9XiUVMArZyk168=}
dev: false
/lodash.throttle/4.1.1:
resolution: {integrity: sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=}
dev: false
/lodash/4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: true
@@ -3548,7 +3536,7 @@ packages:
punycode: 2.1.1
dev: true
/ts-node/10.4.0_typescript@4.5.4:
/ts-node/10.4.0_82b55006877de54992e74492b614ace9:
resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==}
hasBin: true
peerDependencies:
@@ -3567,6 +3555,7 @@ packages:
'@tsconfig/node12': 1.0.9
'@tsconfig/node14': 1.0.1
'@tsconfig/node16': 1.0.2
'@types/node': 17.0.10
acorn: 8.7.0
acorn-walk: 8.2.0
arg: 4.1.3