import { parseHost } from "./add_an_instance.mjs"; import { initializeAddInstanceFlow } from "./add_instance_flow.mjs"; import { initializeInstanceDetailsDialog } from "./confirm_instance_details.mjs"; import { findButtonOrFail, findDialogOrFail, findOlOrFail } from "./dom.mjs"; import storageManager from "./storage_manager.mjs"; let reordering = false; // Dragging code is a heavily modified version of https://stackoverflow.com/a/28962290 let elementBeingDragged: HTMLLIElement | undefined; const mainDialog = findDialogOrFail(document.body, "#mainDialog"); const showAddInstanceDialogButton = findButtonOrFail(document.body, "#showAddInstanceDialog"); const detailsDialog = findDialogOrFail(document.body, "#instanceDetails"); const addDialog = findDialogOrFail(document.body, "#addInstance"); const instanceList = findOlOrFail(document.body, "#instanceList"); const saveButton = findButtonOrFail(document.body, "#save"); const reorderButton = findButtonOrFail(document.body, "#reorder"); showAddInstanceDialogButton.addEventListener("click", e => showAddInstanceDialog()); saveButton.addEventListener("click", e => { storageManager.save(); }); reorderButton.addEventListener("click", () => { reordering = !reordering; if (!reordering) applyReordering(); updateInstanceList(); reorderButton.innerText = reordering ? "Finish reordering" : "Reorder"; }); const { showInstanceDetailsDialog, hideInstanceDetailsDialog, populateInstanceDetailsDialog, } = initializeInstanceDetailsDialog(detailsDialog, () => { }); const { showAddInstanceDialog, hideAddInstanceDialog } = initializeAddInstanceFlow(detailsDialog, addDialog); updateInstanceList(); storageManager.addSaveCallback(updateInstanceList); mainDialog.show(); function updateInstanceList() { instanceList.replaceChildren(); // Erase all child nodes instanceList.style.listStyleType = reordering ? "\"≡ \"" : "disc"; for (let n = 0; n < storageManager.storage.instances.length; n++) { const instance = storageManager.storage.instances[n]; const li = document.createElement("li"); li.setAttribute("x-option", n.toString()); const label = document.createElement("label"); label.htmlFor = instance.origin; label.innerText = instance.name + " "; label.style.cursor = "inherit"; if (instance.iconURL) { const img = new Image(); img.src = instance.iconURL; img.alt = `${instance.name} icon`; img.className = "inlineIcon medium-height"; label.append(img, " "); } if (reordering) { li.draggable = true; li.addEventListener("dragstart", e => { if (e.dataTransfer === null) return; if (!(e.target instanceof HTMLLIElement)) return; e.dataTransfer.effectAllowed = "move"; e.dataTransfer.setData("text/plain", ""); elementBeingDragged = e.target; }); li.addEventListener("dragover", e => { if (elementBeingDragged === undefined) return; if (!(e.target instanceof HTMLElement)) return; const listElement = e.target.closest("li"); if (listElement === null) return; if (listElement.parentNode === null) return; if (isBefore(elementBeingDragged, listElement)) listElement.parentNode.insertBefore(elementBeingDragged, listElement); else listElement.parentNode.insertBefore(elementBeingDragged, listElement.nextSibling); e.preventDefault(); }); li.addEventListener("dragenter", e => e.preventDefault()); li.style.cursor = "grab"; } else { const editLink = document.createElement("a"); editLink.innerText = `Edit`; editLink.href = "#"; editLink.addEventListener("click", e => { const host = parseHost(instance.origin)!; populateInstanceDetailsDialog( instance.name, host.host, host.secure, instance.software, instance.iconURL ?? null ); showInstanceDetailsDialog(); }); const deleteLink = document.createElement("a"); deleteLink.innerText = `Delete`; deleteLink.href = "#"; deleteLink.addEventListener("click", e => { storageManager.storage.instances.splice( storageManager.storage.instances.indexOf(instance) ); updateInstanceList(); }); label.append(editLink, " ", deleteLink); } li.appendChild(label); instanceList.appendChild(li); } } function isBefore(el1: HTMLLIElement, el2: HTMLLIElement) { if (el2.parentNode === el1.parentNode) for (let cur = el1.previousSibling; cur && cur.nodeType !== 9; cur = cur.previousSibling) if (cur === el2) return true; return false; } function applyReordering() { const indices: number[] = []; for (const el of instanceList.children) { if (!(el instanceof HTMLLIElement)) continue; const option = el.getAttribute("x-option"); if (option === null) continue; indices.push(parseInt(option)); } storageManager.storage.instances = indices.map(i => storageManager.storage.instances[i]); }