This commit is contained in:
syuilo 2025-05-03 15:04:31 +09:00
parent c310f7cef6
commit 2f817cec8a
20 changed files with 77 additions and 58 deletions

View File

@ -19,14 +19,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkChannelPreview from '@/components/MkChannelPreview.vue'; import MkChannelPreview from '@/components/MkChannelPreview.vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js'; import { infoImageUrl } from '@/instance.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
pagination: Paging; pagination: PagingCtx;
noGap?: boolean; noGap?: boolean;
extractor?: (item: any) => any; extractor?: (item: any) => any;
}>(), { }>(), {

View File

@ -21,14 +21,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkUserInfo from '@/components/MkUserInfo.vue'; import MkUserInfo from '@/components/MkUserInfo.vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js'; import { infoImageUrl } from '@/instance.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
pagination: Paging; pagination: PagingCtx;
noGap?: boolean; noGap?: boolean;
extractor?: (item: any) => any; extractor?: (item: any) => any;
}>(), { }>(), {

View File

@ -39,15 +39,15 @@ import { i18n } from '@/i18n.js';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import XUser from '@/components/MkUserSetupDialog.User.vue'; import XUser from '@/components/MkUserSetupDialog.User.vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
const pinnedUsers: Paging = { const pinnedUsers: PagingCtx = {
endpoint: 'pinned-users', endpoint: 'pinned-users',
noPaging: true, noPaging: true,
limit: 10, limit: 10,
}; };
const popularUsers: Paging = { const popularUsers: PagingCtx = {
endpoint: 'users', endpoint: 'users',
limit: 10, limit: 10,
noPaging: true, noPaging: true,

View File

@ -55,7 +55,7 @@ import { computed, ref } from 'vue';
import MkInput from '@/components/MkInput.vue'; import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue'; import MkSelect from '@/components/MkSelect.vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue'; import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue';
import FormSplit from '@/components/form/split.vue'; import FormSplit from '@/components/form/split.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
@ -81,7 +81,7 @@ const pagination = {
state.value === 'notResponding' ? { notResponding: true } : state.value === 'notResponding' ? { notResponding: true } :
{}), {}),
})), })),
} as Paging; } as PagingCtx;
function getStatus(instance) { function getStatus(instance) {
if (instance.isSuspended) return 'Suspended'; if (instance.isSuspended) return 'Suspended';

View File

@ -87,7 +87,7 @@ const pagination = {
}; };
function resolved(reportId) { function resolved(reportId) {
reports.value?.removeItem(reportId); reports.value?.paginator.removeItem(reportId);
} }
function closeTutorial() { function closeTutorial() {

View File

@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, useTemplateRef } from 'vue'; import { computed, ref, useTemplateRef } from 'vue';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
@ -73,7 +73,7 @@ const pagingComponent = useTemplateRef('pagingComponent');
const type = ref('all'); const type = ref('all');
const sort = ref('+createdAt'); const sort = ref('+createdAt');
const pagination: Paging = { const pagination: PagingCtx = {
endpoint: 'admin/invite/list' as const, endpoint: 'admin/invite/list' as const,
limit: 10, limit: 10,
params: computed(() => ({ params: computed(() => ({
@ -100,12 +100,12 @@ async function createWithOptions() {
text: tickets.map(x => x.code).join('\n'), text: tickets.map(x => x.code).join('\n'),
}); });
tickets.forEach(ticket => pagingComponent.value?.prepend(ticket)); tickets.forEach(ticket => pagingComponent.value?.paginator.prepend(ticket));
} }
function deleted(id: string) { function deleted(id: string) {
if (pagingComponent.value) { if (pagingComponent.value) {
pagingComponent.value.items.delete(id); pagingComponent.value.paginator.removeItem(id);
} }
} }

View File

@ -121,7 +121,7 @@ async function addUser() {
username: username, username: username,
password: password, password: password,
}).then(res => { }).then(res => {
paginationComponent.value?.reload(); paginationComponent.value?.paginator.reload();
}); });
} }

View File

@ -86,10 +86,10 @@ async function read(target) {
} }
if (!paginationEl.value) return; if (!paginationEl.value) return;
paginationEl.value.updateItem(target.id, a => { paginationEl.value.paginator.updateItem(target.id, a => ({
a.isRead = true; ...a,
return a; isRead: true,
}); }));
misskeyApi('i/read-announcement', { announcementId: target.id }); misskeyApi('i/read-announcement', { announcementId: target.id });
updateCurrentAccountPartial({ updateCurrentAccountPartial({
unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== target.id), unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== target.id),

View File

@ -115,7 +115,7 @@ const selectAll = () => {
if (selectedEmojis.value.length > 0) { if (selectedEmojis.value.length > 0) {
selectedEmojis.value = []; selectedEmojis.value = [];
} else { } else {
selectedEmojis.value = Array.from(emojisPaginationComponent.value?.items.values(), item => item.id); selectedEmojis.value = emojisPaginationComponent.value?.paginator.items.value.map(item => item.id);
} }
}; };
@ -132,7 +132,7 @@ const add = async (ev: MouseEvent) => {
}, { }, {
done: result => { done: result => {
if (result.created) { if (result.created) {
emojisPaginationComponent.value?.prepend(result.created); emojisPaginationComponent.value?.paginator.prepend(result.created);
} }
}, },
closed: () => dispose(), closed: () => dispose(),
@ -145,12 +145,12 @@ const edit = (emoji) => {
}, { }, {
done: result => { done: result => {
if (result.updated) { if (result.updated) {
emojisPaginationComponent.value?.updateItem(result.updated.id, (oldEmoji) => ({ emojisPaginationComponent.value?.paginator.updateItem(result.updated.id, (oldEmoji) => ({
...oldEmoji, ...oldEmoji,
...result.updated, ...result.updated,
})); }));
} else if (result.deleted) { } else if (result.deleted) {
emojisPaginationComponent.value?.removeItem(emoji.id); emojisPaginationComponent.value?.paginator.removeItem(emoji.id);
} }
}, },
closed: () => dispose(), closed: () => dispose(),
@ -242,7 +242,7 @@ const setCategoryBulk = async () => {
ids: selectedEmojis.value, ids: selectedEmojis.value,
category: result, category: result,
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const setLicenseBulk = async () => { const setLicenseBulk = async () => {
@ -254,7 +254,7 @@ const setLicenseBulk = async () => {
ids: selectedEmojis.value, ids: selectedEmojis.value,
license: result, license: result,
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const addTagBulk = async () => { const addTagBulk = async () => {
@ -266,7 +266,7 @@ const addTagBulk = async () => {
ids: selectedEmojis.value, ids: selectedEmojis.value,
aliases: result.split(' '), aliases: result.split(' '),
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const removeTagBulk = async () => { const removeTagBulk = async () => {
@ -278,7 +278,7 @@ const removeTagBulk = async () => {
ids: selectedEmojis.value, ids: selectedEmojis.value,
aliases: result.split(' '), aliases: result.split(' '),
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const setTagBulk = async () => { const setTagBulk = async () => {
@ -290,7 +290,7 @@ const setTagBulk = async () => {
ids: selectedEmojis.value, ids: selectedEmojis.value,
aliases: result.split(' '), aliases: result.split(' '),
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const delBulk = async () => { const delBulk = async () => {
@ -302,7 +302,7 @@ const delBulk = async () => {
await os.apiWithDialog('admin/emoji/delete-bulk', { await os.apiWithDialog('admin/emoji/delete-bulk', {
ids: selectedEmojis.value, ids: selectedEmojis.value,
}); });
emojisPaginationComponent.value?.reload(); emojisPaginationComponent.value?.paginator.reload();
}; };
const headerActions = computed(() => [{ const headerActions = computed(() => [{

View File

@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkInfo from '@/components/MkInfo.vue'; import MkInfo from '@/components/MkInfo.vue';
import MkNotesTimeline from '@/components/MkNotesTimeline.vue'; import MkNotesTimeline from '@/components/MkNotesTimeline.vue';
@ -23,7 +23,7 @@ const props = defineProps<{
const realFileId = computed(() => props.fileId); const realFileId = computed(() => props.fileId);
const pagination = ref<Paging>({ const pagination = ref<PagingCtx>({
endpoint: 'drive/files/attached-notes', endpoint: 'drive/files/attached-notes',
limit: 10, limit: 10,
params: { params: {

View File

@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { useTemplateRef, computed, ref } from 'vue'; import { useTemplateRef, computed, ref } from 'vue';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import { userPage, acct } from '@/filters/user.js'; import { userPage, acct } from '@/filters/user.js';
@ -53,7 +53,7 @@ import { $i } from '@/i.js';
const paginationComponent = useTemplateRef('paginationComponent'); const paginationComponent = useTemplateRef('paginationComponent');
const pagination = computed<Paging>(() => tab.value === 'list' ? { const pagination = computed<PagingCtx>(() => tab.value === 'list' ? {
endpoint: 'following/requests/list', endpoint: 'following/requests/list',
limit: 10, limit: 10,
} : { } : {
@ -63,19 +63,19 @@ const pagination = computed<Paging>(() => tab.value === 'list' ? {
function accept(user: Misskey.entities.UserLite) { function accept(user: Misskey.entities.UserLite) {
os.apiWithDialog('following/requests/accept', { userId: user.id }).then(() => { os.apiWithDialog('following/requests/accept', { userId: user.id }).then(() => {
paginationComponent.value?.reload(); paginationComponent.value?.paginator.reload();
}); });
} }
function reject(user: Misskey.entities.UserLite) { function reject(user: Misskey.entities.UserLite) {
os.apiWithDialog('following/requests/reject', { userId: user.id }).then(() => { os.apiWithDialog('following/requests/reject', { userId: user.id }).then(() => {
paginationComponent.value?.reload(); paginationComponent.value?.paginator.reload();
}); });
} }
function cancel(user: Misskey.entities.UserLite) { function cancel(user: Misskey.entities.UserLite) {
os.apiWithDialog('following/requests/cancel', { userId: user.id }).then(() => { os.apiWithDialog('following/requests/cancel', { userId: user.id }).then(() => {
paginationComponent.value?.reload(); paginationComponent.value?.paginator.reload();
}); });
} }

View File

@ -133,7 +133,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref, computed, watch } from 'vue'; import { ref, computed, watch } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import type { ChartSrc } from '@/components/MkChart.vue'; import type { ChartSrc } from '@/components/MkChart.vue';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkChart from '@/components/MkChart.vue'; import MkChart from '@/components/MkChart.vue';
import MkObjectView from '@/components/MkObjectView.vue'; import MkObjectView from '@/components/MkObjectView.vue';
import FormLink from '@/components/form/link.vue'; import FormLink from '@/components/form/link.vue';
@ -180,7 +180,7 @@ const usersPagination = {
hostname: props.host, hostname: props.host,
}, },
offsetMode: true, offsetMode: true,
} satisfies Paging; } satisfies PagingCtx;
if (iAmModerator) { if (iAmModerator) {
watch(moderationNote, async () => { watch(moderationNote, async () => {

View File

@ -35,7 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, useTemplateRef } from 'vue'; import { computed, ref, useTemplateRef } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
@ -51,7 +51,7 @@ const currentInviteLimit = ref<null | number>(null);
const inviteLimit = (($i != null && $i.policies.inviteLimit) || (($i == null && instance.policies.inviteLimit))) as number; const inviteLimit = (($i != null && $i.policies.inviteLimit) || (($i == null && instance.policies.inviteLimit))) as number;
const inviteLimitCycle = (($i != null && $i.policies.inviteLimitCycle) || ($i == null && instance.policies.inviteLimitCycle)) as number; const inviteLimitCycle = (($i != null && $i.policies.inviteLimitCycle) || ($i == null && instance.policies.inviteLimitCycle)) as number;
const pagination: Paging = { const pagination: PagingCtx = {
endpoint: 'invite/list' as const, endpoint: 'invite/list' as const,
limit: 10, limit: 10,
}; };
@ -74,13 +74,13 @@ async function create() {
text: ticket.code, text: ticket.code,
}); });
pagingComponent.value?.prepend(ticket); pagingComponent.value?.paginator.prepend(ticket);
update(); update();
} }
function deleted(id: string) { function deleted(id: string) {
if (pagingComponent.value) { if (pagingComponent.value) {
pagingComponent.value.items.delete(id); pagingComponent.value.paginator.removeItem(id);
} }
update(); update();
} }

View File

@ -73,15 +73,15 @@ async function create() {
clipsCache.delete(); clipsCache.delete();
pagingComponent.value?.reload(); pagingComponent.value?.paginator.reload();
} }
function onClipCreated() { function onClipCreated() {
pagingComponent.value?.reload(); pagingComponent.value?.paginator.reload();
} }
function onClipDeleted() { function onClipDeleted() {
pagingComponent.value?.reload(); pagingComponent.value?.paginator.reload();
} }
const headerActions = computed(() => []); const headerActions = computed(() => []);

View File

@ -109,7 +109,7 @@ function addUser() {
listId: list.value.id, listId: list.value.id,
userId: user.id, userId: user.id,
}).then(() => { }).then(() => {
paginationEl.value?.reload(); paginationEl.value?.paginator.reload();
}); });
}); });
} }
@ -125,7 +125,7 @@ async function removeUser(item, ev) {
listId: list.value.id, listId: list.value.id,
userId: item.userId, userId: item.userId,
}).then(() => { }).then(() => {
paginationEl.value?.removeItem(item.id); paginationEl.value?.paginator.removeItem(item.id);
}); });
}, },
}], ev.currentTarget ?? ev.target); }], ev.currentTarget ?? ev.target);
@ -147,7 +147,7 @@ async function showMembershipMenu(item, ev) {
userId: item.userId, userId: item.userId,
withReplies, withReplies,
}).then(() => { }).then(() => {
paginationEl.value!.updateItem(item.id, (old) => ({ paginationEl.value!.paginator.updateItem(item.id, (old) => ({
...old, ...old,
withReplies, withReplies,
})); }));

View File

@ -50,7 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, watch, ref } from 'vue'; import { computed, watch, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { host } from '@@/js/config.js'; import { host } from '@@/js/config.js';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkNoteDetailed from '@/components/MkNoteDetailed.vue'; import MkNoteDetailed from '@/components/MkNoteDetailed.vue';
import MkNotesTimeline from '@/components/MkNotesTimeline.vue'; import MkNotesTimeline from '@/components/MkNotesTimeline.vue';
import MkRemoteCaution from '@/components/MkRemoteCaution.vue'; import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
@ -80,7 +80,7 @@ const showPrev = ref<'user' | 'channel' | false>(false);
const showNext = ref<'user' | 'channel' | false>(false); const showNext = ref<'user' | 'channel' | false>(false);
const error = ref(); const error = ref();
const prevUserPagination: Paging = { const prevUserPagination: PagingCtx = {
endpoint: 'users/notes', endpoint: 'users/notes',
limit: 10, limit: 10,
params: computed(() => note.value ? ({ params: computed(() => note.value ? ({
@ -89,7 +89,7 @@ const prevUserPagination: Paging = {
}) : undefined), }) : undefined),
}; };
const nextUserPagination: Paging = { const nextUserPagination: PagingCtx = {
reversed: true, reversed: true,
endpoint: 'users/notes', endpoint: 'users/notes',
limit: 10, limit: 10,
@ -99,7 +99,7 @@ const nextUserPagination: Paging = {
}) : undefined), }) : undefined),
}; };
const prevChannelPagination: Paging = { const prevChannelPagination: PagingCtx = {
endpoint: 'channels/timeline', endpoint: 'channels/timeline',
limit: 10, limit: 10,
params: computed(() => note.value ? ({ params: computed(() => note.value ? ({
@ -108,7 +108,7 @@ const prevChannelPagination: Paging = {
}) : undefined), }) : undefined),
}; };
const nextChannelPagination: Paging = { const nextChannelPagination: PagingCtx = {
reversed: true, reversed: true,
endpoint: 'channels/timeline', endpoint: 'channels/timeline',
limit: 10, limit: 10,

View File

@ -113,7 +113,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, shallowRef, toRef } from 'vue'; import { computed, ref, shallowRef, toRef } from 'vue';
import type * as Misskey from 'misskey-js'; import type * as Misskey from 'misskey-js';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import { host as localHost } from '@@/js/config.js'; import { host as localHost } from '@@/js/config.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
@ -144,7 +144,7 @@ const props = withDefaults(defineProps<{
const router = useRouter(); const router = useRouter();
const key = ref(0); const key = ref(0);
const notePagination = ref<Paging<'notes/search'>>(); const notePagination = ref<PagingCtx<'notes/search'>>();
const searchQuery = ref(toRef(props, 'query').value); const searchQuery = ref(toRef(props, 'query').value);
const hostInput = ref(toRef(props, 'host').value); const hostInput = ref(toRef(props, 'host').value);

View File

@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { ref, toRef } from 'vue'; import { ref, toRef } from 'vue';
import type { Endpoints } from 'misskey-js'; import type { Endpoints } from 'misskey-js';
import type { Paging } from '@/components/MkPagination.vue'; import type { PagingCtx } from '@/use/use-pagination.js';
import MkUserList from '@/components/MkUserList.vue'; import MkUserList from '@/components/MkUserList.vue';
import MkInput from '@/components/MkInput.vue'; import MkInput from '@/components/MkInput.vue';
import MkRadios from '@/components/MkRadios.vue'; import MkRadios from '@/components/MkRadios.vue';
@ -50,7 +50,7 @@ const props = withDefaults(defineProps<{
const router = useRouter(); const router = useRouter();
const key = ref(0); const key = ref(0);
const userPagination = ref<Paging<'users/search'>>(); const userPagination = ref<PagingCtx<'users/search'>>();
const searchQuery = ref(toRef(props, 'query').value); const searchQuery = ref(toRef(props, 'query').value);
const searchOrigin = ref(toRef(props, 'origin').value); const searchOrigin = ref(toRef(props, 'origin').value);

View File

@ -78,7 +78,7 @@ const pagination = {
function revoke(token) { function revoke(token) {
misskeyApi('i/revoke-token', { tokenId: token.id }).then(() => { misskeyApi('i/revoke-token', { tokenId: token.id }).then(() => {
list.value?.reload(); list.value?.paginator.reload();
}); });
} }

View File

@ -196,6 +196,23 @@ export function usePagination<T extends MisskeyEntity>(props: {
queuedAheadItemsCount.value = 0; queuedAheadItemsCount.value = 0;
} }
function removeItem(id: string) {
const index = items.value.findIndex(x => x.id === id);
if (index !== -1) {
items.value.splice(index, 1);
if (props.useShallowRef) triggerRef(items);
}
}
function updateItem(id: string, updator: (item: T) => T) {
const index = items.value.findIndex(x => x.id === id);
if (index !== -1) {
const item = items.value[index]!;
items.value[index] = updator(item);
if (props.useShallowRef) triggerRef(items);
}
}
onMounted(() => { onMounted(() => {
init(); init();
}); });
@ -213,6 +230,8 @@ export function usePagination<T extends MisskeyEntity>(props: {
unshiftItems, unshiftItems,
prepend, prepend,
trim, trim,
removeItem,
updateItem,
enqueue, enqueue,
releaseQueue, releaseQueue,
error, error,