This commit is contained in:
tamaina 2023-07-13 04:38:04 +00:00
parent 88315d3e80
commit 877a7a81bb
3 changed files with 20 additions and 30 deletions

View file

@ -41,7 +41,7 @@
import { computed, ComputedRef, isRef, nextTick, onActivated, onBeforeUnmount, onDeactivated, onMounted, ref, watch } from 'vue'; import { computed, ComputedRef, isRef, nextTick, onActivated, onBeforeUnmount, onDeactivated, onMounted, ref, watch } from 'vue';
import * as misskey from 'misskey-js'; import * as misskey from 'misskey-js';
import * as os from '@/os'; import * as os from '@/os';
import { isBottomVisible, isTopVisible, getBodyScrollHeight, getScrollContainer, scrollToBottom, scroll, scrollToTop } from '@/scripts/scroll'; import { isBottomVisible, isTopVisible, getBodyScrollHeight, getScrollContainer, scrollToBottom, scrollToTop, scroll } from '@/scripts/scroll';
import { useDocumentVisibility } from '@/scripts/use-document-visibility'; import { useDocumentVisibility } from '@/scripts/use-document-visibility';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
@ -151,7 +151,8 @@ const {
const displayLimit = computed(() => props.pagination.displayLimit ?? props.pagination.limit * 2); const displayLimit = computed(() => props.pagination.displayLimit ?? props.pagination.limit * 2);
const contentEl = $computed(() => props.pagination.pageEl ?? rootEl); const contentEl = $computed(() => props.pagination.pageEl ?? rootEl);
const scrollableElement = $computed(() => contentEl ? getScrollContainer(contentEl) ?? document.body : document.body); const scrollableElement = $computed(() => contentEl ? getScrollContainer(contentEl) ?? null : null);
const scrollableElementOrHtml = $computed(() => scrollableElement ?? document.getElementsByName('html')[0]);
const visibility = useDocumentVisibility(); const visibility = useDocumentVisibility();
@ -173,7 +174,7 @@ watch([() => props.pagination.reversed, $$(scrollableElement)], () => {
weakBacked = entries[0].isIntersecting; weakBacked = entries[0].isIntersecting;
if (weakBacked) backed = true; if (weakBacked) backed = true;
}, { }, {
root: scrollableElement, root: scrollableElementOrHtml,
rootMargin: props.pagination.reversed ? '-100% 0px 100% 0px' : '100% 0px -100% 0px', rootMargin: props.pagination.reversed ? '-100% 0px 100% 0px' : '100% 0px -100% 0px',
threshold: 0.1, // 10%queue threshold: 0.1, // 10%queue
}); });
@ -219,7 +220,7 @@ watch([$$(weakBacked), $$(contentEl)], () => {
// //
onScroll(); onScroll();
const container = scrollableElement; const container = scrollableElementOrHtml;
function removeListener() { container.removeEventListener('scroll', onScroll); } function removeListener() { container.removeEventListener('scroll', onScroll); }
container.addEventListener('scroll', onScroll, { passive: true }); container.addEventListener('scroll', onScroll, { passive: true });
@ -232,11 +233,12 @@ watch([$$(weakBacked), $$(contentEl)], () => {
* @param fn DOM操作(unshiftItemsなどで) * @param fn DOM操作(unshiftItemsなどで)
*/ */
function adjustScroll(fn: () => void): Promise<void> { function adjustScroll(fn: () => void): Promise<void> {
const oldHeight = scrollableElement.scrollHeight; const oldHeight = scrollableElement ? scrollableElement.scrollHeight : getBodyScrollHeight();
const oldScroll = scrollableElement.scrollTop; const oldScroll = scrollableElement ? scrollableElement.scrollTop : window.scrollY;
fn(); fn();
return nextTick(() => { return nextTick(() => {
const top = oldScroll + (scrollableElement.scrollHeight - oldHeight); const top = oldScroll + ((scrollableElement ? scrollableElement.scrollHeight : getBodyScrollHeight()) - oldHeight);
scroll(scrollableElement, { top, behavior: 'instant' }); scroll(scrollableElement, { top, behavior: 'instant' });
if (top > TOLERANCE) { if (top > TOLERANCE) {
weakBacked = true; weakBacked = true;
@ -349,22 +351,7 @@ const fetchMore = async (): Promise<void> => {
if (i === 10) item._shouldInsertAd_ = true; if (i === 10) item._shouldInsertAd_ = true;
} }
const reverseConcat = _res => { const reverseConcat = (_res) => adjustScroll(() => concatMapWithArray(items.value, _res));
const oldHeight = scrollableElement ? scrollableElement.scrollHeight : getBodyScrollHeight();
const oldScroll = scrollableElement ? scrollableElement.scrollTop : window.scrollY;
items.value = concatMapWithArray(items.value, _res);
return nextTick(() => {
if (scrollableElement) {
scroll(scrollableElement, { top: oldScroll + (scrollableElement.scrollHeight - oldHeight), behavior: 'instant' });
} else {
window.scroll({ top: oldScroll + (getBodyScrollHeight() - oldHeight), behavior: 'instant' });
}
return nextTick();
});
};
if (res.length === 0) { if (res.length === 0) {
if (props.pagination.reversed) { if (props.pagination.reversed) {

View file

@ -20,7 +20,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, watch } from 'vue'; import { computed, watch } from 'vue';
import MkTimeline from '@/components/MkTimeline.vue'; import MkTimeline from '@/components/MkTimeline.vue';
import { scroll } from '@/scripts/scroll';
import * as os from '@/os'; import * as os from '@/os';
import { useRouter } from '@/router'; import { useRouter } from '@/router';
import { definePageMetadata } from '@/scripts/page-metadata'; import { definePageMetadata } from '@/scripts/page-metadata';

View file

@ -70,12 +70,16 @@ export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance = 1
return removeListener; return removeListener;
} }
export function scroll(el: HTMLElement, options: ScrollToOptions | undefined) { /**
const container = getScrollContainer(el); *
if (container == null) { * @param el Container element
* @param options ScrollToOptions
*/
export function scroll(el: HTMLElement | null, options: ScrollToOptions | undefined) {
if (el == null) {
window.scroll(options); window.scroll(options);
} else { } else {
container.scroll(options); el.scroll(options);
} }
} }
@ -84,8 +88,8 @@ export function scroll(el: HTMLElement, options: ScrollToOptions | undefined) {
* @param el Scroll container element * @param el Scroll container element
* @param options Scroll options * @param options Scroll options
*/ */
export function scrollToTop(el: HTMLElement, options: { behavior?: ScrollBehavior; } = {}) { export function scrollToTop(el: HTMLElement | null, options: { behavior?: ScrollBehavior; } = {}) {
scroll(el, { top: 0, ...options }); scroll(getScrollContainer(el), { top: 0, ...options });
} }
/** /**