From ab18633fbcaed91d0a07d165d2758f97aecb88f6 Mon Sep 17 00:00:00 2001 From: Natty Date: Mon, 1 Jan 2024 20:29:33 +0100 Subject: [PATCH] Frontend: Refactored pagination --- .../src/components/MkDateSeparatedList.vue | 5 - .../client/src/components/MkNotes.vue | 1 - .../client/src/components/MkPagination.vue | 194 ++++-------------- .../frontend/client/src/pages/favorites.vue | 1 - fe_calckey/frontend/client/src/pages/note.vue | 1 + 5 files changed, 43 insertions(+), 159 deletions(-) diff --git a/fe_calckey/frontend/client/src/components/MkDateSeparatedList.vue b/fe_calckey/frontend/client/src/components/MkDateSeparatedList.vue index e2f6dd7..8941846 100644 --- a/fe_calckey/frontend/client/src/components/MkDateSeparatedList.vue +++ b/fe_calckey/frontend/client/src/components/MkDateSeparatedList.vue @@ -30,11 +30,6 @@ export default defineComponent({ required: false, default: false, }, - ad: { - type: Boolean, - required: false, - default: false, - }, }, setup(props, { slots, expose }) { diff --git a/fe_calckey/frontend/client/src/components/MkNotes.vue b/fe_calckey/frontend/client/src/components/MkNotes.vue index a012059..6fb286f 100644 --- a/fe_calckey/frontend/client/src/components/MkNotes.vue +++ b/fe_calckey/frontend/client/src/components/MkNotes.vue @@ -20,7 +20,6 @@ :direction="pagination.reversed ? 'up' : 'down'" :reversed="pagination.reversed" :no-gap="noGap" - :ad="true" class="notes" >
@@ -29,7 +29,7 @@ :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary - @click="fetchMoreAhead" + @click="fetchMore" > {{ i18n.ts.loadMore }} @@ -37,7 +37,7 @@
@@ -134,7 +134,7 @@ const queue = ref([]); 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 => { 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 => { }) .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 => { const fetchMore = async (): Promise => { 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 => { ? 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 => { - 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); } } }; diff --git a/fe_calckey/frontend/client/src/pages/favorites.vue b/fe_calckey/frontend/client/src/pages/favorites.vue index 78cf930..9901eb8 100644 --- a/fe_calckey/frontend/client/src/pages/favorites.vue +++ b/fe_calckey/frontend/client/src/pages/favorites.vue @@ -20,7 +20,6 @@ :items="items" :direction="'down'" :no-gap="false" - :ad="false" >