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