fix(frontend): 一部のページでもっと見るが自動で行われないバグの修正 (#16754)

* 一部のページでもっと見るが自動で行われないバグの修正

* fix(frontend): MkPagination で UI アニメーションオフ時に自動ロードが動作しない問題を修正

Transition コンポーネントの mode="out-in" が、アニメーション無効時でも
適用されており、IntersectionObserver の検出に干渉していた問題を修正。
アニメーション有効時のみ mode="out-in" を適用するように変更。

Co-authored-by: 果物リン <fruitriin@users.noreply.github.com>

* enhance: ユーザーの設定値にかかわらず無限スクロールをオフにできるオプションを追加

* Update Changelog

* MkNotesTimeline.vueにforceDisableInfiniteScrollを追加、 note.vueの前方向の読み込みでこれを有効

* fix lint

* refactor

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: 果物リン <fruitriin@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
This commit is contained in:
果物リン 2025-11-07 11:27:08 +09:00 committed by GitHub
parent e312283ea0
commit 0a67d6f1a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 24 deletions

View File

@ -14,6 +14,7 @@
- Enhance: ユーザーのノート、フォロー、フォロワーページへのリンクをユーザーポップアップに追加 - Enhance: ユーザーのノート、フォロー、フォロワーページへのリンクをユーザーポップアップに追加
- Enhance: プッシュ通知を行うための権限確認をより確実に行うように - Enhance: プッシュ通知を行うための権限確認をより確実に行うように
- Enhance: 投稿フォームのチュートリアルを追加 - Enhance: 投稿フォームのチュートリアルを追加
- Enhance: 「自動でもっと見る」をほとんどの箇所で利用可能に
- Fix: 紙吹雪エフェクトがアニメーション設定を考慮せず常に表示される問題を修正 - Fix: 紙吹雪エフェクトがアニメーション設定を考慮せず常に表示される問題を修正
- Fix: ナビゲーションバーのリアルタイムモード切替ボタンの状態をよりわかりやすく表示するように - Fix: ナビゲーションバーのリアルタイムモード切替ボタンの状態をよりわかりやすく表示するように
- Fix: ページのタイトルが長いとき、はみ出る問題を修正 - Fix: ページのタイトルが長いとき、はみ出る問題を修正

View File

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<MkPagination :paginator="paginator" :direction="direction" :autoLoad="autoLoad" :pullToRefresh="pullToRefresh" :withControl="withControl"> <MkPagination :paginator="paginator" :direction="direction" :autoLoad="autoLoad" :pullToRefresh="pullToRefresh" :withControl="withControl" :forceDisableInfiniteScroll="forceDisableInfiniteScroll">
<template #empty><MkResult type="empty" :text="i18n.ts.noNotes"/></template> <template #empty><MkResult type="empty" :text="i18n.ts.noNotes"/></template>
<template #default="{ items: notes }"> <template #default="{ items: notes }">
@ -40,26 +40,23 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup generic="T extends IPaginator<Misskey.entities.Note>"> <script lang="ts" setup generic="T extends IPaginator<Misskey.entities.Note>">
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import type { MkPaginationOptions } from '@/components/MkPagination.vue';
import type { IPaginator } from '@/utility/paginator.js'; import type { IPaginator } from '@/utility/paginator.js';
import MkNote from '@/components/MkNote.vue'; import MkNote from '@/components/MkNote.vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { globalEvents, useGlobalEvent } from '@/events.js'; import { useGlobalEvent } from '@/events.js';
import { isSeparatorNeeded, getSeparatorInfo } from '@/utility/timeline-date-separate.js'; import { isSeparatorNeeded, getSeparatorInfo } from '@/utility/timeline-date-separate.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<MkPaginationOptions & {
paginator: T; paginator: T;
noGap?: boolean; noGap?: boolean;
direction?: 'up' | 'down' | 'both';
autoLoad?: boolean;
pullToRefresh?: boolean;
withControl?: boolean;
}>(), { }>(), {
autoLoad: true, autoLoad: true,
direction: 'down', direction: 'down',
pullToRefresh: true, pullToRefresh: true,
withControl: true, withControl: true,
forceDisableInfiniteScroll: false,
}); });
useGlobalEvent('noteDeleted', (noteId) => { useGlobalEvent('noteDeleted', (noteId) => {

View File

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:leaveActiveClass="prefer.s.animation ? $style.transition_fade_leaveActive : ''" :leaveActiveClass="prefer.s.animation ? $style.transition_fade_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_fade_enterFrom : ''" :enterFromClass="prefer.s.animation ? $style.transition_fade_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_fade_leaveTo : ''" :leaveToClass="prefer.s.animation ? $style.transition_fade_leaveTo : ''"
mode="out-in" :mode="prefer.s.animation ? 'out-in' : undefined"
> >
<MkLoading v-if="paginator.fetching.value"/> <MkLoading v-if="paginator.fetching.value"/>
@ -26,14 +26,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else key="_root_" class="_gaps"> <div v-else key="_root_" class="_gaps">
<div v-if="direction === 'up' || direction === 'both'" v-show="upButtonVisible"> <div v-if="direction === 'up' || direction === 'both'" v-show="upButtonVisible">
<MkButton v-if="!upButtonLoading" :class="$style.more" primary rounded @click="upButtonClick"> <MkButton v-if="!upButtonLoading" v-appear="shouldEnableInfiniteScroll ? upButtonClick : null" :class="$style.more" primary rounded @click="upButtonClick">
{{ i18n.ts.loadMore }} {{ i18n.ts.loadMore }}
</MkButton> </MkButton>
<MkLoading v-else/> <MkLoading v-else/>
</div> </div>
<slot :items="getValue(paginator.items)" :fetching="paginator.fetching.value || paginator.fetchingOlder.value"></slot> <slot :items="getValue(paginator.items)" :fetching="paginator.fetching.value || paginator.fetchingOlder.value"></slot>
<div v-if="direction === 'down' || direction === 'both'" v-show="downButtonVisible"> <div v-if="direction === 'down' || direction === 'both'" v-show="downButtonVisible">
<MkButton v-if="!downButtonLoading" :class="$style.more" primary rounded @click="downButtonClick"> <MkButton v-if="!downButtonLoading" v-appear="shouldEnableInfiniteScroll ? downButtonClick : null" :class="$style.more" primary rounded @click="downButtonClick">
{{ i18n.ts.loadMore }} {{ i18n.ts.loadMore }}
</MkButton> </MkButton>
<MkLoading v-else/> <MkLoading v-else/>
@ -44,6 +44,24 @@ SPDX-License-Identifier: AGPL-3.0-only
</component> </component>
</template> </template>
<script lang="ts">
export type MkPaginationOptions = {
autoLoad?: boolean;
/**
* ページネーションを進める方向
* - up: 上方向
* - down: 下方向 (default)
* - both: 双方向
*
* NOTE: この方向はページネーションの方向であってアイテムの並び順ではない
*/
direction?: 'up' | 'down' | 'both';
pullToRefresh?: boolean;
withControl?: boolean;
forceDisableInfiniteScroll?: boolean;
};
</script>
<script lang="ts" setup generic="T extends IPaginator"> <script lang="ts" setup generic="T extends IPaginator">
import { isLink } from '@@/js/is-link.js'; import { isLink } from '@@/js/is-link.js';
import { onMounted, computed, watch, unref } from 'vue'; import { onMounted, computed, watch, unref } from 'vue';
@ -56,24 +74,18 @@ import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
import MkPaginationControl from '@/components/MkPaginationControl.vue'; import MkPaginationControl from '@/components/MkPaginationControl.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<MkPaginationOptions & {
paginator: T; paginator: T;
//
// up:
// down: (default)
// both:
// NOTE:
direction?: 'up' | 'down' | 'both';
autoLoad?: boolean;
pullToRefresh?: boolean;
withControl?: boolean;
}>(), { }>(), {
autoLoad: true, autoLoad: true,
direction: 'down', direction: 'down',
pullToRefresh: true, pullToRefresh: true,
withControl: false, withControl: false,
forceDisableInfiniteScroll: false,
});
const shouldEnableInfiniteScroll = computed(() => {
return prefer.r.enableInfiniteScroll.value && !props.forceDisableInfiniteScroll;
}); });
function onContextmenu(ev: MouseEvent) { function onContextmenu(ev: MouseEvent) {

View File

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<Transition :name="prefer.s.animation ? 'fade' : ''" mode="out-in"> <Transition :name="prefer.s.animation ? 'fade' : ''" mode="out-in">
<div v-if="note"> <div v-if="note">
<div v-if="showNext" class="_margin"> <div v-if="showNext" class="_margin">
<MkNotesTimeline direction="up" :withControl="false" :pullToRefresh="false" class="" :paginator="showNext === 'channel' ? nextChannelPaginator : nextUserPaginator" :noGap="true"/> <MkNotesTimeline direction="up" :withControl="false" :pullToRefresh="false" class="" :paginator="showNext === 'channel' ? nextChannelPaginator : nextUserPaginator" :noGap="true" :forceDisableInfiniteScroll="true" />
</div> </div>
<div class="_margin"> <div class="_margin">