This commit is contained in:
syuilo 2023-05-29 18:22:15 +09:00
parent f469f555e8
commit 3097bb6c7d
1 changed files with 303 additions and 375 deletions

View File

@ -4,25 +4,25 @@
v-show="!isDeleted" v-show="!isDeleted"
ref="el" ref="el"
v-hotkey="keymap" v-hotkey="keymap"
class="lxwezrsl" :class="[$style.root, { [$style.renote]: isRenote }]"
:tabindex="!isDeleted ? '-1' : null"
:class="{ renote: isRenote }"
> >
<MkNoteSub v-for="note in conversation" :key="note.id" class="reply-to-more" :note="note"/> <MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to"/> <MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
<div v-if="isRenote" class="renote"> <div v-if="isRenote" :class="$style.renote">
<MkAvatar class="avatar" :user="note.user" link preview/> <MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<i class="ti ti-repeat"></i> <i class="ti ti-repeat" style="margin-right: 4px;"></i>
<I18n :src="i18n.ts.renotedBy" tag="span"> <span :class="$style.renoteText">
<template #user> <I18n :src="i18n.ts.renotedBy" tag="span">
<MkA v-user-preview="note.userId" class="name" :to="userPage(note.user)"> <template #user>
<MkUserName :user="note.user"/> <MkA v-user-preview="note.userId" :class="$style.renoteName" :to="userPage(note.user)">
</MkA> <MkUserName :user="note.user"/>
</template> </MkA>
</I18n> </template>
<div class="info"> </I18n>
<button ref="renoteTime" class="_button time" @click="showRenoteMenu()"> </span>
<i v-if="isMyRenote" class="ti ti-dots dropdownIcon"></i> <div :class="$style.renoteInfo">
<button ref="renoteTime" class="_button" :class="$style.renoteTime" @click="showRenoteMenu()">
<i v-if="isMyRenote" class="ti ti-dots" style="margin-right: 4px;"></i>
<MkTime :time="note.createdAt"/> <MkTime :time="note.createdAt"/>
</button> </button>
<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]"> <span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]">
@ -33,16 +33,16 @@
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span> <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
</div> </div>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu"> <article :class="$style.note" @contextmenu.stop="onContextmenu">
<header class="header"> <header :class="$style.noteHeader">
<MkAvatar class="avatar" :user="appearNote.user" indicator link preview/> <MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
<div class="body"> <div :class="$style.noteHeaderBody">
<div class="top"> <div>
<MkA v-user-preview="appearNote.user.id" class="name" :to="userPage(appearNote.user)"> <MkA v-user-preview="appearNote.user.id" :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
<MkUserName :nowrap="false" :user="appearNote.user"/> <MkUserName :nowrap="false" :user="appearNote.user"/>
</MkA> </MkA>
<span v-if="appearNote.user.isBot" class="is-bot">bot</span> <span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
<div class="info"> <div :class="$style.noteHeaderInfo">
<span v-if="appearNote.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[appearNote.visibility]"> <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-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 === 'followers'" class="ti ti-lock"></i>
@ -51,84 +51,81 @@
<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></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> </div>
<div class="username"><MkAcct :user="appearNote.user"/></div> <div :class="$style.noteHeaderUsername"><MkAcct :user="appearNote.user"/></div>
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> <MkInstanceTicker v-if="showTicker" :class="$style.ticker" :instance="appearNote.user.instance"/>
</div> </div>
</header> </header>
<div class="main"> <div :class="$style.noteContent">
<div class="body"> <p v-if="appearNote.cw != null" :class="$style.cw">
<p v-if="appearNote.cw != null" class="cw"> <Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :i="$i"/>
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i"/> <MkCwButton v-model="showContent" :note="appearNote"/>
<MkCwButton v-model="showContent" :note="appearNote"/> </p>
</p> <div v-show="appearNote.cw == null || showContent">
<div v-show="appearNote.cw == null || showContent" class="content"> <span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<div class="text"> <MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span> <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA> <a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/> <div v-if="translating || translation" :class="$style.translation">
<a v-if="appearNote.renote != null" class="rp">RN:</a> <MkLoading v-if="translating" mini/>
<div v-if="translating || translation" class="translation"> <div v-else>
<MkLoading v-if="translating" mini/> <b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
<div v-else class="translated"> <Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/>
</div>
</div>
</div> </div>
<div v-if="appearNote.files.length > 0" class="files">
<MkMediaList :mediaList="appearNote.files"/>
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" class="poll"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" class="url-preview"/>
<div v-if="appearNote.renote" class="renote"><MkNoteSimple :note="appearNote.renote" class="note"/></div>
</div> </div>
<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA> <div v-if="appearNote.files.length > 0" :class="$style.files">
<MkMediaList :mediaList="appearNote.files"/>
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :note="appearNote" :class="$style.poll"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="true" style="margin-top: 6px;"/>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
</div> </div>
<footer class="footer"> <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 class="info">
<MkA class="created-at" :to="notePage(appearNote)">
<MkTime :time="appearNote.createdAt" mode="detail"/>
</MkA>
</div>
<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
<button class="button _button" @click="reply()">
<i class="ti ti-arrow-back-up"></i>
<p v-if="appearNote.repliesCount > 0" class="count">{{ appearNote.repliesCount }}</p>
</button>
<button
v-if="canRenote"
ref="renoteButton"
class="button _button"
@mousedown="renote()"
>
<i class="ti ti-repeat"></i>
<p v-if="appearNote.renoteCount > 0" class="count">{{ appearNote.renoteCount }}</p>
</button>
<button v-else class="button _button" disabled>
<i class="ti ti-ban"></i>
</button>
<button v-if="appearNote.myReaction == null" ref="reactButton" class="button _button" @mousedown="react()">
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
<i v-else class="ti ti-plus"></i>
</button>
<button v-if="appearNote.myReaction != null" ref="reactButton" class="button _button reacted" @click="undoReact(appearNote)">
<i class="ti ti-minus"></i>
</button>
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="button _button" @mousedown="clip()">
<i class="ti ti-paperclip"></i>
</button>
<button ref="menuButton" class="button _button" @mousedown="menu()">
<i class="ti ti-dots"></i>
</button>
</footer>
</div> </div>
<footer>
<div :class="$style.noteFooterInfo">
<MkA :to="notePage(appearNote)">
<MkTime :time="appearNote.createdAt" mode="detail"/>
</MkA>
</div>
<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
<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">{{ appearNote.repliesCount }}</p>
</button>
<button
v-if="canRenote"
ref="renoteButton"
class="_button"
:class="$style.noteFooterButton"
@mousedown="renote()"
>
<i class="ti ti-repeat"></i>
<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.renoteCount }}</p>
</button>
<button v-else class="_button" :class="$style.noteFooterButton" disabled>
<i class="ti ti-ban"></i>
</button>
<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.noteFooterButton" class="_button" @mousedown="react()">
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
<i v-else class="ti ti-plus"></i>
</button>
<button v-if="appearNote.myReaction != null" ref="reactButton" class="_button" :class="[$style.noteFooterButton, $style.reacted]" @click="undoReact(appearNote)">
<i class="ti ti-minus"></i>
</button>
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown="clip()">
<i class="ti ti-paperclip"></i>
</button>
<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown="menu()">
<i class="ti ti-dots"></i>
</button>
</footer>
</article> </article>
<MkNoteSub v-for="note in replies" :key="note.id" :note="note" class="reply" :detail="true"/> <MkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true"/>
</div> </div>
<div v-else class="_panel muted" @click="muted = false"> <div v-else class="_panel" :class="$style.muted" @click="muted = false">
<I18n :src="i18n.ts.userSaysSomething" tag="small"> <I18n :src="i18n.ts.userSaysSomething" tag="small">
<template #name> <template #name>
<MkA v-user-preview="appearNote.userId" class="name" :to="userPage(appearNote.user)"> <MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
<MkUserName :user="appearNote.user"/> <MkUserName :user="appearNote.user"/>
</MkA> </MkA>
</template> </template>
@ -438,318 +435,249 @@ if (appearNote.replyId) {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" module>
.lxwezrsl { .root {
position: relative; position: relative;
transition: box-shadow 0.1s ease; transition: box-shadow 0.1s ease;
overflow: clip; overflow: clip;
contain: content; contain: content;
}
&:focus-visible { .replyTo {
outline: none; opacity: 0.7;
padding-bottom: 0;
}
&:after { .replyToMore {
content: ""; opacity: 0.7;
pointer-events: none; }
display: block;
position: absolute;
z-index: 10;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: calc(100% - 8px);
height: calc(100% - 8px);
border: dashed 1px var(--focus);
border-radius: var(--radius);
box-sizing: border-box;
}
}
&:hover > .article > .main > .footer > .button { .renote {
display: flex;
align-items: center;
padding: 16px 32px 8px 32px;
line-height: 28px;
white-space: pre;
color: var(--renote);
}
.renoteAvatar {
flex-shrink: 0;
display: inline-block;
width: 28px;
height: 28px;
margin: 0 8px 0 0;
border-radius: 6px;
}
.renoteText {
overflow: hidden;
flex-shrink: 1;
text-overflow: ellipsis;
white-space: nowrap;
}
.renoteName {
font-weight: bold;
}
.renoteInfo {
margin-left: auto;
font-size: 0.9em;
}
.renoteTime {
flex-shrink: 0;
color: inherit;
}
.renote + .note {
padding-top: 8px;
}
.note {
padding: 32px;
font-size: 1.2em;
&:hover > .main > .footer > .button {
opacity: 1; opacity: 1;
} }
}
> .reply-to {
opacity: 0.7; .noteHeader {
padding-bottom: 0; display: flex;
} position: relative;
margin-bottom: 16px;
> .reply-to-more { align-items: center;
opacity: 0.7; }
}
.noteHeaderAvatar {
> .renote { display: block;
display: flex; flex-shrink: 0;
align-items: center; width: 58px;
padding: 16px 32px 8px 32px; height: 58px;
line-height: 28px; }
white-space: pre;
color: var(--renote); .noteHeaderBody {
flex: 1;
> .avatar { display: flex;
flex-shrink: 0; flex-direction: column;
display: inline-block; justify-content: center;
width: 28px; padding-left: 16px;
height: 28px; font-size: 0.95em;
margin: 0 8px 0 0; }
border-radius: 6px;
} .noteHeaderName {
font-weight: bold;
> i { line-height: 1.3;
margin-right: 4px; }
}
.isBot {
> span { display: inline-block;
overflow: hidden; margin: 0 0.5em;
flex-shrink: 1; padding: 4px 6px;
text-overflow: ellipsis; font-size: 80%;
white-space: nowrap; line-height: 1;
border: solid 0.5px var(--divider);
> .name { border-radius: 4px;
font-weight: bold; }
}
} .noteHeaderInfo {
float: right;
> .info { }
margin-left: auto;
font-size: 0.9em; .noteHeaderUsername {
margin-bottom: 2px;
> .time { line-height: 1.3;
flex-shrink: 0; word-wrap: anywhere;
color: inherit; }
> .dropdownIcon { .noteContent {
margin-right: 4px; container-type: inline-size;
} overflow-wrap: break-word;
} }
}
} .cw {
cursor: default;
> .renote + .article { display: block;
padding-top: 8px; margin: 0;
} padding: 0;
overflow-wrap: break-word;
> .article { }
padding: 32px;
font-size: 1.2em; .noteReplyTarget {
color: var(--accent);
> .header { margin-right: 0.5em;
display: flex; }
position: relative;
margin-bottom: 16px; .rn {
align-items: center; margin-left: 4px;
font-style: oblique;
> .avatar { color: var(--renote);
display: block; }
flex-shrink: 0;
width: 58px; .translation {
height: 58px; border: solid 0.5px var(--divider);
} border-radius: var(--radius);
padding: 12px;
> .body { margin-top: 8px;
flex: 1; }
display: flex;
flex-direction: column; .poll {
justify-content: center; font-size: 80%;
padding-left: 16px; }
font-size: 0.95em;
.quote {
> .top { padding: 8px 0;
> .name { }
font-weight: bold;
line-height: 1.3; .quoteNote {
} padding: 16px;
border: dashed 1px var(--renote);
> .is-bot { border-radius: 8px;
display: inline-block; }
margin: 0 0.5em;
padding: 4px 6px; .channel {
font-size: 80%; opacity: 0.7;
line-height: 1; font-size: 80%;
border: solid 0.5px var(--divider); }
border-radius: 4px;
} .noteFooterInfo {
margin: 16px 0;
> .info { opacity: 0.7;
float: right; font-size: 0.9em;
} }
}
.noteFooterButton {
> .username { margin: 0;
margin-bottom: 2px; padding: 8px;
line-height: 1.3; opacity: 0.7;
word-wrap: anywhere;
} &:not(:last-child) {
} margin-right: 28px;
} }
> .main { &:hover {
> .body { color: var(--fgHighlighted);
container-type: inline-size; }
}
> .cw {
cursor: default; .noteFooterButtonCount {
display: block; display: inline;
margin: 0; margin: 0 0 0 8px;
padding: 0; opacity: 0.7;
overflow-wrap: break-word;
&.reacted {
> .text { color: var(--accent);
margin-right: 8px; }
} }
}
.reply {
> .content { border-top: solid 0.5px var(--divider);
> .text {
overflow-wrap: break-word;
> .reply {
color: var(--accent);
margin-right: 0.5em;
}
> .rp {
margin-left: 4px;
font-style: oblique;
color: var(--renote);
}
> .translation {
border: solid 0.5px var(--divider);
border-radius: var(--radius);
padding: 12px;
margin-top: 8px;
}
}
> .url-preview {
margin-top: 8px;
}
> .poll {
font-size: 80%;
}
> .renote {
padding: 8px 0;
> .note {
padding: 16px;
border: dashed 1px var(--renote);
border-radius: 8px;
}
}
}
> .channel {
opacity: 0.7;
font-size: 80%;
}
}
> .footer {
> .info {
margin: 16px 0;
opacity: 0.7;
font-size: 0.9em;
}
> .button {
margin: 0;
padding: 8px;
opacity: 0.7;
&:not(:last-child) {
margin-right: 28px;
}
&:hover {
color: var(--fgHighlighted);
}
> .count {
display: inline;
margin: 0 0 0 8px;
opacity: 0.7;
}
&.reacted {
color: var(--accent);
}
}
}
}
}
> .reply {
border-top: solid 0.5px var(--divider);
}
} }
@container (max-width: 500px) { @container (max-width: 500px) {
.lxwezrsl { .root {
font-size: 0.9em; font-size: 0.9em;
} }
} }
@container (max-width: 450px) { @container (max-width: 450px) {
.lxwezrsl { .renote {
> .renote { padding: 8px 16px 0 16px;
padding: 8px 16px 0 16px; }
}
> .article { .note {
padding: 16px; padding: 16px;
}
> .header { .noteHeaderAvatar {
> .avatar { width: 50px;
width: 50px; height: 50px;
height: 50px;
}
}
}
} }
} }
@container (max-width: 350px) { @container (max-width: 350px) {
.lxwezrsl { .noteFooterButton {
> .article { &:not(:last-child) {
> .main { margin-right: 18px;
> .footer {
> .button {
&:not(:last-child) {
margin-right: 18px;
}
}
}
}
} }
} }
} }
@container (max-width: 300px) { @container (max-width: 300px) {
.lxwezrsl { .root {
font-size: 0.825em; font-size: 0.825em;
}
> .article { .noteHeaderAvatar {
> .header { width: 50px;
> .avatar { height: 50px;
width: 50px; }
height: 50px;
}
}
> .main { .noteFooterButton {
> .footer { &:not(:last-child) {
> .button { margin-right: 12px;
&:not(:last-child) {
margin-right: 12px;
}
}
}
}
} }
} }
} }