From cb43994841935c6512c530c96ee409ffbd9f00f8 Mon Sep 17 00:00:00 2001
From: dakkar <dakkar@thenautilus.net>
Date: Fri, 7 Jun 2024 11:40:44 +0100
Subject: [PATCH] only allow a single boost via hotkey - fixes #467 #468
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

As usual, have to write the same thing four times ☹

The parentheses around `q` tell the hotkey/keymap code to ignore
auto-repeat events (which works fine in Chrome but not in Firefox, I
reported the bug https://bugzilla.mozilla.org/show_bug.cgi?id=1900397
)

In addition, I've added a guard variable that is true while calling
the backend to boost/renote, and false otherwise. This way, even in
Firefox we don't spam-boost. Unboosting is still *only with the
mouse*, I have not added that functionality.
---
 packages/frontend/src/components/MkNote.vue         | 8 +++++---
 packages/frontend/src/components/MkNoteDetailed.vue | 8 +++++---
 packages/frontend/src/components/SkNote.vue         | 8 +++++---
 packages/frontend/src/components/SkNoteDetailed.vue | 8 +++++---
 4 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 9a667c3118..a1d241690f 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -328,10 +328,12 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
 	return false;
 }
 
+let renoting = false;
+
 const keymap = {
 	'r': () => reply(true),
 	'e|a|plus': () => react(true),
-	'q': () => renote(appearNote.value.visibility),
+	'(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } },
 	'up|k|shift+tab': focusBefore,
 	'down|j|tab': focusAfter,
 	'esc': blur,
@@ -436,7 +438,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
 				renoted.value = true;
-			});
+			}).then(() => { renoting = false });
 		}
 	} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
 		const el = renoteButton.value as HTMLElement | null | undefined;
@@ -455,7 +457,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
 				renoted.value = true;
-			});
+			}).then(() => renoting = false);
 		}
 	}
 }
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 3d15f69f73..ec3c3ea3dc 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -336,10 +336,12 @@ if ($i) {
 	});
 }
 
+let renoting = false;
+
 const keymap = {
 	'r': () => reply(true),
 	'e|a|plus': () => react(true),
-	'q': () => renote(appearNote.value.visibility),
+	'(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } },
 	'esc': blur,
 	'm|o': () => showMenu(true),
 	's': () => showContent.value !== showContent.value,
@@ -457,7 +459,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
-		});
+		}).then(() => { renoting = false });
 	} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
 		const el = renoteButton.value as HTMLElement | null | undefined;
 		if (el) {
@@ -474,7 +476,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
-		});
+		}).then(() => { renoting = false });
 	}
 }
 
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 09decad1a2..fe14b1eafd 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -329,10 +329,12 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
 	return false;
 }
 
+let renoting = false;
+
 const keymap = {
 	'r': () => reply(true),
 	'e|a|plus': () => react(true),
-	'q': () => renote(appearNote.value.visibility),
+	'(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } },
 	'up|k|shift+tab': focusBefore,
 	'down|j|tab': focusAfter,
 	'esc': blur,
@@ -437,7 +439,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
 				renoted.value = true;
-			});
+			}).then(() => { renoting = false });
 		}
 	} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
 		const el = renoteButton.value as HTMLElement | null | undefined;
@@ -456,7 +458,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 			}).then(() => {
 				os.toast(i18n.ts.renoted);
 				renoted.value = true;
-			});
+			}).then(() => { renoting = false });
 		}
 	}
 }
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index ced7e7a176..084c46ddcd 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -345,10 +345,12 @@ if ($i) {
 	});
 }
 
+let renoting = false;
+
 const keymap = {
 	'r': () => reply(true),
 	'e|a|plus': () => react(true),
-	'q': () => renote(appearNote.value.visibility),
+	'(q)': () => { if (canRenote && !renoted.value && !renoting) { renoting = true; renote(appearNote.value.visibility) } },
 	'esc': blur,
 	'm|o': () => showMenu(true),
 	's': () => showContent.value !== showContent.value,
@@ -466,7 +468,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
-		});
+		}).then(() => { renoting = false });
 	} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
 		const el = renoteButton.value as HTMLElement | null | undefined;
 		if (el) {
@@ -483,7 +485,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
 		}).then(() => {
 			os.toast(i18n.ts.renoted);
 			renoted.value = true;
-		});
+		}).then(() => { renoting = false });
 	}
 }