128 lines
3.7 KiB
JavaScript
128 lines
3.7 KiB
JavaScript
const port = browser.runtime.connect({ name: "devtools" });
|
|
port.onMessage.addListener((message) => {
|
|
if (message.type === "PAGE_LOADED") {
|
|
loadContextStack(); // Refresh your context stack here.
|
|
}
|
|
});
|
|
|
|
const tabId = browser.devtools.inspectedWindow.tabId;
|
|
|
|
document.getElementById("refresh").addEventListener("click", loadContextStack);
|
|
|
|
function loadContextStack() {
|
|
const container = document.getElementById("contextContainer");
|
|
container.innerHTML = "";
|
|
|
|
browser.runtime.sendMessage({ type: "GET_CONTEXT_STACK", tabId }).then(
|
|
(response) => {
|
|
if (response.error) {
|
|
container.innerHTML = `<p>Error: ${response.error}</p>`;
|
|
return;
|
|
}
|
|
|
|
if (!response || !response.contextStack) {
|
|
container.innerHTML = "<p>No context stack found.</p>";
|
|
return;
|
|
}
|
|
|
|
const contextStack = coalesceContextStack(response.contextStack);
|
|
const form = generateObjectForm(contextStack);
|
|
container.appendChild(form);
|
|
},
|
|
);
|
|
}
|
|
|
|
function generateObjectForm(obj, path = "") {
|
|
const detail = document.createElement("details");
|
|
detail.open = path === "";
|
|
const summary = document.createElement("summary");
|
|
summary.textContent = path.split(".").at(-1);
|
|
detail.appendChild(summary);
|
|
const form = document.createElement("form");
|
|
let count = 0;
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
if (value == undefined || value === "[Circular]") continue;
|
|
const isObject = value.constructor === Object;
|
|
const isArray = Array.isArray(value);
|
|
if (isObject || isArray) {
|
|
const nestedForm = generateObjectForm(
|
|
value,
|
|
path ? path + "." + key : key,
|
|
);
|
|
if (!nestedForm) {
|
|
continue;
|
|
}
|
|
const div = document.createElement("div");
|
|
div.appendChild(nestedForm);
|
|
form.appendChild(div);
|
|
count++;
|
|
continue;
|
|
}
|
|
const div = document.createElement("div");
|
|
const label = document.createElement("label");
|
|
label.textContent = key;
|
|
div.appendChild(label);
|
|
const input = document.createElement("input");
|
|
input.name = key;
|
|
const isBoolean = typeof value === "boolean";
|
|
if (isBoolean) {
|
|
input.type = "checkbox";
|
|
input.checked = value;
|
|
input.addEventListener("change", () => {
|
|
browser.runtime.sendMessage({
|
|
type: "UPDATE_CONTEXT_VALUE",
|
|
key: path ? path + "." + key : key,
|
|
value: input.checked,
|
|
tabId,
|
|
}).then((updateResponse) => {
|
|
if (updateResponse && updateResponse.success) {
|
|
console.log(`Updated ${key} to ${input.checked}`);
|
|
} else {
|
|
console.error(`Failed to update ${key}:`, updateResponse.error);
|
|
}
|
|
});
|
|
});
|
|
} else {
|
|
input.type = "text";
|
|
input.value = value;
|
|
input.addEventListener("change", () => {
|
|
browser.runtime.sendMessage({
|
|
type: "UPDATE_CONTEXT_VALUE",
|
|
key: path ? path + "." + key : key,
|
|
value: input.value,
|
|
tabId,
|
|
}).then((updateResponse) => {
|
|
if (updateResponse && updateResponse.success) {
|
|
console.log(`Updated ${key} to ${input.value}`);
|
|
} else {
|
|
console.error(`Failed to update ${key}:`, updateResponse.error);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
div.appendChild(input);
|
|
form.appendChild(div);
|
|
count++;
|
|
}
|
|
if (count === 0) {
|
|
const pre = document.createElement("pre");
|
|
pre.textContent = JSON.stringify(obj, null, 2);
|
|
detail.appendChild(pre);
|
|
} else {
|
|
detail.appendChild(form);
|
|
}
|
|
return detail;
|
|
}
|
|
|
|
function coalesceContextStack(contextStack) {
|
|
const obj = {};
|
|
for (const ctx of contextStack) {
|
|
Object.assign(obj, ctx);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
loadContextStack();
|
|
});
|