TornPDA Quick Link Sidebar (Improved)

Custom sidebar with user-defined quick links (mobile optimized)

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         TornPDA Quick Link Sidebar (Improved)
// @namespace    torn.custom.sidebar
// @version      2.1
// @description  Custom sidebar with user-defined quick links (mobile optimized)
// @match        https://www.torn.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const STORAGE_KEY = "torn_custom_links";

    function getLinks() {
        return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
    }

    function saveLinks(links) {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(links));
    }

    // -------------------------
    // TOGGLE TAB
    // -------------------------
    const toggle = document.createElement("div");
    toggle.innerText = "☰";
    toggle.style.position = "fixed";
    toggle.style.left = "0";
    toggle.style.top = "45%";
    toggle.style.width = "30px";
    toggle.style.height = "60px";
    toggle.style.background = "#111";
    toggle.style.color = "#fff";
    toggle.style.display = "flex";
    toggle.style.alignItems = "center";
    toggle.style.justifyContent = "center";
    toggle.style.borderRadius = "0 8px 8px 0";
    toggle.style.zIndex = "9999";
    toggle.style.cursor = "pointer";
    document.body.appendChild(toggle);

    // -------------------------
    // SIDEBAR PANEL
    // -------------------------
    const panel = document.createElement("div");
    panel.style.position = "fixed";
    panel.style.left = "-45%";
    panel.style.top = "10%"; // keeps the offset
    panel.style.width = "45%"; // wider panel
    panel.style.height = "90%";
    panel.style.background = "#2b2b2b"; // grey background
    panel.style.color = "#fff";
    panel.style.zIndex = "9998";
    panel.style.transition = "0.3s";
    panel.style.padding = "10px";
    panel.style.boxSizing = "border-box";
    panel.style.overflowY = "auto";
    panel.style.boxShadow = "2px 0 10px rgba(0,0,0,0.6)";
    document.body.appendChild(panel);

    let isOpen = false;

    toggle.onclick = () => {
        isOpen = !isOpen;
        panel.style.left = isOpen ? "0" : "-45%";
    };

    // -------------------------
    // PANEL CONTENT
    // -------------------------
    const title = document.createElement("h3");
    title.innerText = "Quick Links";
    title.style.marginTop = "0";
    panel.appendChild(title);

    // ADD BUTTON (BLACK)
    const addBtn = document.createElement("button");
    addBtn.innerText = "➕ Add Button";
    addBtn.style.width = "100%";
    addBtn.style.marginBottom = "10px";
    addBtn.style.background = "#000";
    addBtn.style.color = "#fff";
    addBtn.style.border = "none";
    addBtn.style.padding = "10px";
    addBtn.style.borderRadius = "6px";
    panel.appendChild(addBtn);

    // INPUT CONTAINER (NO PROMPTS)
    const inputContainer = document.createElement("div");
    inputContainer.style.display = "none";
    inputContainer.style.marginBottom = "10px";

    const nameInput = document.createElement("input");
    nameInput.placeholder = "Button name";
    nameInput.style.width = "100%";
    nameInput.style.marginBottom = "5px";

    const urlInput = document.createElement("input");
    urlInput.placeholder = "Torn link";
    urlInput.style.width = "100%";
    urlInput.style.marginBottom = "5px";

    const saveBtn = document.createElement("button");
    saveBtn.innerText = "Save";
    saveBtn.style.width = "100%";
    saveBtn.style.background = "#444";
    saveBtn.style.color = "#fff";
    saveBtn.style.border = "none";
    saveBtn.style.padding = "8px";

    inputContainer.appendChild(nameInput);
    inputContainer.appendChild(urlInput);
    inputContainer.appendChild(saveBtn);
    panel.appendChild(inputContainer);

    const listContainer = document.createElement("div");
    panel.appendChild(listContainer);

    // -------------------------
    // CLEAR ALL BUTTON
    // -------------------------
    const clearBtn = document.createElement("button");
    clearBtn.innerText = "🧹 Clear All Buttons";
    clearBtn.style.width = "100%";
    clearBtn.style.marginTop = "20px";
    clearBtn.style.background = "#444";
    clearBtn.style.color = "#fff";
    clearBtn.style.border = "none";
    clearBtn.style.padding = "10px";
    clearBtn.style.borderRadius = "6px";
    panel.appendChild(clearBtn);

    // -------------------------
    // RENDER LINKS
    // -------------------------
    function renderLinks() {
        listContainer.innerHTML = "";
        const links = getLinks();

        links.forEach((link, index) => {
            const btn = document.createElement("button");
            btn.innerText = link.name;
            btn.style.width = "100%";
            btn.style.marginBottom = "8px";
            btn.style.padding = "10px";
            btn.style.background = "#3a3a3a";
            btn.style.color = "#fff";
            btn.style.border = "none";
            btn.style.borderRadius = "6px";

            btn.onclick = () => {
                window.location.href = link.url;
                panel.style.left = "-45%"; // close panel after click
            };

            // LONG PRESS DELETE
            let pressTimer;
            btn.onmousedown = () => {
                pressTimer = setTimeout(() => {
                    if (confirm("Delete this button?")) {
                        const links = getLinks();
                        links.splice(index, 1);
                        saveLinks(links);
                        renderLinks();
                    }
                }, 800);
            };

            btn.onmouseup = () => clearTimeout(pressTimer);
            btn.onmouseleave = () => clearTimeout(pressTimer);

            listContainer.appendChild(btn);
        });
    }

    // -------------------------
    // ADD BUTTON FLOW
    // -------------------------
    addBtn.onclick = () => {
        inputContainer.style.display =
            inputContainer.style.display === "none" ? "block" : "none";
    };

    saveBtn.onclick = () => {
        const name = nameInput.value.trim();
        const url = urlInput.value.trim();

        if (!name || !url) {
            alert("Fill in both fields");
            return;
        }

        const links = getLinks();
        links.push({ name, url });
        saveLinks(links);

        nameInput.value = "";
        urlInput.value = "";
        inputContainer.style.display = "none";

        renderLinks();
    };

    // -------------------------
    // CLEAR ALL FLOW
    // -------------------------
    clearBtn.onclick = () => {
        if (confirm("Are you sure you want to delete all buttons?")) {
            saveLinks([]);
            renderLinks();
        }
    };

    // INIT
    renderLinks();

})();