summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2025-12-13 18:22:40 +0900
committerGitHub <noreply@github.com>2025-12-13 18:22:40 +0900
commitcb03f3f0131659f8ea68d8537eb2b5d0ae9fcf06 (patch)
tree27c639c35dfe9e179cff639da06edc758623145e
parentfix(frontend): ドライブファイルを日付以外で並び替える場... (diff)
downloadmisskey-cb03f3f0131659f8ea68d8537eb2b5d0ae9fcf06.tar.gz
misskey-cb03f3f0131659f8ea68d8537eb2b5d0ae9fcf06.tar.bz2
misskey-cb03f3f0131659f8ea68d8537eb2b5d0ae9fcf06.zip
fix(frontend): follow-up of 16970 (#16975)
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue318
1 files changed, 160 insertions, 158 deletions
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 25a55d2d90..825133d482 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -46,178 +46,180 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="isRenote && note.renote == null" :class="$style.deleted">
{{ i18n.ts.deletedNote }}
</div>
- <article v-else :class="$style.note" @contextmenu.stop="onContextmenu">
- <header :class="$style.noteHeader">
- <MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
- <div :class="$style.noteHeaderBody">
- <div>
- <MkA v-user-preview="appearNote.user.id" :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
- <MkUserName :nowrap="false" :user="appearNote.user"/>
- </MkA>
- <span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
- <div :class="$style.noteHeaderInfo">
- <span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]">
- <i v-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
- <i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
- <i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
- </span>
- <span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
+ <template v-else>
+ <article :class="$style.note" @contextmenu.stop="onContextmenu">
+ <header :class="$style.noteHeader">
+ <MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
+ <div :class="$style.noteHeaderBody">
+ <div>
+ <MkA v-user-preview="appearNote.user.id" :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
+ <MkUserName :nowrap="false" :user="appearNote.user"/>
+ </MkA>
+ <span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
+ <div :class="$style.noteHeaderInfo">
+ <span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]">
+ <i v-if="appearNote.visibility === 'home'" class="ti ti-home"></i>
+ <i v-else-if="appearNote.visibility === 'followers'" class="ti ti-lock"></i>
+ <i v-else-if="appearNote.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
+ </span>
+ <span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
+ </div>
+ </div>
+ <div :class="$style.noteHeaderUsernameAndBadgeRoles">
+ <div :class="$style.noteHeaderUsername">
+ <MkAcct :user="appearNote.user"/>
+ </div>
+ <div v-if="appearNote.user.badgeRoles" :class="$style.noteHeaderBadgeRoles">
+ <img v-for="(role, i) in appearNote.user.badgeRoles" :key="i" v-tooltip="role.name" :class="$style.noteHeaderBadgeRole" :src="role.iconUrl!"/>
+ </div>
</div>
+ <MkInstanceTicker v-if="showTicker" :host="appearNote.user.host" :instance="appearNote.user.instance"/>
</div>
- <div :class="$style.noteHeaderUsernameAndBadgeRoles">
- <div :class="$style.noteHeaderUsername">
- <MkAcct :user="appearNote.user"/>
+ </header>
+ <div :class="$style.noteContent">
+ <p v-if="appearNote.cw != null" :class="$style.cw">
+ <Mfm
+ v-if="appearNote.cw != ''"
+ :text="appearNote.cw"
+ :author="appearNote.user"
+ :nyaize="'respect'"
+ :enableEmojiMenu="true"
+ :enableEmojiMenuReaction="true"
+ />
+ <MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
+ </p>
+ <div v-show="appearNote.cw == null || showContent">
+ <span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
+ <MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
+ <Mfm
+ v-if="appearNote.text"
+ :parsedNodes="parsed"
+ :text="appearNote.text"
+ :author="appearNote.user"
+ :nyaize="'respect'"
+ :emojiUrls="appearNote.emojis"
+ :enableEmojiMenu="true"
+ :enableEmojiMenuReaction="true"
+ class="_selectable"
+ />
+ <a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
+ <div v-if="translating || translation" :class="$style.translation">
+ <MkLoading v-if="translating" mini/>
+ <div v-else-if="translation">
+ <b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
+ <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/>
+ </div>
</div>
- <div v-if="appearNote.user.badgeRoles" :class="$style.noteHeaderBadgeRoles">
- <img v-for="(role, i) in appearNote.user.badgeRoles" :key="i" v-tooltip="role.name" :class="$style.noteHeaderBadgeRole" :src="role.iconUrl!"/>
+ <div v-if="appearNote.files && appearNote.files.length > 0">
+ <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div>
- </div>
- <MkInstanceTicker v-if="showTicker" :host="appearNote.user.host" :instance="appearNote.user.instance"/>
- </div>
- </header>
- <div :class="$style.noteContent">
- <p v-if="appearNote.cw != null" :class="$style.cw">
- <Mfm
- v-if="appearNote.cw != ''"
- :text="appearNote.cw"
- :author="appearNote.user"
- :nyaize="'respect'"
- :enableEmojiMenu="true"
- :enableEmojiMenuReaction="true"
- />
- <MkCwButton v-model="showContent" :text="appearNote.text" :renote="appearNote.renote" :files="appearNote.files" :poll="appearNote.poll"/>
- </p>
- <div v-show="appearNote.cw == null || showContent">
- <span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
- <MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
- <Mfm
- v-if="appearNote.text"
- :parsedNodes="parsed"
- :text="appearNote.text"
- :author="appearNote.user"
- :nyaize="'respect'"
- :emojiUrls="appearNote.emojis"
- :enableEmojiMenu="true"
- :enableEmojiMenuReaction="true"
- class="_selectable"
- />
- <a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
- <div v-if="translating || translation" :class="$style.translation">
- <MkLoading v-if="translating" mini/>
- <div v-else-if="translation">
- <b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
- <Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/>
+ <MkPoll
+ v-if="appearNote.poll"
+ :noteId="appearNote.id"
+ :multiple="appearNote.poll.multiple"
+ :expiresAt="appearNote.poll.expiresAt"
+ :choices="$appearNote.pollChoices"
+ :author="appearNote.user"
+ :emojiUrls="appearNote.emojis"
+ :class="$style.poll"
+ />
+ <div v-if="isEnabledUrlPreview">
+ <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
</div>
+ <div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
</div>
- <div v-if="appearNote.files && appearNote.files.length > 0">
- <MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
+ <MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
+ </div>
+ <footer>
+ <div :class="$style.noteFooterInfo">
+ <MkA :to="notePage(appearNote)">
+ <MkTime :time="appearNote.createdAt" mode="detail" colored/>
+ </MkA>
</div>
- <MkPoll
- v-if="appearNote.poll"
+ <MkReactionsViewer
+ v-if="appearNote.reactionAcceptance !== 'likeOnly'"
+ style="margin-top: 6px;"
+ :reactions="$appearNote.reactions"
+ :reactionEmojis="$appearNote.reactionEmojis"
+ :myReaction="$appearNote.myReaction"
:noteId="appearNote.id"
- :multiple="appearNote.poll.multiple"
- :expiresAt="appearNote.poll.expiresAt"
- :choices="$appearNote.pollChoices"
- :author="appearNote.user"
- :emojiUrls="appearNote.emojis"
- :class="$style.poll"
+ :maxNumber="16"
+ @mockUpdateMyReaction="emitUpdReaction"
/>
- <div v-if="isEnabledUrlPreview">
- <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
- </div>
- <div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
- </div>
- <MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
+ <button class="_button" :class="$style.noteFooterButton" @click="reply()">
+ <i class="ti ti-arrow-back-up"></i>
+ <p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p>
+ </button>
+ <button
+ v-if="canRenote"
+ ref="renoteButton"
+ class="_button"
+ :class="$style.noteFooterButton"
+ @mousedown.prevent="renote()"
+ >
+ <i class="ti ti-repeat"></i>
+ <p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
+ </button>
+ <button v-else class="_button" :class="$style.noteFooterButton" disabled>
+ <i class="ti ti-ban"></i>
+ </button>
+ <button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
+ <i v-if="appearNote.reactionAcceptance === 'likeOnly' && $appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
+ <i v-else-if="$appearNote.myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
+ <i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
+ <i v-else class="ti ti-plus"></i>
+ <p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && $appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number($appearNote.reactionCount) }}</p>
+ </button>
+ <button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
+ <i class="ti ti-paperclip"></i>
+ </button>
+ <button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="showMenu()">
+ <i class="ti ti-dots"></i>
+ </button>
+ </footer>
+ </article>
+ <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>
- <footer>
- <div :class="$style.noteFooterInfo">
- <MkA :to="notePage(appearNote)">
- <MkTime :time="appearNote.createdAt" mode="detail" colored/>
- </MkA>
+ <div>
+ <div v-if="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>
- <MkReactionsViewer
- v-if="appearNote.reactionAcceptance !== 'likeOnly'"
- style="margin-top: 6px;"
- :reactions="$appearNote.reactions"
- :reactionEmojis="$appearNote.reactionEmojis"
- :myReaction="$appearNote.myReaction"
- :noteId="appearNote.id"
- :maxNumber="16"
- @mockUpdateMyReaction="emitUpdReaction"
- />
- <button class="_button" :class="$style.noteFooterButton" @click="reply()">
- <i class="ti ti-arrow-back-up"></i>
- <p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.repliesCount) }}</p>
- </button>
- <button
- v-if="canRenote"
- ref="renoteButton"
- class="_button"
- :class="$style.noteFooterButton"
- @mousedown.prevent="renote()"
- >
- <i class="ti ti-repeat"></i>
- <p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
- </button>
- <button v-else class="_button" :class="$style.noteFooterButton" disabled>
- <i class="ti ti-ban"></i>
- </button>
- <button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
- <i v-if="appearNote.reactionAcceptance === 'likeOnly' && $appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
- <i v-else-if="$appearNote.myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
- <i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
- <i v-else class="ti ti-plus"></i>
- <p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && $appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number($appearNote.reactionCount) }}</p>
- </button>
- <button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
- <i class="ti ti-paperclip"></i>
- </button>
- <button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="showMenu()">
- <i class="ti ti-dots"></i>
- </button>
- </footer>
- </article>
- <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'">
- <div v-if="!repliesLoaded" style="padding: 16px">
- <MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
+ <div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
+ <MkPagination :paginator="renotesPaginator" :forceDisableInfiniteScroll="true">
+ <template #default="{ items }">
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
+ <MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
+ <MkUserCardMini :user="item.user" :withChart="false"/>
+ </MkA>
+ </div>
+ </template>
+ </MkPagination>
</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 :paginator="renotesPaginator" :forceDisableInfiniteScroll="true">
- <template #default="{ items }">
- <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
- <MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
- <MkUserCardMini :user="item.user" :withChart="false"/>
- </MkA>
- </div>
- </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 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 v-if="reactionTabType" :key="reactionTabType" :paginator="reactionsPaginator" :forceDisableInfiniteScroll="true">
+ <template #default="{ items }">
+ <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
+ <MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
+ <MkUserCardMini :user="item.user" :withChart="false"/>
+ </MkA>
+ </div>
+ </template>
+ </MkPagination>
</div>
- <MkPagination v-if="reactionTabType" :key="reactionTabType" :paginator="reactionsPaginator" :forceDisableInfiniteScroll="true">
- <template #default="{ items }">
- <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); grid-gap: 12px;">
- <MkA v-for="item in items" :key="item.id" :to="userPage(item.user)">
- <MkUserCardMini :user="item.user" :withChart="false"/>
- </MkA>
- </div>
- </template>
- </MkPagination>
</div>
- </div>
+ </template>
</div>
<div v-else-if="muted" class="_panel" :class="$style.muted" @click="muted = false">
<I18n :src="i18n.ts.userSaysSomething" tag="small">