This commit is contained in:
tamaina 2023-07-28 15:25:50 +00:00
parent 796b4ebc0f
commit 4e29da828f
3 changed files with 58 additions and 13 deletions

View File

@ -87,6 +87,11 @@ export type Paging<E extends keyof misskey.Endpoints = keyof misskey.Endpoints>
offsetMode?: boolean; offsetMode?: boolean;
pageEl?: HTMLElement; pageEl?: HTMLElement;
/**
* 変換関数
*/
transform?: (source: Omit<MisskeyEntity, '_shouldInsertAd_'>[]) => MisskeyEntity[];
}; };
type MisskeyEntityMap = Map<string, MisskeyEntity>; type MisskeyEntityMap = Map<string, MisskeyEntity>;
@ -169,6 +174,11 @@ const visibility = useDocumentVisibility();
const isPausingUpdateByExecutingQueue = ref(false); const isPausingUpdateByExecutingQueue = ref(false);
const denyMoveTransition = ref(false); const denyMoveTransition = ref(false);
/**
* 変換関数
*/
const transform = computed(() => props.pagination.transform ?? ((source: MisskeyEntity[]) => source));
//#region scrolling //#region scrolling
const checkFn = props.pagination.reversed ? isBottomVisible : isTopVisible; const checkFn = props.pagination.reversed ? isBottomVisible : isTopVisible;
const checkTop = (tolerance?: number) => { const checkTop = (tolerance?: number) => {
@ -298,7 +308,9 @@ async function init(): Promise<void> {
await os.api(props.pagination.endpoint, { await os.api(props.pagination.endpoint, {
...params, ...params,
limit: props.pagination.limit ?? 10, limit: props.pagination.limit ?? 10,
}).then(res => { }).then(_res => {
const res = transform.value(_res);
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 (i === 3) item._shouldInsertAd_ = true; if (i === 3) item._shouldInsertAd_ = true;
@ -378,7 +390,9 @@ const fetchMore = async (): Promise<void> => {
} : { } : {
untilId: Array.from(items.value.keys()).at(-1), untilId: Array.from(items.value.keys()).at(-1),
}), }),
}).then(res => { }).then(_res => {
const res = transform.value(_res);
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 (i === 10) item._shouldInsertAd_ = true; if (i === 10) item._shouldInsertAd_ = true;
@ -425,15 +439,15 @@ const fetchMoreAhead = async (): Promise<void> => {
} : { } : {
sinceId: Array.from(items.value.keys()).at(-1), sinceId: Array.from(items.value.keys()).at(-1),
}), }),
}).then(res => { }).then(_res => {
if (res.length === 0) { if (_res.length === 0) {
items.value = concatMapWithArray(items.value, res);
more.value = false; more.value = false;
} else { } else {
const res = transform.value(_res);
items.value = concatMapWithArray(items.value, res); items.value = concatMapWithArray(items.value, res);
more.value = true; more.value = true;
} }
offset.value += res.length; offset.value += _res.length;
moreFetching.value = false; moreFetching.value = false;
}, err => { }, err => {
moreFetching.value = false; moreFetching.value = false;
@ -484,9 +498,12 @@ watch([active, visibility], () => {
/** /**
* 最新のものとして1つだけアイテムを追加する * 最新のものとして1つだけアイテムを追加する
* ストリーミングから降ってきたアイテムはこれで追加する * ストリーミングから降ってきたアイテムはこれで追加する
* @param item アイテム * @param item アイテムtransform前
*/ */
const prepend = (item: MisskeyEntity): void => { const prepend = (_item: MisskeyEntity): void => {
const item = transform.value([_item])[0];
if (!item) return;
if (items.value.size === 0) { if (items.value.size === 0) {
items.value.set(item.id, item); items.value.set(item.id, item);
fetching.value = false; fetching.value = false;
@ -570,8 +587,12 @@ function prependQueue(newItem: MisskeyEntity) {
/* /*
* アイテムを末尾に追加する使うの * アイテムを末尾に追加する使うの
* @param item アイテムtransform前
*/ */
const appendItem = (item: MisskeyEntity): void => { const appendItem = (_item: MisskeyEntity): void => {
const item = transform.value([_item])[0];
if (!item) return;
items.value.set(item.id, item); items.value.set(item.id, item);
}; };

View File

@ -26,6 +26,9 @@ import { $i } from '@/account';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
import { instance } from '@/instance'; import { instance } from '@/instance';
import { noteManager } from '@/scripts/entity-manager';
import { Note } from 'misskey-js/built/entities';
import { MisskeyEntity } from '@/types/date-separated-list';
const props = defineProps<{ const props = defineProps<{
src: string; src: string;
@ -62,6 +65,16 @@ const prepend = note => {
} }
}; };
const transform = (notes: Note[]): MisskeyEntity[] => {
return notes.map(note => {
noteManager.set(note);
return {
id: note.id,
createdAt: note.createdAt,
};
});
};
let endpoint; let endpoint;
let query; let query;
let connection; let connection;
@ -165,6 +178,7 @@ const pagination = {
endpoint: endpoint, endpoint: endpoint,
limit: 10, limit: 10,
params: query, params: query,
transform: transform,
}; };
onUnmounted(() => { onUnmounted(() => {

View File

@ -53,8 +53,9 @@ export class NoteManager {
private notesSource: Map<Note['id'], CachedNoteSource>; private notesSource: Map<Note['id'], CachedNoteSource>;
/** /**
* user, renote, replyを取得したComputedRef * user, renote, replyを取得したComputedRefのキャッシュを保持しておく
* nullは削除済みであることを表す * nullは削除済みであることを表す
* 0
*/ */
private notesComputed: Map<Note['id'], CachedNote>; private notesComputed: Map<Note['id'], CachedNote>;
private updatedAt: Map<Note['id'], number>; private updatedAt: Map<Note['id'], number>;
@ -81,7 +82,7 @@ export class NoteManager {
}); });
} }
public set(_note: Note): CachedNote { public set(_note: Note): void {
const note: Note = { ..._note }; const note: Note = { ..._note };
userLiteManager.set(note.user); userLiteManager.set(note.user);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@ -98,7 +99,6 @@ export class NoteManager {
this.notesSource.set(note.id, ref(note)); this.notesSource.set(note.id, ref(note));
} }
this.updatedAt.set(note.id, Date.now()); this.updatedAt.set(note.id, Date.now());
return this.get(note.id)!;
} }
public get(id: string): CachedNote { public get(id: string): CachedNote {
@ -139,7 +139,10 @@ export class NoteManager {
} }
} }
return api('notes/show', { noteId: id }) return api('notes/show', { noteId: id })
.then(fetchedNote => this.set(fetchedNote)) .then(fetchedNote => {
this.set(fetchedNote);
return this.get(id)!;
})
.catch(() => { .catch(() => {
// エラーが発生した場合はとりあえず削除されたものとして扱う // エラーが発生した場合はとりあえず削除されたものとして扱う
const cached = this.notesSource.get(id); const cached = this.notesSource.get(id);
@ -161,6 +164,8 @@ export class NoteManager {
if (!note || !note.value) { if (!note || !note.value) {
this.connection?.send('un', { id }); this.connection?.send('un', { id });
this.captureing.delete(id); this.captureing.delete(id);
this.notesComputed.delete(id);
this.updatedAt.delete(id);
return; return;
} }
@ -219,6 +224,8 @@ export class NoteManager {
break; break;
} }
} }
this.updatedAt.set(id, Date.now());
} }
private capture(id: string, markRead = true): void { private capture(id: string, markRead = true): void {
@ -252,6 +259,9 @@ export class NoteManager {
} }
this.captureing.delete(id); this.captureing.delete(id);
// キャプチャが終わったらcomputedキャッシュも消してしまう
this.notesComputed.delete(id);
} }
/** /**