fix: apply copilot reviews / remove listeners on unmount
This commit is contained in:
parent
c8d8d92d82
commit
96e11c1b08
|
|
@ -44,6 +44,19 @@ const pullDistance = ref(0);
|
||||||
let startScreenY: number | null = null;
|
let startScreenY: number | null = null;
|
||||||
|
|
||||||
let moveBySystemCancel: (() => void) | null = null;
|
let moveBySystemCancel: (() => void) | null = null;
|
||||||
|
let moveBySystemRafId: number | null = null;
|
||||||
|
|
||||||
|
const onMouseMove = (event: MouseEvent) => moving(event);
|
||||||
|
const onMouseUp = () => {
|
||||||
|
window.removeEventListener('mousemove', onMouseMove);
|
||||||
|
onPullRelease();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTouchMove = (event: TouchEvent) => moving(event);
|
||||||
|
const onTouchEnd = () => {
|
||||||
|
window.removeEventListener('touchmove', onTouchMove);
|
||||||
|
onPullRelease();
|
||||||
|
};
|
||||||
|
|
||||||
const rootEl = useTemplateRef('rootEl');
|
const rootEl = useTemplateRef('rootEl');
|
||||||
let scrollEl: HTMLElement | null = null;
|
let scrollEl: HTMLElement | null = null;
|
||||||
|
|
@ -99,11 +112,8 @@ function moveStartByMouse(event: MouseEvent) {
|
||||||
startScreenY = getScreenY(event);
|
startScreenY = getScreenY(event);
|
||||||
pullDistance.value = 0;
|
pullDistance.value = 0;
|
||||||
|
|
||||||
window.addEventListener('mousemove', moving, { passive: true });
|
window.addEventListener('mousemove', onMouseMove, { passive: true });
|
||||||
window.addEventListener('mouseup', () => {
|
window.addEventListener('mouseup', onMouseUp, { passive: true, once: true });
|
||||||
window.removeEventListener('mousemove', moving);
|
|
||||||
onPullRelease();
|
|
||||||
}, { passive: true, once: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveStartByTouch(event: TouchEvent) {
|
function moveStartByTouch(event: TouchEvent) {
|
||||||
|
|
@ -121,11 +131,8 @@ function moveStartByTouch(event: TouchEvent) {
|
||||||
startScreenY = getScreenY(event);
|
startScreenY = getScreenY(event);
|
||||||
pullDistance.value = 0;
|
pullDistance.value = 0;
|
||||||
|
|
||||||
window.addEventListener('touchmove', moving, { passive: true });
|
window.addEventListener('touchmove', onTouchMove, { passive: true });
|
||||||
window.addEventListener('touchend', () => {
|
window.addEventListener('touchend', onTouchEnd, { passive: true, once: true });
|
||||||
window.removeEventListener('touchmove', moving);
|
|
||||||
onPullRelease();
|
|
||||||
}, { passive: true, once: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveBySystem(to: number): Promise<void> {
|
function moveBySystem(to: number): Promise<void> {
|
||||||
|
|
@ -143,14 +150,18 @@ function moveBySystem(to: number): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let startTime: number | null = null;
|
let startTime: DOMHighResTimeStamp | null = null;
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
moveBySystemCancel = () => {
|
moveBySystemCancel = () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
startTime = null;
|
startTime = null;
|
||||||
|
if (moveBySystemRafId != null) {
|
||||||
|
window.cancelAnimationFrame(moveBySystemRafId);
|
||||||
|
moveBySystemRafId = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const tick = (now: number) => {
|
const tick = (now: DOMHighResTimeStamp) => {
|
||||||
if (cancelled) {
|
if (cancelled) {
|
||||||
r();
|
r();
|
||||||
return;
|
return;
|
||||||
|
|
@ -163,26 +174,27 @@ function moveBySystem(to: number): Promise<void> {
|
||||||
if (time >= RELEASE_TRANSITION_DURATION) {
|
if (time >= RELEASE_TRANSITION_DURATION) {
|
||||||
pullDistance.value = to;
|
pullDistance.value = to;
|
||||||
moveBySystemCancel = null;
|
moveBySystemCancel = null;
|
||||||
|
moveBySystemRafId = null;
|
||||||
r();
|
r();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nextHeight = startHeight - (overHeight / RELEASE_TRANSITION_DURATION) * time;
|
const nextHeight = startHeight - (overHeight / RELEASE_TRANSITION_DURATION) * time;
|
||||||
if (overHeight > 0) {
|
if (overHeight > 0) {
|
||||||
if (pullDistance.value < nextHeight) {
|
if (pullDistance.value < nextHeight) {
|
||||||
window.requestAnimationFrame(tick);
|
moveBySystemRafId = window.requestAnimationFrame(tick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (pullDistance.value > nextHeight) {
|
if (pullDistance.value > nextHeight) {
|
||||||
window.requestAnimationFrame(tick);
|
moveBySystemRafId = window.requestAnimationFrame(tick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pullDistance.value = nextHeight;
|
pullDistance.value = nextHeight;
|
||||||
window.requestAnimationFrame(tick);
|
moveBySystemRafId = window.requestAnimationFrame(tick);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.requestAnimationFrame(tick);
|
moveBySystemRafId = window.requestAnimationFrame(tick);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,6 +278,14 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
if (moveBySystemCancel != null) {
|
||||||
|
moveBySystemCancel();
|
||||||
|
moveBySystemCancel = null;
|
||||||
|
}
|
||||||
|
moveBySystemRafId = null;
|
||||||
|
// pull中にwindowへ登録したリスナーが残るのを防ぐ
|
||||||
|
window.removeEventListener('mousemove', onMouseMove);
|
||||||
|
window.removeEventListener('touchmove', onTouchMove);
|
||||||
unlockDownScroll();
|
unlockDownScroll();
|
||||||
if (rootEl.value) rootEl.value.removeEventListener('mousedown', moveStartByMouse);
|
if (rootEl.value) rootEl.value.removeEventListener('mousedown', moveStartByMouse);
|
||||||
if (rootEl.value) rootEl.value.removeEventListener('touchstart', moveStartByTouch);
|
if (rootEl.value) rootEl.value.removeEventListener('touchstart', moveStartByTouch);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, useTemplateRef, computed, watch } from 'vue';
|
import { ref, useTemplateRef, computed, watch, onUnmounted } from 'vue';
|
||||||
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
|
import type { Tab } from '@/components/global/MkPageHeader.tabs.vue';
|
||||||
import { isHorizontalSwipeSwiping as isSwiping } from '@/utility/touch.js';
|
import { isHorizontalSwipeSwiping as isSwiping } from '@/utility/touch.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
|
|
@ -122,6 +122,16 @@ function cancelMoveBySystem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// コンポーネント破棄後にpullDistanceを書き換えないようにする
|
||||||
|
if (rafId != null) {
|
||||||
|
window.cancelAnimationFrame(rafId);
|
||||||
|
rafId = null;
|
||||||
|
}
|
||||||
|
pendingPullDistance = null;
|
||||||
|
cancelMoveBySystem();
|
||||||
|
});
|
||||||
|
|
||||||
function moveBySystem(to: number, duration = RELEASE_TRANSITION_DURATION): Promise<void> {
|
function moveBySystem(to: number, duration = RELEASE_TRANSITION_DURATION): Promise<void> {
|
||||||
cancelMoveBySystem();
|
cancelMoveBySystem();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue