From f92f474088696f4379650f6a03688b44eb934632 Mon Sep 17 00:00:00 2001
From: Volpeon <git@volpeon.ink>
Date: Mon, 1 Jan 2024 17:44:13 +0100
Subject: Bring note style closer to Firefish

---
 packages/frontend/src/components/SkNoteSub.vue | 59 +++++++++++++-------------
 1 file changed, 30 insertions(+), 29 deletions(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index bc482294b4..0fb6e00ab1 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -426,22 +426,22 @@ if (props.detail) {
 <style lang="scss" module>
 .root {
 	padding: 28px 32px;
-	font-size: 0.9em;
 	position: relative;
 
+	--reply-indent: calc(.5 * var(--avatar));
+
 	&.children {
 		padding: 10px 0 0 16px;
-		font-size: 1em;
 	}
 }
 
 .line {
 	position: absolute;
-	height: calc(100% - 58px); // 58px of avatar height (see SkNote)
-	left: 60px;
+	left: calc(32px + .5 * var(--avatar));
 	// using solid instead of dotted, stylelistic choice
-	border-left: 2.5px solid rgb(174, 174, 174);
-	top: 86px; // 28px of .root padding, plus 58px of avatar height (see SkNote)
+	border-left: var(--thread-width) solid var(--thread);
+	top: calc(28px + var(--avatar)); // 28px of .root padding, plus 58px of avatar height (see SkNote)
+	bottom: -28px;
 }
 
 .footer {
@@ -471,8 +471,8 @@ if (props.detail) {
 	flex-shrink: 0;
 	display: block;
 	margin: 0 14px 0 0;
-	width: 58px;
-	height: 58px;
+	width: var(--avatar);
+	height: var(--avatar);
 	border-radius: var(--radius-sm);
 }
 
@@ -521,15 +521,11 @@ if (props.detail) {
 @container (max-width: 580px) {
 	.root {
 		padding: 28px 26px 0;
+		--avatar: 46px;
 	}
 
 	.line {
-		left: 50.5px;
-	}
-
-	.avatar {
-		width: 50px;
-		height: 50px;
+		left: calc(26px + .5 * var(--avatar));
 	}
 }
 
@@ -537,6 +533,11 @@ if (props.detail) {
 	.root {
 		padding: 23px 25px;
 	}
+
+	.line {
+		top: calc(23px + var(--avatar));
+		left: calc(25px + .5 * var(--avatar));
+	}
 }
 
 @container (max-width: 400px) {
@@ -586,16 +587,16 @@ if (props.detail) {
 			padding: 10px 0 0 8px;
 		}
 	}
-}
 
-@container (max-width: 450px) {
 	.line {
-		left: 46px;
+		top: calc(22px + var(--avatar));
+		left: calc(24px + .5 * var(--avatar));
 	}
+}
 
-	.avatar {
-		width: 46px;
-		height: 46px;
+@container (max-width: 450px) {
+	.root {
+		--avatar: 44px;
 	}
 }
 
@@ -616,19 +617,19 @@ if (props.detail) {
 .threadLine {
 	width: 0;
 	flex-grow: 1;
-	border-left: 2.5px solid rgb(174, 174, 174);
-	margin-left: 29px;
+	border-left: var(--thread-width) solid var(--thread);
+	margin-left: var(--reply-indent);
 }
 
 .reply {
-	margin-left: 29px;
+	margin-left: var(--reply-indent);
 }
 
 .reply:not(:last-child) {
-	border-left: 2.5px solid rgb(174, 174, 174);
+	border-left: var(--thread-width) solid var(--thread);
 
 	&::before {
-		left: -2px;
+		left: calc(-1 * var(--thread-width));
 	}
 }
 
@@ -637,10 +638,10 @@ if (props.detail) {
 	content: '';
 	left: 0px;
 	top: -10px;
-	height: 49px;
+	height: calc(10px + 10px + .5 * var(--avatar));
 	width: 15px;
-	border-left: 2.5px solid rgb(174, 174, 174);
-	border-bottom: 2.5px solid rgb(174, 174, 174);
+	border-left: var(--thread-width) solid var(--thread);
+	border-bottom: var(--thread-width) solid var(--thread);
 	border-bottom-left-radius: 15px;
 }
 
@@ -649,7 +650,7 @@ if (props.detail) {
 	padding-left: 0 !important;
 
 	&::before {
-		left: 29px;
+		left: var(--reply-indent);
 		width: 0;
 		border-bottom: unset;
 	}
-- 
cgit v1.2.3-freya


From c9ca1dd3f13cfe6211fbc313d84f44e26a424dd7 Mon Sep 17 00:00:00 2001
From: Marie <marie@kaifa.ch>
Date: Mon, 1 Jan 2024 20:34:18 +0100
Subject: upd: add boost settings

---
 packages/frontend/src/components/MkNote.vue        | 64 ++++++++++++----------
 .../frontend/src/components/MkNoteDetailed.vue     | 64 ++++++++++++----------
 packages/frontend/src/components/MkNoteSub.vue     | 64 ++++++++++++----------
 packages/frontend/src/components/SkNote.vue        | 64 ++++++++++++----------
 .../frontend/src/components/SkNoteDetailed.vue     | 64 ++++++++++++----------
 packages/frontend/src/components/SkNoteSub.vue     | 64 ++++++++++++----------
 packages/frontend/src/pages/settings/general.vue   | 21 +++++++
 packages/frontend/src/store.ts                     |  8 +++
 8 files changed, 233 insertions(+), 180 deletions(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 6274419c54..1f69307dea 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -399,39 +399,43 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi
 }
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: Visibility | 'local') {
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 6558e24630..4da72898a4 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -441,39 +441,43 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi
 }
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: Visibility | 'local') {
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index d96785a2d9..2d2044ce07 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -269,39 +269,43 @@ watch(() => props.expandAllCws, (expandAllCws) => {
 });
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'local') {
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 10c7c72e61..e2f4660ad6 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -400,39 +400,43 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi
 }
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: Visibility | 'local') {
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 6bd5d77442..ba53991646 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -449,39 +449,43 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi
 }
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: Visibility | 'local') {
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 0fb6e00ab1..d978edd5a6 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -278,39 +278,43 @@ watch(() => props.expandAllCws, (expandAllCws) => {
 });
 
 function boostVisibility() {
-	os.popupMenu([
-		{
-			type: 'button',
-			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-			text: i18n.ts._visibility['public'],
-			action: () => {
-				renote('public');
-			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-house ph-bold ph-lg',
-			text: i18n.ts._visibility['home'],
-			action: () => {
-				renote('home');
+	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+		renote(defaultStore.state.visibilityOnBoost);
+	} else {
+		os.popupMenu([
+			{
+				type: 'button',
+				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+				text: i18n.ts._visibility['public'],
+				action: () => {
+					renote('public');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-lock ph-bold ph-lg',
-			text: i18n.ts._visibility['followers'],
-			action: () => {
-				renote('followers');
+			{
+				type: 'button',
+				icon: 'ph-house ph-bold ph-lg',
+				text: i18n.ts._visibility['home'],
+				action: () => {
+					renote('home');
+				},
 			},
-		},
-		{
-			type: 'button',
-			icon: 'ph-planet ph-bold ph-lg',
-			text: i18n.ts._timelines.local,
-			action: () => {
-				renote('local');
+			{
+				type: 'button',
+				icon: 'ph-lock ph-bold ph-lg',
+				text: i18n.ts._visibility['followers'],
+				action: () => {
+					renote('followers');
+				},
 			},
-		}], renoteButton.value);
+			{
+				type: 'button',
+				icon: 'ph-planet ph-bold ph-lg',
+				text: i18n.ts._timelines.local,
+				action: () => {
+					renote('local');
+				},
+			}], renoteButton.value);
+	}
 }
 
 function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'local') {
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
index 8eacdd32e6..170ca8936b 100644
--- a/packages/frontend/src/pages/settings/general.vue
+++ b/packages/frontend/src/pages/settings/general.vue
@@ -190,6 +190,23 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<template #caption>{{ i18n.ts.numberOfPageCacheDescription }}</template>
 			</MkRange>
 
+			<MkFolder>
+				<template #label>Boost Settings</template>
+				<div class="_gaps_m">
+					<MkSwitch v-model="showVisibilitySelectorOnBoost">
+						Disable Visibility Selector
+						<template #caption>Disables the visiblity selector when clicking boost and uses the default visiblity defined</template>
+					</MkSwitch>
+					<MkSelect v-model="visibilityOnBoost">
+						<template #label>Default boost visibility</template>
+						<option value="public">{{ i18n.ts._visibility['public'] }}</option>
+						<option value="home">{{ i18n.ts._visibility['home'] }}</option>
+						<option value="followers">{{ i18n.ts._visibility['followers'] }}</option>
+						<option value="local">{{ i18n.ts._timelines.local }}</option>
+					</MkSelect>
+				</div>
+			</MkFolder>
+
 			<MkFolder>
 				<template #label>{{ i18n.ts.dataSaver }}</template>
 
@@ -326,6 +343,8 @@ const noteDesign = computed(defaultStore.makeGetterSetter('noteDesign'));
 const uncollapseCW = computed(defaultStore.makeGetterSetter('uncollapseCW'));
 const expandLongNote = computed(defaultStore.makeGetterSetter('expandLongNote'));
 const enableSeasonalScreenEffect = computed(defaultStore.makeGetterSetter('enableSeasonalScreenEffect'));
+const showVisibilitySelectorOnBoost = computed(defaultStore.makeGetterSetter('showVisibilitySelectorOnBoost'));
+const visibilityOnBoost = computed(defaultStore.makeGetterSetter('visibilityOnBoost'));
 
 watch(lang, () => {
 	miLocalStorage.setItem('lang', lang.value as string);
@@ -381,6 +400,8 @@ watch([
 	keepScreenOn,
 	disableStreamingTimeline,
 	enableSeasonalScreenEffect,
+	showVisibilitySelectorOnBoost,
+	visibilityOnBoost,
 ], async () => {
 	await reloadAsk();
 });
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index 18cfad2102..c60dfb9388 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -151,6 +151,14 @@ export const defaultStore = markRaw(new Storage('base', {
 		where: 'account',
 		default: true,
 	},
+	showVisibilitySelectorOnBoost: {
+		where: 'account',
+		default: true,
+	},
+	visibilityOnBoost: {
+		where: 'account',
+		default: 'public' as 'public' | 'home' | 'followers' | 'local',
+	},
 
 	menu: {
 		where: 'deviceAccount',
-- 
cgit v1.2.3-freya


From b87142d2f7ddc1aa5f4bd615726d689d83ec7b22 Mon Sep 17 00:00:00 2001
From: Marie <marie@kaifa.ch>
Date: Tue, 2 Jan 2024 00:47:08 +0100
Subject: fix: like button not playing reaction sound

---
 packages/frontend/src/components/MkNote.vue         | 1 +
 packages/frontend/src/components/MkNoteDetailed.vue | 1 +
 packages/frontend/src/components/MkNoteSub.vue      | 1 +
 packages/frontend/src/components/SkNote.vue         | 1 +
 packages/frontend/src/components/SkNoteDetailed.vue | 1 +
 packages/frontend/src/components/SkNoteSub.vue      | 1 +
 6 files changed, 6 insertions(+)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 1f69307dea..426307be49 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -562,6 +562,7 @@ function reply(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	if (props.mock) {
 		return;
 	}
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 4da72898a4..537a99dc01 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -628,6 +628,7 @@ function react(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	os.api('notes/like', {
 		noteId: appearNote.value.id,
 		override: defaultLike.value,
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 2d2044ce07..08423219f7 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -224,6 +224,7 @@ function react(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	os.api('notes/like', {
 		noteId: props.note.id,
 		override: defaultLike.value,
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index e2f4660ad6..b98e20bad6 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -563,6 +563,7 @@ function reply(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	if (props.mock) {
 		return;
 	}
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index ba53991646..ca3e8ca3f7 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -636,6 +636,7 @@ function react(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	os.api('notes/like', {
 		noteId: appearNote.value.id,
 		override: defaultLike.value,
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index d978edd5a6..8350e7154a 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -233,6 +233,7 @@ function react(viaKeyboard = false): void {
 function like(): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	os.api('notes/like', {
 		noteId: props.note.id,
 		override: defaultLike.value,
-- 
cgit v1.2.3-freya


From 0197d3354a596b2e326e5ed3485045c7c569c070 Mon Sep 17 00:00:00 2001
From: Marie <marie@kaifa.ch>
Date: Tue, 2 Jan 2024 12:32:49 +0100
Subject: fix: lint

---
 packages/frontend/src/components/MkNoteSub.vue | 2 ++
 packages/frontend/src/components/SkNoteSub.vue | 2 ++
 2 files changed, 4 insertions(+)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 08423219f7..d725ca15af 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -91,6 +91,7 @@ import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
 import MkCwButton from '@/components/MkCwButton.vue';
 import { notePage } from '@/filters/note.js';
 import * as os from '@/os.js';
+import * as sound from '@/scripts/sound.js';
 import { i18n } from '@/i18n.js';
 import { $i } from '@/account.js';
 import { userPage } from '@/filters/user.js';
@@ -193,6 +194,7 @@ function reply(viaKeyboard = false): void {
 function react(viaKeyboard = false): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	if (props.note.reactionAcceptance === 'likeOnly') {
 		os.api('notes/like', {
 			noteId: props.note.id,
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 8350e7154a..79e171f34c 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -99,6 +99,7 @@ import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
 import MkCwButton from '@/components/MkCwButton.vue';
 import { notePage } from '@/filters/note.js';
 import * as os from '@/os.js';
+import * as sound from '@/scripts/sound.js';
 import { i18n } from '@/i18n.js';
 import { $i } from '@/account.js';
 import { userPage } from '@/filters/user.js';
@@ -202,6 +203,7 @@ function reply(viaKeyboard = false): void {
 function react(viaKeyboard = false): void {
 	pleaseLogin();
 	showMovedDialog();
+	sound.play('reaction');
 	if (props.note.reactionAcceptance === 'likeOnly') {
 		os.api('notes/like', {
 			noteId: props.note.id,
-- 
cgit v1.2.3-freya


From 1ca0cd727e3fc14e88f4cc2c60472a2616bf9efa Mon Sep 17 00:00:00 2001
From: Volpeon <git@volpeon.ink>
Date: Wed, 3 Jan 2024 14:42:51 +0100
Subject: Hover effect for conversation notes (like Firefish)

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

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 3087eee164..4a06e8f56a 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<SkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note" :expandAllCws="props.expandAllCws"/>
 	</template>
 	<SkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo" :expandAllCws="props.expandAllCws"/>
-	<article ref="noteEl" :class="$style.note" tabindex="-1" @contextmenu.stop="onContextmenu">
+	<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/>
 			<div style="display: flex; align-items: center; white-space: nowrap; overflow: hidden;">
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 79e171f34c..c0c50670d1 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -461,7 +461,26 @@ if (props.detail) {
 }
 
 .main {
-	display: flex;
+	position: relative;
+	display:  flex;
+
+	&::after {
+		content: "";
+		position: absolute;
+		top: -12px;
+		right: -12px;
+		left: -12px;
+		bottom: -12px;
+		background: var(--panelHighlight);
+		border-radius: var(--radius);
+		opacity: 0;
+		transition: opacity .2s, background .2s;
+		z-index: -1;
+	}
+	
+	&:hover::after {
+		opacity: 1;
+	}
 }
 
 .colorBar {
-- 
cgit v1.2.3-freya


From 96df8c25defce6314066709452708c35062bf85a Mon Sep 17 00:00:00 2001
From: Volpeon <git@volpeon.ink>
Date: Wed, 3 Jan 2024 16:22:36 +0100
Subject: Show conversation note hover effect on focus

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

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index c0c50670d1..8b3ced3761 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -478,7 +478,8 @@ if (props.detail) {
 		z-index: -1;
 	}
 	
-	&:hover::after {
+	&:hover::after,
+	&:focus-within::after {
 		opacity: 1;
 	}
 }
-- 
cgit v1.2.3-freya


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: 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.
---
 .../frontend/src/components/SkNoteDetailed.vue     |  4 +-
 packages/frontend/src/components/SkNoteSub.vue     | 50 +++++-----------------
 2 files changed, 13 insertions(+), 41 deletions(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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>
-- 
cgit v1.2.3-freya


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: 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 +++---
 .../frontend/src/components/SkNoteDetailed.vue     | 25 +++++++++++-----------
 packages/frontend/src/components/SkNoteSub.vue     | 13 +++++------
 4 files changed, 26 insertions(+), 26 deletions(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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);
 	}
-- 
cgit v1.2.3-freya


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: upd: smoothly resize reply avatars depending on container size

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

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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);
 	}
 }
 
-- 
cgit v1.2.3-freya


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: 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(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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"/>
-- 
cgit v1.2.3-freya


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: 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(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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;
 	}
 }
-- 
cgit v1.2.3-freya


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: 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(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

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);
 	}
-- 
cgit v1.2.3-freya


From 27ce301f452cc1a674e2580c8048749fb6dc28e8 Mon Sep 17 00:00:00 2001
From: ShittyKopper <shittykopper@w.on-t.work>
Date: Sun, 4 Feb 2024 16:42:43 +0300
Subject: fix: reply hover effect

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

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 6eec2da57d..1641f8a5a4 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -476,7 +476,7 @@ if (props.detail) {
 	position: relative;
 	display:  flex;
 
-	:is(.detailed, .replyRoot) &::after {
+	:is(.detailed, .isReply) &::after {
 		content: "";
 		position: absolute;
 		top: -12px;
@@ -490,8 +490,8 @@ if (props.detail) {
 		z-index: -1;
 	}
 
-	:is(.detailed, .replyRoot) &:hover::after,
-	:is(.detailed, .replyRoot) &:focus-within::after {
+	:is(.detailed, .isReply) &:hover::after,
+	:is(.detailed, .isReply) &:focus-within::after {
 		opacity: 1;
 	}
 }
-- 
cgit v1.2.3-freya


From aa72db76c4ce5c90ea502aca0ca0cc5d5b18829b Mon Sep 17 00:00:00 2001
From: dakkar <dakkar@thenautilus.net>
Date: Fri, 16 Feb 2024 12:24:35 +0000
Subject: rework boost visibility #388

* only show allowed visibilities
* "local only" is a switch

notice that the backend will limit the visibility, too
---
 packages/frontend/src/components/MkNote.vue        | 60 ++--------------
 .../frontend/src/components/MkNoteDetailed.vue     | 59 ++--------------
 packages/frontend/src/components/MkNoteSub.vue     | 47 +++----------
 packages/frontend/src/components/SkNote.vue        | 60 ++--------------
 .../frontend/src/components/SkNoteDetailed.vue     | 59 ++--------------
 packages/frontend/src/components/SkNoteSub.vue     | 47 +++----------
 packages/frontend/src/pages/settings/general.vue   |  1 -
 packages/frontend/src/scripts/boost-quote.ts       | 81 ++++++++++++++++++++++
 packages/frontend/src/store.ts                     |  2 +-
 9 files changed, 118 insertions(+), 298 deletions(-)
 create mode 100644 packages/frontend/src/scripts/boost-quote.ts

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index ff9bf3c395..158fdc2c36 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -216,6 +216,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
 import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
 import { shouldCollapsed } from '@/scripts/collapsed.js';
 import { useRouter } from '@/router/supplier.js';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const props = withDefaults(defineProps<{
 	note: Misskey.entities.Note;
@@ -407,58 +408,15 @@ if (!props.mock) {
 	}
 }
 
-type Visibility = 'public' | 'home' | 'followers' | 'specified';
-
-// defaultStore.state.visibilityがstringなためstringも受け付けている
-function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
-	if (a === 'specified' || b === 'specified') return 'specified';
-	if (a === 'followers' || b === 'followers') return 'followers';
-	if (a === 'home' || b === 'home') return 'home';
-	// if (a === 'public' || b === 'public')
-	return 'public';
-}
-
 function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: Visibility | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -489,18 +447,10 @@ function renote(visibility: Visibility | 'local') {
 			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 		}
 
-		const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
-		const localOnlySetting = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
-
-		let noteVisibility = visibility === 'local' || visibility === 'specified' ? smallerVisibility(appearNote.value.visibility, configuredVisibility) : smallerVisibility(visibility, configuredVisibility);
-		if (appearNote.value.channel?.isSensitive) {
-			noteVisibility = smallerVisibility(visibility === 'local' || visibility === 'specified' ? appearNote.value.visibility : visibility, 'home');
-		}
-
 		if (!props.mock) {
 			misskeyApi('notes/create', {
-				localOnly: visibility === 'local' ? true : localOnlySetting,
-				visibility: noteVisibility,
+				localOnly: localOnly,
+				visibility: visibility,
 				renoteId: appearNote.value.id,
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index a2e3a747d9..28c1f5d6ff 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -257,6 +257,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
 import MkPagination, { type Paging } from '@/components/MkPagination.vue';
 import MkReactionIcon from '@/components/MkReactionIcon.vue';
 import MkButton from '@/components/MkButton.vue';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const props = defineProps<{
 	note: Misskey.entities.Note;
@@ -429,57 +430,15 @@ useTooltip(quoteButton, async (showing) => {
 	}, {}, 'closed');
 });
 
-type Visibility = 'public' | 'home' | 'followers' | 'specified';
-
-function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
-	if (a === 'specified' || b === 'specified') return 'specified';
-	if (a === 'followers' || b === 'followers') return 'followers';
-	if (a === 'home' || b === 'home') return 'home';
-	// if (a === 'public' || b === 'public')
-	return 'public';
-}
-
 function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: Visibility | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -508,17 +467,9 @@ function renote(visibility: Visibility | 'local') {
 			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 		}
 
-		const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
-		const localOnlySetting = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
-
-		let noteVisibility = visibility === 'local' || visibility === 'specified' ? smallerVisibility(appearNote.value.visibility, configuredVisibility) : smallerVisibility(visibility, configuredVisibility);
-		if (appearNote.value.channel?.isSensitive) {
-			noteVisibility = smallerVisibility(visibility === 'local' || visibility === 'specified' ? appearNote.value.visibility : visibility, 'home');
-		}
-
 		misskeyApi('notes/create', {
-			localOnly: visibility === 'local' ? true : localOnlySetting,
-			visibility: noteVisibility,
+			localOnly: localOnly,
+			visibility: visibility,
 			renoteId: appearNote.value.id,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index bb30fe53cf..6bd99b845c 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -105,6 +105,7 @@ import { reactionPicker } from '@/scripts/reaction-picker.js';
 import { claimAchievement } from '@/scripts/achievements.js';
 import { getNoteMenu } from '@/scripts/get-note-menu.js';
 import { useNoteCapture } from '@/scripts/use-note-capture.js';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
 
@@ -276,43 +277,11 @@ function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -326,8 +295,8 @@ function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'loc
 		}
 
 		misskeyApi('notes/create', {
-			renoteId: props.note.id,
-			channelId: props.note.channelId,
+			renoteId: appearNote.value.id,
+			channelId: appearNote.value.channelId,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
@@ -342,9 +311,9 @@ function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'loc
 		}
 
 		misskeyApi('notes/create', {
-			renoteId: props.note.id,
-			localOnly: visibility === 'local' ? true : false,
-			visibility: visibility === 'local' || visibility === 'specified' ? props.note.visibility : visibility,
+			renoteId: appearNote.value.id,
+			localOnly: localOnly,
+			visibility: visibility,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index dc74c4928d..09decad1a2 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -217,6 +217,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
 import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
 import { shouldCollapsed } from '@/scripts/collapsed.js';
 import { useRouter } from '@/router/supplier.js';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const props = withDefaults(defineProps<{
 	note: Misskey.entities.Note;
@@ -408,58 +409,15 @@ if (!props.mock) {
 	}
 }
 
-type Visibility = 'public' | 'home' | 'followers' | 'specified';
-
-// defaultStore.state.visibilityがstringなためstringも受け付けている
-function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
-	if (a === 'specified' || b === 'specified') return 'specified';
-	if (a === 'followers' || b === 'followers') return 'followers';
-	if (a === 'home' || b === 'home') return 'home';
-	// if (a === 'public' || b === 'public')
-	return 'public';
-}
-
 function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: Visibility | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -490,18 +448,10 @@ function renote(visibility: Visibility | 'local') {
 			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 		}
 
-		const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
-		const localOnlySetting = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
-
-		let noteVisibility = visibility === 'local' || visibility === 'specified' ? smallerVisibility(appearNote.value.visibility, configuredVisibility) : smallerVisibility(visibility, configuredVisibility);
-		if (appearNote.value.channel?.isSensitive) {
-			noteVisibility = smallerVisibility(visibility === 'local' || visibility === 'specified' ? appearNote.value.visibility : visibility, 'home');
-		}
-
 		if (!props.mock) {
 			misskeyApi('notes/create', {
-				localOnly: visibility === 'local' ? true : localOnlySetting,
-				visibility: noteVisibility,
+				localOnly: localOnly,
+				visibility: visibility,
 				renoteId: appearNote.value.id,
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index ef17a2e8a6..80d6ac369e 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -265,6 +265,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
 import MkPagination, { type Paging } from '@/components/MkPagination.vue';
 import MkReactionIcon from '@/components/MkReactionIcon.vue';
 import MkButton from '@/components/MkButton.vue';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const props = defineProps<{
 	note: Misskey.entities.Note;
@@ -438,57 +439,15 @@ useTooltip(quoteButton, async (showing) => {
 	}, {}, 'closed');
 });
 
-type Visibility = 'public' | 'home' | 'followers' | 'specified';
-
-function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
-	if (a === 'specified' || b === 'specified') return 'specified';
-	if (a === 'followers' || b === 'followers') return 'followers';
-	if (a === 'home' || b === 'home') return 'home';
-	// if (a === 'public' || b === 'public')
-	return 'public';
-}
-
 function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: Visibility | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -517,17 +476,9 @@ function renote(visibility: Visibility | 'local') {
 			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 		}
 
-		const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
-		const localOnlySetting = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
-
-		let noteVisibility = visibility === 'local' || visibility === 'specified' ? smallerVisibility(appearNote.value.visibility, configuredVisibility) : smallerVisibility(visibility, configuredVisibility);
-		if (appearNote.value.channel?.isSensitive) {
-			noteVisibility = smallerVisibility(visibility === 'local' || visibility === 'specified' ? appearNote.value.visibility : visibility, 'home');
-		}
-
 		misskeyApi('notes/create', {
-			localOnly: visibility === 'local' ? true : localOnlySetting,
-			visibility: noteVisibility,
+			localOnly: localOnly,
+			visibility: visibility,
 			renoteId: appearNote.value.id,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 1641f8a5a4..1486742f42 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -113,6 +113,7 @@ import { reactionPicker } from '@/scripts/reaction-picker.js';
 import { claimAchievement } from '@/scripts/achievements.js';
 import { getNoteMenu } from '@/scripts/get-note-menu.js';
 import { useNoteCapture } from '@/scripts/use-note-capture.js';
+import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
 
 const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
 const hideLine = computed(() => { return props.detail ? true : false; });
@@ -290,43 +291,11 @@ function boostVisibility() {
 	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
-		os.popupMenu([
-			{
-				type: 'button',
-				icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
-				text: i18n.ts._visibility['public'],
-				action: () => {
-					renote('public');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-house ph-bold ph-lg',
-				text: i18n.ts._visibility['home'],
-				action: () => {
-					renote('home');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-lock ph-bold ph-lg',
-				text: i18n.ts._visibility['followers'],
-				action: () => {
-					renote('followers');
-				},
-			},
-			{
-				type: 'button',
-				icon: 'ph-planet ph-bold ph-lg',
-				text: i18n.ts._timelines.local,
-				action: () => {
-					renote('local');
-				},
-			}], renoteButton.value);
+		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
 	}
 }
 
-function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'local') {
+function renote(visibility: Visibility, localOnly: boolean = false) {
 	pleaseLogin();
 	showMovedDialog();
 
@@ -340,8 +309,8 @@ function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'loc
 		}
 
 		misskeyApi('notes/create', {
-			renoteId: props.note.id,
-			channelId: props.note.channelId,
+			renoteId: appearNote.value.id,
+			channelId: appearNote.value.channelId,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
@@ -356,9 +325,9 @@ function renote(visibility: 'public' | 'home' | 'followers' | 'specified' | 'loc
 		}
 
 		misskeyApi('notes/create', {
-			renoteId: props.note.id,
-			localOnly: visibility === 'local' ? true : false,
-			visibility: visibility === 'local' || visibility === 'specified' ? props.note.visibility : visibility,
+			renoteId: appearNote.value.id,
+			localOnly: localOnly,
+			visibility: visibility,
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
index 3b2946e2b7..a27902c467 100644
--- a/packages/frontend/src/pages/settings/general.vue
+++ b/packages/frontend/src/pages/settings/general.vue
@@ -212,7 +212,6 @@ SPDX-License-Identifier: AGPL-3.0-only
 						<option value="public">{{ i18n.ts._visibility['public'] }}</option>
 						<option value="home">{{ i18n.ts._visibility['home'] }}</option>
 						<option value="followers">{{ i18n.ts._visibility['followers'] }}</option>
-						<option value="local">{{ i18n.ts._timelines.local }}</option>
 					</MkSelect>
 				</div>
 			</MkFolder>
diff --git a/packages/frontend/src/scripts/boost-quote.ts b/packages/frontend/src/scripts/boost-quote.ts
new file mode 100644
index 0000000000..4e025f5d4f
--- /dev/null
+++ b/packages/frontend/src/scripts/boost-quote.ts
@@ -0,0 +1,81 @@
+/*
+ * SPDX-FileCopyrightText: dakkar and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+*/
+
+import { ref, Ref } from 'vue';
+import * as Misskey from 'misskey-js';
+import { i18n } from '@/i18n.js';
+import { defaultStore } from '@/store.js';
+import { MenuItem } from '@/types/menu.js';
+
+/*
+	this script should eventually contain all Sharkey-specific bits of
+	boosting and quoting that we would otherwise have to replicate in
+	`{M,S}kNote{,Detailed,Sub}.vue`
+ */
+
+export type Visibility = 'public' | 'home' | 'followers' | 'specified';
+
+export function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
+	if (a === 'specified' || b === 'specified') return 'specified';
+	if (a === 'followers' || b === 'followers') return 'followers';
+	if (a === 'home' || b === 'home') return 'home';
+	// if (a === 'public' || b === 'public')
+	return 'public';
+}
+
+export function visibilityIsAtLeast(a: Visibility | string, b: Visibility | string): boolean {
+	return smallerVisibility(a, b) === b;
+}
+
+export function boostMenuItems(appearNote: Ref<Misskey.entities.Note>, renote: (v: Visibility, l: boolean) => void): MenuItem[] {
+	const localOnly = ref(defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly);
+	const effectiveVisibility = (
+		appearNote.value.channel?.isSensitive
+			? smallerVisibility(appearNote.value.visibility, 'home')
+			: appearNote.value.visibility
+	);
+
+	const menuItems: MenuItem[] = [];
+	if (visibilityIsAtLeast(effectiveVisibility, 'public')) {
+		menuItems.push({
+			type: 'button',
+			icon: 'ph-globe-hemisphere-west ph-bold ph-lg',
+			text: i18n.ts._visibility['public'],
+			action: () => {
+				renote('public', localOnly.value);
+			},
+		} as MenuItem);
+	}
+	if (visibilityIsAtLeast(effectiveVisibility, 'home')) {
+		menuItems.push({
+			type: 'button',
+			icon: 'ph-house ph-bold ph-lg',
+			text: i18n.ts._visibility['home'],
+			action: () => {
+				renote('home', localOnly.value);
+			},
+		} as MenuItem);
+	}
+	if (visibilityIsAtLeast(effectiveVisibility, 'followers')) {
+		menuItems.push({
+			type: 'button',
+			icon: 'ph-lock ph-bold ph-lg',
+			text: i18n.ts._visibility['followers'],
+			action: () => {
+				renote('followers', localOnly.value);
+			},
+		} as MenuItem);
+	}
+
+	return [
+		...menuItems,
+		{
+			type: 'switch',
+			icon: 'ph-planet ph-bold ph-lg',
+			text: i18n.ts._timelines.local,
+			ref: localOnly,
+		} as MenuItem,
+	];
+}
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index d695caa95f..53d259cf39 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -159,7 +159,7 @@ export const defaultStore = markRaw(new Storage('base', {
 	},
 	visibilityOnBoost: {
 		where: 'account',
-		default: 'public' as 'public' | 'home' | 'followers' | 'local',
+		default: 'public' as 'public' | 'home' | 'followers',
 	},
 
 	menu: {
-- 
cgit v1.2.3-freya


From b0bc69aac8033e4022394358aeaac632a77054ef Mon Sep 17 00:00:00 2001
From: Marie <marie@kaifa.ch>
Date: Thu, 22 Feb 2024 21:16:08 +0000
Subject: Reactions not working on child notes in detailed view

---
 packages/frontend/src/components/MkNoteSub.vue | 4 ++--
 packages/frontend/src/components/SkNoteSub.vue | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'packages/frontend/src/components/SkNoteSub.vue')

diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index ea108ad51c..37811dd52e 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -141,7 +141,7 @@ const replies = ref<Misskey.entities.Note[]>([]);
 const isRenote = (
 	props.note.renote != null &&
 	props.note.text == null &&
-	props.note.fileIds.length === 0 &&
+	props.note.fileIds && props.note.fileIds.length === 0 &&
 	props.note.poll == null
 );
 
@@ -211,7 +211,7 @@ function react(viaKeyboard = false): void {
 		}
 	} else {
 		blur();
-		reactionPicker.show(reactButton.value, reaction => {
+		reactionPicker.show(reactButton.value ?? null, props.note, reaction => {
 			misskeyApi('notes/reactions/create', {
 				noteId: props.note.id,
 				reaction: reaction,
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 1486742f42..1cffd8dd66 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -155,7 +155,7 @@ const replies = ref<Misskey.entities.Note[]>([]);
 const isRenote = (
 	props.note.renote != null &&
 	props.note.text == null &&
-	props.note.fileIds.length === 0 &&
+	props.note.fileIds && props.note.fileIds.length === 0 &&
 	props.note.poll == null
 );
 
@@ -225,7 +225,7 @@ function react(viaKeyboard = false): void {
 		}
 	} else {
 		blur();
-		reactionPicker.show(reactButton.value, reaction => {
+		reactionPicker.show(reactButton.value ?? null, props.note, reaction => {
 			misskeyApi('notes/reactions/create', {
 				noteId: props.note.id,
 				reaction: reaction,
-- 
cgit v1.2.3-freya

