enhance(frontend): improve note detail page
This commit is contained in:
parent
5c6b7991ef
commit
907d519da3
8 changed files with 152 additions and 235 deletions
|
@ -32,6 +32,10 @@
|
|||
- ローカリゼーションの更新
|
||||
|
||||
### Client
|
||||
- ノート詳細ページを改修
|
||||
- 読み込み時のパフォーマンスが向上しました
|
||||
- リノート一覧、リアクション一覧がタブとして追加されました
|
||||
- ノートのメニューからは当該項目は消えました
|
||||
- プロフィールにその人が作ったPlayの一覧出せるように
|
||||
- メニューのスイッチの動作を改善
|
||||
- 絵文字ピッカーの検索の表示件数を100件に増加
|
||||
|
@ -48,7 +52,6 @@
|
|||
- `$[rainbow ]`記法が、動きのあるMFMが無効になっていても使用できるようになりました
|
||||
- Playの操作を行うAPI TokenをAPIコンソールから発行できるように
|
||||
- リアクションの表示サイズをより大きくできるように
|
||||
- ノート詳細ページ読み込み時のパフォーマンスを改善
|
||||
- タイムラインでリスト/アンテナ選択時のパフォーマンスを改善
|
||||
- 「Moderation note」、「Add moderation note」をローカライズできるように
|
||||
- 新しい実績を追加
|
||||
|
|
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
|
@ -1110,6 +1110,10 @@ export interface Locale {
|
|||
"pastAnnouncements": string;
|
||||
"youHaveUnreadAnnouncements": string;
|
||||
"useSecurityKey": string;
|
||||
"replies": string;
|
||||
"renotes": string;
|
||||
"loadReplies": string;
|
||||
"loadConversation": string;
|
||||
"_announcement": {
|
||||
"forExistingUsers": string;
|
||||
"forExistingUsersDescription": string;
|
||||
|
|
|
@ -15,7 +15,7 @@ gotIt: "わかった"
|
|||
cancel: "キャンセル"
|
||||
noThankYou: "やめておく"
|
||||
enterUsername: "ユーザー名を入力"
|
||||
renotedBy: "{user}がRenote"
|
||||
renotedBy: "{user}がリノート"
|
||||
noNotes: "ノートはありません"
|
||||
noNotifications: "通知はありません"
|
||||
instance: "サーバー"
|
||||
|
@ -45,10 +45,10 @@ pin: "ピン留め"
|
|||
unpin: "ピン留め解除"
|
||||
copyContent: "内容をコピー"
|
||||
copyLink: "リンクをコピー"
|
||||
copyLinkRenote: "Renoteのリンクをコピー"
|
||||
copyLinkRenote: "リノートのリンクをコピー"
|
||||
delete: "削除"
|
||||
deleteAndEdit: "削除して編集"
|
||||
deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、Renote、返信も全て削除されます。"
|
||||
deleteAndEditConfirm: "このノートを削除してもう一度編集しますか?このノートへのリアクション、リノート、返信も全て削除されます。"
|
||||
addToList: "リストに追加"
|
||||
addToAntenna: "アンテナに追加"
|
||||
sendMessage: "メッセージを送信"
|
||||
|
@ -105,13 +105,13 @@ followRequests: "フォロー申請"
|
|||
unfollow: "フォロー解除"
|
||||
followRequestPending: "フォロー許可待ち"
|
||||
enterEmoji: "絵文字を入力"
|
||||
renote: "Renote"
|
||||
unrenote: "Renote解除"
|
||||
renoted: "Renoteしました。"
|
||||
cantRenote: "この投稿はRenoteできません。"
|
||||
cantReRenote: "RenoteをRenoteすることはできません。"
|
||||
renote: "リノート"
|
||||
unrenote: "リノート解除"
|
||||
renoted: "リノートしました。"
|
||||
cantRenote: "この投稿はリノートできません。"
|
||||
cantReRenote: "リノートをリノートすることはできません。"
|
||||
quote: "引用"
|
||||
inChannelRenote: "チャンネル内Renote"
|
||||
inChannelRenote: "チャンネル内リノート"
|
||||
inChannelQuote: "チャンネル内引用"
|
||||
pinnedNote: "ピン留めされたノート"
|
||||
pinned: "ピン留め"
|
||||
|
@ -657,7 +657,7 @@ behavior: "動作"
|
|||
sample: "サンプル"
|
||||
abuseReports: "通報"
|
||||
reportAbuse: "通報"
|
||||
reportAbuseRenote: "Renoteを通報"
|
||||
reportAbuseRenote: "リノートを通報"
|
||||
reportAbuseOf: "{name}を通報する"
|
||||
fillAbuseReportDescription: "通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。"
|
||||
abuseReported: "内容が送信されました。ご報告ありがとうございました。"
|
||||
|
@ -691,9 +691,9 @@ manageAccessTokens: "アクセストークンの管理"
|
|||
accountInfo: "アカウント情報"
|
||||
notesCount: "ノートの数"
|
||||
repliesCount: "返信した数"
|
||||
renotesCount: "Renoteした数"
|
||||
renotesCount: "リノートした数"
|
||||
repliedCount: "返信された数"
|
||||
renotedCount: "Renoteされた数"
|
||||
renotedCount: "リノートされた数"
|
||||
followingCount: "フォロー数"
|
||||
followersCount: "フォロワー数"
|
||||
sentReactionsCount: "リアクションした数"
|
||||
|
@ -989,7 +989,7 @@ thisPostMayBeAnnoying: "この投稿は迷惑になる可能性があります
|
|||
thisPostMayBeAnnoyingHome: "ホームに投稿"
|
||||
thisPostMayBeAnnoyingCancel: "やめる"
|
||||
thisPostMayBeAnnoyingIgnore: "このまま投稿"
|
||||
collapseRenotes: "見たことのあるRenoteを省略して表示"
|
||||
collapseRenotes: "見たことのあるリノートを省略して表示"
|
||||
internalServerError: "サーバー内部エラー"
|
||||
internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。"
|
||||
copyErrorInfo: "エラー情報をコピー"
|
||||
|
@ -1037,7 +1037,7 @@ forceShowAds: "常に広告を表示する"
|
|||
addMemo: "メモを追加"
|
||||
editMemo: "メモを編集"
|
||||
reactionsList: "リアクション一覧"
|
||||
renotesList: "Renote一覧"
|
||||
renotesList: "リノート一覧"
|
||||
notificationDisplay: "通知の表示"
|
||||
leftTop: "左上"
|
||||
rightTop: "右上"
|
||||
|
@ -1107,6 +1107,10 @@ currentAnnouncements: "現在のお知らせ"
|
|||
pastAnnouncements: "過去のお知らせ"
|
||||
youHaveUnreadAnnouncements: "未読のお知らせがあります。"
|
||||
useSecurityKey: "ブラウザまたはデバイスの指示に従って、セキュリティキーまたはパスキーを使用してください。"
|
||||
replies: "返信"
|
||||
renotes: "リノート"
|
||||
loadReplies: "返信を見る"
|
||||
loadConversation: "会話を見る"
|
||||
|
||||
_announcement:
|
||||
forExistingUsers: "既存ユーザーのみ"
|
||||
|
|
|
@ -86,9 +86,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
<MkReactionsViewer :note="appearNote" :maxNumber="16">
|
||||
<template #more>
|
||||
<button class="_button" :class="$style.reactionDetailsButton" @click="showReactions">
|
||||
{{ i18n.ts.more }}
|
||||
</button>
|
||||
<div :class="$style.reactionOmitted">{{ i18n.ts.more }}</div>
|
||||
</template>
|
||||
</MkReactionsViewer>
|
||||
<footer :class="$style.footer">
|
||||
|
@ -457,7 +455,7 @@ function showRenoteMenu(viaKeyboard = false): void {
|
|||
} else {
|
||||
os.popupMenu([
|
||||
getCopyNoteLinkMenu(note, i18n.ts.copyLinkRenote),
|
||||
null,
|
||||
null,
|
||||
getAbuseNoteMenu(note, i18n.ts.reportAbuseRenote),
|
||||
$i.isModerator || $i.isAdmin ? getUnrenote() : undefined,
|
||||
], renoteTime.value, {
|
||||
|
@ -488,12 +486,6 @@ function readPromo() {
|
|||
});
|
||||
isDeleted.value = true;
|
||||
}
|
||||
|
||||
function showReactions(): void {
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkReactedUsersDialog.vue')), {
|
||||
noteId: appearNote.id,
|
||||
}, {}, 'closed');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
@ -941,7 +933,7 @@ function showReactions(): void {
|
|||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.reactionDetailsButton {
|
||||
.reactionOmitted {
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
margin: 2px;
|
||||
|
@ -950,9 +942,5 @@ function showReactions(): void {
|
|||
border-radius: 4px;
|
||||
background: transparent;
|
||||
opacity: .8;
|
||||
|
||||
&:hover {
|
||||
background: var(--X5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,7 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-hotkey="keymap"
|
||||
:class="$style.root"
|
||||
>
|
||||
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
|
||||
<div v-if="appearNote.reply.replyId">
|
||||
<div v-if="!conversationLoaded" style="padding: 16px">
|
||||
<MkButton style="margin: 0 auto;" primary rounded @click="loadConversation">{{ i18n.ts.loadConversation }}</MkButton>
|
||||
</div>
|
||||
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
|
||||
</div>
|
||||
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
|
||||
<div v-if="isRenote" :class="$style.renote">
|
||||
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
|
||||
|
@ -125,7 +130,43 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</button>
|
||||
</footer>
|
||||
</article>
|
||||
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
|
||||
<div :class="$style.tabs">
|
||||
<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'replies' }]" @click="tab = 'replies'"><i class="ti ti-arrow-back-up"></i> {{ i18n.ts.replies }}</button>
|
||||
<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'renotes' }]" @click="tab = 'renotes'"><i class="ti ti-repeat"></i> {{ i18n.ts.renotes }}</button>
|
||||
<button class="_button" :class="[$style.tab, { [$style.tabActive]: tab === 'reactions' }]" @click="tab = 'reactions'"><i class="ti ti-icons"></i> {{ i18n.ts.reactions }}</button>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="tab === 'replies'" :class="$style.tab_replies">
|
||||
<div v-if="!repliesLoaded" style="padding: 16px">
|
||||
<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
|
||||
</div>
|
||||
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
|
||||
</div>
|
||||
<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
|
||||
<MkPagination :pagination="renotesPagination">
|
||||
<template #default="{ items }">
|
||||
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
||||
<MkUserCardMini :user="item.user" :withChart="false"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</MkPagination>
|
||||
</div>
|
||||
<div v-else-if="tab === 'reactions'" :class="$style.tab_reactions">
|
||||
<div :class="$style.reactionTabs">
|
||||
<button v-for="reaction in Object.keys(appearNote.reactions)" :key="reaction" :class="[$style.reactionTab, { [$style.reactionTabActive]: reactionTabType === reaction }]" class="_button" @click="reactionTabType = reaction">
|
||||
<MkReactionIcon :reaction="reaction"/>
|
||||
<span style="margin-left: 4px;">{{ appearNote.reactions[reaction] }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<MkPagination :pagination="reactionsPagination">
|
||||
<template #default="{ items }">
|
||||
<MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
|
||||
<MkUserCardMini :user="item.user" :withChart="false"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</MkPagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="_panel" :class="$style.muted" @click="muted = false">
|
||||
<I18n :src="i18n.ts.userSaysSomething" tag="small">
|
||||
|
@ -169,6 +210,10 @@ import { claimAchievement } from '@/scripts/achievements';
|
|||
import { MenuItem } from '@/types/menu';
|
||||
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||
import { showMovedDialog } from '@/scripts/show-moved-dialog';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
note: Misskey.entities.Note;
|
||||
|
@ -224,6 +269,26 @@ const keymap = {
|
|||
's': () => showContent.value !== showContent.value,
|
||||
};
|
||||
|
||||
let tab = $ref('replies');
|
||||
let reactionTabType = $ref(null);
|
||||
|
||||
const renotesPagination = $computed(() => ({
|
||||
endpoint: 'notes/renotes',
|
||||
limit: 10,
|
||||
params: {
|
||||
noteId: appearNote.id,
|
||||
},
|
||||
}));
|
||||
|
||||
const reactionsPagination = $computed(() => ({
|
||||
endpoint: 'notes/reactions',
|
||||
limit: 10,
|
||||
params: {
|
||||
noteId: appearNote.id,
|
||||
type: reactionTabType,
|
||||
},
|
||||
}));
|
||||
|
||||
useNoteCapture({
|
||||
rootEl: el,
|
||||
note: $$(appearNote),
|
||||
|
@ -426,14 +491,20 @@ function blur() {
|
|||
el.value.blur();
|
||||
}
|
||||
|
||||
os.api('notes/children', {
|
||||
noteId: appearNote.id,
|
||||
limit: 30,
|
||||
}).then(res => {
|
||||
replies.value = res;
|
||||
});
|
||||
const repliesLoaded = ref(false);
|
||||
function loadReplies() {
|
||||
repliesLoaded.value = true;
|
||||
os.api('notes/children', {
|
||||
noteId: appearNote.id,
|
||||
limit: 30,
|
||||
}).then(res => {
|
||||
replies.value = res;
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.replyId) {
|
||||
const conversationLoaded = ref(false);
|
||||
function loadConversation() {
|
||||
conversationLoaded.value = true;
|
||||
os.api('notes/conversation', {
|
||||
noteId: appearNote.replyId,
|
||||
}).then(res => {
|
||||
|
@ -640,10 +711,52 @@ if (appearNote.replyId) {
|
|||
}
|
||||
}
|
||||
|
||||
.reply {
|
||||
.reply:not(:first-child) {
|
||||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
.tabs {
|
||||
border-top: solid 0.5px var(--divider);
|
||||
border-bottom: solid 0.5px var(--divider);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
padding: 12px 8px;
|
||||
border-top: solid 2px transparent;
|
||||
border-bottom: solid 2px transparent;
|
||||
}
|
||||
|
||||
.tabActive {
|
||||
border-bottom: solid 2px var(--accent);
|
||||
}
|
||||
|
||||
.tab_renotes {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.tab_reactions {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.reactionTabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.reactionTab {
|
||||
padding: 4px 6px;
|
||||
border: solid 1px var(--divider);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.reactionTabActive {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
@container (max-width: 500px) {
|
||||
.root {
|
||||
font-size: 0.9em;
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<MkModalWindow
|
||||
ref="dialog"
|
||||
:width="400"
|
||||
:height="450"
|
||||
@close="dialog.close()"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
<template #header>{{ i18n.ts.reactionsList }}</template>
|
||||
|
||||
<MkSpacer :marginMin="20" :marginMax="28">
|
||||
<div v-if="note" class="_gaps">
|
||||
<div v-if="reactions.length === 0" class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<div :class="$style.tabs">
|
||||
<button v-for="reaction in reactions" :key="reaction" :class="[$style.tab, { [$style.tabActive]: tab === reaction }]" class="_button" @click="tab = reaction">
|
||||
<MkReactionIcon :reaction="reaction"/>
|
||||
<span style="margin-left: 4px;">{{ note.reactions[reaction] }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<MkA v-for="user in users" :key="user.id" :to="userPage(user)" @click="dialog.close()">
|
||||
<MkUserCardMini :user="user" :withChart="false"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else>
|
||||
<MkLoading/>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkModalWindow>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, watch } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { userPage } from '@/filters/user';
|
||||
import { i18n } from '@/i18n';
|
||||
import * as os from '@/os';
|
||||
import { infoImageUrl } from '@/instance';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void,
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
noteId: Misskey.entities.Note['id'];
|
||||
}>();
|
||||
|
||||
const dialog = $shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
|
||||
let note = $ref<Misskey.entities.Note>();
|
||||
let tab = $ref<string>();
|
||||
let reactions = $ref<string[]>();
|
||||
let users = $ref();
|
||||
|
||||
watch($$(tab), async () => {
|
||||
const res = await os.api('notes/reactions', {
|
||||
noteId: props.noteId,
|
||||
type: tab,
|
||||
limit: 30,
|
||||
});
|
||||
|
||||
users = res.map(x => x.user);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
os.api('notes/show', {
|
||||
noteId: props.noteId,
|
||||
}).then((res) => {
|
||||
reactions = Object.keys(res.reactions);
|
||||
tab = reactions[0];
|
||||
note = res;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 4px 6px;
|
||||
border: solid 1px var(--divider);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.tabActive {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
</style>
|
|
@ -1,71 +0,0 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<MkModalWindow
|
||||
ref="dialog"
|
||||
:width="400"
|
||||
:height="450"
|
||||
@close="dialog.close()"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
<template #header>{{ i18n.ts.renotesList }}</template>
|
||||
|
||||
<MkSpacer :marginMin="20" :marginMax="28">
|
||||
<div v-if="renotes" class="_gaps">
|
||||
<div v-if="renotes.length === 0" class="_fullinfo">
|
||||
<img :src="infoImageUrl" class="_ghost"/>
|
||||
<div>{{ i18n.ts.nothing }}</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<MkA v-for="user in users" :key="user.id" :to="userPage(user)" @click="dialog.close()">
|
||||
<MkUserCardMini :user="user" :withChart="false"/>
|
||||
</MkA>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else>
|
||||
<MkLoading/>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkModalWindow>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { userPage } from '@/filters/user';
|
||||
import { i18n } from '@/i18n';
|
||||
import * as os from '@/os';
|
||||
import { infoImageUrl } from '@/instance';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void,
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
noteId: Misskey.entities.Note['id'];
|
||||
}>();
|
||||
|
||||
const dialog = $shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||
|
||||
let note = $ref<Misskey.entities.Note>();
|
||||
let renotes = $ref();
|
||||
let users = $ref();
|
||||
|
||||
onMounted(async () => {
|
||||
const res = await os.api('notes/renotes', {
|
||||
noteId: props.noteId,
|
||||
limit: 30,
|
||||
});
|
||||
|
||||
renotes = res;
|
||||
users = res.map(x => x.user);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
|
@ -238,18 +238,6 @@ export function getNoteMenu(props: {
|
|||
os.pageWindow(`/notes/${appearNote.id}`);
|
||||
}
|
||||
|
||||
function showReactions(): void {
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkReactedUsersDialog.vue')), {
|
||||
noteId: appearNote.id,
|
||||
}, {}, 'closed');
|
||||
}
|
||||
|
||||
function showRenotes(): void {
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkRenotedUsersDialog.vue')), {
|
||||
noteId: appearNote.id,
|
||||
}, {}, 'closed');
|
||||
}
|
||||
|
||||
async function translate(): Promise<void> {
|
||||
if (props.translation.value != null) return;
|
||||
props.translating.value = true;
|
||||
|
@ -279,14 +267,6 @@ export function getNoteMenu(props: {
|
|||
icon: 'ti ti-info-circle',
|
||||
text: i18n.ts.details,
|
||||
action: openDetail,
|
||||
}, {
|
||||
icon: 'ti ti-repeat',
|
||||
text: i18n.ts.renotesList,
|
||||
action: showRenotes,
|
||||
}, {
|
||||
icon: 'ti ti-icons',
|
||||
text: i18n.ts.reactionsList,
|
||||
action: showReactions,
|
||||
}, {
|
||||
icon: 'ti ti-copy',
|
||||
text: i18n.ts.copyContent,
|
||||
|
|
Loading…
Reference in a new issue