From 179d990c39ed5c7f79e7481ca86b07ec9f70d474 Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 3 Jul 2025 18:52:16 +0900
Subject: fix(frontend):
 タブが不可視なあいだのpaginationのアップデートを停止するように (#16243)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): タブが不可視なあいだのpaginationのアップデートを停止するように

* fix lint

* 待たない
---
 .../MkStreamingNotificationsTimeline.vue           | 51 +++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

(limited to 'packages/frontend/src/components/MkStreamingNotificationsTimeline.vue')

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);
+		}
 	}
 }
 
-- 
cgit v1.2.3-freya

