Frontend: Refactored pagination
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
ci/woodpecker/push/ociImagePush Pipeline was successful
Details
This commit is contained in:
parent
6003f5e404
commit
ab18633fbc
|
@ -30,11 +30,6 @@ export default defineComponent({
|
||||||
required: false,
|
required: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
ad: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { slots, expose }) {
|
setup(props, { slots, expose }) {
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
:direction="pagination.reversed ? 'up' : 'down'"
|
:direction="pagination.reversed ? 'up' : 'down'"
|
||||||
:reversed="pagination.reversed"
|
:reversed="pagination.reversed"
|
||||||
:no-gap="noGap"
|
:no-gap="noGap"
|
||||||
:ad="true"
|
|
||||||
class="notes"
|
class="notes"
|
||||||
>
|
>
|
||||||
<XNoteResolvingProxy
|
<XNoteResolvingProxy
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<div v-else ref="rootEl" class="list">
|
<div v-else ref="rootEl" class="list">
|
||||||
<div
|
<div
|
||||||
v-show="pagination.reversed && more"
|
v-show="pagination.reversed && hasMore"
|
||||||
key="_more_"
|
key="_more_"
|
||||||
class="cxiknjgy _gap"
|
class="cxiknjgy _gap"
|
||||||
>
|
>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
:disabled="moreFetching"
|
:disabled="moreFetching"
|
||||||
:style="{ cursor: moreFetching ? 'wait' : 'pointer' }"
|
:style="{ cursor: moreFetching ? 'wait' : 'pointer' }"
|
||||||
primary
|
primary
|
||||||
@click="fetchMoreAhead"
|
@click="fetchMore"
|
||||||
>
|
>
|
||||||
{{ i18n.ts.loadMore }}
|
{{ i18n.ts.loadMore }}
|
||||||
</MkButton>
|
</MkButton>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</div>
|
</div>
|
||||||
<slot :items="items"></slot>
|
<slot :items="items"></slot>
|
||||||
<div
|
<div
|
||||||
v-show="!pagination.reversed && more"
|
v-show="!pagination.reversed && hasMore"
|
||||||
key="_more_"
|
key="_more_"
|
||||||
class="cxiknjgy _gap"
|
class="cxiknjgy _gap"
|
||||||
>
|
>
|
||||||
|
@ -134,7 +134,7 @@ const queue = ref<Item[]>([]);
|
||||||
const offset = ref(0);
|
const offset = ref(0);
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
const moreFetching = ref(false);
|
const moreFetching = ref(false);
|
||||||
const more = ref(false);
|
const hasMore = ref(false);
|
||||||
const backed = ref(false); // 遡り中か否か
|
const backed = ref(false); // 遡り中か否か
|
||||||
const isBackTop = ref(false);
|
const isBackTop = ref(false);
|
||||||
const empty = computed(() => items.value.length === 0);
|
const empty = computed(() => items.value.length === 0);
|
||||||
|
@ -151,27 +151,14 @@ const init = async (): Promise<void> => {
|
||||||
await os
|
await os
|
||||||
.api(props.pagination.endpoint, {
|
.api(props.pagination.endpoint, {
|
||||||
...params,
|
...params,
|
||||||
limit: props.pagination.noPaging
|
limit: props.pagination.limit || 10,
|
||||||
? props.pagination.limit || 10
|
|
||||||
: (props.pagination.limit || 10) + 1,
|
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
(res) => {
|
(res) => {
|
||||||
if (
|
items.value = props.pagination.reversed
|
||||||
!props.pagination.noPaging &&
|
? [...res].reverse()
|
||||||
res.length > (props.pagination.limit || 10)
|
: res;
|
||||||
) {
|
hasMore.value = !props.pagination.noPaging && res.length > 0;
|
||||||
res.pop();
|
|
||||||
items.value = props.pagination.reversed
|
|
||||||
? [...res].reverse()
|
|
||||||
: res;
|
|
||||||
more.value = true;
|
|
||||||
} else {
|
|
||||||
items.value = props.pagination.reversed
|
|
||||||
? [...res].reverse()
|
|
||||||
: res;
|
|
||||||
more.value = false;
|
|
||||||
}
|
|
||||||
offset.value = res.length;
|
offset.value = res.length;
|
||||||
error.value = false;
|
error.value = false;
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
|
@ -202,17 +189,14 @@ const refresh = async (): Promise<void> => {
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
(res) => {
|
(res) => {
|
||||||
let ids = items.value.reduce((a, b) => {
|
let ids = new Set(items.value.map((i) => i.id));
|
||||||
a[b.id] = true;
|
|
||||||
return a;
|
|
||||||
}, {} as { [id: string]: boolean });
|
|
||||||
|
|
||||||
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 (!updateItem(item.id, (old) => item)) {
|
if (!updateItem(item.id, (old) => item)) {
|
||||||
append(item);
|
append(item);
|
||||||
}
|
}
|
||||||
delete ids[item.id];
|
ids.delete(item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id in ids) {
|
for (const id in ids) {
|
||||||
|
@ -228,12 +212,13 @@ const refresh = async (): Promise<void> => {
|
||||||
|
|
||||||
const fetchMore = async (): Promise<void> => {
|
const fetchMore = async (): Promise<void> => {
|
||||||
if (
|
if (
|
||||||
!more.value ||
|
!hasMore.value ||
|
||||||
fetching.value ||
|
fetching.value ||
|
||||||
moreFetching.value ||
|
moreFetching.value ||
|
||||||
items.value.length === 0
|
items.value.length === 0
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
moreFetching.value = true;
|
moreFetching.value = true;
|
||||||
backed.value = true;
|
backed.value = true;
|
||||||
const params = props.pagination.params
|
const params = props.pagination.params
|
||||||
|
@ -241,117 +226,34 @@ const fetchMore = async (): Promise<void> => {
|
||||||
? props.pagination.params.value
|
? props.pagination.params.value
|
||||||
: props.pagination.params
|
: props.pagination.params
|
||||||
: {};
|
: {};
|
||||||
|
const lastItem = items.value.at(props.pagination.reversed ? 0 : -1);
|
||||||
await os
|
await os
|
||||||
.api(props.pagination.endpoint, {
|
.api(props.pagination.endpoint, {
|
||||||
...params,
|
...params,
|
||||||
limit: SECOND_FETCH_LIMIT + 1,
|
limit: SECOND_FETCH_LIMIT,
|
||||||
...(props.pagination.offsetMode
|
...(props.pagination.offsetMode
|
||||||
? {
|
? {
|
||||||
offset: offset.value,
|
offset: offset.value,
|
||||||
}
|
}
|
||||||
: props.pagination.reversed
|
|
||||||
? {
|
|
||||||
sinceDate: new Date(
|
|
||||||
magTransProperty(
|
|
||||||
items.value[0],
|
|
||||||
"createdAt",
|
|
||||||
"created_at"
|
|
||||||
)
|
|
||||||
).getTime(),
|
|
||||||
sinceId: items.value[0].id,
|
|
||||||
}
|
|
||||||
: {
|
: {
|
||||||
untilDate: new Date(
|
untilDate: lastItem
|
||||||
magTransProperty(
|
? new Date(
|
||||||
items.value[items.value.length - 1],
|
magTransProperty(
|
||||||
"createdAt",
|
lastItem,
|
||||||
"created_at"
|
"createdAt",
|
||||||
)
|
"created_at"
|
||||||
).getTime(),
|
)
|
||||||
untilId: items.value[items.value.length - 1].id,
|
).getTime()
|
||||||
|
: undefined,
|
||||||
|
untilId: lastItem?.id ?? undefined,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
(res) => {
|
(res) => {
|
||||||
if (res.length > SECOND_FETCH_LIMIT) {
|
items.value = props.pagination.reversed
|
||||||
res.pop();
|
? [...res].reverse().concat(items.value)
|
||||||
items.value = props.pagination.reversed
|
: items.value.concat(res);
|
||||||
? [...res].reverse().concat(items.value)
|
hasMore.value = res.length > 0;
|
||||||
: items.value.concat(res);
|
|
||||||
more.value = true;
|
|
||||||
} else {
|
|
||||||
items.value = props.pagination.reversed
|
|
||||||
? [...res].reverse().concat(items.value)
|
|
||||||
: items.value.concat(res);
|
|
||||||
more.value = false;
|
|
||||||
}
|
|
||||||
offset.value += res.length;
|
|
||||||
moreFetching.value = false;
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
moreFetching.value = false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchMoreAhead = async (): Promise<void> => {
|
|
||||||
if (
|
|
||||||
!more.value ||
|
|
||||||
fetching.value ||
|
|
||||||
moreFetching.value ||
|
|
||||||
items.value.length === 0
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
moreFetching.value = true;
|
|
||||||
const params = props.pagination.params
|
|
||||||
? isRef(props.pagination.params)
|
|
||||||
? props.pagination.params.value
|
|
||||||
: props.pagination.params
|
|
||||||
: {};
|
|
||||||
await os
|
|
||||||
.api(props.pagination.endpoint, {
|
|
||||||
...params,
|
|
||||||
limit: SECOND_FETCH_LIMIT + 1,
|
|
||||||
...(props.pagination.offsetMode
|
|
||||||
? {
|
|
||||||
offset: offset.value,
|
|
||||||
}
|
|
||||||
: props.pagination.reversed
|
|
||||||
? {
|
|
||||||
untilDate: new Date(
|
|
||||||
magTransProperty(
|
|
||||||
items.value[0],
|
|
||||||
"createdAt",
|
|
||||||
"created_at"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
untilId: items.value[0].id,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
sinceDate: new Date(
|
|
||||||
magTransProperty(
|
|
||||||
items.value[items.value.length - 1],
|
|
||||||
"createdAt",
|
|
||||||
"created_at"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
sinceId: items.value[items.value.length - 1].createdAt,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.then(
|
|
||||||
(res) => {
|
|
||||||
if (res.length > SECOND_FETCH_LIMIT) {
|
|
||||||
res.pop();
|
|
||||||
items.value = props.pagination.reversed
|
|
||||||
? [...res].reverse().concat(items.value)
|
|
||||||
: items.value.concat(res);
|
|
||||||
more.value = true;
|
|
||||||
} else {
|
|
||||||
items.value = props.pagination.reversed
|
|
||||||
? [...res].reverse().concat(items.value)
|
|
||||||
: items.value.concat(res);
|
|
||||||
more.value = false;
|
|
||||||
}
|
|
||||||
offset.value += res.length;
|
offset.value += res.length;
|
||||||
moreFetching.value = false;
|
moreFetching.value = false;
|
||||||
},
|
},
|
||||||
|
@ -373,15 +275,8 @@ const prepend = (item: Item): void => {
|
||||||
const height = container.scrollHeight;
|
const height = container.scrollHeight;
|
||||||
const isBottom = pos + viewHeight > height - 32;
|
const isBottom = pos + viewHeight > height - 32;
|
||||||
if (isBottom) {
|
if (isBottom) {
|
||||||
// オーバーフローしたら古いアイテムは捨てる
|
items.value = items.value.slice(-props.displayLimit);
|
||||||
if (items.value.length >= props.displayLimit) {
|
hasMore.value = true;
|
||||||
// このやり方だとVue 3.2以降アニメーションが動かなくなる
|
|
||||||
//items.value = items.value.slice(-props.displayLimit);
|
|
||||||
while (items.value.length >= props.displayLimit) {
|
|
||||||
items.value.shift();
|
|
||||||
}
|
|
||||||
more.value = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,24 +297,19 @@ const prepend = (item: Item): void => {
|
||||||
if (isTop) {
|
if (isTop) {
|
||||||
// Prepend the item
|
// Prepend the item
|
||||||
items.value.unshift(item);
|
items.value.unshift(item);
|
||||||
|
items.value = items.value.slice(0, props.displayLimit);
|
||||||
// オーバーフローしたら古いアイテムは捨てる
|
|
||||||
if (items.value.length >= props.displayLimit) {
|
|
||||||
// このやり方だとVue 3.2以降アニメーションが動かなくなる
|
|
||||||
//this.items = items.value.slice(0, props.displayLimit);
|
|
||||||
while (items.value.length >= props.displayLimit) {
|
|
||||||
items.value.pop();
|
|
||||||
}
|
|
||||||
more.value = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
if (!queue.value.length) {
|
||||||
|
onScrollTop(rootEl.value, () => {
|
||||||
|
for (const queueItem of queue.value) {
|
||||||
|
prepend(queueItem);
|
||||||
|
}
|
||||||
|
queue.value = [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
queue.value.push(item);
|
queue.value.push(item);
|
||||||
onScrollTop(rootEl.value, () => {
|
queue.value = queue.value.slice(0, props.displayLimit);
|
||||||
for (const queueItem of queue.value) {
|
|
||||||
prepend(queueItem);
|
|
||||||
}
|
|
||||||
queue.value = [];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
:items="items"
|
:items="items"
|
||||||
:direction="'down'"
|
:direction="'down'"
|
||||||
:no-gap="false"
|
:no-gap="false"
|
||||||
:ad="false"
|
|
||||||
>
|
>
|
||||||
<XNoteResolvingProxy
|
<XNoteResolvingProxy
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
|
|
|
@ -114,6 +114,7 @@ const nextPagination = {
|
||||||
appearNote
|
appearNote
|
||||||
? {
|
? {
|
||||||
userId: appearNote.user.id,
|
userId: appearNote.user.id,
|
||||||
|
sinceDate: new Date(appearNote.created_at).getTime(),
|
||||||
sinceId: appearNote.id,
|
sinceId: appearNote.id,
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
|
|
Loading…
Reference in New Issue