wip
This commit is contained in:
parent
631715c86e
commit
417969604e
|
@ -595,7 +595,7 @@ export class NoteEntityService implements OnModuleInit {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async ogogogo(noteIds: MiNote['id'][]) {
|
||||
public async fetchDiffs(noteIds: MiNote['id'][]) {
|
||||
if (noteIds.length === 0) return [];
|
||||
|
||||
const notes = await this.notesRepository.find({
|
||||
|
@ -603,25 +603,32 @@ export class NoteEntityService implements OnModuleInit {
|
|||
id: In(noteIds),
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
userHost: true,
|
||||
reactions: true,
|
||||
reactionAndUserPairCache: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(notes);
|
||||
|
||||
const bufferedReactionsMap = this.meta.enableReactionsBuffering ? await this.reactionsBufferingService.getMany(noteIds) : null;
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const note of notes) {
|
||||
const packings = notes.map(note => {
|
||||
const bufferedReactions = bufferedReactionsMap?.get(note.id);
|
||||
const reactionAndUserPairCache = note.reactionAndUserPairCache.concat(bufferedReactions.pairs.map(x => x.join('/')));
|
||||
//const reactionAndUserPairCache = note.reactionAndUserPairCache.concat(bufferedReactions.pairs.map(x => x.join('/')));
|
||||
|
||||
results.push({
|
||||
const reactions = this.reactionService.convertLegacyReactions(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions?.deltas ?? {}));
|
||||
|
||||
const reactionEmojiNames = Object.keys(reactions)
|
||||
.filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ
|
||||
.map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', ''));
|
||||
|
||||
return this.customEmojiService.populateEmojis(reactionEmojiNames, note.userHost).then(reactionEmojis => ({
|
||||
id: note.id,
|
||||
reactions: this.reactionService.convertLegacyReactions(this.reactionsBufferingService.mergeReactions(note.reactions, bufferedReactions.deltas ?? {})),
|
||||
});
|
||||
}
|
||||
reactions,
|
||||
reactionEmojis,
|
||||
}));
|
||||
});
|
||||
|
||||
return await Promise.all(packings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,6 +317,7 @@ export * as 'notes/replies' from './endpoints/notes/replies.js';
|
|||
export * as 'notes/search' from './endpoints/notes/search.js';
|
||||
export * as 'notes/search-by-tag' from './endpoints/notes/search-by-tag.js';
|
||||
export * as 'notes/show' from './endpoints/notes/show.js';
|
||||
export * as 'notes/show-partial-bulk' from './endpoints/notes/show-partial-bulk.js';
|
||||
export * as 'notes/state' from './endpoints/notes/state.js';
|
||||
export * as 'notes/thread-muting/create' from './endpoints/notes/thread-muting/create.js';
|
||||
export * as 'notes/thread-muting/delete' from './endpoints/notes/thread-muting/delete.js';
|
||||
|
|
|
@ -38,9 +38,10 @@ export const paramDef = {
|
|||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
private noteEntityService: NoteEntityService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
|
||||
return await this.noteEntityService.fetchDiffs(ps.noteIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import type { Ref, ShallowRef } from 'vue';
|
|||
import { useStream } from '@/stream.js';
|
||||
import { $i } from '@/i.js';
|
||||
import { store } from '@/store.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
|
||||
const noteEvents = new EventEmitter<{
|
||||
reacted: Misskey.entities.Note;
|
||||
|
@ -18,16 +19,31 @@ const noteEvents = new EventEmitter<{
|
|||
deleted: Misskey.entities.Note;
|
||||
}>();
|
||||
|
||||
const fetchEvent = new EventEmitter<{
|
||||
[id: string]: Pick<Misskey.entities.Note, 'reactions' | 'reactionEmojis'>;
|
||||
}>();
|
||||
|
||||
const capturedNoteIdMapForPolling = new Map<string, number>();
|
||||
|
||||
const CAPTURE_MAX = 30;
|
||||
const POLLING_INTERVAL = 1000 * 10;
|
||||
|
||||
window.setInterval(() => {
|
||||
const ids = [...capturedNoteIdMapForPolling.keys()];
|
||||
const ids = [...capturedNoteIdMapForPolling.keys()].sort((a, b) => (a > b ? -1 : 1)).slice(0, CAPTURE_MAX); // 新しいものを優先するためにIDで降順ソート
|
||||
if (ids.length === 0) return;
|
||||
if (window.document.hidden) return;
|
||||
|
||||
console.log('Polling notes', ids);
|
||||
// まとめてリクエストするのではなく、個別にHTTPリクエスト投げてCDNにキャッシュさせた方がサーバーの負荷低減には良いかもしれない
|
||||
misskeyApi('notes/show-partial-bulk', {
|
||||
noteIds: ids,
|
||||
}).then((items) => {
|
||||
for (const item of items) {
|
||||
fetchEvent.emit(item.id, {
|
||||
reactions: item.reactions,
|
||||
reactionEmojis: item.reactionEmojis,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, POLLING_INTERVAL);
|
||||
|
||||
function pseudoNoteCapture(props: {
|
||||
|
@ -43,17 +59,27 @@ function pseudoNoteCapture(props: {
|
|||
|
||||
}
|
||||
|
||||
function onFetched(data: Pick<Misskey.entities.Note, 'reactions' | 'reactionEmojis'>): void {
|
||||
note.value.reactions = data.reactions;
|
||||
note.value.reactionCount = Object.values(data.reactions).reduce((a, b) => a + b, 0);
|
||||
note.value.reactionEmojis = data.reactionEmojis;
|
||||
}
|
||||
|
||||
if (capturedNoteIdMapForPolling.has(note.value.id)) {
|
||||
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! + 1);
|
||||
} else {
|
||||
capturedNoteIdMapForPolling.set(note.value.id, 1);
|
||||
}
|
||||
|
||||
fetchEvent.on(note.value.id, onFetched);
|
||||
|
||||
onUnmounted(() => {
|
||||
capturedNoteIdMapForPolling.set(note.value.id, capturedNoteIdMapForPolling.get(note.value.id)! - 1);
|
||||
if (capturedNoteIdMapForPolling.get(note.value.id) === 0) {
|
||||
capturedNoteIdMapForPolling.delete(note.value.id);
|
||||
}
|
||||
|
||||
fetchEvent.off(note.value.id, onFetched);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue