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:
11
assets/components.d.ts
vendored
11
assets/components.d.ts
vendored
@@ -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']
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
31
pnpm-lock.yaml
generated
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user