// This file handles the "Add an instance" dialog import { FormDialog, ONCE } from "./dialog.mjs"; import { findButtonOrFail, findFormOrFail, findInputOrFail } from "./dom.mjs"; export function parseHost(host: string): { host: string, secure: boolean } | null { let parsedInstance = URL.parse(host); parsedInstance ??= URL.parse("https://" + host); if (!parsedInstance?.host) return null; if (!/https?:/.test(parsedInstance.protocol)) return null; return { host: parsedInstance.host, secure: parsedInstance.protocol === "https:" }; } export type AddInstanceDialogData = { host: string, secure: boolean, autoQueryMetadata: boolean, }; export class AddInstanceDialog extends FormDialog { protected instanceHost: HTMLInputElement; protected autoQueryMetadata: HTMLInputElement; protected closeButton: HTMLButtonElement; constructor(dialog: HTMLDialogElement, initializeDOM: boolean = true) { super(dialog, findFormOrFail(dialog, ".addInstanceForm")); this.instanceHost = findInputOrFail(this.form, "#instanceHost"); this.autoQueryMetadata = findInputOrFail(this.form, "#autoQueryMetadata"); this.closeButton = findButtonOrFail(this.form, ".close"); if (initializeDOM) this.initializeDOM(); } protected override initializeDOM() { super.initializeDOM(); this.instanceHost.addEventListener("input", e => this.#getDataIfValid()); this.closeButton.addEventListener("click", e => this.close()); } #getDataIfValid(): AddInstanceDialogData | null { const parsedHost = parseHost(this.instanceHost.value); if (parsedHost === null) { this.instanceHost.setCustomValidity("Invalid instance hostname or URL"); return null; } this.instanceHost.setCustomValidity(""); return { host: parsedHost.host, secure: parsedHost.secure, autoQueryMetadata: this.autoQueryMetadata.checked }; } #handleSubmit(resolve: (data: AddInstanceDialogData) => void) { this.form.addEventListener("submit", e => { const data = this.#getDataIfValid(); if (data === null) { // Prevent the user from submitting the form if it's invalid and let them try again e.preventDefault(); this.#handleSubmit(resolve); return; } resolve(data); this.close(); }, ONCE); } async present(): Promise { return new Promise((resolve, reject) => { this.cancelOnceClosed(reject); this.#handleSubmit(resolve); this.open(); }); } }