« get me outta code hell

userstuff: initial commit - dotfiles - Miscellaneous configuration files of my personal use
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2025-01-20 10:39:07 -0400
committer(quasar) nebula <qznebula@protonmail.com>2025-01-20 10:43:43 -0400
commitf168193e64793621652a86a3b2f238fe153f5b65 (patch)
tree70e2fd53eb269a1a8caab6a875d0271d74a4cf12
parent07f1dd42bcecd27b2bd6c7a6cfaa01f4fb40293b (diff)
userstuff: initial commit HEAD main
Userscripts and userstyles. Extension/platform-agnostic.
At the moment we're using the macOS 'Userscripts' app
(from the app store), which we've configured to point to
a folder in iCloud Documents, 'Userscripts Folder'.

'Userscripts Folder' is flat and each file is hardlinked
with the appropriate placement in userstuff, though we
haven't checked if the Userscripts app breaks hardlinks
or not.
-rw-r--r--userstuff/discord/Highlight hovered message.user.css10
-rw-r--r--userstuff/e621/Search their favorites!.user.js152
-rw-r--r--userstuff/google-docs/Banish Gemini.user.css9
-rw-r--r--userstuff/youtube/Copy YouTube chat messages.user.js18
4 files changed, 189 insertions, 0 deletions
diff --git a/userstuff/discord/Highlight hovered message.user.css b/userstuff/discord/Highlight hovered message.user.css
new file mode 100644
index 0000000..fe9d89b
--- /dev/null
+++ b/userstuff/discord/Highlight hovered message.user.css
@@ -0,0 +1,10 @@
+/* ==UserStyle==
+@name        Highlight hovered message
+@description Adds a background and underline to the Discord message under the mouse cursor
+@match       https://discord.com/*
+==/UserStyle== */
+
+div[class*=cozyMessage]:hover {
+    background-color: #ccc1;
+    box-shadow: 0 1px 0px #eee5;
+}
diff --git a/userstuff/e621/Search their favorites!.user.js b/userstuff/e621/Search their favorites!.user.js
new file mode 100644
index 0000000..e34f4ee
--- /dev/null
+++ b/userstuff/e621/Search their favorites!.user.js
@@ -0,0 +1,152 @@
+// ==UserScript==
+// @name        Search their favorites!
+// @description This is your new file, start writing code
+// @match       https://e621.net/posts/*/favorites
+// ==/UserScript==
+
+const settings = {
+  normalHoverInfoDelay: 400,
+  fastHoveringInfoDelay: 150,
+  endFastHoveringDelay: 500,
+
+  focusInfoDelay: 750,
+
+  hideTooltipDelay: 500,
+};
+
+const state = {
+  hoverTimeout: null,
+  focusTimeout: null,
+
+  fastHovering: false,
+  endFastHoveringTimeout: false,
+  
+  showing: false,
+  justHidden: false,
+  
+  row: null,
+};
+
+const thumb = document.querySelector('#a-index .thumbnail');
+
+const container = document.createElement('div');
+
+const tagLabel = document.createElement('label');
+const tagInput = document.createElement('input');
+tagLabel.appendChild(document.createTextNode('Search these tags: '));
+tagLabel.appendChild(tagInput);
+container.appendChild(tagLabel);
+
+let hoverTimeout = null;
+for (const a of document.querySelectorAll('#a-index td a[href^="/favorites"]')) {
+  a.addEventListener('mouseover', event => {
+    const hoverTimeoutDelay =
+          (state.fastHovering
+           ? settings.fastHoveringInfoDelay
+           : settings.normalHoverInfoDelay);
+
+    state.hoverTimeout = setTimeout(() => {
+      state.hoverTimeout = null;
+      state.fastHovering = true;
+      show(a);
+    }, hoverTimeoutDelay);
+
+    if (state.endFastHoveringTimeout) {
+      clearTimeout(state.endFastHoveringTimeout);
+      state.endFastHoveringTimeout = null;
+    }
+
+    if (state.hideTimeout) {
+      clearTimeout(state.hideTimeout);
+      state.hideTimeout = null;
+    }
+  });
+  
+  a.addEventListener('mouseleave', event => {
+    if (state.hoverTimeout) {
+      clearTimeout(state.hoverTimeout);
+      state.hoverTimeout = null;
+    }
+
+    if (state.fastHovering && !state.endFastHoveringTimeout) {
+      state.endFastHoveringTimeout = setTimeout(() => {
+        state.endFastHoveringTimeout = null;
+        state.fastHovering = false;
+      }, settings.endFastHoveringDelay);
+    }
+  });
+  
+  a.closest('tr').addEventListener('mouseleave', event => {
+    if (state.showing && !state.hideTimeout) {
+      state.hideTimeout = setTimeout(() => {
+        state.hideTimeout = null;
+        hide();
+      }, settings.hideTooltipDelay);
+    }
+  });
+  
+  a.addEventListener('focus', event => {
+    state.focusTimeout = setTimeout(() => {
+      state.focusTimeout = null;
+      show(a);
+    }, settings.focusInfoDelay);
+
+    if (state.justHidden) {
+      clearTimeout(state.focusTimeout);
+      state.focusTimeout = null;
+      show(a);
+    }
+  })
+}
+
+function show(a) {
+  hide();
+  
+  const tr = document.createElement('tr');
+  const td = document.createElement('td');
+  const aa = document.createElement('a');
+  aa.href = '#';
+  aa.appendChild(document.createTextNode('Hiya'));
+  td.appendChild(aa);
+  tr.appendChild(td);
+
+  state.showing = true;
+  state.row = tr;
+  
+  tr.addEventListener('mouseenter', event => {
+    if (state.hideTimeout) {
+      clearTimeout(state.hideTimeout);
+      state.hideTimeout = null;
+    }
+  });
+  
+  tr.addEventListener('focusin', event => {
+    if (state.hideTimeout) {
+      clearTimeout(state.hideTimeout);
+      state.hideTimeout = null;
+    }
+  });
+  
+  tr.addEventListener('focusout', event => {
+    hide();
+  });
+  
+  a.closest('tr').after(tr);
+}
+
+function hide() {
+  if (!state.showing) return;
+  if (!state.row) return;
+
+  state.row.remove();
+
+  state.showing = false;
+  state.row = null;
+
+  state.justHidden = true;
+  setTimeout(() => {
+    state.justHiden = false;
+  });
+}
+
+thumb.after(container);
diff --git a/userstuff/google-docs/Banish Gemini.user.css b/userstuff/google-docs/Banish Gemini.user.css
new file mode 100644
index 0000000..04f78cc
--- /dev/null
+++ b/userstuff/google-docs/Banish Gemini.user.css
@@ -0,0 +1,9 @@
+/* ==UserStyle==
+@name        Banish Gemini
+@description Removes Gemini promo button from Google Docs, etc
+@match       https://docs.google.com/*
+==/UserStyle== */
+
+#docs-sidekick-gen-ai-promo-button-container {
+    display: none;
+}
\ No newline at end of file
diff --git a/userstuff/youtube/Copy YouTube chat messages.user.js b/userstuff/youtube/Copy YouTube chat messages.user.js
new file mode 100644
index 0000000..9665e12
--- /dev/null
+++ b/userstuff/youtube/Copy YouTube chat messages.user.js
@@ -0,0 +1,18 @@
+// ==UserScript==
+// @name        Copy YouTube chat messages
+// @description Copies the text of a message when you click it (no emotes, sorry)
+// @match       https://www.youtube.com/live_chat_replay*
+// ==/UserScript==
+
+document.body.addEventListener('click', event => {
+    const mouseElem = document.elementFromPoint(event.clientX, event.clientY);
+    if (!mouseElem) return;
+    const rendererElem = mouseElem.closest('yt-live-chat-text-message-renderer');
+    if (!rendererElem) return;
+    const messageElem = rendererElem.querySelector('#message');
+    if (!messageElem) {
+        console.warn(`Couldn't find message in message renderer`);
+        return;
+    }
+    navigator.clipboard.writeText(messageElem.innerText.trim());
+});