feat: Linux bulk importer for the Allflame Voyage Solver
Mirrors the solver's Windows-only voyage-import.ahk on KDE Wayland: - poe-clip-bridge.py: clipboard watcher that keeps only PoE item text, serves it on loopback and can trigger a sweep from the browser - voyage-sweep.py: hovers every cell of the in-game chart grid, Ctrl+C's it and hands over the whole batch in one go - userscript: feeds the batch into the solver page without focusing it Includes notes on the four Wayland pointer pitfalls this ran into. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// ==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();
|
||||
})();
|
||||
Reference in New Issue
Block a user