import { Packet, type_direction } from "./protocol.ts";
import createDebug from "debug";
const logger = createDebug("jsonview");
let selected = document.getElementById("explorer_selected")!;
let table = document.getElementById("explorer_json")!;
export function show_packet(
maybe_packet: Packet | null,
sequence_number: number,
) {
logger(`selected packet ${sequence_number}`);
if (maybe_packet === null) {
selected.textContent = "Selected: --";
table.innerHTML = "";
return;
}
let packet = maybe_packet!;
let direction = type_direction(packet.t);
selected.textContent = `Selected: #${sequence_number} ${direction} ${packet.t}`;
// iterate over everything and calculate a max depth
let max_depth = depthOf(packet.c);
logger(`indent depth ${max_depth}`);
// generate a tree
let tree = generateTree(packet.c, 0);
logger(`generating tree of ${tree.length} items`);
let table_html = "";
for (let i = 0; i < tree.length; i++) {
let [indent, key, value, is_text] = tree[i];
table_html += `
<tr>
<td style="padding-left: calc(var(--indent-spacing) * ${indent})" class="json-ident">${key}</td>
<td style="padding-left: calc(var(--indent-spacing) * ${
max_depth + 1
})" class="${
is_text ? "json-string" : "json-literal"
}">${value}</td>
</tr>
`;
}
table.innerHTML = `
<!-- Rendered tree of ${tree.length} items -->
<thead>
<tr></tr>
<tr></tr>
</thead>
<tbody>
${table_html}
</tbody>
`;
}
function depthOf(object: any) {
let level = 0;
for (let key in object) {
if (!object.hasOwnProperty(key)) continue;
if (typeof object[key] == "object") {
let depth = depthOf(object[key]) + 1;
level = Math.max(depth, level);
}
}
return level;
}
function generateTree(
object: any,
level: number,
): [indent: number, key: string, value: string, value_string: boolean][] {
let items: [
indent: number,
key: string,
value: string,
value_string: boolean,
][] = [];
for (let key in object) {
if (!object.hasOwnProperty(key)) continue;
if (object[key] === null) {
items.push([level, key, "null", false]);
} else if (object[key] === undefined) {
items.push([level, key, "undefined", false]);
} else if (typeof object[key] === "object") {
if (Array.isArray(object[key])) {
if (object[key].length == 0) {
items.push([level, key + ":", "[]", false]);
} else {
items.push([level, key + ":", "", false]);
}
for (let i = 0; i < object[key].length; i++) {
items.push([level + 1, i.toString() + ":", "", false]);
items = items.concat(generateTree(object[key][i], level + 2));
}
continue;
}
items.push([level, key + ":", "", false]);
items = items.concat(generateTree(object[key], level + 1));
} else if (Array.isArray(object[key])) {
for (let i = 0; i < object[key].length; i++) {
items.push([level, i.toString() + ":", "", false]);
items = items.concat(generateTree(object[key][i], level));
}
} else if (typeof object[key] === "string") {
items.push([level, key + ":", '"' + object[key] + '"', true]);
} else {
items.push([level, key + ":", object[key].toString(), false]);
}
}
return items;
}
export let packets: Packet[] = [];
export let selected_packet: number | null = null;
// @ts-ignore
let last_packet: Date | null = null;
// @ts-ignore
const log_body = document.getElementById("log_body")!;
// @ts-ignore
const up_arrow = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="log-icon log-leaving">
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18" />
</svg>`;
// @ts-ignore
const down_arrow = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="log-icon log-arriving">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" />
</svg>`;
export function selectPacket(id: number) {
console.log("selecting packet " + id);
if (selected_packet !== null) {
document
.getElementById("packet-" + selected_packet)!
.classList.remove("log-selected");
document
.getElementById("packet-" + selected_packet)!
.classList.add("log-item");
}
document.getElementById("packet-" + id)!.classList.add("log-selected");
document.getElementById("packet-" + id)!.classList.remove("log-item");
selected_packet = id;
show_packet(packets[id], id);
}
export function appendPacket(packet: Packet) {
packets.push(packet);
return;
/*
let duration = "--";
if (last_packet !== null) {
duration = (new Date().getTime() - last_packet!.getTime()).toString() + "ms";
}
last_packet = new Date();
let index_deepcopy = packets.length + 1;
let index = index_deepcopy - 2;
let tr = document.createElement("tr");
tr.classList.add("log-item");
tr.id = "packet-" + index;
let td_idx = document.createElement("td");
td_idx.innerHTML = index.toString();
td_idx.classList.add("log-td");
tr.appendChild(td_idx);
let td_direction = document.createElement("td");
td_direction.innerHTML = type_direction(packet.t) == Direction.Clientbound ? down_arrow : up_arrow;
td_direction.classList.add("log-td");
tr.appendChild(td_direction);
let td_type = document.createElement("td");
td_type.innerHTML = packet.t;
td_type.classList.add("log-td");
tr.appendChild(td_type);
let td_ts = document.createElement("td");
td_ts.innerHTML = duration;
td_ts.classList.add(type_direction(packet.t) == Direction.Clientbound ? "log-arriving" : "log-leaving")
td_ts.classList.add("log-td");
tr.appendChild(td_ts);
tr.onclick = () => {
selectPacket(index);
};
log_body.appendChild(tr);
log_body.scrollTop = log_body.scrollHeight;
*/
}