From 3f73251df5967ad47f61f1a6541f9d5ff6563f72 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 7 Apr 2024 17:49:20 +0100 Subject: [PATCH 1/3] allow computed `offsetMode` in `MkPagination` - #490 --- packages/frontend/src/components/MkPagination.vue | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue index 6f6007d432..9a324849e2 100644 --- a/packages/frontend/src/components/MkPagination.vue +++ b/packages/frontend/src/components/MkPagination.vue @@ -73,7 +73,7 @@ export type Paging */ reversed?: boolean; - offsetMode?: boolean; + offsetMode?: boolean | ComputedRef; pageEl?: HTMLElement; }; @@ -240,10 +240,11 @@ const fetchMore = async (): Promise => { if (!more.value || fetching.value || moreFetching.value || items.value.size === 0) return; moreFetching.value = true; const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; + const offsetMode = props.offsetMode ? isRef(props.offsetMode) ? props.offsetMode.value : props.offsetMode : false; await misskeyApi(props.pagination.endpoint, { ...params, limit: SECOND_FETCH_LIMIT, - ...(props.pagination.offsetMode ? { + ...(offsetMode ? { offset: offset.value, } : { untilId: Array.from(items.value.keys()).at(-1), @@ -304,10 +305,11 @@ const fetchMoreAhead = async (): Promise => { if (!more.value || fetching.value || moreFetching.value || items.value.size === 0) return; moreFetching.value = true; const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; + const offsetMode = props.offsetMode ? isRef(props.offsetMode) ? props.offsetMode.value : props.offsetMode : false; await misskeyApi(props.pagination.endpoint, { ...params, limit: SECOND_FETCH_LIMIT, - ...(props.pagination.offsetMode ? { + ...(offsetMode ? { offset: offset.value, } : { sinceId: Array.from(items.value.keys()).at(-1), From 9d91196344ce359fd27dabd778d4d084d1fc6c5e Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 7 Apr 2024 17:49:53 +0100 Subject: [PATCH 2/3] allow `offset` in `admin/emoji/list` - #490 also, use `skip` + `take` instead of `limit` (the TypeORM docs say so https://github.com/typeorm/typeorm/blob/master/docs/select-query-builder.md#adding-limit-expression ) --- .../backend/src/server/api/endpoints/admin/emoji/list.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 5e21111f9f..f35a6667f4 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -66,6 +66,7 @@ export const paramDef = { properties: { query: { type: 'string', nullable: true, default: null }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', minimum: 1, nullable: true, default: null }, sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, }, @@ -91,7 +92,7 @@ export default class extends Endpoint { // eslint- //q.andWhere('emoji.name ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }); //const emojis = await q.limit(ps.limit).getMany(); - emojis = await q.orderBy('length(emoji.name)', 'ASC').getMany(); + emojis = await q.orderBy('length(emoji.name)', 'ASC').addOrderBy('id', 'DESC').getMany(); const queryarry = ps.query.match(/:([\p{Letter}\p{Number}\p{Mark}_+-]*):/ug); if (queryarry) { @@ -105,9 +106,9 @@ export default class extends Endpoint { // eslint- emoji.aliases.some(a => a.includes(queryNfc)) || emoji.category?.includes(queryNfc)); } - emojis.splice(ps.limit + 1); + emojis = emojis.slice((ps.offset ?? 0), ((ps.offset ?? 0) + ps.limit)); } else { - emojis = await q.limit(ps.limit).getMany(); + emojis = await q.take(ps.limit).skip(ps.offset ?? 0).getMany(); } return this.emojiEntityService.packDetailedMany(emojis); From a676b0ee6178ad45370864195afa09c87d865265 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 7 Apr 2024 17:50:53 +0100 Subject: [PATCH 3/3] paginate in offset mode when querying emoji - fixes #490 since the backend sorts emojis by name length when a query is present, the normal pagination with `sinceId` / `untilId` would not work reliably `offsetMode` is better in this case, although it will produce non-stable results if custom emojis that match the query are added or removed while we paginate --- packages/frontend/src/pages/custom-emojis-manager.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue index 1f9a99d4f5..9357735c82 100644 --- a/packages/frontend/src/pages/custom-emojis-manager.vue +++ b/packages/frontend/src/pages/custom-emojis-manager.vue @@ -98,6 +98,9 @@ const selectedEmojis = ref([]); const pagination = { endpoint: 'admin/emoji/list' as const, limit: 30, + offsetMode: computed(() => ( + (query.value && query.value !== '') ? true : false + )), params: computed(() => ({ query: (query.value && query.value !== '') ? query.value : null, })),