summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2025-07-03 18:52:16 +0900
committerGitHub <noreply@github.com>2025-07-03 18:52:16 +0900
commit179d990c39ed5c7f79e7481ca86b07ec9f70d474 (patch)
tree6210475837a0c413eceecf9d6e5a30ee9ac8c6d9 /packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
parentenhance(backend): avatarUrlの上限文字数の引き上げ (#16235) (diff)
downloadmisskey-179d990c39ed5c7f79e7481ca86b07ec9f70d474.tar.gz
misskey-179d990c39ed5c7f79e7481ca86b07ec9f70d474.tar.bz2
misskey-179d990c39ed5c7f79e7481ca86b07ec9f70d474.zip
fix(frontend): タブが不可視なあいだのpaginationのアップデートを停止するように (#16243)
* fix(frontend): タブが不可視なあいだのpaginationのアップデートを停止するように * fix lint * 待たない
Diffstat (limited to 'packages/frontend/src/components/MkStreamingNotificationsTimeline.vue')
-rw-r--r--packages/frontend/src/components/MkStreamingNotificationsTimeline.vue51
1 files changed, 50 insertions, 1 deletions
diff --git a/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue b/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
index 869d848d90..e21adab36c 100644
--- a/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
+++ b/packages/frontend/src/components/MkStreamingNotificationsTimeline.vue
@@ -45,7 +45,9 @@ SPDX-License-Identifier: AGPL-3.0-only
import { onUnmounted, onMounted, computed, useTemplateRef, TransitionGroup, markRaw, watch } from 'vue';
import * as Misskey from 'misskey-js';
import { useInterval } from '@@/js/use-interval.js';
+import { useDocumentVisibility } from '@@/js/use-document-visibility.js';
import type { notificationTypes } from '@@/js/const.js';
+import { getScrollContainer, scrollToTop } from '@@/js/scroll.js';
import XNotification from '@/components/MkNotification.vue';
import MkNote from '@/components/MkNote.vue';
import { useStream } from '@/stream.js';
@@ -92,6 +94,49 @@ if (!store.s.realtimeMode) {
});
}
+function isTop() {
+ if (scrollContainer == null) return true;
+ if (rootEl.value == null) return true;
+ const scrollTop = scrollContainer.scrollTop;
+ const tlTop = rootEl.value.offsetTop - scrollContainer.offsetTop;
+ return scrollTop <= tlTop;
+}
+
+function releaseQueue() {
+ paginator.releaseQueue();
+ scrollToTop(rootEl.value!);
+}
+
+let scrollContainer: HTMLElement | null = null;
+
+function onScrollContainerScroll() {
+ if (isTop()) {
+ paginator.releaseQueue();
+ }
+}
+
+watch(rootEl, (el) => {
+ if (el && scrollContainer == null) {
+ scrollContainer = getScrollContainer(el);
+ if (scrollContainer == null) return;
+ scrollContainer.addEventListener('scroll', onScrollContainerScroll, { passive: true }); // ほんとはscrollendにしたいけどiosが非対応
+ }
+}, { immediate: true });
+
+const visibility = useDocumentVisibility();
+let isPausingUpdate = false;
+
+watch(visibility, () => {
+ if (visibility.value === 'hidden') {
+ isPausingUpdate = true;
+ } else { // 'visible'
+ isPausingUpdate = false;
+ if (isTop()) {
+ releaseQueue();
+ }
+ }
+});
+
function onNotification(notification) {
const isMuted = props.excludeTypes ? props.excludeTypes.includes(notification.type) : false;
if (isMuted || window.document.visibilityState === 'visible') {
@@ -101,7 +146,11 @@ function onNotification(notification) {
}
if (!isMuted) {
- paginator.prepend(notification);
+ if (isTop() && !isPausingUpdate) {
+ paginator.prepend(notification);
+ } else {
+ paginator.enqueue(notification);
+ }
}
}