From 7825f6e95eab864796b31e589e14cdc2a0353096 Mon Sep 17 00:00:00 2001
From: HellhoundSoftware <keith@keithhacks.cyou>
Date: Tue, 14 Jan 2025 19:42:35 -0500
Subject: [PATCH 1/4] Open boost visibility menu on shift-click

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

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 25d04a0b6a..98ec61cefd 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -132,7 +132,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
 					@click.stop
-					@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility()"
+					@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
 				>
 					<i class="ti ti-repeat"></i>
 					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
@@ -506,10 +506,10 @@ if (!props.mock) {
 	}
 }
 
-function boostVisibility() {
+function boostVisibility(forceMenu: boolean = false) {
 	if (renoting) return;
 
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 243b95215a..a5e82782b0 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -143,7 +143,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
-				@mousedown.prevent="renoted ? undoRenote() : boostVisibility()"
+				@mousedown.prevent="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
 			>
 				<i class="ti ti-repeat"></i>
 				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
@@ -478,10 +478,10 @@ useTooltip(quoteButton, async (showing) => {
 	});
 });
 
-function boostVisibility() {
+function boostVisibility(forceMenu: boolean = false) {
 	if (renoting) return;
 
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 3523babe46..f9e54f70aa 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
-					@mousedown="renoted ? undoRenote() : boostVisibility()"
+					@mousedown="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
 				>
 					<i class="ph-rocket-launch ph-bold ph-lg"></i>
 					<p v-if="note.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ note.renoteCount }}</p>
@@ -285,8 +285,8 @@ watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
 });
 
-function boostVisibility() {
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+function boostVisibility(forceMenu: boolean = false) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index b4a9fa34cc..c6754764b2 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -133,7 +133,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
 					@click.stop
-					@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility()"
+					@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
 				>
 					<i class="ti ti-repeat"></i>
 					<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
@@ -506,10 +506,10 @@ if (!props.mock) {
 	}
 }
 
-function boostVisibility() {
+function boostVisibility(forceMenu: boolean = false) {
 	if (renoting) return;
 
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 8d7b47ae6d..5017e3d902 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -148,7 +148,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
-				@mousedown.prevent="renoted ? undoRenote() : boostVisibility()"
+				@mousedown.prevent="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
 			>
 				<i class="ti ti-repeat"></i>
 				<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
@@ -484,10 +484,10 @@ useTooltip(quoteButton, async (showing) => {
 	});
 });
 
-function boostVisibility() {
+function boostVisibility(forceMenu: boolean = false) {
 	if (renoting) return;
 
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index bd25e1e3ad..9205983850 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
-					@mousedown="renoted ? undoRenote() : boostVisibility()"
+					@mousedown="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
 				>
 					<i class="ph-rocket-launch ph-bold ph-lg"></i>
 					<p v-if="note.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ note.renoteCount }}</p>
@@ -299,8 +299,8 @@ watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
 });
 
-function boostVisibility() {
-	if (!defaultStore.state.showVisibilitySelectorOnBoost) {
+function boostVisibility(forceMenu: boolean = false) {
+	if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
 		renote(defaultStore.state.visibilityOnBoost);
 	} else {
 		os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);

From 2c90eebe869d56f6c6e948d96e4565c8c6761a45 Mon Sep 17 00:00:00 2001
From: HellhoundSoftware <keith@keithhacks.cyou>
Date: Wed, 15 Jan 2025 14:38:34 -0500
Subject: [PATCH 2/4] Add tooltip for shift-boost

---
 locales/index.d.ts                                  | 4 ++++
 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 +
 sharkey-locales/en-US.yml                           | 1 +
 8 files changed, 11 insertions(+)

diff --git a/locales/index.d.ts b/locales/index.d.ts
index bcb78e4ee1..8276ead05e 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -10805,6 +10805,10 @@ export interface Locale extends ILocale {
      * Date
      */
     "date": string;
+    /**
+     * Boost (hold Shift for visibility menu)
+     */
+    "renoteShift": string;
     /**
      * Quoted.
      */
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 98ec61cefd..b4193369ef 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -128,6 +128,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
+					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 					:class="$style.footerButton"
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index a5e82782b0..21d8568300 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -140,6 +140,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<button
 				v-if="canRenote"
 				ref="renoteButton"
+				v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index f9e54f70aa..c84d80475f 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
+					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index c6754764b2..a4265896af 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -129,6 +129,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
+					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 					:class="$style.footerButton"
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 5017e3d902..a66e17a134 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -145,6 +145,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<button
 				v-if="canRenote"
 				ref="renoteButton"
+				v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 9205983850..39cbaa3195 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -36,6 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
+					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml
index db3ef9c3eb..e2a57f3613 100644
--- a/sharkey-locales/en-US.yml
+++ b/sharkey-locales/en-US.yml
@@ -17,6 +17,7 @@ emailDestination: "Destination address"
 date: "Date"
 renote: "Boost"
 unrenote: "Remove boost"
+renoteShift: "Boost (hold Shift for visibility menu)"
 renoted: "Boosted."
 quoted: "Quoted."
 rmboost: "Unboosted."

From 3717654309be5bd3dfb87ad0d71f04c52125c00b Mon Sep 17 00:00:00 2001
From: HellhoundSoftware <keith@keithhacks.cyou>
Date: Wed, 15 Jan 2025 16:14:35 -0500
Subject: [PATCH 3/4] move tooltip message to computed

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

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index b4193369ef..2971252dbf 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -128,7 +128,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
-					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+					v-tooltip="renoteTooltip"
 					:class="$style.footerButton"
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -339,6 +339,11 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
 	url: `https://${host}/notes/${appearNote.value.id}`,
 }));
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 /* Overload FunctionにLintが対応していないのでコメントアウト
 function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean;
 function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): boolean | 'sensitiveMute';
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 21d8568300..a855b3269c 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -140,7 +140,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<button
 				v-if="canRenote"
 				ref="renoteButton"
-				v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+				v-tooltip="renoteTooltip"
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -348,6 +348,11 @@ const quotes = ref<Misskey.entities.Note[]>([]);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
 });
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index c84d80475f..4bdeeb7ab4 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
-					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+					v-tooltip="renoteTooltip"
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -136,6 +136,11 @@ const quoteButton = shallowRef<HTMLElement>();
 const menuButton = shallowRef<HTMLElement>();
 const likeButton = shallowRef<HTMLElement>();
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 const replies = ref<Misskey.entities.Note[]>([]);
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index a4265896af..eef6129792 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -129,7 +129,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
-					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+					v-tooltip="renoteTooltip"
 					:class="$style.footerButton"
 					class="_button"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -334,6 +334,11 @@ const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.
 const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
 const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
 	type: 'lookup',
 	url: `https://${host}/notes/${appearNote.value.id}`,
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index a66e17a134..e7e225304e 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -145,7 +145,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<button
 				v-if="canRenote"
 				ref="renoteButton"
-				v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+				v-tooltip="renoteTooltip"
 				class="_button"
 				:class="$style.noteFooterButton"
 				:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -354,6 +354,11 @@ const quotes = ref<Misskey.entities.Note[]>([]);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
 });
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index 39cbaa3195..ff8af5b72b 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<button
 					v-if="canRenote"
 					ref="renoteButton"
-					v-tooltip="renoted ? i18n.ts.unrenote : (!defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renoteShift : i18n.ts.renote)"
+					v-tooltip="renoteTooltip"
 					class="_button"
 					:class="$style.noteFooterButton"
 					:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
@@ -150,6 +150,11 @@ const quoteButton = shallowRef<HTMLElement>();
 const menuButton = shallowRef<HTMLElement>();
 const likeButton = shallowRef<HTMLElement>();
 
+const renoteTooltip = computed(() => {
+	if (renoted.value) return i18n.ts.unrenote;
+	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
+});
+
 let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 const replies = ref<Misskey.entities.Note[]>([]);

From 5a76b7069f5120f4b1698b4c254111ad8cce78d9 Mon Sep 17 00:00:00 2001
From: HellhoundSoftware <keith@keithhacks.cyou>
Date: Sat, 18 Jan 2025 08:28:57 -0500
Subject: [PATCH 4/4] Refactor renote tooltip text

---
 packages/frontend/src/components/MkNote.vue         |  7 ++-----
 packages/frontend/src/components/MkNoteDetailed.vue |  7 ++-----
 packages/frontend/src/components/MkNoteSub.vue      |  7 ++-----
 packages/frontend/src/components/SkNote.vue         |  7 ++-----
 packages/frontend/src/components/SkNoteDetailed.vue |  7 ++-----
 packages/frontend/src/components/SkNoteSub.vue      |  7 ++-----
 packages/frontend/src/scripts/boost-quote.ts        | 10 +++++++++-
 7 files changed, 21 insertions(+), 31 deletions(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 2971252dbf..5c6c6f45bb 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -239,7 +239,7 @@ import { getNoteSummary } from '@/scripts/get-note-summary.js';
 import MkRippleEffect from '@/components/MkRippleEffect.vue';
 import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
 import { useRouter } from '@/router/supplier.js';
-import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/scripts/boost-quote.js';
 import { isEnabledUrlPreview } from '@/instance.js';
 import { type Keymap } from '@/scripts/hotkey.js';
 import { focusPrev, focusNext } from '@/scripts/focus.js';
@@ -339,10 +339,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
 	url: `https://${host}/notes/${appearNote.value.id}`,
 }));
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(renoted);
 
 /* Overload FunctionにLintが対応していないのでコメントアウト
 function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean;
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index a855b3269c..93a543dff1 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -281,7 +281,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';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/scripts/boost-quote.js';
 import { isEnabledUrlPreview } from '@/instance.js';
 import { getAppearNote } from '@/scripts/get-appear-note.js';
 import { type Keymap } from '@/scripts/hotkey.js';
@@ -348,10 +348,7 @@ const quotes = ref<Misskey.entities.Note[]>([]);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(renoted);
 
 watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 4bdeeb7ab4..9febc1219c 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -107,7 +107,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';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/scripts/boost-quote.js';
 
 const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
 
@@ -136,10 +136,7 @@ const quoteButton = shallowRef<HTMLElement>();
 const menuButton = shallowRef<HTMLElement>();
 const likeButton = shallowRef<HTMLElement>();
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(computed);
 
 let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index eef6129792..7dc513ff0b 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -239,7 +239,7 @@ import { getNoteSummary } from '@/scripts/get-note-summary.js';
 import MkRippleEffect from '@/components/MkRippleEffect.vue';
 import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
 import { useRouter } from '@/router/supplier.js';
-import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/scripts/boost-quote.js';
 import { isEnabledUrlPreview } from '@/instance.js';
 import { type Keymap } from '@/scripts/hotkey.js';
 import { focusPrev, focusNext } from '@/scripts/focus.js';
@@ -334,10 +334,7 @@ const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.
 const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
 const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(renoted);
 
 const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
 	type: 'lookup',
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index e7e225304e..69e2898264 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -286,7 +286,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';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/scripts/boost-quote.js';
 import { isEnabledUrlPreview } from '@/instance.js';
 import { getAppearNote } from '@/scripts/get-appear-note.js';
 import { type Keymap } from '@/scripts/hotkey.js';
@@ -354,10 +354,7 @@ const quotes = ref<Misskey.entities.Note[]>([]);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(renoted);
 
 watch(() => props.expandAllCws, (expandAllCws) => {
 	if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index ff8af5b72b..a3d27c9e16 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -115,7 +115,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';
+import { boostMenuItems, type Visibility, computeRenoteTooltip } 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; });
@@ -150,10 +150,7 @@ const quoteButton = shallowRef<HTMLElement>();
 const menuButton = shallowRef<HTMLElement>();
 const likeButton = shallowRef<HTMLElement>();
 
-const renoteTooltip = computed(() => {
-	if (renoted.value) return i18n.ts.unrenote;
-	return defaultStore.state.showVisibilitySelectorOnBoost ? i18n.ts.renote : i18n.ts.renoteShift;
-});
+const renoteTooltip = computeRenoteTooltip(renoted);
 
 let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
 const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
diff --git a/packages/frontend/src/scripts/boost-quote.ts b/packages/frontend/src/scripts/boost-quote.ts
index 4e025f5d4f..feb949772b 100644
--- a/packages/frontend/src/scripts/boost-quote.ts
+++ b/packages/frontend/src/scripts/boost-quote.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
 */
 
-import { ref, Ref } from 'vue';
+import { ref, Ref, computed, ComputedRef } from 'vue';
 import * as Misskey from 'misskey-js';
 import { i18n } from '@/i18n.js';
 import { defaultStore } from '@/store.js';
@@ -79,3 +79,11 @@ export function boostMenuItems(appearNote: Ref<Misskey.entities.Note>, renote: (
 		} as MenuItem,
 	];
 }
+
+export function computeRenoteTooltip(renoted: Ref<boolean>): ComputedRef<string> {
+	return computed(() => {
+		if (renoted.value) return i18n.ts.unrenote;
+		if (defaultStore.state.showVisibilitySelectorOnBoost) return i18n.ts.renote;
+		return i18n.ts.renoteShift;
+	});
+}