import { parseHost } from "./add_an_instance.mjs"; import { AddInstanceFlow } from "./add_instance_flow.mjs"; import { dialogDetailsFromInstance, dialogDetailsToInstance, InstanceDetailsDialog, InstanceDetailsDialogData } from "./confirm_instance_details.mjs"; import { findButtonOrFail, findDialogOrFail, findOlOrFail } from "./dom.mjs"; import storageManager, { Instance } from "./storage_manager.mjs"; let reordering = false; let unsaved = 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 startAddInstanceFlowButton = findButtonOrFail(document.body, "#startAddInstanceFlow"); const addDialog = findDialogOrFail(document.body, "#addInstance"); const spinnerDialog = findDialogOrFail(document.body, "#spinner"); const detailsDialog = findDialogOrFail(document.body, "#instanceDetails"); const instanceList = findOlOrFail(document.body, "#instanceList"); const saveButton = findButtonOrFail(document.body, "#save"); const reorderButton = findButtonOrFail(document.body, "#reorder"); let instanceDetailsDialog = new InstanceDetailsDialog(detailsDialog, true); let addInstanceFlow = new AddInstanceFlow(addDialog, spinnerDialog, instanceDetailsDialog); startAddInstanceFlowButton.addEventListener("click", e => { addInstanceFlow.start(false).then(_ => { updateInstanceList(); unsavedChanges(); }); }); saveButton.addEventListener("click", e => saveChanges()); reorderButton.addEventListener("click", () => { reordering = !reordering; if (!reordering) applyReordering(); updateInstanceList(); reorderButton.innerText = reordering ? "Finish reordering" : "Reorder"; }); updateInstanceList(); storageManager.addSaveCallback(updateInstanceList); mainDialog.show(); function saveChanges() { storageManager.save(); unsaved = false; saveButton.classList.remove("pulse-red"); } function unsavedChanges() { if (!unsaved) { unsaved = true; saveButton.classList.add("pulse-red"); } } async function editInstance(instance: Instance) { const data = dialogDetailsFromInstance(instance); const newData = await instanceDetailsDialog.present(data); dialogDetailsToInstance(newData, instance); unsavedChanges(); } function deleteInstance(instance: Instance) { storageManager.storage.instances.splice( storageManager.storage.instances.indexOf(instance) ); updateInstanceList(); unsavedChanges(); } 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 => editInstance(instance)); const deleteLink = document.createElement("a"); deleteLink.innerText = `Delete`; deleteLink.href = "#"; deleteLink.addEventListener("click", e => deleteInstance(instance)); 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]); unsavedChanges(); }