BSKY EASY/AUTO HASHTAGS

Add pre-defined tags easily!

// ==UserScript==
// @name         BSKY EASY/AUTO HASHTAGS
// @namespace    http://tampermonkey.net/
// @version      2024-11-25
// @description  Add pre-defined tags easily!
// @author       written by ai and me >.<
// @match        https://bsky.app/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bsky.app
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

// ====================================================
    
// !!! ADD YOUR TAGS HERE !!!
    const tags = {
        "tagLabel-1": "#this #is #first #test",
        "tagLabel-2": "#next #test"
    };

// ==================================================== 


    // Add styles
    const styleEZ = document.createElement('style');
    styleEZ.innerHTML = `

    :root {
        color-scheme: light dark;
    }
.light {
  /* forces light color-scheme */
  color-scheme: light;
}
.dark {
  /* forces dark color-scheme */
  color-scheme: dark;
}
    /* .custom-button:hover {
        background-color: light-dark(#7981B1, #7981B1) !important;
        fill: red !important;
    } */
    .EZOptions {
        display: none;
        position: relative;
        background-color: light-dark(#D8DFF2, #0F1B27);
        color: light-dark(#ffffff, #000000);
        border: 1px solid light-dark(#7B8EBF, #344F95);
        border-radius: 8px;
        padding: 10px;
        z-index: 10000000000000000000;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }
    .EZOptions.EZvisible {
        display: block;
    }
    `;
    document.head.appendChild(styleEZ);

    document.addEventListener("DOMContentLoaded", () => {
        const htmlElement = document.documentElement;

        if (htmlElement.classList.contains('theme--light')) {
            htmlElement.classList.add("light");
        } else {
            htmlElement.classList.add("light");
        }
    });



    // Create and configure the button and options dynamically
    const createTagButton = () => {
        const actionBtns = document.querySelector(".r-1xfd6ze > div:nth-child(1) > div:nth-child(1) > div:nth-child(4) > div:nth-child(1)");
        if (actionBtns && !document.querySelector(".custom-button")) {
            // Create the new button
            const newBtn = document.createElement("button");
            newBtn.setAttribute("aria-label", "Tags");
            newBtn.className = "css-175oi2r r-1loqt21 r-1otgn73 custom-button";
            newBtn.style.flexDirection = "row";
            newBtn.style.alignItems = "center";
            newBtn.style.justifyContent = "center";
            // newBtn.style.backgroundColor = "light-dark(#ffffff, #000000)";
            newBtn.style.borderRadius = "999px";
            newBtn.style.padding = "8px";
            newBtn.style.position = "relative"; // Ensure proper relative positioning
            newBtn.innerHTML = `
                <svg class="w-6 h-6 text-gray-800 custom-button dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
                <path fill="hsl(211, 99%, 53%)" d="M18.045 3.007 12.31 3a1.965 1.965 0 0 0-1.4.585l-7.33 7.394a2 2 0 0 0 0 2.805l6.573 6.631a1.957 1.957 0 0 0 1.4.585 1.965 1.965 0 0 0 1.4-.585l7.409-7.477A2 2 0 0 0 21 11.479v-5.5a2.972 2.972 0 0 0-2.955-2.972Zm-2.452 6.438a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/>
                </svg>
            `;
            actionBtns.append(newBtn);

            // Create the options dropdown
            const options = document.createElement("div");
            options.classList.add("EZOptions");
            newBtn.appendChild(options);

            // Add tags options
            for (const [key, value] of Object.entries(tags)) {
                const option = document.createElement("button");
                option.textContent = key;
                option.style.margin = "5px";
                option.style.padding = "5px 10px";
                option.style.border = "1px solid light-dark(#1471D5, #1471D5)";
                option.style.borderRadius = "4px";
                option.style.cursor = "pointer";
                option.style.backgroundColor = "light-dark(#1471D5, #000000)";
                option.style.color = "light-dark(#ffffff, #ffffff)";
                option.addEventListener("click", () => {
                    const textBox = document.querySelector(".tiptap");
                    if (textBox) {
                        console.log("TEXT BOX EXISTS");
                        textBox.click();

                        // Insert the selected tags into the contenteditable div
                        const selectedTags = tags[key];
                        const range = document.getSelection().getRangeAt(0);
                        const newNode = document.createTextNode(` ${selectedTags}`); // Insert the tags text
                        range.insertNode(newNode); // Insert the text node at the current cursor position

                        // Optionally, move the cursor after the inserted text
                        range.setStartAfter(newNode);
                        range.setEndAfter(newNode);
                        const selection = window.getSelection();
                        selection.removeAllRanges();
                        selection.addRange(range);

                        // Dispatch input event if necessary
                        textBox.dispatchEvent(new Event("input"));
                    } else {
                        console.log("TEXT BOX NOT FOUND");
                    }
                });
                options.appendChild(option);
            }

            // Toggle dropdown visibility on button click
            newBtn.addEventListener("click", (e) => {
                e.stopPropagation();
                options.classList.toggle("EZvisible");
            });

            // Hide dropdown when clicking outside
            document.body.addEventListener("click", () => {
                options.classList.remove("EZvisible");
            });
        }
    };

    // Observe changes in the DOM and re-run the button creation if necessary
    const observer = new MutationObserver(() => {
        createTagButton(); // Try creating the button each time a mutation occurs
    });

    // Start observing for changes in the DOM
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

})();