Frontend: Fixed note rendering for renote notes
ci/woodpecker/push/ociImagePush Pipeline was successful Details

This commit is contained in:
Natty 2023-12-22 21:25:00 +01:00
parent 10bddd886e
commit 72ed3391fc
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
3 changed files with 74 additions and 53 deletions

View File

@ -17,10 +17,10 @@
:note="note" :note="note"
:detailedView="true" :detailedView="true"
/> />
<MkLoading v-else-if="note.parent_note" mini /> <MkLoading v-else-if="appearNote.parent_note_id" mini />
<MkNoteSub <MkNoteSub
v-if="note.parent_note" v-if="parentNote"
:note="note.parent_note" :note="parentNote"
class="reply-to" class="reply-to"
:detailedView="true" :detailedView="true"
/> />
@ -64,14 +64,14 @@
</MkTab> </MkTab>
<MkNoteSub <MkNoteSub
v-if="directReplies && tab === 'replies'" v-if="directReplies.length && tab === 'replies'"
v-for="note in directReplies" v-for="note in directReplies"
:key="note.id" :key="note.id"
:note="note" :note="note"
class="reply" class="reply"
:conversation="replies" :conversation="replies"
:detailedView="true" :detailedView="true"
:parentId="note.id" :parentId="appearNote.id"
/> />
<MkLoading v-else-if="tab === 'replies' && note.reply_count > 0" /> <MkLoading v-else-if="tab === 'replies' && note.reply_count > 0" />
@ -83,7 +83,7 @@
class="reply" class="reply"
:conversation="replies" :conversation="replies"
:detailedView="true" :detailedView="true"
:parentId="note.id" :parentId="appearNote.id"
/> />
<MkLoading v-else-if="tab === 'quotes' && directQuotes.length > 0" /> <MkLoading v-else-if="tab === 'quotes' && directQuotes.length > 0" />
@ -101,7 +101,9 @@
:with-chart="false" :with-chart="false"
/> />
<!-- </MkPagination> --> <!-- </MkPagination> -->
<MkLoading v-else-if="tab === 'renotes' && note.renote_count > 0" /> <MkLoading
v-else-if="tab === 'renotes' && appearNote.renote_count > 0"
/>
<div v-if="tab === 'clips' && clips.length > 0" class="_content clips"> <div v-if="tab === 'clips' && clips.length > 0" class="_content clips">
<MkA <MkA
@ -127,7 +129,7 @@
<MkLoading v-else-if="tab === 'clips' && clips.length > 0" /> <MkLoading v-else-if="tab === 'clips' && clips.length > 0" />
<MkReactedUsers <MkReactedUsers
v-if="tab === 'reactions' && magReactionCount(note) > 0" v-if="tab === 'reactions' && magReactionCount(appearNote) > 0"
:note-id="note.id" :note-id="note.id"
></MkReactedUsers> ></MkReactedUsers>
</div> </div>
@ -135,11 +137,11 @@
<I18n :src="softMuteReasonI18nSrc(muted.what)" tag="small"> <I18n :src="softMuteReasonI18nSrc(muted.what)" tag="small">
<template #name> <template #name>
<MkA <MkA
v-user-preview="note.user.id" v-user-preview="appearNote.user.id"
class="name" class="name"
:to="userPage(note.user)" :to="userPage(appearNote.user)"
> >
<MkUserName :user="note.user" /> <MkUserName :user="appearNote.user" />
</MkA> </MkA>
</template> </template>
<template #reason> <template #reason>
@ -150,7 +152,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, onUnmounted, onUpdated, ref, toRaw } from "vue"; import { onMounted, onUnmounted, onUpdated, ref, toRaw, watch } from "vue";
import * as misskey from "calckey-js"; import * as misskey from "calckey-js";
import MkTab from "@/components/MkTab.vue"; import MkTab from "@/components/MkTab.vue";
import MkNoteSub from "@/components/MkNoteSub.vue"; import MkNoteSub from "@/components/MkNoteSub.vue";
@ -169,8 +171,9 @@ import { getNoteMenu } from "@/scripts/get-note-menu";
import { useNoteCapture } from "@/scripts/use-note-capture"; import { useNoteCapture } from "@/scripts/use-note-capture";
import { stream } from "@/stream"; import { stream } from "@/stream";
import { NoteUpdatedEvent } from "calckey-js/built/streaming.types"; import { NoteUpdatedEvent } from "calckey-js/built/streaming.types";
import { packed } from "magnetar-common"; import { endpoints, packed } from "magnetar-common";
import { import {
magEffectiveNote,
magIsRenote, magIsRenote,
magReactionCount, magReactionCount,
magReactionToLegacy, magReactionToLegacy,
@ -212,14 +215,20 @@ const noteEl = $ref();
const menuButton = ref<HTMLElement>(); const menuButton = ref<HTMLElement>();
const renoteButton = ref<InstanceType<typeof XRenoteButton>>(); const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
const reactButton = ref<HTMLElement>(); const reactButton = ref<HTMLElement>();
let appearNote = $computed(
() => magEffectiveNote(note) as packed.PackNoteMaybeFull
);
let parentNote = $ref(appearNote.parent_note);
const showContent = ref(false); const showContent = ref(false);
const isDeleted = ref(false); const isDeleted = ref(false);
const muted = ref(getWordSoftMute(note, $i, defaultStore.state.mutedWords)); const muted = ref(
getWordSoftMute(appearNote, $i, defaultStore.state.mutedWords)
);
const translation = ref(null); const translation = ref(null);
const translating = ref(false); const translating = ref(false);
let conversation = $ref<null | misskey.entities.Note[]>([]); let conversation = $ref<null | misskey.entities.Note[]>([]);
const replies = ref<misskey.entities.Note[]>([]); const replies = ref<misskey.entities.Note[]>([]);
let directReplies = $ref<null | misskey.entities.Note[]>([]); let directReplies = $ref<misskey.entities.Note[]>([]);
let directQuotes = $ref<null | misskey.entities.Note[]>([]); let directQuotes = $ref<null | misskey.entities.Note[]>([]);
let clips = $ref(); let clips = $ref();
let renotes = $ref(); let renotes = $ref();
@ -236,7 +245,7 @@ const keymap = {
useNoteCapture({ useNoteCapture({
rootEl: el, rootEl: el,
note: $$(note), note: $$(appearNote),
isDeletedRef: isDeleted, isDeletedRef: isDeleted,
}); });
@ -257,7 +266,7 @@ function react(viaKeyboard = false): void {
reactButton.value, reactButton.value,
(reaction) => { (reaction) => {
os.api("notes/reactions/create", { os.api("notes/reactions/create", {
noteId: note.id, noteId: appearNote.id,
reaction: magReactionToLegacy(reaction), reaction: magReactionToLegacy(reaction),
}); });
}, },
@ -267,14 +276,6 @@ function react(viaKeyboard = false): void {
); );
} }
function undoReact(note): void {
const oldReaction = note.myReaction;
if (!oldReaction) return;
os.api("notes/reactions/delete", {
noteId: note.id,
});
}
function onContextmenu(ev: MouseEvent): void { function onContextmenu(ev: MouseEvent): void {
const isLink = (el: HTMLElement) => { const isLink = (el: HTMLElement) => {
if (el.tagName === "A") return true; if (el.tagName === "A") return true;
@ -326,29 +327,52 @@ function blur() {
noteEl.blur(); noteEl.blur();
} }
directReplies = null; async function updateParent(note: packed.PackNoteMaybeFull) {
if (note.parent_note) {
parentNote = note.parent_note;
return;
} else if (note.parent_note_id) {
parentNote = null;
parentNote = await os.magApi(
endpoints.GetNoteById,
{ attachments: true, context: true },
{ id: note.parent_note_id }
);
return;
}
parentNote = null;
}
watch(appearNote, updateParent);
updateParent(note);
directReplies = [];
os.api("notes/children", { os.api("notes/children", {
noteId: note.id, noteId: appearNote.id,
limit: 30, limit: 30,
depth: 12, depth: 12,
}).then((res) => { }).then((res) => {
res = res.reduce((acc, resNote) => { res = res.reduce(
if (resNote.userId == note.user.id) { (acc: misskey.entities.Note[], resNote: misskey.entities.Note) => {
if (resNote.userId == appearNote.user.id) {
return [...acc, resNote]; return [...acc, resNote];
} }
return [resNote, ...acc]; return [resNote, ...acc];
}, []); },
[]
);
replies.value = res; replies.value = res;
directReplies = res directReplies = res
.filter((resNote) => resNote.replyId === note.id) .filter((resNote) => resNote.replyId === appearNote.id)
.reverse(); .reverse();
directQuotes = res.filter((resNote) => resNote.renoteId === note.id); directQuotes = res.filter((resNote) => resNote.renoteId === appearNote.id);
}); });
conversation = null; conversation = null;
if (note.parent_note_id) { if (appearNote.parent_note_id) {
os.api("notes/conversation", { os.api("notes/conversation", {
noteId: note.parent_note_id, noteId: appearNote.parent_note_id,
limit: 30, limit: 30,
}).then((res) => { }).then((res) => {
conversation = res.reverse(); conversation = res.reverse();
@ -358,7 +382,7 @@ if (note.parent_note_id) {
clips = null; clips = null;
os.api("notes/clips", { os.api("notes/clips", {
noteId: note.id, noteId: appearNote.id,
}).then((res) => { }).then((res) => {
clips = res; clips = res;
}); });
@ -375,7 +399,7 @@ renotes = null;
function loadTab() { function loadTab() {
if (tab === "renotes" && !renotes) { if (tab === "renotes" && !renotes) {
os.api("notes/renotes", { os.api("notes/renotes", {
noteId: note.id, noteId: appearNote.id,
limit: 100, limit: 100,
}).then((res) => { }).then((res) => {
renotes = res; renotes = res;
@ -387,7 +411,7 @@ async function onNoteUpdated(noteData: NoteUpdatedEvent): Promise<void> {
const { type, id, body } = noteData; const { type, id, body } = noteData;
let found = -1; let found = -1;
if (id === note.id) { if (id === appearNote.id) {
found = 0; found = 0;
} else { } else {
for (let i = 0; i < replies.value.length; i++) { for (let i = 0; i < replies.value.length; i++) {

View File

@ -8,7 +8,7 @@
v-size="{ max: [500, 350] }" v-size="{ max: [500, 350] }"
class="tkcbzcuz note-container" class="tkcbzcuz note-container"
:tabindex="!isDeleted ? '-1' : null" :tabindex="!isDeleted ? '-1' : null"
:class="{ renote: isRenote }" :class="{ renote: magIsRenote(note) }"
:id="appearNote.id" :id="appearNote.id"
> >
<MkNoteSub <MkNoteSub
@ -264,7 +264,11 @@ import { getNoteMenu } from "@/scripts/get-note-menu";
import { useNoteCapture } from "@/scripts/use-note-capture"; import { useNoteCapture } from "@/scripts/use-note-capture";
import { notePage } from "@/filters/note"; import { notePage } from "@/filters/note";
import { getNoteSummary } from "@/scripts/get-note-summary"; import { getNoteSummary } from "@/scripts/get-note-summary";
import { magReactionToLegacy } from "@/scripts-mag/mag-util"; import {
magEffectiveNote,
magIsRenote,
magReactionToLegacy,
} from "@/scripts-mag/mag-util";
const router = useRouter(); const router = useRouter();
@ -298,12 +302,6 @@ if (noteViewInterruptors.length > 0) {
}); });
} }
const isRenote =
note.renote != null &&
note.text == null &&
note.fileIds.length === 0 &&
note.poll == null;
const el = ref<HTMLElement>(); const el = ref<HTMLElement>();
const footerEl = ref<HTMLElement>(); const footerEl = ref<HTMLElement>();
const menuButton = ref<HTMLElement>(); const menuButton = ref<HTMLElement>();
@ -311,8 +309,8 @@ const starButton = ref<InstanceType<typeof XStarButton>>();
const renoteButton = ref<InstanceType<typeof XRenoteButton>>(); const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
const renoteTime = ref<HTMLElement>(); const renoteTime = ref<HTMLElement>();
const reactButton = ref<HTMLElement>(); const reactButton = ref<HTMLElement>();
let appearNote = $computed(() => let appearNote = $computed(
isRenote ? (note.renote as misskey.entities.Note) : note () => magEffectiveNote(note) as misskey.entities.Note
); );
const isMyRenote = $i && $i.id === note.userId; const isMyRenote = $i && $i.id === note.userId;
const showContent = ref(false); const showContent = ref(false);

View File

@ -221,7 +221,6 @@ import {
magIsRenote, magIsRenote,
magReactionCount, magReactionCount,
magReactionToLegacy, magReactionToLegacy,
magTransMap,
magTransProperty, magTransProperty,
} from "@/scripts-mag/mag-util"; } from "@/scripts-mag/mag-util";
@ -280,8 +279,8 @@ const replies: misskey.entities.Note[] =
props.conversation props.conversation
?.filter( ?.filter(
(item) => (item) =>
item.replyId === props.note.id || item.replyId === appearNote.id ||
item.renoteId === props.note.id item.renoteId === appearNote.id
) )
.reverse() ?? []; .reverse() ?? [];
const enableEmojiReactions = defaultStore.state.enableEmojiReactions; const enableEmojiReactions = defaultStore.state.enableEmojiReactions;