From 8a55d8a468cdbf39e9d741411d42a205e20e0f70 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Wed, 24 Jan 2024 19:26:28 +0300
Subject: [PATCH 01/17] upd: add a download button to videos and audio

this only works for media from the same origin due to annoying browser
restrictions, but then the same applies to every other download button
in misskey (e.g. the one in drive) and there's basically nothing i can
to do solve it.
---
 packages/frontend/src/components/MkMediaAudio.vue | 3 +++
 packages/frontend/src/components/MkMediaVideo.vue | 3 +++
 packages/frontend/src/style.scss                  | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue
index a52f2a0e05..dc76d2bcdb 100644
--- a/packages/frontend/src/components/MkMediaAudio.vue
+++ b/packages/frontend/src/components/MkMediaAudio.vue
@@ -32,6 +32,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</button>
 		</div>
 		<div :class="[$style.controlsChild, $style.controlsRight]">
+			<a class="_button" :class="$style.controlButton" :href="audio.url" :download="audio.name" target="_blank">
+				<i class="ph-download ph-bold ph-lg"></i>
+			</a>
 			<button class="_button" :class="$style.controlButton" @click="showMenu">
 				<i class="ph-gear ph-bold ph-lg"></i>
 			</button>
diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index 3b8d43c85b..b4ad92cf09 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -51,6 +51,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</button>
 			</div>
 			<div :class="[$style.controlsChild, $style.controlsRight]">
+				<a class="_button" :class="$style.controlButton" :href="video.url" :download="video.name" target="_blank">
+					<i class="ph-download ph-bold ph-lg"></i>
+				</a>
 				<button class="_button" :class="$style.controlButton" @click="showMenu">
 					<i class="ph-settings ph-bold ph-lg"></i>
 				</button>
diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss
index 46f88825b8..bc43d85376 100644
--- a/packages/frontend/src/style.scss
+++ b/packages/frontend/src/style.scss
@@ -253,6 +253,10 @@ rt {
 	line-height: inherit;
 	max-width: 100%;
 
+	&:hover {
+		text-decoration: none;
+	}
+
 	&:focus-visible {
 		outline: none;
 	}

From a4439ed803f73302e82fe9ae4a01cee6c5865a1b Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Wed, 24 Jan 2024 19:36:19 +0300
Subject: [PATCH 02/17] fix: bring back the ability to hover on videos to show
 alt text

---
 packages/frontend/src/components/MkMediaVideo.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index b4ad92cf09..04a424e0fe 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -430,7 +430,6 @@ onDeactivated(() => {
 	display: block;
 	height: 100%;
 	width: 100%;
-	pointer-events: none;
 }
 
 .videoOverlayPlayButton {

From f40c3a2d9f9fd8e8cd8fe69a9cf4605a737de554 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sun, 28 Jan 2024 15:07:22 +0300
Subject: [PATCH 03/17] fix: duplicate root dom element in dev mode

---
 packages/frontend/src/index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/index.html b/packages/frontend/src/index.html
index ec9110ecff..097c0080ae 100644
--- a/packages/frontend/src/index.html
+++ b/packages/frontend/src/index.html
@@ -30,7 +30,7 @@
 </head>
 
 <body>
-<div id="misskey_app"></div>
+<div id="sharkey_app"></div>
 <script type="module" src="./_dev_boot_.ts"></script>
 </body>
 </html>

From fae3af4342c8f0588871508e4b21418b6c73f6e7 Mon Sep 17 00:00:00 2001
From: blueb <ihateblueb@proton.me>
Date: Sun, 28 Jan 2024 12:29:16 -0500
Subject: [PATCH 04/17] fix: adjust alignment and margin of icon in detailed
 note tabs

---
 packages/frontend/src/components/SkNoteDetailed.vue | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index d26e431c95..0681ddc6c8 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -1081,10 +1081,17 @@ onUnmounted(() => {
 }
 
 .tab {
+	display: flex;
+	align-items: center;
+	justify-content: center;
 	flex: 1;
 	padding: 12px 8px;
 	border-top: solid 2px transparent;
 	border-bottom: solid 2px transparent;
+
+	> i {
+		margin-right: 8px;
+	}
 }
 
 .tabActive {

From 02c9c420755ae9d9c3cf88d2c39dc8995435daa3 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Mon, 29 Jan 2024 00:11:09 +0300
Subject: [PATCH 05/17] fix: links triggering clickToOpen

---
 packages/frontend/src/components/MkLink.vue       | 1 +
 packages/frontend/src/components/global/MkUrl.vue | 1 +
 2 files changed, 2 insertions(+)

diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue
index bda683002d..a2e95fb690 100644
--- a/packages/frontend/src/components/MkLink.vue
+++ b/packages/frontend/src/components/MkLink.vue
@@ -7,6 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <component
 	:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel ?? 'nofollow noopener'" :target="target"
 	:title="url"
+	@click.stop
 >
 	<slot></slot>
 	<i v-if="target === '_blank'" class="ph-arrow-square-out ph-bold ph-lg" :class="$style.icon"></i>
diff --git a/packages/frontend/src/components/global/MkUrl.vue b/packages/frontend/src/components/global/MkUrl.vue
index 667a113432..552253d35e 100644
--- a/packages/frontend/src/components/global/MkUrl.vue
+++ b/packages/frontend/src/components/global/MkUrl.vue
@@ -7,6 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <component
 	:is="self ? 'MkA' : 'a'" ref="el" :class="$style.root" class="_link" :[attr]="self ? props.url.substring(local.length) : props.url" :rel="rel ?? 'nofollow noopener'" :target="target"
 	@contextmenu.stop="() => {}"
+	@click.stop
 >
 	<template v-if="!self">
 		<span :class="$style.schema">{{ schema }}//</span>

From cd52686fd30da4d84b460946a093bf8593b035b2 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Wed, 31 Jan 2024 15:20:41 +0300
Subject: [PATCH 06/17] fix: click to open on quotes

---
 packages/frontend/src/components/MkNote.vue           | 2 +-
 packages/frontend/src/components/MkSubNoteContent.vue | 6 +++---
 packages/frontend/src/components/SkNote.vue           | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index bdad1fc1fe..4842ab2f1a 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -49,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
 		<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
 		<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!mock"/>
-		<div :class="[$style.main, { [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
+		<div :class="[$style.main, { [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
 			<MkNoteHeader :note="appearNote" :mini="true" @click.stop/>
 			<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
 			<div style="container-type: inline-size;">
diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue
index 038f5aa30d..dfaa583d6f 100644
--- a/packages/frontend/src/components/MkSubNoteContent.vue
+++ b/packages/frontend/src/components/MkSubNoteContent.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <div :class="[$style.root, { [$style.collapsed]: collapsed }]">
-	<div :class="{ [$style.clickToOpen]: defaultStore.state.clickToOpen }" @click="defaultStore.state.clickToOpen ? noteclick(note.id) : undefined">
+	<div :class="{ [$style.clickToOpen]: defaultStore.state.clickToOpen }" @click.stop="defaultStore.state.clickToOpen ? noteclick(note.id) : undefined">
 		<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
 		<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deletedNote }})</span>
 		<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`" @click.stop><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
@@ -29,10 +29,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<summary>{{ i18n.ts.poll }}</summary>
 		<MkPoll :noteId="note.id" :poll="note.poll"/>
 	</details>
-	<button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click="collapsed = false">
+	<button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click.stop="collapsed = false">
 		<span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span>
 	</button>
-	<button v-else-if="isLong && !collapsed" :class="$style.showLess" class="_button" @click="collapsed = true">
+	<button v-else-if="isLong && !collapsed" :class="$style.showLess" class="_button" @click.stop="collapsed = true">
 		<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
 	</button>
 </div>
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 4e224d2e6d..704c31e92a 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<SkNoteHeader :note="appearNote" :mini="true"/>
 			</div>
 		</div>
-		<div :class="[{ [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
+		<div :class="[{ [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
 			<div style="container-type: inline-size;">
 				<p v-if="appearNote.cw != null" :class="$style.cw">
 					<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'respect'"/>

From bc993187075f2a355ebc8a323d73196a324a089d Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Wed, 31 Jan 2024 16:01:14 +0300
Subject: [PATCH 07/17] fix: mentions wrapping

---
 packages/frontend/src/components/MkMention.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/frontend/src/components/MkMention.vue b/packages/frontend/src/components/MkMention.vue
index 4d42053657..8aeacd361e 100644
--- a/packages/frontend/src/components/MkMention.vue
+++ b/packages/frontend/src/components/MkMention.vue
@@ -51,6 +51,7 @@ const avatarUrl = computed(() => defaultStore.state.disableShowingAnimatedImages
 	padding: 4px 8px 4px 4px;
 	border-radius: var(--radius-ellipse);
 	color: var(--mention);
+	white-space: nowrap;
 
 	&.isMe {
 		color: var(--mentionMe);

From 44a82494041ac5d38ec5e4d0c7ac22f75dc70c71 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Wed, 31 Jan 2024 17:07:29 +0300
Subject: [PATCH 08/17] fix: blue highlight on chromium when using click to
 open

---
 packages/frontend/src/components/MkNote.vue           | 1 +
 packages/frontend/src/components/MkSubNoteContent.vue | 1 +
 packages/frontend/src/components/SkNote.vue           | 1 +
 3 files changed, 3 insertions(+)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 4842ab2f1a..aee74138c2 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -1278,5 +1278,6 @@ function emitUpdReaction(emoji: string, delta: number) {
 
 .clickToOpen {
 	cursor: pointer;
+	-webkit-tap-highlight-color: transparent;
 }
 </style>
diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue
index dfaa583d6f..852fb8cc99 100644
--- a/packages/frontend/src/components/MkSubNoteContent.vue
+++ b/packages/frontend/src/components/MkSubNoteContent.vue
@@ -165,5 +165,6 @@ const collapsed = ref(isLong);
 
 .clickToOpen {
 	cursor: pointer;
+	-webkit-tap-highlight-color: transparent;
 }
 </style>
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 704c31e92a..0e00b60daf 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -1312,5 +1312,6 @@ function emitUpdReaction(emoji: string, delta: number) {
 
 .clickToOpen {
 	cursor: pointer;
+	-webkit-tap-highlight-color: transparent;
 }
 </style>

From 1baec59efdc1b5f96af8823db283bf266afe1d44 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Fri, 2 Feb 2024 13:02:26 +0300
Subject: [PATCH 09/17] fix: missing icon in MkMediaVideo

---
 packages/frontend/src/components/MkMediaVideo.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index 04a424e0fe..b2609193fa 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<i class="ph-download ph-bold ph-lg"></i>
 				</a>
 				<button class="_button" :class="$style.controlButton" @click="showMenu">
-					<i class="ph-settings ph-bold ph-lg"></i>
+					<i class="ph-gear ph-bold ph-lg"></i>
 				</button>
 				<button class="_button" :class="$style.controlButton" @click="toggleFullscreen">
 					<i v-if="isFullscreen" class="ph-arrows-in ph-bold ph-lg"></i>

From 1bc2da2bda00c802efd85421f51884a075e059e5 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sun, 28 Jan 2024 18:20:59 +0300
Subject: [PATCH 10/17] upd: make avatars smaller on replies to allow more
 space for text

i'm unsure about the batch of @container blocks at the end of the CSS,
they seem like leftovers from a previous implementation. removing them
didn't seem to change anything but i may be overlooking something.
---
 .../src/components/SkNoteDetailed.vue         |  4 +-
 .../frontend/src/components/SkNoteSub.vue     | 50 ++++---------------
 2 files changed, 13 insertions(+), 41 deletions(-)

diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 0681ddc6c8..cf54d9d50e 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -178,7 +178,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<div v-if="!repliesLoaded" style="padding: 16px">
 				<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
 			</div>
-			<SkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply"/>
+			<SkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :reply="true"/>
 		</div>
 		<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
 			<MkPagination :pagination="renotesPagination" :disableAutoLoad="true">
@@ -195,7 +195,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<div v-if="!quotesLoaded" style="padding: 16px">
 				<MkButton style="margin: 0 auto;" primary rounded @click="loadQuotes">{{ i18n.ts.loadReplies }}</MkButton>
 			</div>
-			<SkNoteSub v-for="note in quotes" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws"/>
+			<SkNoteSub v-for="note in quotes" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :reply="true"/>
 		</div>
 		<div v-else-if="tab === 'reactions'" :class="$style.tab_reactions">
 			<div :class="$style.reactionTabs">
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 363dcef348..164f4e883a 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1 }]">
+<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.replyRoot]: props.reply }]">
 	<div v-if="!hideLine" :class="$style.line"></div>
 	<div :class="$style.main">
 		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
@@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</div>
 	<template v-if="depth < numberOfReplies">
-		<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply"/>
+		<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :reply="props.reply"/>
 	</template>
 	<div v-else :class="$style.more">
 		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
@@ -125,8 +125,11 @@ const props = withDefaults(defineProps<{
 
 	// how many notes are in between this one and the note being viewed in detail
 	depth?: number;
+
+	reply?: boolean;
 }>(), {
 	depth: 1,
+	reply: false,
 });
 
 const el = shallowRef<HTMLElement>();
@@ -439,7 +442,11 @@ if (props.detail) {
 	--reply-indent: calc(.5 * var(--avatar));
 
 	&.children {
-		padding: 10px 0 0 16px;
+		padding: 10px 0 0 8px;
+	}
+
+	&.replyRoot {
+		--avatar: 36px;
 	}
 }
 
@@ -478,7 +485,7 @@ if (props.detail) {
 		transition: opacity .2s, background .2s;
 		z-index: -1;
 	}
-	
+
 	&:hover::after,
 	&:focus-within::after {
 		opacity: 1;
@@ -610,10 +617,6 @@ if (props.detail) {
 @container (max-width: 480px) {
 	.root {
 		padding: 22px 24px;
-
-		&.children {
-			padding: 10px 0 0 8px;
-		}
 	}
 
 	.line {
@@ -683,35 +686,4 @@ if (props.detail) {
 		border-bottom: unset;
 	}
 }
-
-@container (max-width: 580px) {
-	.threadLine, .reply {
-		margin-left: 25px;
-	}
-	.reply::before {
-		height: 45px;
-	}
-	.single::before {
-		left: 25px;
-	}
-	.single {
-		margin-left: 0;
-	}
-}
-
-@container (max-width: 450px) {
-	.threadLine, .reply {
-		margin-left: 23px;
-	}
-	.reply::before {
-		height: 43px;
-	}
-	.single::before {
-		left: 23px;
-		width: 9px;
-	}
-	.single {
-		margin-left: 0;
-	}
-}
 </style>

From 3818e9531f35214b136b3b50daa52e8724874a08 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sat, 6 Jan 2024 19:28:38 +0300
Subject: [PATCH 11/17] upd: make note footer wider on smaller screens

https://git.gay/eepy.zone/Sharkey/commit/3cc8320eb7d840e2a1bf458d4adfd8f41ac43e26

Co-authored-by: blueb <ihateblueb@proton.me>
---
 packages/frontend/src/components/MkNote.vue   |  7 +++---
 packages/frontend/src/components/SkNote.vue   |  7 +++---
 .../src/components/SkNoteDetailed.vue         | 25 ++++++++++---------
 .../frontend/src/components/SkNoteSub.vue     | 13 ++++------
 4 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index aee74138c2..fa35c59aaf 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -854,12 +854,13 @@ function emitUpdReaction(emoji: string, delta: number) {
 	}
 
 	.footer {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
 		position: relative;
 		z-index: 1;
 		margin-top: 0.4em;
-		width: max-content;
-		min-width: min-content;
-		max-width: fit-content;
+		max-width: 400px;
 	}
 
 	&:hover > .article > .main > .footer > .footerButton {
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 0e00b60daf..0bad3fd61d 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -855,12 +855,13 @@ function emitUpdReaction(emoji: string, delta: number) {
 	}
 
 	.footer {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
 		position: relative;
 		z-index: 1;
 		margin-top: 0.4em;
-		width: max-content;
-		min-width: min-content;
-		max-width: fit-content;
+		max-width: 400px;
 	}
 
 	&:hover > .article > .main > .footer > .footerButton {
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index cf54d9d50e..18cba35c0a 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -112,16 +112,16 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</div>
 			<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
 		</div>
-		<footer :class="$style.footer">
-			<div :class="$style.noteFooterInfo">
-				<div v-if="appearNote.updatedAt">
-					{{ i18n.ts.edited }}: <MkTime :time="appearNote.updatedAt" mode="detail"/>
-				</div>
-				<MkA :to="notePage(appearNote)">
-					<MkTime :time="appearNote.createdAt" mode="detail" colored/>
-				</MkA>
+		<div :class="$style.noteFooterInfo">
+			<div v-if="appearNote.updatedAt">
+				{{ i18n.ts.edited }}: <MkTime :time="appearNote.updatedAt" mode="detail"/>
 			</div>
-			<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
+			<MkA :to="notePage(appearNote)">
+				<MkTime :time="appearNote.createdAt" mode="detail" colored/>
+			</MkA>
+		</div>
+		<MkReactionsViewer ref="reactionsViewer" :note="appearNote"/>
+		<footer :class="$style.footer">
 			<button class="_button" :class="$style.noteFooterButton" @click="reply()">
 				<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 				<p v-if="appearNote.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ appearNote.repliesCount }}</p>
@@ -836,12 +836,13 @@ onUnmounted(() => {
 }
 
 .footer {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
 		position: relative;
 		z-index: 1;
 		margin-top: 0.4em;
-		width: max-content;
-		min-width: min-content;
-		max-width: fit-content;
+		max-width: 400px;
 }
 
 .replyTo {
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 164f4e883a..01ba5138e6 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -27,8 +27,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<MkSubNoteContent :class="$style.text" :note="note" :translating="translating" :translation="translation"/>
 				</div>
 			</div>
+			<MkReactionsViewer ref="reactionsViewer" :note="note"/>
 			<footer :class="$style.footer">
-				<MkReactionsViewer ref="reactionsViewer" :note="note"/>
 				<button class="_button" :class="$style.noteFooterButton" @click="reply()">
 					<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
 					<p v-if="note.repliesCount > 0" :class="$style.noteFooterButtonCount">{{ note.repliesCount }}</p>
@@ -460,12 +460,13 @@ if (props.detail) {
 }
 
 .footer {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
 	position: relative;
 	z-index: 1;
 	margin-top: 0.4em;
-	width: max-content;
-	min-width: min-content;
-	max-width: fit-content;
+	max-width: 400px;
 }
 
 .main {
@@ -535,10 +536,6 @@ if (props.detail) {
 	padding-top: 10px;
 	opacity: 0.7;
 
-	&:not(:last-child) {
-		margin-right: 1.5em;
-	}
-
 	&:hover {
 		color: var(--fgHighlighted);
 	}

From 7461332d0f61a96405c1bb62ef2c72f928642eea Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Fri, 2 Feb 2024 14:14:04 +0300
Subject: [PATCH 12/17] upd: add hover effect to quote posts

---
 packages/frontend/src/components/SkNoteSimple.vue | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/packages/frontend/src/components/SkNoteSimple.vue b/packages/frontend/src/components/SkNoteSimple.vue
index fe12baedeb..1eb685dbb5 100644
--- a/packages/frontend/src/components/SkNoteSimple.vue
+++ b/packages/frontend/src/components/SkNoteSimple.vue
@@ -48,6 +48,11 @@ watch(() => props.expandAllCws, (expandAllCws) => {
 	margin: 0;
 	padding: 0;
 	font-size: 0.95em;
+
+	&:hover, &:focus-within {
+		background: var(--panelHighlight);
+		transition: background .2s;
+	}
 }
 
 .avatar {

From bffac25c57807836798f9233af142bbe1e1746d3 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Fri, 2 Feb 2024 14:40:02 +0300
Subject: [PATCH 13/17] upd: smoothly resize reply avatars depending on
 container size

---
 packages/frontend/src/components/SkNoteSub.vue | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 01ba5138e6..51812e8cf4 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -446,7 +446,8 @@ if (props.detail) {
 	}
 
 	&.replyRoot {
-		--avatar: 36px;
+		/* @link https://utopia.fyi/clamp/calculator?a=450,580,26—36 */
+		--avatar: clamp(26px, -8.6154px + 7.6923cqi, 36px);
 	}
 }
 

From c61adcf61d6e8f3a4967dc237739a026ea96d9f6 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sat, 3 Feb 2024 14:55:20 +0300
Subject: [PATCH 14/17] upd: expandAllCws also expands all long posts on first
 click

this mimics glitch-soc behavior
---
 packages/frontend/src/components/MkNoteSimple.vue     | 2 +-
 packages/frontend/src/components/MkNoteSub.vue        | 2 +-
 packages/frontend/src/components/MkSubNoteContent.vue | 7 ++++++-
 packages/frontend/src/components/SkNoteSimple.vue     | 2 +-
 packages/frontend/src/components/SkNoteSub.vue        | 2 +-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/packages/frontend/src/components/MkNoteSimple.vue b/packages/frontend/src/components/MkNoteSimple.vue
index 7a6109ee0b..e4c90acdd2 100644
--- a/packages/frontend/src/components/MkNoteSimple.vue
+++ b/packages/frontend/src/components/MkNoteSimple.vue
@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
 			</p>
 			<div v-show="note.cw == null || showContent">
-				<MkSubNoteContent :hideFiles="hideFiles" :class="$style.text" :note="note"/>
+				<MkSubNoteContent :hideFiles="hideFiles" :class="$style.text" :note="note" :expandAllCws="props.expandAllCws"/>
 			</div>
 		</div>
 	</div>
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 6deb1b855d..bb30fe53cf 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
 				</p>
 				<div v-show="note.cw == null || showContent">
-					<MkSubNoteContent :class="$style.text" :note="note" :translating="translating" :translation="translation"/>
+					<MkSubNoteContent :class="$style.text" :note="note" :translating="translating" :translation="translation" :expandAllCws="props.expandAllCws"/>
 				</div>
 			</div>
 			<footer :class="$style.footer">
diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue
index 852fb8cc99..c4daf3403f 100644
--- a/packages/frontend/src/components/MkSubNoteContent.vue
+++ b/packages/frontend/src/components/MkSubNoteContent.vue
@@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
 import * as Misskey from 'misskey-js';
 import * as mfm from '@transfem-org/sfm-js';
 import MkMediaList from '@/components/MkMediaList.vue';
@@ -57,6 +57,7 @@ const props = defineProps<{
 	translating?: boolean;
 	translation?: any;
 	hideFiles?: boolean;
+	expandAllCws?: boolean;
 }>();
 
 const router = useRouter();
@@ -87,6 +88,10 @@ function animatedMFM() {
 }
 
 const collapsed = ref(isLong);
+
+watch(() => props.expandAllCws, (expandAllCws) => {
+	if (expandAllCws) collapsed.value = false;
+});
 </script>
 
 <style lang="scss" module>
diff --git a/packages/frontend/src/components/SkNoteSimple.vue b/packages/frontend/src/components/SkNoteSimple.vue
index 1eb685dbb5..533aa60961 100644
--- a/packages/frontend/src/components/SkNoteSimple.vue
+++ b/packages/frontend/src/components/SkNoteSimple.vue
@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll" @click.stop/>
 			</p>
 			<div v-show="note.cw == null || showContent">
-				<MkSubNoteContent :hideFiles="hideFiles" :class="$style.text" :note="note"/>
+				<MkSubNoteContent :hideFiles="hideFiles" :class="$style.text" :note="note" :expandAllCws="props.expandAllCws"/>
 			</div>
 		</div>
 	</div>
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 51812e8cf4..8d76c1e22c 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<MkCwButton v-model="showContent" :text="note.text" :files="note.files" :poll="note.poll"/>
 				</p>
 				<div v-show="note.cw == null || showContent">
-					<MkSubNoteContent :class="$style.text" :note="note" :translating="translating" :translation="translation"/>
+					<MkSubNoteContent :class="$style.text" :note="note" :translating="translating" :translation="translation" :expandAllCws="props.expandAllCws"/>
 				</div>
 			</div>
 			<MkReactionsViewer ref="reactionsViewer" :note="note"/>

From 5ef8e3123bbc7ff1f28204a7bcd3f04db473e802 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sat, 3 Feb 2024 15:22:12 +0300
Subject: [PATCH 15/17] upd: only enable hover effect on SkNoteDetailed and
 replies

---
 packages/frontend/src/components/SkNoteDetailed.vue |  6 +++---
 packages/frontend/src/components/SkNoteSub.vue      | 10 ++++++----
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 18cba35c0a..5b28a2e8eb 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -40,9 +40,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</div>
 	<template v-if="appearNote.reply && appearNote.reply.replyId">
-		<SkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note" :expandAllCws="props.expandAllCws"/>
+		<SkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note" :expandAllCws="props.expandAllCws" detailed/>
 	</template>
-	<SkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws"/>
+	<SkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws" detailed/>
 	<article :id="appearNote.id" ref="noteEl" :class="$style.note" tabindex="-1" @contextmenu.stop="onContextmenu">
 		<header :class="$style.noteHeader">
 			<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
@@ -850,7 +850,7 @@ onUnmounted(() => {
 }
 
 .replyToMore {
-	
+
 }
 
 .renote {
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 8d76c1e22c..ceb0057d63 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.replyRoot]: props.reply }]">
+<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.replyRoot]: props.reply, [$style.detailed]: props.detailed }]">
 	<div v-if="!hideLine" :class="$style.line"></div>
 	<div :class="$style.main">
 		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
@@ -127,9 +127,11 @@ const props = withDefaults(defineProps<{
 	depth?: number;
 
 	reply?: boolean;
+	detailed?: boolean;
 }>(), {
 	depth: 1,
 	reply: false,
+	detailed: false,
 });
 
 const el = shallowRef<HTMLElement>();
@@ -474,7 +476,7 @@ if (props.detail) {
 	position: relative;
 	display:  flex;
 
-	&::after {
+	:is(.detailed, .replyRoot) &::after {
 		content: "";
 		position: absolute;
 		top: -12px;
@@ -488,8 +490,8 @@ if (props.detail) {
 		z-index: -1;
 	}
 
-	&:hover::after,
-	&:focus-within::after {
+	:is(.detailed, .replyRoot) &:hover::after,
+	:is(.detailed, .replyRoot) &:focus-within::after {
 		opacity: 1;
 	}
 }

From 3107345d3ce8d2f42892b0c082a082b90cae7e5e Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sun, 4 Feb 2024 15:02:03 +0300
Subject: [PATCH 16/17] fix: local instance ticker bug that fails to render
 notes in dev mode

---
 packages/frontend/src/index.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/frontend/src/index.html b/packages/frontend/src/index.html
index 097c0080ae..68866b36e1 100644
--- a/packages/frontend/src/index.html
+++ b/packages/frontend/src/index.html
@@ -27,6 +27,7 @@
 	/>
 	<meta property="og:site_name" content="[DEV BUILD] Misskey" />
 	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<meta name="theme-color-orig" content="#86b300">
 </head>
 
 <body>

From 592f77371f3cc49a10edc46d9b0a06f05a1d2d51 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sun, 4 Feb 2024 15:20:11 +0300
Subject: [PATCH 17/17] upd: rename SkNoteSub property

---
 packages/frontend/src/components/SkNoteDetailed.vue |  2 +-
 packages/frontend/src/components/SkNoteSub.vue      | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 5b28a2e8eb..d88c779974 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -178,7 +178,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<div v-if="!repliesLoaded" style="padding: 16px">
 				<MkButton style="margin: 0 auto;" primary rounded @click="loadReplies">{{ i18n.ts.loadReplies }}</MkButton>
 			</div>
-			<SkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :reply="true"/>
+			<SkNoteSub v-for="note in replies" :key="note.id" :note="note" :class="$style.reply" :detail="true" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="true"/>
 		</div>
 		<div v-else-if="tab === 'renotes'" :class="$style.tab_renotes">
 			<MkPagination :pagination="renotesPagination" :disableAutoLoad="true">
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index ceb0057d63..6eec2da57d 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.replyRoot]: props.reply, [$style.detailed]: props.detailed }]">
+<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.isReply]: props.isReply, [$style.detailed]: props.detailed }]">
 	<div v-if="!hideLine" :class="$style.line"></div>
 	<div :class="$style.main">
 		<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
@@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</div>
 	<template v-if="depth < numberOfReplies">
-		<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :reply="props.reply"/>
+		<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="props.isReply"/>
 	</template>
 	<div v-else :class="$style.more">
 		<MkA class="_link" :to="notePage(note)">{{ i18n.ts.continueThread }} <i class="ph-caret-double-right ph-bold ph-lg"></i></MkA>
@@ -126,11 +126,11 @@ const props = withDefaults(defineProps<{
 	// how many notes are in between this one and the note being viewed in detail
 	depth?: number;
 
-	reply?: boolean;
+	isReply?: boolean;
 	detailed?: boolean;
 }>(), {
 	depth: 1,
-	reply: false,
+	isReply: false,
 	detailed: false,
 });
 
@@ -447,7 +447,7 @@ if (props.detail) {
 		padding: 10px 0 0 8px;
 	}
 
-	&.replyRoot {
+	&.isReply {
 		/* @link https://utopia.fyi/clamp/calculator?a=450,580,26—36 */
 		--avatar: clamp(26px, -8.6154px + 7.6923cqi, 36px);
 	}