Compare commits
2 Commits
8e6294c96f
...
f7fedd25a6
Author | SHA1 | Date | |
---|---|---|---|
f7fedd25a6 | |||
9124abb749 |
54
devtools/background.js
Normal file
54
devtools/background.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
console.log("background.js loaded");
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.type === "GET_CONTEXT_STACK") {
|
||||||
|
browser.tabs.sendMessage(message.tabId, message)
|
||||||
|
.then((res) => {
|
||||||
|
console.log("RESPONSE", res);
|
||||||
|
sendResponse(res);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Error sending message to content script:", err);
|
||||||
|
sendResponse({ error: err });
|
||||||
|
});
|
||||||
|
// browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
|
||||||
|
// if (tabs.length) {
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
return true;
|
||||||
|
} else if (message.type === "UPDATE_CONTEXT_VALUE") {
|
||||||
|
browser.tabs.sendMessage(message.tabId, message).then(sendResponse);
|
||||||
|
// browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
|
||||||
|
// if (tabs.length) {
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let devtoolsPort = null;
|
||||||
|
|
||||||
|
browser.runtime.onConnect.addListener((port) => {
|
||||||
|
if (port.name === "devtools") {
|
||||||
|
devtoolsPort = port;
|
||||||
|
console.log("Devtools panel connected.");
|
||||||
|
|
||||||
|
// port.onMessage.addListener((msg) => {
|
||||||
|
// console.log("Received message from devtools panel:", msg);
|
||||||
|
// });
|
||||||
|
|
||||||
|
port.onDisconnect.addListener(() => {
|
||||||
|
devtoolsPort = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Relay messages from content scripts to the devtools panel.
|
||||||
|
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.type === "PAGE_LOADED") {
|
||||||
|
console.log("Background received PAGE_LOADED message from content script.");
|
||||||
|
if (devtoolsPort) {
|
||||||
|
devtoolsPort.postMessage({ type: "PAGE_LOADED" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
20
devtools/content.js
Normal file
20
devtools/content.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.type === "GET_CONTEXT_STACK") {
|
||||||
|
const contextStack = window.wrappedJSObject.getContextStack();
|
||||||
|
|
||||||
|
sendResponse({ contextStack });
|
||||||
|
} else if (message.type === "UPDATE_CONTEXT_VALUE") {
|
||||||
|
const { key, value, depth } = message;
|
||||||
|
if (window.wrappedJSObject.updateContextValue) {
|
||||||
|
window.wrappedJSObject.updateContextValue(key, value, depth);
|
||||||
|
sendResponse({ success: true });
|
||||||
|
} else {
|
||||||
|
sendResponse({
|
||||||
|
success: false,
|
||||||
|
error: "updateContextValue not defined",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.runtime.sendMessage({ type: "PAGE_LOADED" });
|
12
devtools/devtools.html
Normal file
12
devtools/devtools.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<script src="devtools.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body></body>
|
||||||
|
|
||||||
|
</html>
|
7
devtools/devtools.js
Normal file
7
devtools/devtools.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Create a new devtools panel named "Context Stack"
|
||||||
|
browser.devtools.panels.create(
|
||||||
|
"Context Stack", // Tab title
|
||||||
|
"train icon.png", // Icon for your panel (optional)
|
||||||
|
"panel.html", // HTML page for your panel content
|
||||||
|
);
|
||||||
|
console.log("devtools loaded");
|
28
devtools/manifest.json
Normal file
28
devtools/manifest.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "Context Stack DevTools",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "A devtools panel to view and edit context stack values.",
|
||||||
|
"devtools_page": "devtools.html",
|
||||||
|
"background": {
|
||||||
|
"scripts": [
|
||||||
|
"background.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"<all_urls>"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"content.js"
|
||||||
|
],
|
||||||
|
"all_frames": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"devtools",
|
||||||
|
"tabs",
|
||||||
|
"*://*/*"
|
||||||
|
]
|
||||||
|
}
|
48
devtools/panel.html
Normal file
48
devtools/panel.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Context Stack</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
/* margin: 10px; */
|
||||||
|
/* width: 100%;
|
||||||
|
height: 100%; */
|
||||||
|
background-color: #302040;
|
||||||
|
color: #fff;
|
||||||
|
/* text-align: right; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-row {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-key {
|
||||||
|
width: 150px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.context-value input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Context Stack</h1>
|
||||||
|
<div id="contextContainer"></div>
|
||||||
|
<button id="refresh">Refresh</button>
|
||||||
|
<script src="panel.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
127
devtools/panel.js
Normal file
127
devtools/panel.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
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;
|
||||||
|
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();
|
||||||
|
});
|
BIN
devtools/train icon.png
Normal file
BIN
devtools/train icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
@ -92,3 +92,27 @@ function safeStringify(obj: any) {
|
|||||||
return value;
|
return value;
|
||||||
}, 2);
|
}, 2);
|
||||||
}
|
}
|
||||||
|
const getContextStack = () => JSON.parse(safeStringify(contextStack));
|
||||||
|
const updateContextValue = (
|
||||||
|
key: string,
|
||||||
|
value: unknown,
|
||||||
|
depth = contextStack.length - 1,
|
||||||
|
) => {
|
||||||
|
console.log("updateContextValue", key, value, depth);
|
||||||
|
const keys = key.split(".");
|
||||||
|
let context = contextStack[depth] ?? defaultContext;
|
||||||
|
for (let i = 0; i < keys.length - 1; i++) {
|
||||||
|
context = context[keys[i]];
|
||||||
|
}
|
||||||
|
context[keys.at(-1)!] = value;
|
||||||
|
};
|
||||||
|
if (location.hostname === "localhost") {
|
||||||
|
globalThis.getContextStack = getContextStack;
|
||||||
|
globalThis.updateContextValue = updateContextValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var getContextStack: () => ContextStore[];
|
||||||
|
var updateContextValue: (key: string, value: unknown, depth?: number) => void;
|
||||||
|
var contextStack: ContextStore[];
|
||||||
|
}
|
||||||
|
@ -42,12 +42,12 @@ export class LoadState extends State<States> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const doodler = getContextItem<Doodler>("doodler");
|
const doodler = getContextItem<Doodler>("doodler");
|
||||||
this.layers.push(doodler.createLayer((_, __, dTime) => {
|
// this.layers.push(doodler.createLayer((_, __, dTime) => {
|
||||||
doodler.clearRect(new Vector(0, 0), doodler.width, doodler.height);
|
// doodler.clearRect(new Vector(0, 0), doodler.width, doodler.height);
|
||||||
doodler.fillRect(new Vector(0, 0), doodler.width, doodler.height, {
|
// doodler.fillRect(new Vector(0, 0), doodler.width, doodler.height, {
|
||||||
color: "#302040",
|
// color: "#302040",
|
||||||
});
|
// });
|
||||||
}));
|
// }));
|
||||||
}
|
}
|
||||||
override stop(): void {
|
override stop(): void {
|
||||||
// noop
|
// noop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user