Merge pull request 'note-improvements but this time fix boosted avatars' (#9535) from Freeplay/calckey:note-improvements into develop

Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9535
This commit is contained in:
Kainoa Kanter 2023-02-01 19:48:34 +00:00
commit 83b56f4ad5
12 changed files with 372 additions and 274 deletions

BIN
.yarn/install-state.gz Normal file

Binary file not shown.

View File

@ -31,7 +31,7 @@ const computedStyle = getComputedStyle(document.documentElement);
const themeColor = instance.themeColor ?? computedStyle.getPropertyValue('--bg'); const themeColor = instance.themeColor ?? computedStyle.getPropertyValue('--bg');
const bg = { const bg = {
background: `linear-gradient(90deg, ${themeColor}, ${themeColor}33)`, background: `linear-gradient(90deg, ${themeColor}, ${themeColor}55)`,
}; };
function getInstanceIcon(instance): string { function getInstanceIcon(instance): string {
@ -41,11 +41,15 @@ function getInstanceIcon(instance): string {
<style lang="scss" scoped> <style lang="scss" scoped>
.hpaizdrt { .hpaizdrt {
display: flex;
align-items: center;
height: 1.1em;
display: flex; display: flex;
align-items: center; align-items: center;
height: 1.1em; height: 1.1em;
justify-self: flex-end; justify-self: flex-end;
padding: .2em .4em; padding: .2em .4em;
padding: .2em .4em;
border-radius: 100px; border-radius: 100px;
font-size: .8em; font-size: .8em;
text-shadow: 0 2px 2px var(--shadow); text-shadow: 0 2px 2px var(--shadow);
@ -54,6 +58,10 @@ function getInstanceIcon(instance): string {
width: max-content; width: max-content;
max-width: 100%; max-width: 100%;
} }
.header > .body & {
width: max-content;
max-width: 100%;
}
> .icon { > .icon {
height: 100%; height: 100%;
@ -61,17 +69,24 @@ function getInstanceIcon(instance): string {
} }
> .name { > .name {
display: none;
display: none; display: none;
margin-left: 4px; margin-left: 4px;
font-size: 0.85em; font-size: 0.85em;
font-size: 0.85em;
vertical-align: top; vertical-align: top;
font-weight: bold; font-weight: bold;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis;
white-space: nowrap;
text-shadow: -1px -1px 0 var(--bg), 1px -1px 0 var(--bg), -1px 1px 0 var(--bg), 1px 1px 0 var(--bg); text-shadow: -1px -1px 0 var(--bg), 1px -1px 0 var(--bg), -1px 1px 0 var(--bg), 1px 1px 0 var(--bg);
.article > .main &, .header > .body & { .article > .main &, .header > .body & {
display: unset; display: unset;
} }
.article > .main &, .header > .body & {
display: unset;
}
} }
} }
</style> </style>

View File

@ -143,6 +143,8 @@ const previewable = (file: misskey.entities.DriveFile): boolean => {
position: relative; position: relative;
width: 100%; width: 100%;
margin-top: 4px; margin-top: 4px;
border-radius: var(--radius);
overflow: hidden;
&:before { &:before {
content: ''; content: '';

View File

@ -10,32 +10,35 @@
:class="{ renote: isRenote }" :class="{ renote: isRenote }"
> >
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to"/> <MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" class="reply-to"/>
<div v-if="pinned" class="info"><i class="ph-push-pin-bold ph-lg"></i> {{ i18n.ts.pinnedNote }}</div> <div class="note-context">
<div v-if="appearNote._prId_" class="info"><i class="ph-megaphone-simple-bold ph-lg"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ph-x-bold ph-lg"></i></button></div> <div class="line"></div>
<div v-if="appearNote._featuredId_" class="info"><i class="ph-lightning-bold ph-lg"></i> {{ i18n.ts.featured }}</div> <div v-if="appearNote._prId_" class="info"><i class="ph-megaphone-simple-bold ph-lg"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ph-x-bold ph-lg"></i></button></div>
<div v-if="isRenote" class="renote"> <div v-if="appearNote._featuredId_" class="info"><i class="ph-lightning-bold ph-lg"></i> {{ i18n.ts.featured }}</div>
<!-- <MkAvatar class="avatar" :user="note.user"/> --> <div v-if="pinned" class="info"><i class="ph-push-pin-bold ph-lg"></i>{{ i18n.ts.pinnedNote }}</div>
<i class="ph-repeat-bold ph-lg"></i> <div v-if="isRenote" class="renote">
<I18n :src="i18n.ts.renotedBy" tag="span"> <i class="ph-repeat-bold ph-lg"></i>
<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="name" :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()"> <div class="info">
<i v-if="isMyRenote" class="ph-dots-three-outline-bold ph-lg dropdownIcon"></i> <button ref="renoteTime" class="_button time" @click="showRenoteMenu()">
<MkTime :time="note.createdAt"/> <i v-if="isMyRenote" class="ph-dots-three-outline-bold ph-lg dropdownIcon"></i>
</button> <MkTime :time="note.createdAt"/>
<MkVisibility :note="note"/> </button>
<MkVisibility :note="note"/>
</div>
</div> </div>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu" @click.self="router.push(notePage(appearNote))"> <article class="article" @contextmenu.stop="onContextmenu" @click.self="router.push(notePage(appearNote))">
<MkAvatar class="avatar" :user="appearNote.user"/>
<div class="main" @click.self="router.push(notePage(appearNote))"> <div class="main" @click.self="router.push(notePage(appearNote))">
<XNoteHeader class="header" :note="appearNote" :mini="true"/> <div class="header-container">
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> <MkAvatar class="avatar" :user="appearNote.user"/>
<XNoteHeader class="header" :note="appearNote" :mini="true"/>
</div>
<div class="body"> <div class="body">
<p v-if="appearNote.cw != null" class="cw"> <p v-if="appearNote.cw != null" class="cw">
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> <Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
@ -43,7 +46,6 @@
</p> </p>
<div v-show="appearNote.cw == null || showContent" class="content" :class="{ collapsed, isLong }"> <div v-show="appearNote.cw == null || showContent" class="content" :class="{ collapsed, isLong }">
<div class="text" @click.self="router.push(notePage(appearNote))"> <div class="text" @click.self="router.push(notePage(appearNote))">
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ph-arrow-bend-up-left-bold ph-lg"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<!-- <a v-if="appearNote.renote != null" class="rp">RN:</a> --> <!-- <a v-if="appearNote.renote != null" class="rp">RN:</a> -->
<div v-if="translating || translation" class="translation"> <div v-if="translating || translation" class="translation">
@ -344,146 +346,139 @@ function readPromo() {
opacity: 1; opacity: 1;
} }
> .info {
display: flex;
align-items: center;
padding: 16px 32px 8px 32px;
line-height: 24px;
font-size: 90%;
white-space: pre;
color: #f6c177;
> i {
margin-right: 4px;
}
> .hide {
margin-left: auto;
color: inherit;
}
}
> .info + .article {
padding-top: 8px;
}
> .reply-to { > .reply-to {
opacity: 0.7; & + .note-context {
padding-bottom: 0; .line::before {
content: "";
display: block;
margin-bottom: -10px;
width: 2px;
background-color: var(--accentDarken);
margin-inline: auto;
}
}
} }
> .renote { .note-context {
padding: 0 32px 0 32px;
display: flex; display: flex;
align-items: center; &:first-child {
padding: 16px 32px 8px 32px; margin-top: 20px;
line-height: 28px; }
white-space: pre; > :not(.line) {
color: var(--renote); width: 0;
flex-grow: 1;
> .avatar { position: relative;
flex-shrink: 0; margin-bottom: -10px;
display: inline-block; line-height: 28px;
width: 28px; }
height: 28px; > .line {
margin: 0 8px 0 0; width: var(--avatarSize);
border-radius: 6px; display: flex;
margin-right: 14px;
margin-top: 0;
flex-grow: 0;
} }
> i { > div > i {
margin-right: 4px; position: absolute;
right: 100%;
} }
> .info {
display: flex;
align-items: center;
font-size: 90%;
white-space: pre;
color: #f6c177;
> span { > i {
overflow: hidden; margin-right: 4px;
flex-shrink: 1; }
text-overflow: ellipsis;
white-space: nowrap;
> .name { > .hide {
font-weight: bold; margin-left: auto;
color: inherit;
} }
} }
> .info {
margin-left: auto;
font-size: 0.9em;
> .time { > .renote {
flex-shrink: 0; display: flex;
color: inherit; align-items: center;
white-space: pre;
color: var(--renote);
> .dropdownIcon {
margin-right: 4px; > i {
margin-right: 4px;
}
> span {
overflow: hidden;
flex-shrink: 1;
text-overflow: ellipsis;
white-space: nowrap;
> .name {
font-weight: bold;
}
}
> .info {
margin-left: auto;
font-size: 0.9em;
display: flex;
> .time {
flex-shrink: 0;
color: inherit;
display: inline-flex;
align-items: center;
> .dropdownIcon {
margin-right: 4px;
}
} }
} }
} }
}
> .renote + .article { & + .article {
padding-top: 8px; padding-top: 10px !important;
}
} }
> .article { > .article {
padding: 28px 32px 18px; padding: 28px 32px 16px;
cursor: pointer; cursor: pointer;
display: grid;
align-items: center;
grid-template-columns: 58px;
@media (pointer: coarse) { @media (pointer: coarse) {
cursor: default; cursor: default;
} }
> .avatar { .header-container {
flex-shrink: 0; display: flex;
display: block; > .avatar {
margin: 0 14px 8px 0; flex-shrink: 0;
grid-row: 1 / span 2; display: block;
width: 48px; margin: 0 14px 0 0;
height: 48px; width: var(--avatarSize);
position: relative; height: var(--avatarSize);
top: 0; position: relative;
left: 0; top: 0;
left: 0;
}
> .header {
width: 0;
flex-grow: 1;
}
} }
> .main { > .main {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
display: contents;
> header.header {
display: contents;
> .name, .info {
grid-row: 1;
}
}
> :not(.ticker) {
grid-column: 1 / span 3;
width: 100%;
max-width: 100%;
}
> .name, .info {
grid-row: 1;
}
> .ticker {
grid-row: 2;
align-self: flex-start;
margin-left: auto;
}
> .ticker {
font-size: 0.9em;
}
> .body { > .body {
margin-top: .2em; margin-top: .7em;
overflow: hidden; overflow: hidden;
margin-inline: -100px;
padding-inline: 100px;
> .cw { > .cw {
cursor: default; cursor: default;
@ -520,7 +515,11 @@ function readPromo() {
position: relative; position: relative;
max-height: 9em; max-height: 9em;
overflow: hidden; overflow: hidden;
> .text {
max-height: 9em;
mask: linear-gradient(black calc(100% - 64px), transparent);
-webkit-mask: linear-gradient(black calc(100% - 64px), transparent);
}
> .fade { > .fade {
display: block; display: block;
position: absolute; position: absolute;
@ -528,7 +527,6 @@ function readPromo() {
left: 0; left: 0;
width: 100%; width: 100%;
height: 64px; height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
> span { > span {
display: inline-block; display: inline-block;
@ -569,6 +567,10 @@ function readPromo() {
} }
} }
> .files {
margin-top: .4em;
margin-bottom: .4em;
}
> .url-preview { > .url-preview {
margin-top: 8px; margin-top: 8px;
} }
@ -595,15 +597,18 @@ function readPromo() {
} }
> .footer { > .footer {
display: flex;
flex-wrap: wrap;
> .button { > .button {
margin: 0; margin: 0;
padding: 8px; padding: 8px;
opacity: 0.7; opacity: 0.7;
flex-grow: 1;
&:not(:last-child) { max-width: 3.5em;
margin-right: 16px; min-width: max-content;
&:first-of-type {
margin-left: -.5em;
} }
&:hover { &:hover {
color: var(--fgHighlighted); color: var(--fgHighlighted);
} }
@ -628,67 +633,31 @@ function readPromo() {
&.max-width_500px { &.max-width_500px {
font-size: 0.9em; font-size: 0.9em;
> .article {
> .avatar {
width: 50px;
height: 50px;
}
}
} }
&.max-width_450px { &.max-width_450px {
> .renote { --avatarSize: 46px;
padding: 8px 16px 0 16px; > .note-context {
padding-inline: 16px;
margin-top: 0;
> :not(.line) {
margin-top: 10px;
}
} }
> .info {
padding: 8px 16px 0 16px;
}
> .article { > .article {
padding: 14px 16px 9px; padding: 16px 16px 9px;
> .avatar { > .main > .header-container > .avatar {
margin: 0 10px 8px 0; margin-right: 10px;
width: 46px;
height: 46px;
// top: calc(14px + var(--stickyTop, 0px)); // top: calc(14px + var(--stickyTop, 0px));
} }
} }
} }
&.max-width_350px {
> .article {
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 18px;
}
}
}
}
}
}
&.max-width_300px { &.max-width_300px {
> .article { --avatarSize: 40px;
> .avatar {
width: 44px;
height: 44px;
}
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 12px;
}
}
}
}
}
} }
} }

View File

@ -54,9 +54,7 @@
</p> </p>
<div v-show="appearNote.cw == null || showContent" class="content"> <div v-show="appearNote.cw == null || showContent" class="content">
<div class="text" @click.self="router.push(notePage(appearNote))"> <div class="text" @click.self="router.push(notePage(appearNote))">
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ph-arrow-bend-up-left-bold ph-lg"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
<!-- <a v-if="appearNote.renote != null" class="rp">RN:</a> -->
<div v-if="translating || translation" class="translation"> <div v-if="translating || translation" class="translation">
<MkLoading v-if="translating" mini/> <MkLoading v-if="translating" mini/>
<div v-else class="translated"> <div v-else class="translated">
@ -338,14 +336,12 @@ if (appearNote.replyId) {
&:hover > .article > .main > .footer > .button { &:hover > .article > .main > .footer > .button {
opacity: 1; opacity: 1;
} }
> .reply-to { > .reply-to {
opacity: 0.7; margin-bottom: -16px;
padding-bottom: 0;
} }
> .reply-to-more { > .reply-to-more {
opacity: 0.7; // opacity: 0.7;
cursor: pointer; cursor: pointer;
@media (pointer: coarse) { @media (pointer: coarse) {
@ -416,21 +412,26 @@ if (appearNote.replyId) {
> .avatar { > .avatar {
display: block; display: block;
flex-shrink: 0; flex-shrink: 0;
width: 52px; width: var(--avatarSize);
height: 52px; height: var(--avatarSize);
} }
> .body { > .body {
width: 0;
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
padding-left: 16px; padding-left: 14px;
font-size: 0.95em; font-size: 0.95em;
> .top { > .top {
display: flex;
align-items: center;
> .name { > .name {
font-weight: bold; font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
} }
> .is-bot { > .is-bot {
@ -568,18 +569,18 @@ if (appearNote.replyId) {
} }
&.max-width_450px { &.max-width_450px {
> .reply-to-more:first-child {
padding-top: 14px;
}
> .renote { > .renote {
padding: 8px 16px 0 16px; padding: 8px 16px 0 16px;
} }
> .article { > .article {
padding: 16px; padding: 16px;
> .header > .body {
> .header { padding-left: 10px;
> .avatar {
width: 50px;
height: 50px;
}
} }
} }
} }
@ -602,12 +603,6 @@ if (appearNote.replyId) {
font-size: 0.825em; font-size: 0.825em;
> .article { > .article {
> .header {
> .avatar {
width: 50px;
height: 50px;
}
}
> .main { > .main {
> .footer { > .footer {

View File

@ -1,16 +1,23 @@
<template> <template>
<header class="kkwtjztg"> <header class="kkwtjztg">
<MkA v-user-preview="note.user.id" class="name" :to="userPage(note.user)"> <div class="user-info">
<MkUserName :user="note.user" class="mkusername"> <div>
<span v-if="note.user.isBot" class="is-bot">bot</span> <MkA v-user-preview="note.user.id" class="name" :to="userPage(note.user)">
</MkUserName> <MkUserName :user="note.user" class="mkusername">
</MkA> <span v-if="note.user.isBot" class="is-bot">bot</span>
<div class="username"><MkAcct :user="note.user"/></div> </MkUserName>
<div class="info"> </MkA>
<MkA class="created-at" :to="notePage(note)"> <div class="username"><MkAcct :user="note.user"/></div>
<MkTime :time="note.createdAt"/> </div>
</MkA> <div>
<MkVisibility :note="note"/> <div class="info">
<MkA class="created-at" :to="notePage(note)">
<MkTime :time="note.createdAt"/>
</MkA>
<MkVisibility :note="note"/>
</div>
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="note.user.instance"/>
</div>
</div> </div>
</header> </header>
</template> </template>
@ -18,66 +25,124 @@
<script lang="ts" setup> <script lang="ts" setup>
import { } from 'vue'; import { } from 'vue';
import type * as misskey from 'calckey-js'; import type * as misskey from 'calckey-js';
import { defaultStore, noteViewInterruptors } from '@/store';
import MkVisibility from '@/components/MkVisibility.vue'; import MkVisibility from '@/components/MkVisibility.vue';
import MkInstanceTicker from '@/components/MkInstanceTicker.vue';
import { notePage } from '@/filters/note'; import { notePage } from '@/filters/note';
import { userPage } from '@/filters/user'; import { userPage } from '@/filters/user';
import { deepClone } from '@/scripts/clone';
defineProps<{ const props = defineProps<{
note: misskey.entities.Note; note: misskey.entities.Note;
pinned?: boolean; pinned?: boolean;
}>(); }>();
let note = $ref(deepClone(props.note));
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && note.user.instance);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.kkwtjztg { .kkwtjztg {
display: flex; display: flex;
align-items: baseline; align-items: center;
white-space: nowrap; white-space: nowrap;
justify-self: flex-end; justify-self: flex-end;
padding: .1em .7em;
border-radius: 100px; border-radius: 100px;
font-size: .8em; font-size: .8em;
text-shadow: 0 2px 2px var(--shadow); text-shadow: 0 2px 2px var(--shadow);
> .name { > .avatar {
flex-shrink: 1; width: 3.7em;
display: block; height: 3.7em;
margin: 0 .5em 0 0; margin-right: 1em;
padding: 0; }
overflow: hidden; > .user-info {
width: 0;
flex-grow: 1;
line-height: 1.5;
display: flex;
font-size: 1.2em; font-size: 1.2em;
font-weight: bold; > div {
text-decoration: none; &:first-child {
text-overflow: ellipsis; flex-grow: 1;
width: 0;
>.mkusername >.is-bot { overflow: hidden;
flex-shrink: 0; text-overflow: ellipsis;
align-self: center; }
&:last-child {
max-width: 50%;
gap: .2em .5em;
}
.article > .main & {
display: flex;
flex-direction: column;
align-items: flex-start;
&:last-child {
align-items: flex-end;
}
> * {
max-width: 100%;
}
}
}
.name {
// flex: 1 1 0px;
display: inline;
margin: 0 .5em 0 0; margin: 0 .5em 0 0;
padding: 1px 6px; padding: 0;
font-size: 80%; overflow: hidden;
border: solid 0.5px var(--divider); font-weight: bold;
border-radius: 3px; text-decoration: none;
text-overflow: ellipsis;
.mkusername >.is-bot {
flex-shrink: 0;
align-self: center;
margin: 0 .5em 0 0;
padding: 1px 6px;
font-size: 80%;
border: solid 0.5px var(--divider);
border-radius: 3px;
}
&:hover {
text-decoration: underline;
}
} }
&:hover { .username {
text-decoration: underline; display: inline;
margin: 0 .5em 0 0;
overflow: hidden;
text-overflow: ellipsis;
align-self: flex-start;
font-size: .9em;
} }
}
> .username { .info {
flex-shrink: 9999999; display: inline-flex;
margin: 0 .5em 0 0; flex-shrink: 0;
overflow: hidden; margin-left: .5em;
text-overflow: ellipsis; font-size: 0.9em;
grid-row: 2; .created-at {
align-self: flex-start; max-width: 100%;
} overflow: hidden;
text-overflow: ellipsis;
}
}
> .info { .ticker {
flex-shrink: 0; display: inline-flex;
margin-left: auto; margin-left: .5em;
font-size: 0.9em; vertical-align: middle;
> .name {
display: none;
}
}
} }
} }
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-size="{ min: [350, 500] }" class="yohlumlk"> <div v-size="{ min: [350, 500] }" class="yohlumlk">
<!-- <MkAvatar class="avatar" :user="note.user"/> --> <MkAvatar class="avatar" :user="note.user"/>
<div class="main"> <div class="main">
<XNoteHeader class="header" :note="note" :mini="true"/> <XNoteHeader class="header" :note="note" :mini="true"/>
<div class="body"> <div class="body">

View File

@ -1,7 +1,10 @@
<template> <template>
<div v-size="{ max: [450] }" class="wrpstxzv" :class="{ children: depth > 1 }"> <div v-size="{ max: [450] }" class="wrpstxzv" :class="{ children: depth > 1 }">
<div class="main" @click="router.push(notePage(note.reply))"> <div class="main" @click="router.push(notePage(note))">
<MkAvatar class="avatar" :user="note.user"/> <div class="avatar-container">
<MkAvatar class="avatar" :user="note.user"/>
<div class="line"></div>
</div>
<div class="body"> <div class="body">
<XNoteHeader class="header" :note="note" :mini="true"/> <XNoteHeader class="header" :note="note" :mini="true"/>
<div class="body"> <div class="body">
@ -56,11 +59,7 @@ const replies: misskey.entities.Note[] = props.conversation?.filter(item => item
<style lang="scss" scoped> <style lang="scss" scoped>
.wrpstxzv { .wrpstxzv {
padding: 16px 32px; padding: 16px 32px;
font-size: 0.9em;
&.max-width_450px {
padding: 14px 16px;
}
&.children { &.children {
padding: 10px 0 0 16px; padding: 10px 0 0 16px;
@ -75,20 +74,21 @@ const replies: misskey.entities.Note[] = props.conversation?.filter(item => item
> .main { > .main {
display: flex; display: flex;
> .avatar { > .avatar-container {
flex-shrink: 0; margin-right: 8px;
display: block; > .avatar {
margin: 0 8px 0 0; flex-shrink: 0;
width: 38px; display: block;
height: 38px; width: 38px;
border-radius: 8px; height: 38px;
border-radius: 8px;
}
} }
> .body { > .body {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
cursor: pointer; cursor: pointer;
@media (pointer: coarse) { @media (pointer: coarse) {
cursor: default; cursor: default;
} }
@ -129,5 +129,54 @@ const replies: misskey.entities.Note[] = props.conversation?.filter(item => item
> .more { > .more {
padding: 10px 0 0 16px; padding: 10px 0 0 16px;
} }
&.reply-to, &.reply-to-more {
padding-bottom: 0;
&:first-child {
padding-top: 30px;
}
.avatar-container {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 14px;
width: var(--avatarSize);
> .avatar {
width: var(--avatarSize);
height: var(--avatarSize);
margin: 0;
}
> .line {
width: var(--avatarSize);
display: flex;
flex-grow: 1;
&::before {
content: "";
display: block;
width: 2px;
background-color: var(--accentDarken);
margin-inline: auto;
.note > & {
margin-bottom: -16px;
}
}
}
}
> .main > .body {
padding-bottom: 16px;
}
}
&.max-width_450px {
padding: 14px 16px;
&.reply-to, &.reply-to-more {
padding-top: 14px !important;
padding-bottom: 0 !important;
margin-bottom: 0 !important;
}
> .main > .avatar-container {
margin-right: 10px;
}
}
} }
</style> </style>

View File

@ -22,6 +22,7 @@ const isMe = computed(() => $i && $i.id === props.note.userId);
<style lang="scss" scoped> <style lang="scss" scoped>
.tdflqwzn { .tdflqwzn {
margin: 4px -2px 0 -2px; margin: 4px -2px 0 -2px;
width: 100%;
&:empty { &:empty {
display: none; display: none;

View File

@ -4,7 +4,7 @@
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deleted }})</span> <span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deleted }})</span>
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ph-arrow-bend-up-left-bold ph-lg"></i></MkA> <MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ph-arrow-bend-up-left-bold ph-lg"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/> <Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">QB: ...</MkA> <MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">{{ i18n.ts.quoteAttached }}: ...</MkA>
</div> </div>
<div v-if="note.files.length > 0"> <div v-if="note.files.length > 0">
<summary>({{ i18n.t('withNFiles', { n: note.files.length }) }})</summary> <summary>({{ i18n.t('withNFiles', { n: note.files.length }) }})</summary>
@ -65,7 +65,11 @@ const collapsed = $ref(props.note.cw == null && isLong);
position: relative; position: relative;
max-height: 9em; max-height: 9em;
overflow: hidden; overflow: hidden;
> .body {
max-height: 9em;
mask: linear-gradient(black calc(100% - 64px), transparent);
-webkit-mask: linear-gradient(black calc(100% - 64px), transparent);
}
> .fade { > .fade {
display: block; display: block;
position: absolute; position: absolute;
@ -73,7 +77,6 @@ const collapsed = $ref(props.note.cw == null && isLong);
left: 0; left: 0;
width: 100%; width: 100%;
height: 64px; height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
> span { > span {
display: inline-block; display: inline-block;

View File

@ -210,14 +210,12 @@ onUnmounted(() => {
position: relative; position: relative;
display: block; display: block;
font-size: 14px; font-size: 14px;
box-shadow: 0 0 0 1px var(--divider); border: 1px solid var(--divider);
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
&:hover { &:hover {
text-decoration: none; text-decoration: none;
border-color: rgba(0, 0, 0, 0.2);
> article > header > h1 { > article > header > h1 {
text-decoration: underline; text-decoration: underline;
} }

View File

@ -4,6 +4,7 @@
--radius: 12px; --radius: 12px;
--marginFull: 16px; --marginFull: 16px;
--marginHalf: 10px; --marginHalf: 10px;
--avatarSize: 48px;
--margin: var(--marginFull); --margin: var(--marginFull);