Custom sidebar with user-defined quick links (mobile optimized)
// ==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();
})();