real-time updates on note detail view
`useNoteCapture` already subscribes to all updates for a note, so we can tell it when a note gets replied to, too Since I'm not actually adding any extra subscription in the client, just an extra callback, there should be no overhead when replies are not coming in. Also, all the timelines already call `useNoteCapture` for each note displayed, so we know the whole `GlobalEventService` thing works fine. Many thanks to VueJS for taking care of all the DOM complications
This commit is contained in:
parent
b3b89567ee
commit
683b4aafb2
7 changed files with 42 additions and 4 deletions
|
@ -130,6 +130,9 @@ export interface NoteEventTypes {
|
||||||
reaction: string;
|
reaction: string;
|
||||||
userId: MiUser['id'];
|
userId: MiUser['id'];
|
||||||
};
|
};
|
||||||
|
replied: {
|
||||||
|
id: MiNote['id'];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
type NoteStreamEventTypes = {
|
type NoteStreamEventTypes = {
|
||||||
[key in keyof NoteEventTypes]: {
|
[key in keyof NoteEventTypes]: {
|
||||||
|
|
|
@ -780,6 +780,9 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
|
|
||||||
// If has in reply to note
|
// If has in reply to note
|
||||||
if (data.reply) {
|
if (data.reply) {
|
||||||
|
this.globalEventService.publishNoteStream(data.reply.id, 'replied', {
|
||||||
|
id: note.id,
|
||||||
|
});
|
||||||
// 通知
|
// 通知
|
||||||
if (data.reply.userHost === null) {
|
if (data.reply.userHost === null) {
|
||||||
const isThreadMuted = await this.noteThreadMutingsRepository.exist({
|
const isThreadMuted = await this.noteThreadMutingsRepository.exist({
|
||||||
|
|
|
@ -372,11 +372,16 @@ const reactionsPagination = computed(() => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
async function addReplyTo(note, replyNote: Misskey.entities.Note) {
|
||||||
|
replies.value.unshift(replyNote);
|
||||||
|
}
|
||||||
|
|
||||||
useNoteCapture({
|
useNoteCapture({
|
||||||
rootEl: el,
|
rootEl: el,
|
||||||
note: appearNote,
|
note: appearNote,
|
||||||
pureNote: note,
|
pureNote: note,
|
||||||
isDeletedRef: isDeleted,
|
isDeletedRef: isDeleted,
|
||||||
|
onReplyCallback: addReplyTo,
|
||||||
});
|
});
|
||||||
|
|
||||||
useTooltip(renoteButton, async (showing) => {
|
useTooltip(renoteButton, async (showing) => {
|
||||||
|
|
|
@ -132,6 +132,7 @@ const likeButton = shallowRef<HTMLElement>();
|
||||||
|
|
||||||
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
||||||
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
||||||
|
const replies = ref<Misskey.entities.Note[]>([]);
|
||||||
|
|
||||||
const isRenote = (
|
const isRenote = (
|
||||||
props.note.renote != null &&
|
props.note.renote != null &&
|
||||||
|
@ -140,10 +141,16 @@ const isRenote = (
|
||||||
props.note.poll == null
|
props.note.poll == null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function addReplyTo(note, replyNote: Misskey.entities.Note) {
|
||||||
|
replies.value.unshift(replyNote);
|
||||||
|
}
|
||||||
|
|
||||||
useNoteCapture({
|
useNoteCapture({
|
||||||
rootEl: el,
|
rootEl: el,
|
||||||
note: appearNote,
|
note: appearNote,
|
||||||
isDeletedRef: isDeleted,
|
isDeletedRef: isDeleted,
|
||||||
|
// only update replies if we are, in fact, showing replies
|
||||||
|
onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($i) {
|
if ($i) {
|
||||||
|
@ -250,8 +257,6 @@ watch(() => props.expandAllCws, (expandAllCws) => {
|
||||||
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
||||||
});
|
});
|
||||||
|
|
||||||
let replies = ref<Misskey.entities.Note[]>([]);
|
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
os.popupMenu([
|
os.popupMenu([
|
||||||
{
|
{
|
||||||
|
|
|
@ -380,11 +380,16 @@ const reactionsPagination = computed(() => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
async function addReplyTo(note, replyNote: Misskey.entities.Note) {
|
||||||
|
replies.value.unshift(replyNote);
|
||||||
|
}
|
||||||
|
|
||||||
useNoteCapture({
|
useNoteCapture({
|
||||||
rootEl: el,
|
rootEl: el,
|
||||||
note: appearNote,
|
note: appearNote,
|
||||||
pureNote: note,
|
pureNote: note,
|
||||||
isDeletedRef: isDeleted,
|
isDeletedRef: isDeleted,
|
||||||
|
onReplyCallback: addReplyTo,
|
||||||
});
|
});
|
||||||
|
|
||||||
useTooltip(renoteButton, async (showing) => {
|
useTooltip(renoteButton, async (showing) => {
|
||||||
|
|
|
@ -141,6 +141,7 @@ const likeButton = shallowRef<HTMLElement>();
|
||||||
|
|
||||||
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
|
||||||
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
|
||||||
|
const replies = ref<Misskey.entities.Note[]>([]);
|
||||||
|
|
||||||
const isRenote = (
|
const isRenote = (
|
||||||
props.note.renote != null &&
|
props.note.renote != null &&
|
||||||
|
@ -149,10 +150,16 @@ const isRenote = (
|
||||||
props.note.poll == null
|
props.note.poll == null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function addReplyTo(note, replyNote: Misskey.entities.Note) {
|
||||||
|
replies.value.unshift(replyNote);
|
||||||
|
}
|
||||||
|
|
||||||
useNoteCapture({
|
useNoteCapture({
|
||||||
rootEl: el,
|
rootEl: el,
|
||||||
note: appearNote,
|
note: appearNote,
|
||||||
isDeletedRef: isDeleted,
|
isDeletedRef: isDeleted,
|
||||||
|
// only update replies if we are, in fact, showing replies
|
||||||
|
onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($i) {
|
if ($i) {
|
||||||
|
@ -259,8 +266,6 @@ watch(() => props.expandAllCws, (expandAllCws) => {
|
||||||
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
||||||
});
|
});
|
||||||
|
|
||||||
let replies = ref<Misskey.entities.Note[]>([]);
|
|
||||||
|
|
||||||
function boostVisibility() {
|
function boostVisibility() {
|
||||||
os.popupMenu([
|
os.popupMenu([
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@ export function useNoteCapture(props: {
|
||||||
note: Ref<Misskey.entities.Note>;
|
note: Ref<Misskey.entities.Note>;
|
||||||
pureNote: Ref<Misskey.entities.Note>;
|
pureNote: Ref<Misskey.entities.Note>;
|
||||||
isDeletedRef: Ref<boolean>;
|
isDeletedRef: Ref<boolean>;
|
||||||
|
onReplyCallback: (note, replyNote: Misskey.entities.Note) => void | undefined;
|
||||||
}) {
|
}) {
|
||||||
const note = props.note;
|
const note = props.note;
|
||||||
const pureNote = props.pureNote !== undefined ? props.pureNote : 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;
|
if ((id !== note.value.id) && (id !== pureNote.value.id)) return;
|
||||||
|
|
||||||
switch (type) {
|
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': {
|
case 'reacted': {
|
||||||
const reaction = body.reaction;
|
const reaction = body.reaction;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue