Frontend: Refactored pagination
ci/woodpecker/push/ociImagePush Pipeline was successful Details

This commit is contained in:
Natty 2024-01-01 20:29:33 +01:00
parent 6003f5e404
commit ab18633fbc
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
5 changed files with 43 additions and 159 deletions

View File

@ -30,11 +30,6 @@ export default defineComponent({
required: false,
default: false,
},
ad: {
type: Boolean,
required: false,
default: false,
},
},
setup(props, { slots, expose }) {

View File

@ -20,7 +20,6 @@
:direction="pagination.reversed ? 'up' : 'down'"
:reversed="pagination.reversed"
:no-gap="noGap"
:ad="true"
class="notes"
>
<XNoteResolvingProxy

View File

@ -19,7 +19,7 @@
<div v-else ref="rootEl" class="list">
<div
v-show="pagination.reversed && more"
v-show="pagination.reversed && hasMore"
key="_more_"
class="cxiknjgy _gap"
>
@ -29,7 +29,7 @@
:disabled="moreFetching"
:style="{ cursor: moreFetching ? 'wait' : 'pointer' }"
primary
@click="fetchMoreAhead"
@click="fetchMore"
>
{{ i18n.ts.loadMore }}
</MkButton>
@ -37,7 +37,7 @@
</div>
<slot :items="items"></slot>
<div
v-show="!pagination.reversed && more"
v-show="!pagination.reversed && hasMore"
key="_more_"
class="cxiknjgy _gap"
>
@ -134,7 +134,7 @@ const queue = ref<Item[]>([]);
const offset = ref(0);
const fetching = ref(true);
const moreFetching = ref(false);
const more = ref(false);
const hasMore = ref(false);
const backed = ref(false); //
const isBackTop = ref(false);
const empty = computed(() => items.value.length === 0);
@ -151,27 +151,14 @@ const init = async (): Promise<void> => {
await os
.api(props.pagination.endpoint, {
...params,
limit: props.pagination.noPaging
? props.pagination.limit || 10
: (props.pagination.limit || 10) + 1,
limit: props.pagination.limit || 10,
})
.then(
(res) => {
if (
!props.pagination.noPaging &&
res.length > (props.pagination.limit || 10)
) {
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;
}
items.value = props.pagination.reversed
? [...res].reverse()
: res;
hasMore.value = !props.pagination.noPaging && res.length > 0;
offset.value = res.length;
error.value = false;
fetching.value = false;
@ -202,17 +189,14 @@ const refresh = async (): Promise<void> => {
})
.then(
(res) => {
let ids = items.value.reduce((a, b) => {
a[b.id] = true;
return a;
}, {} as { [id: string]: boolean });
let ids = new Set(items.value.map((i) => i.id));
for (let i = 0; i < res.length; i++) {
const item = res[i];
if (!updateItem(item.id, (old) => item)) {
append(item);
}
delete ids[item.id];
ids.delete(item.id);
}
for (const id in ids) {
@ -228,12 +212,13 @@ const refresh = async (): Promise<void> => {
const fetchMore = async (): Promise<void> => {
if (
!more.value ||
!hasMore.value ||
fetching.value ||
moreFetching.value ||
items.value.length === 0
)
return;
moreFetching.value = true;
backed.value = true;
const params = props.pagination.params
@ -241,117 +226,34 @@ const fetchMore = async (): Promise<void> => {
? props.pagination.params.value
: props.pagination.params
: {};
const lastItem = items.value.at(props.pagination.reversed ? 0 : -1);
await os
.api(props.pagination.endpoint, {
...params,
limit: SECOND_FETCH_LIMIT + 1,
limit: SECOND_FETCH_LIMIT,
...(props.pagination.offsetMode
? {
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(
magTransProperty(
items.value[items.value.length - 1],
"createdAt",
"created_at"
)
).getTime(),
untilId: items.value[items.value.length - 1].id,
untilDate: lastItem
? new Date(
magTransProperty(
lastItem,
"createdAt",
"created_at"
)
).getTime()
: undefined,
untilId: lastItem?.id ?? undefined,
}),
})
.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;
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;
}
items.value = props.pagination.reversed
? [...res].reverse().concat(items.value)
: items.value.concat(res);
hasMore.value = res.length > 0;
offset.value += res.length;
moreFetching.value = false;
},
@ -373,15 +275,8 @@ const prepend = (item: Item): void => {
const height = container.scrollHeight;
const isBottom = pos + viewHeight > height - 32;
if (isBottom) {
//
if (items.value.length >= props.displayLimit) {
// Vue 3.2
//items.value = items.value.slice(-props.displayLimit);
while (items.value.length >= props.displayLimit) {
items.value.shift();
}
more.value = true;
}
items.value = items.value.slice(-props.displayLimit);
hasMore.value = true;
}
}
}
@ -402,24 +297,19 @@ const prepend = (item: Item): void => {
if (isTop) {
// Prepend the item
items.value.unshift(item);
//
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;
}
items.value = items.value.slice(0, props.displayLimit);
} else {
if (!queue.value.length) {
onScrollTop(rootEl.value, () => {
for (const queueItem of queue.value) {
prepend(queueItem);
}
queue.value = [];
});
}
queue.value.push(item);
onScrollTop(rootEl.value, () => {
for (const queueItem of queue.value) {
prepend(queueItem);
}
queue.value = [];
});
queue.value = queue.value.slice(0, props.displayLimit);
}
}
};

View File

@ -20,7 +20,6 @@
:items="items"
:direction="'down'"
:no-gap="false"
:ad="false"
>
<XNoteResolvingProxy
:key="item.id"

View File

@ -114,6 +114,7 @@ const nextPagination = {
appearNote
? {
userId: appearNote.user.id,
sinceDate: new Date(appearNote.created_at).getTime(),
sinceId: appearNote.id,
}
: null