summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkNoteDetailed.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components/MkNoteDetailed.vue')
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue80
1 files changed, 32 insertions, 48 deletions
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 52cc836926..7f38b9ec02 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -89,21 +89,21 @@ SPDX-License-Identifier: AGPL-3.0-only
</p>
<div v-show="mergedCW == 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="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
- <Mfm
- v-if="appearNote.text"
- :parsedNodes="parsed"
- :text="appearNote.text"
- :author="appearNote.user"
- :nyaize="'respect'"
- :emojiUrls="appearNote.emojis"
- :enableEmojiMenu="true"
- :enableEmojiMenuReaction="true"
- :isAnim="allowAnim"
- :isBlock="true"
- class="_selectable"
- />
- <a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
+ <div>
+ <MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
+ <Mfm
+ v-if="appearNote.text"
+ :parsedNodes="parsed"
+ :text="appearNote.text"
+ :author="appearNote.user"
+ :nyaize="'respect'"
+ :emojiUrls="appearNote.emojis"
+ :enableEmojiMenu="true"
+ :enableEmojiMenuReaction="true"
+ :isAnim="allowAnim"
+ class="_selectable"
+ />
+ </div>
<SkNoteTranslation :note="note" :translation="translation" :translating="translating"></SkNoteTranslation>
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
<MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
@@ -112,13 +112,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :local="!appearNote.user.host" :class="$style.poll" :author="appearNote.user" :emojiUrls="appearNote.emojis"/>
<div v-if="isEnabledUrlPreview">
- <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" style="margin-top: 6px;"/>
+ <SkUrlPreviewGroup :sourceNodes="nodes" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" style="margin-top: 6px;" @click.stop/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws"/></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>
</div>
- <footer :class="$style.footer">
+ <footer :class="$style.footer" class="_gaps _h_gaps" tabindex="0" role="group" :aria-label="i18n.ts.noteFooterLabel">
<div :class="$style.noteFooterInfo">
<div v-if="appearNote.updatedAt">
{{ i18n.ts.edited }}: <MkTime :time="appearNote.updatedAt" mode="detail"/>
@@ -169,7 +169,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @click.stop="clip()">
<i class="ti ti-paperclip"></i>
</button>
- <button v-if="prefer.s.showTranslationButtonInNoteFooter && $i?.policies.canUseTranslator && instance.translatorAvailable" ref="translationButton" class="_button" :class="$style.noteFooterButton" :disabled="translating || !!translation" @click.stop="translate()">
+ <button v-if="prefer.s.showTranslationButtonInNoteFooter && policies.canUseTranslator && instance.translatorAvailable" ref="translationButton" class="_button" :class="$style.noteFooterButton" :disabled="translating || !!translation" @click.stop="translate()">
<i class="ti ti-language-hiragana"></i>
</button>
<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @click.stop="showMenu()">
@@ -233,7 +233,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, inject, onMounted, provide, ref, useTemplateRef, watch } from 'vue';
-import * as mfm from '@transfem-org/sfm-js';
+import * as mfm from 'mfm-js';
import * as Misskey from 'misskey-js';
import { isLink } from '@@/js/is-link.js';
import * as config from '@@/js/config.js';
@@ -278,7 +278,7 @@ import MkPagination from '@/components/MkPagination.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
import MkButton from '@/components/MkButton.vue';
import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
-import { instance, isEnabledUrlPreview } from '@/instance.js';
+import { instance, isEnabledUrlPreview, policies } from '@/instance.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
@@ -286,7 +286,7 @@ import { DI } from '@/di.js';
import SkMutedNote from '@/components/SkMutedNote.vue';
import SkNoteTranslation from '@/components/SkNoteTranslation.vue';
import { getSelfNoteIds } from '@/utility/get-self-note-ids.js';
-import { extractPreviewUrls } from '@/utility/extract-preview-urls.js';
+import SkUrlPreviewGroup from '@/components/SkUrlPreviewGroup.vue';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -339,8 +339,7 @@ const isDeleted = ref(false);
const renoted = ref(false);
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
const translating = ref(false);
-const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null);
-const urls = computed(() => parsed.value ? extractPreviewUrls(props.note, parsed.value) : null);
+const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : []);
const selfNoteIds = computed(() => getSelfNoteIds(props.note));
const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
const allowAnim = ref(prefer.s.advancedMfm && prefer.s.animatedMfm);
@@ -388,7 +387,7 @@ const keymap = {
clip();
},
't': () => {
- if (prefer.s.showTranslationButtonInNoteFooter && $i?.policies.canUseTranslator && instance.translatorAvailable) {
+ if (prefer.s.showTranslationButtonInNoteFooter && policies.value.canUseTranslator && instance.translatorAvailable) {
translate();
}
},
@@ -415,6 +414,11 @@ provide(DI.mfmEmojiReactCallback, (reaction) => {
const tab = ref(props.initialTab);
const reactionTabType = ref<string | null>(null);
+// Auto-select the first page of reactions
+watch(appearNote, n => {
+ reactionTabType.value ??= Object.keys(n.reactions)[0] ?? null;
+}, { immediate: true });
+
const renotesPagination = computed<Paging>(() => ({
endpoint: 'notes/renotes',
limit: 10,
@@ -886,12 +890,10 @@ function animatedMFM() {
}
.footer {
- position: relative;
- z-index: 1;
- margin-top: 0.4em;
- width: max-content;
- min-width: min-content;
- max-width: fit-content;
+ position: relative;
+ z-index: 1;
+ margin-top: 0.4em;
+ overflow-x: auto;
}
.replyTo {
@@ -1083,10 +1085,6 @@ function animatedMFM() {
padding: 8px;
opacity: 0.7;
- &:not(:last-child) {
- margin-right: 1.5em;
- }
-
&:hover {
color: var(--MI_THEME-fgHighlighted);
}
@@ -1169,14 +1167,6 @@ function animatedMFM() {
}
}
-@container (max-width: 350px) {
- .noteFooterButton {
- &:not(:last-child) {
- margin-right: 0.1em;
- }
- }
-}
-
@container (max-width: 300px) {
.root {
font-size: 0.825em;
@@ -1186,12 +1176,6 @@ function animatedMFM() {
width: 50px;
height: 50px;
}
-
- .noteFooterButton {
- &:not(:last-child) {
- margin-right: 0.1em;
- }
- }
}
.muted {