diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index d175f21f2..95a4eba74 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -130,6 +130,9 @@ export interface NoteEventTypes { reaction: string; userId: MiUser['id']; }; + replied: { + id: MiNote['id']; + }; } type NoteStreamEventTypes = { [key in keyof NoteEventTypes]: { diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 0b0693121..6406bc4c5 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -780,6 +780,9 @@ export class NoteCreateService implements OnApplicationShutdown { // If has in reply to note if (data.reply) { + this.globalEventService.publishNoteStream(data.reply.id, 'replied', { + id: note.id, + }); // 通知 if (data.reply.userHost === null) { const isThreadMuted = await this.noteThreadMutingsRepository.exist({ diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index f29b9db6a..ae9d8a0d6 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -372,11 +372,16 @@ const reactionsPagination = computed(() => ({ }, })); +async function addReplyTo(note, replyNote: Misskey.entities.Note) { + replies.value.unshift(replyNote); +} + useNoteCapture({ rootEl: el, note: appearNote, pureNote: note, isDeletedRef: isDeleted, + onReplyCallback: addReplyTo, }); useTooltip(renoteButton, async (showing) => { diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue index 8d394c0c1..3c840cf59 100644 --- a/packages/frontend/src/components/MkNoteSub.vue +++ b/packages/frontend/src/components/MkNoteSub.vue @@ -132,6 +132,7 @@ const likeButton = shallowRef(); let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note); const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null); +const replies = ref([]); const isRenote = ( props.note.renote != null && @@ -140,10 +141,16 @@ const isRenote = ( props.note.poll == null ); +async function addReplyTo(note, replyNote: Misskey.entities.Note) { + replies.value.unshift(replyNote); +} + useNoteCapture({ rootEl: el, note: appearNote, isDeletedRef: isDeleted, + // only update replies if we are, in fact, showing replies + onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined, }); if ($i) { @@ -250,8 +257,6 @@ watch(() => props.expandAllCws, (expandAllCws) => { if (expandAllCws !== showContent.value) showContent.value = expandAllCws; }); -let replies = ref([]); - function boostVisibility() { os.popupMenu([ { diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index 8bf9e244e..ff2058d79 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -380,11 +380,16 @@ const reactionsPagination = computed(() => ({ }, })); +async function addReplyTo(note, replyNote: Misskey.entities.Note) { + replies.value.unshift(replyNote); +} + useNoteCapture({ rootEl: el, note: appearNote, pureNote: note, isDeletedRef: isDeleted, + onReplyCallback: addReplyTo, }); useTooltip(renoteButton, async (showing) => { diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue index fc30dc87a..f4279fe8a 100644 --- a/packages/frontend/src/components/SkNoteSub.vue +++ b/packages/frontend/src/components/SkNoteSub.vue @@ -141,6 +141,7 @@ const likeButton = shallowRef(); let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note); const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null); +const replies = ref([]); const isRenote = ( props.note.renote != null && @@ -149,10 +150,16 @@ const isRenote = ( props.note.poll == null ); +async function addReplyTo(note, replyNote: Misskey.entities.Note) { + replies.value.unshift(replyNote); +} + useNoteCapture({ rootEl: el, note: appearNote, isDeletedRef: isDeleted, + // only update replies if we are, in fact, showing replies + onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined, }); if ($i) { @@ -259,8 +266,6 @@ watch(() => props.expandAllCws, (expandAllCws) => { if (expandAllCws !== showContent.value) showContent.value = expandAllCws; }); -let replies = ref([]); - function boostVisibility() { os.popupMenu([ { diff --git a/packages/frontend/src/scripts/use-note-capture.ts b/packages/frontend/src/scripts/use-note-capture.ts index ab232598c..8692d056b 100644 --- a/packages/frontend/src/scripts/use-note-capture.ts +++ b/packages/frontend/src/scripts/use-note-capture.ts @@ -14,6 +14,7 @@ export function useNoteCapture(props: { note: Ref; pureNote: Ref; isDeletedRef: Ref; + onReplyCallback: (note, replyNote: Misskey.entities.Note) => void | undefined; }) { const note = props.note; const pureNote = props.pureNote !== undefined ? props.pureNote : props.note; @@ -25,6 +26,17 @@ export function useNoteCapture(props: { if ((id !== note.value.id) && (id !== pureNote.value.id)) return; switch (type) { + case 'replied': { + if (!props.onReplyCallback) break; + + const replyNote = await os.api("notes/show", { + noteId: body.id, + }); + + await props.onReplyCallback(pureNote, replyNote); + break; + } + case 'reacted': { const reaction = body.reaction;