// ==UserScript== // @name Allflame Voyage Solver - clipboard auto-paste // @namespace templis // @version 1.0 // @description Polls the local clipboard bridge and feeds copied PoE items into the solver without focusing the browser. // @match https://one-more-map.github.io/allflame-voyage-solver/* // @grant GM_xmlhttpRequest // @connect 127.0.0.1 // @run-at document-idle // ==/UserScript== (function () { "use strict"; const ENDPOINT = "http://127.0.0.1:8477/clip"; const INTERVAL = 400; let lastSeq = -1; const toast = document.createElement("div"); toast.style.cssText = "position:fixed;bottom:12px;right:12px;z-index:99999;padding:6px 10px;" + "border-radius:6px;font:12px/1.4 monospace;background:#222;color:#8f8;" + "opacity:0;transition:opacity .2s;pointer-events:none"; document.body.appendChild(toast); function flash(msg, color) { toast.textContent = msg; toast.style.color = color; toast.style.opacity = "1"; setTimeout(() => (toast.style.opacity = "0"), 1500); } function feed(text) { const dt = new DataTransfer(); dt.setData("text/plain", text); document.dispatchEvent( new ClipboardEvent("paste", { clipboardData: dt, bubbles: true, cancelable: true, }) ); flash("item pasted", "#8f8"); } function poll() { GM_xmlhttpRequest({ method: "GET", url: ENDPOINT, onload: (r) => { try { const data = JSON.parse(r.responseText); if (data.seq !== lastSeq) { lastSeq = data.seq; if (data.text) feed(data.text); // also feeds the last item on page load } } catch (e) { /* ignore malformed response */ } }, onerror: () => flash("bridge offline", "#f88"), }); } setInterval(poll, INTERVAL); poll(); })();