wip
This commit is contained in:
parent
6ca9cfb24d
commit
74cc831332
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<template #default="{ items: notes }">
|
||||
<div :class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap, [$style.reverse]: pagination.reversed }]">
|
||||
<div :class="[$style.root, { [$style.noGap]: noGap, '_gaps': !noGap }]">
|
||||
<template v-for="(note, i) in notes" :key="note.id">
|
||||
<div v-if="note._shouldInsertAd_" :class="[$style.noteWithAd, { '_gaps': !noGap }]" :data-scroll-anchor="note.id">
|
||||
<MkNote :class="$style.note" :note="note" :withHardMute="true"/>
|
||||
|
@ -62,11 +62,6 @@ defineExpose({
|
|||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.reverse {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.root {
|
||||
container-type: inline-size;
|
||||
|
||||
|
|
|
@ -27,15 +27,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
|
||||
<div v-else ref="rootEl" class="_gaps">
|
||||
<div v-show="pagination.reversed && paginator.canFetchMore.value" key="_more_">
|
||||
<MkButton v-if="!paginator.moreFetching.value" v-appear="(prefer.s.enableInfiniteScroll && !props.disableAutoLoad) ? appearFetchMoreAhead : null" :class="$style.more" :wait="paginator.moreFetching.value" primary rounded @click="paginator.fetchNewer">
|
||||
<div v-show="pagination.reversed && paginator.canFetchOlder.value" key="_more_">
|
||||
<MkButton v-if="!paginator.fetchingOlder.value" v-appear="(prefer.s.enableInfiniteScroll && !props.disableAutoLoad) ? appearFetchMoreAhead : null" :class="$style.more" :wait="paginator.fetchingOlder.value" primary rounded @click="paginator.fetchNewer">
|
||||
{{ i18n.ts.loadMore }}
|
||||
</MkButton>
|
||||
<MkLoading v-else/>
|
||||
</div>
|
||||
<slot :items="paginator.items.value" :fetching="paginator.fetching.value || paginator.moreFetching.value"></slot>
|
||||
<div v-show="!pagination.reversed && paginator.canFetchMore.value" key="_more_">
|
||||
<MkButton v-if="!paginator.moreFetching.value" v-appear="(prefer.s.enableInfiniteScroll && !props.disableAutoLoad) ? appearFetchMore : null" :class="$style.more" :wait="paginator.moreFetching.value" primary rounded @click="paginator.fetchOlder">
|
||||
<slot :items="paginator.items.value" :fetching="paginator.fetching.value || paginator.fetchingOlder.value"></slot>
|
||||
<div v-show="!pagination.reversed && paginator.canFetchOlder.value" key="_more_">
|
||||
<MkButton v-if="!paginator.fetchingOlder.value" v-appear="(prefer.s.enableInfiniteScroll && !props.disableAutoLoad) ? appearFetchMore : null" :class="$style.more" :wait="paginator.fetchingOlder.value" primary rounded @click="paginator.fetchOlder">
|
||||
{{ i18n.ts.loadMore }}
|
||||
</MkButton>
|
||||
<MkLoading v-else/>
|
||||
|
|
|
@ -44,8 +44,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkNote v-else :class="$style.note" :note="note" :withHardMute="true" :data-scroll-anchor="note.id"/>
|
||||
</template>
|
||||
</component>
|
||||
<button v-show="paginator.canFetchMore.value" key="_more_" v-appear="prefer.s.enableInfiniteScroll ? paginator.fetchOlder : null" :disabled="paginator.moreFetching.value" class="_button" :class="$style.more" @click="paginator.fetchOlder">
|
||||
<div v-if="!paginator.moreFetching.value">{{ i18n.ts.loadMore }}</div>
|
||||
<button v-show="paginator.canFetchOlder.value" key="_more_" v-appear="prefer.s.enableInfiniteScroll ? paginator.fetchOlder : null" :disabled="paginator.fetchingOlder.value" class="_button" :class="$style.more" @click="paginator.fetchOlder">
|
||||
<div v-if="!paginator.fetchingOlder.value">{{ i18n.ts.loadMore }}</div>
|
||||
<MkLoading v-else :inline="true"/>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -33,8 +33,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<XNotification v-else :class="$style.item" :notification="notification" :withTime="true" :full="true" :data-scroll-anchor="notification.id"/>
|
||||
</template>
|
||||
</component>
|
||||
<button v-show="paginator.canFetchMore.value" key="_more_" v-appear="prefer.s.enableInfiniteScroll ? paginator.fetchOlder : null" :disabled="paginator.moreFetching.value" class="_button" :class="$style.more" @click="paginator.fetchOlder">
|
||||
<div v-if="!paginator.moreFetching.value">{{ i18n.ts.loadMore }}</div>
|
||||
<button v-show="paginator.canFetchOlder.value" key="_more_" v-appear="prefer.s.enableInfiniteScroll ? paginator.fetchOlder : null" :disabled="paginator.fetchingOlder.value" class="_button" :class="$style.more" @click="paginator.fetchOlder">
|
||||
<div v-if="!paginator.fetchingOlder.value">{{ i18n.ts.loadMore }}</div>
|
||||
<MkLoading v-else/>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -6,42 +6,40 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
|
||||
<div class="_spacer" style="--MI_SPACER-w: 800px;">
|
||||
<div>
|
||||
<Transition :name="prefer.s.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="note">
|
||||
<div v-if="showNext" class="_margin">
|
||||
<MkNotesTimeline :pullToRefresh="false" class="" :pagination="showNext === 'channel' ? nextChannelPagination : nextUserPagination" :noGap="true" :disableAutoLoad="true"/>
|
||||
</div>
|
||||
<Transition :name="prefer.s.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="note">
|
||||
<div v-if="showNext" class="_margin">
|
||||
<MkNotesTimeline :pullToRefresh="false" class="" :pagination="showNext === 'channel' ? nextChannelPagination : nextUserPagination" :noGap="true" :disableAutoLoad="true"/>
|
||||
</div>
|
||||
|
||||
<div class="_margin">
|
||||
<div v-if="!showNext" class="_buttons" :class="$style.loadNext">
|
||||
<MkButton v-if="note.channelId" rounded :class="$style.loadButton" @click="showNext = 'channel'"><i class="ti ti-chevron-up"></i> <i class="ti ti-device-tv"></i></MkButton>
|
||||
<MkButton rounded :class="$style.loadButton" @click="showNext = 'user'"><i class="ti ti-chevron-up"></i> <i class="ti ti-user"></i></MkButton>
|
||||
</div>
|
||||
<div class="_margin _gaps_s">
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url ?? note.uri"/>
|
||||
<MkNoteDetailed :key="note.id" v-model:note="note" :initialTab="initialTab" :class="$style.note"/>
|
||||
</div>
|
||||
<div v-if="clips && clips.length > 0" class="_margin">
|
||||
<div style="font-weight: bold; padding: 12px;">{{ i18n.ts.clip }}</div>
|
||||
<div class="_gaps">
|
||||
<MkClipPreview v-for="item in clips" :key="item.id" :clip="item"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!showPrev" class="_buttons" :class="$style.loadPrev">
|
||||
<MkButton v-if="note.channelId" rounded :class="$style.loadButton" @click="showPrev = 'channel'"><i class="ti ti-chevron-down"></i> <i class="ti ti-device-tv"></i></MkButton>
|
||||
<MkButton rounded :class="$style.loadButton" @click="showPrev = 'user'"><i class="ti ti-chevron-down"></i> <i class="ti ti-user"></i></MkButton>
|
||||
<div class="_margin">
|
||||
<div v-if="!showNext" class="_buttons" :class="$style.loadNext">
|
||||
<MkButton v-if="note.channelId" rounded :class="$style.loadButton" @click="showNext = 'channel'"><i class="ti ti-chevron-up"></i> <i class="ti ti-device-tv"></i></MkButton>
|
||||
<MkButton rounded :class="$style.loadButton" @click="showNext = 'user'"><i class="ti ti-chevron-up"></i> <i class="ti ti-user"></i></MkButton>
|
||||
</div>
|
||||
<div class="_margin _gaps_s">
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url ?? note.uri"/>
|
||||
<MkNoteDetailed :key="note.id" v-model:note="note" :initialTab="initialTab" :class="$style.note"/>
|
||||
</div>
|
||||
<div v-if="clips && clips.length > 0" class="_margin">
|
||||
<div style="font-weight: bold; padding: 12px;">{{ i18n.ts.clip }}</div>
|
||||
<div class="_gaps">
|
||||
<MkClipPreview v-for="item in clips" :key="item.id" :clip="item"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showPrev" class="_margin">
|
||||
<MkNotesTimeline :pullToRefresh="false" class="" :pagination="showPrev === 'channel' ? prevChannelPagination : prevUserPagination" :noGap="true"/>
|
||||
<div v-if="!showPrev" class="_buttons" :class="$style.loadPrev">
|
||||
<MkButton v-if="note.channelId" rounded :class="$style.loadButton" @click="showPrev = 'channel'"><i class="ti ti-chevron-down"></i> <i class="ti ti-device-tv"></i></MkButton>
|
||||
<MkButton rounded :class="$style.loadButton" @click="showPrev = 'user'"><i class="ti ti-chevron-down"></i> <i class="ti ti-user"></i></MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<MkError v-else-if="error" @retry="fetchNote()"/>
|
||||
<MkLoading v-else/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<div v-if="showPrev" class="_margin">
|
||||
<MkNotesTimeline :pullToRefresh="false" class="" :pagination="showPrev === 'channel' ? prevChannelPagination : prevUserPagination" :noGap="true"/>
|
||||
</div>
|
||||
</div>
|
||||
<MkError v-else-if="error" @retry="fetchNote()"/>
|
||||
<MkLoading v-else/>
|
||||
</Transition>
|
||||
</div>
|
||||
</PageWithHeader>
|
||||
</template>
|
||||
|
@ -83,19 +81,20 @@ const error = ref();
|
|||
const prevUserPagination: PagingCtx = {
|
||||
endpoint: 'users/notes',
|
||||
limit: 10,
|
||||
baseId: props.noteId,
|
||||
direction: 'older',
|
||||
params: computed(() => note.value ? ({
|
||||
userId: note.value.userId,
|
||||
untilId: note.value.id,
|
||||
}) : undefined),
|
||||
};
|
||||
|
||||
const nextUserPagination: PagingCtx = {
|
||||
reversed: true,
|
||||
endpoint: 'users/notes',
|
||||
limit: 10,
|
||||
baseId: props.noteId,
|
||||
direction: 'newer',
|
||||
params: computed(() => note.value ? ({
|
||||
userId: note.value.userId,
|
||||
sinceId: note.value.id,
|
||||
}) : undefined),
|
||||
};
|
||||
|
||||
|
|
|
@ -31,12 +31,10 @@ export type PagingCtx<E extends keyof Misskey.Endpoints = keyof Misskey.Endpoint
|
|||
*/
|
||||
noPaging?: boolean;
|
||||
|
||||
/**
|
||||
* items 配列の中身を逆順にする(新しい方が最後)
|
||||
*/
|
||||
reversed?: boolean;
|
||||
|
||||
offsetMode?: boolean;
|
||||
|
||||
baseId?: MisskeyEntity['id'];
|
||||
direction?: 'newer' | 'older';
|
||||
};
|
||||
|
||||
export function usePagination<T extends MisskeyEntity>(props: {
|
||||
|
@ -47,8 +45,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
let aheadQueue: T[] = [];
|
||||
const queuedAheadItemsCount = ref(0);
|
||||
const fetching = ref(true);
|
||||
const moreFetching = ref(false);
|
||||
const canFetchMore = ref(false);
|
||||
const fetchingOlder = ref(false);
|
||||
const canFetchOlder = ref(false);
|
||||
const error = ref(false);
|
||||
|
||||
// パラメータに何らかの変更があった際、再読込したい(チャンネル等のIDが変わったなど)
|
||||
|
@ -73,11 +71,22 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
queuedAheadItemsCount.value = 0;
|
||||
fetching.value = true;
|
||||
const params = props.ctx.params ? isRef(props.ctx.params) ? props.ctx.params.value : props.ctx.params : {};
|
||||
|
||||
await misskeyApi<T[]>(props.ctx.endpoint, {
|
||||
...params,
|
||||
limit: props.ctx.limit ?? FIRST_FETCH_LIMIT,
|
||||
allowPartial: true,
|
||||
...(props.ctx.baseId && props.ctx.direction === 'newer' ? {
|
||||
sinceId: props.ctx.baseId,
|
||||
} : props.ctx.baseId && props.ctx.direction === 'older' ? {
|
||||
untilId: props.ctx.baseId,
|
||||
} : {}),
|
||||
}).then(res => {
|
||||
// 逆順で返ってくるので
|
||||
if (props.ctx.baseId && props.ctx.direction === 'newer') {
|
||||
res.reverse();
|
||||
}
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const item = res[i];
|
||||
if (i === 3) item._shouldInsertAd_ = true;
|
||||
|
@ -85,11 +94,10 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
|
||||
if (res.length === 0 || props.ctx.noPaging) {
|
||||
pushItems(res);
|
||||
canFetchMore.value = false;
|
||||
canFetchOlder.value = false;
|
||||
} else {
|
||||
if (props.ctx.reversed) moreFetching.value = true;
|
||||
pushItems(res);
|
||||
canFetchMore.value = true;
|
||||
canFetchOlder.value = true;
|
||||
}
|
||||
|
||||
error.value = false;
|
||||
|
@ -105,8 +113,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
}
|
||||
|
||||
async function fetchOlder(): Promise<void> {
|
||||
if (!canFetchMore.value || fetching.value || moreFetching.value || items.value.length === 0) return;
|
||||
moreFetching.value = true;
|
||||
if (!canFetchOlder.value || fetching.value || fetchingOlder.value || items.value.length === 0) return;
|
||||
fetchingOlder.value = true;
|
||||
const params = props.ctx.params ? isRef(props.ctx.params) ? props.ctx.params.value : props.ctx.params : {};
|
||||
await misskeyApi<T[]>(props.ctx.endpoint, {
|
||||
...params,
|
||||
|
@ -123,16 +131,16 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
}
|
||||
|
||||
if (res.length === 0) {
|
||||
canFetchMore.value = false;
|
||||
moreFetching.value = false;
|
||||
canFetchOlder.value = false;
|
||||
fetchingOlder.value = false;
|
||||
} else {
|
||||
items.value.push(...res);
|
||||
if (props.useShallowRef) triggerRef(items);
|
||||
canFetchMore.value = true;
|
||||
moreFetching.value = false;
|
||||
canFetchOlder.value = true;
|
||||
fetchingOlder.value = false;
|
||||
}
|
||||
}, err => {
|
||||
moreFetching.value = false;
|
||||
fetchingOlder.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -163,7 +171,7 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
}
|
||||
|
||||
function trim() {
|
||||
if (items.value.length >= MAX_ITEMS) canFetchMore.value = true;
|
||||
if (items.value.length >= MAX_ITEMS) canFetchOlder.value = true;
|
||||
items.value = items.value.slice(0, MAX_ITEMS);
|
||||
}
|
||||
|
||||
|
@ -225,8 +233,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
|
|||
items,
|
||||
queuedAheadItemsCount,
|
||||
fetching,
|
||||
moreFetching,
|
||||
canFetchMore,
|
||||
fetchingOlder,
|
||||
canFetchOlder,
|
||||
init,
|
||||
reload,
|
||||
fetchOlder,
|
||||
|
|
Loading…
Reference in New Issue