summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkPullToRefresh.vue
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-11-04 08:56:48 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-11-04 08:56:48 +0900
commita656447aa58440e9a41fa39e1c5d6ff3d859b64e (patch)
treef2cd2ff1b3b2db25e9584c7078522d26b132f687 /packages/frontend/src/components/MkPullToRefresh.vue
parentUpdate CHANGELOG.md (diff)
downloadmisskey-a656447aa58440e9a41fa39e1c5d6ff3d859b64e.tar.gz
misskey-a656447aa58440e9a41fa39e1c5d6ff3d859b64e.tar.bz2
misskey-a656447aa58440e9a41fa39e1c5d6ff3d859b64e.zip
enhance(frontend): improve pull to refresh
Diffstat (limited to 'packages/frontend/src/components/MkPullToRefresh.vue')
-rw-r--r--packages/frontend/src/components/MkPullToRefresh.vue72
1 files changed, 43 insertions, 29 deletions
diff --git a/packages/frontend/src/components/MkPullToRefresh.vue b/packages/frontend/src/components/MkPullToRefresh.vue
index f3f5660143..64c4d6e91d 100644
--- a/packages/frontend/src/components/MkPullToRefresh.vue
+++ b/packages/frontend/src/components/MkPullToRefresh.vue
@@ -23,9 +23,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { onMounted, onUnmounted } from 'vue';
+import { onMounted, onUnmounted, watch } from 'vue';
import { deviceKind } from '@/scripts/device-kind.js';
import { i18n } from '@/i18n.js';
+import { getScrollContainer } from '@/scripts/scroll.js';
const SCROLL_STOP = 10;
const MAX_PULL_DISTANCE = Infinity;
@@ -57,18 +58,6 @@ const emit = defineEmits<{
(ev: 'refresh'): void;
}>();
-function getScrollableParentElement(node) {
- if (node == null) {
- return null;
- }
-
- if (node.scrollHeight > node.clientHeight) {
- return node;
- } else {
- return getScrollableParentElement(node.parentNode);
- }
-}
-
function getScreenY(event) {
if (supportPointerDesktop) {
return event.screenY;
@@ -138,12 +127,9 @@ function moveEnd() {
}
}
-function moving(event) {
+function moving(event: TouchEvent | PointerEvent) {
if (!isPullStart || isRefreshing || disabled) return;
- if (!scrollEl) {
- scrollEl = getScrollableParentElement(rootEl);
- }
if ((scrollEl?.scrollTop ?? 0) > (supportPointerDesktop ? SCROLL_STOP : SCROLL_STOP + pullDistance)) {
pullDistance = 0;
isPullEnd = false;
@@ -159,6 +145,10 @@ function moving(event) {
const moveHeight = moveScreenY - startScreenY!;
pullDistance = Math.min(Math.max(moveHeight, 0), MAX_PULL_DISTANCE);
+ if (pullDistance > 0) {
+ if (event.cancelable) event.preventDefault();
+ }
+
isPullEnd = pullDistance >= FIRE_THRESHOLD;
}
@@ -178,24 +168,48 @@ function setDisabled(value) {
disabled = value;
}
-onMounted(() => {
- // マウス操作でpull to refreshするのは不便そう
- //supportPointerDesktop = !!window.PointerEvent && deviceKind === 'desktop';
+function onScrollContainerScroll() {
+ const scrollPos = scrollEl!.scrollTop;
- if (supportPointerDesktop) {
- rootEl.addEventListener('pointerdown', moveStart);
- // ポインターの場合、ポップアップ系の動作をするとdownだけ発火されてupが発火されないため
- window.addEventListener('pointerup', moveEnd);
- rootEl.addEventListener('pointermove', moving, { passive: true });
+ // When at the top of the page, disable vertical overscroll so passive touch listeners can take over.
+ if (scrollPos === 0) {
+ scrollEl!.style.touchAction = 'pan-x pan-down pinch-zoom';
+ registerEventListenersForReadyToPull();
} else {
- rootEl.addEventListener('touchstart', moveStart);
- rootEl.addEventListener('touchend', moveEnd);
- rootEl.addEventListener('touchmove', moving, { passive: true });
+ scrollEl!.style.touchAction = 'auto';
+ unregisterEventListenersForReadyToPull();
}
+}
+
+function registerEventListenersForReadyToPull() {
+ if (rootEl == null) return;
+ rootEl.addEventListener('touchstart', moveStart, { passive: true });
+ rootEl.addEventListener('touchmove', moving, { passive: false }); // passive: falseにしないとpreventDefaultが使えない
+}
+
+function unregisterEventListenersForReadyToPull() {
+ if (rootEl == null) return;
+ rootEl.removeEventListener('touchstart', moveStart);
+ rootEl.removeEventListener('touchmove', moving);
+}
+
+onMounted(() => {
+ if (rootEl == null) return;
+
+ scrollEl = getScrollContainer(rootEl);
+ if (scrollEl == null) return;
+
+ scrollEl.addEventListener('scroll', onScrollContainerScroll, { passive: true });
+
+ rootEl.addEventListener('touchend', moveEnd, { passive: true });
+
+ registerEventListenersForReadyToPull();
});
onUnmounted(() => {
- if (supportPointerDesktop) window.removeEventListener('pointerup', moveEnd);
+ if (scrollEl) scrollEl.removeEventListener('scroll', onScrollContainerScroll);
+
+ unregisterEventListenersForReadyToPull();
});
defineExpose({