From 360c820b9d42ca68a52fa22912b2f6df18412895 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Wed, 30 Dec 2020 09:58:57 +0900
Subject: [PATCH] Resolve #3620

---
 locales/ja-JP.yml              |  1 +
 src/client/components/note.vue | 45 +++++++++++++++++++++++++++++++---
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 3899a0bda5..99b1482538 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -49,6 +49,7 @@ copyUsername: "ユーザー名をコピー"
 searchUser: "ユーザーを検索"
 reply: "返信"
 loadMore: "もっと見る"
+showMore: "もっと見る"
 youGotNewFollower: "フォローされました"
 receiveFollowRequest: "フォローリクエストされました"
 followRequestAccepted: "フォローが承認されました"
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index 1778acc0dd..85b16cd8be 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -46,7 +46,7 @@
 					<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
 					<XCwButton v-model:value="showContent" :note="appearNote"/>
 				</p>
-				<div class="content" v-show="appearNote.cw == null || showContent">
+				<div class="content" :class="{ collapsed }" v-show="appearNote.cw == null || showContent">
 					<div class="text">
 						<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $ts.private }})</span>
 						<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><Fa :icon="faReply"/></MkA>
@@ -59,6 +59,9 @@
 					<XPoll v-if="appearNote.poll" :note="appearNote" ref="pollViewer" class="poll"/>
 					<MkUrlPreview v-for="url in urls" :url="url" :key="url" :compact="true" :detail="detail" class="url-preview"/>
 					<div class="renote" v-if="appearNote.renote"><XNotePreview :note="appearNote.renote"/></div>
+					<button v-if="collapsed" class="fade _button" @click="collapsed = false">
+						<span>{{ $ts.showMore }}</span>
+					</button>
 				</div>
 				<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><Fa :icon="faSatelliteDish"/> {{ appearNote.channel.name }}</MkA>
 			</div>
@@ -174,6 +177,7 @@ export default defineComponent({
 			conversation: [],
 			replies: [],
 			showContent: false,
+			collapsed: false,
 			isDeleted: false,
 			muted: false,
 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish
@@ -273,6 +277,12 @@ export default defineComponent({
 			this.connection = os.stream;
 		}
 
+		this.collapsed = this.appearNote.text && (
+			(this.appearNote.text.split('\n').length > 8) ||
+			(this.appearNote.text.length > 300)
+		);
+		this.muted = await checkWordMute(this.appearNote, this.$i, this.$store.state.mutedWords);
+
 		// plugin
 		if (noteViewInterruptors.length > 0) {
 			let result = this.note;
@@ -282,8 +292,6 @@ export default defineComponent({
 			this.$emit('update:note', Object.freeze(result));
 		}
 
-		this.muted = await checkWordMute(this.appearNote, this.$i, this.$store.state.mutedWords);
-
 		if (this.detail) {
 			os.api('notes/children', {
 				noteId: this.appearNote.id,
@@ -1038,6 +1046,37 @@ export default defineComponent({
 				}
 
 				> .content {
+					&.collapsed {
+						position: relative;
+						max-height: 9em;
+						overflow: hidden;
+
+						> .fade {
+							display: block;
+							position: absolute;
+							bottom: 0;
+							left: 0;
+							width: 100%;
+							height: 64px;
+							background: linear-gradient(0deg, var(--panel), var(--X15));
+
+							> span {
+								display: inline-block;
+								background: var(--panel);
+								padding: 6px 10px;
+								font-size: 0.8em;
+								border-radius: 999px;
+								box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
+							}
+
+							&:hover {
+								> span {
+									background: var(--panelHighlight);
+								}
+							}
+						}
+					}
+
 					> .text {
 						overflow-wrap: break-word;