const loadingDialog = { dialog: document.querySelector("dialog#loading-dialog"), init() { this.dialog.addEventListener("cancel", (ev) => { ev.preventDefault(); }); }, show() { this.dialog.showModal(); }, close() { this.dialog.close(); }, }; const errorDialog = { dialog: document.querySelector("dialog#error-dialog"), error: document.querySelector("textarea#error"), reload: document.querySelector("button#error-reload"), init() { this.dialog.addEventListener("close", (ev) => { window.location.reload(); }); this.reload.addEventListener("click", (ev) => { window.location.href = "/"; }); }, show(err) { this.error.value = err; console.error(err); this.dialog.showModal(); }, }; const urlDialog = { dialog: document.querySelector("dialog#url-dialog"), url: document.querySelector("input#url"), urlCopy: document.querySelector("button#url-copy"), close: document.querySelector("button#url-close"), init() { this.dialog.addEventListener("close", (ev) => {}); this.urlCopy.addEventListener("click", (ev) => { this.url.select(); this.url.setSelectionRange(0, 99999); navigator.clipboard.writeText(this.url.value); }); this.close.addEventListener("click", (ev) => { this.dialog.close(); }); }, show(url) { this.url.value = url; this.dialog.showModal(); }, }; const notFoundDialog = { dialog: document.querySelector("dialog#not-found"), close: document.querySelector("button#not-found-close"), init() { this.dialog.addEventListener("close", (ev) => { window.location.hash = ""; window.location.reload(); }); this.close.addEventListener("click", (ev) => { window.location.hash = ""; window.location.reload(); }); }, show() { this.dialog.showModal(); }, }; const viewDialog = { dialog: document.querySelector("dialog#view-dialog"), password: document.querySelector("textarea#view-password"), close: document.querySelector("button#view-close"), init() { this.dialog.addEventListener("close", (ev) => { window.location.hash = ""; window.location.reload(); }); this.close.addEventListener("click", (ev) => { this.dialog.close(); }); }, show(password) { this.password.value = password; this.dialog.showModal(); }, }; const confirmViewDialog = { dialog: document.querySelector("dialog#confirm-view-dialog"), cancel: document.querySelector("button#view-cancel"), confirm: document.querySelector("button#view-confirm"), resolve: null, reject: null, init() { this.dialog.addEventListener("cancel", (ev) => { this.dialog.close(); this.resolve(false); }); this.cancel.addEventListener("click", (ev) => { this.dialog.close(); this.resolve(false); }); this.confirm.addEventListener("click", (ev) => { this.dialog.close(); this.resolve(true); }); }, show() { return new Promise((resolve, reject) => { this.resolve = resolve; this.reject = reject; this.dialog.showModal(); }); }, }; async function viewPassword() { try { loadingDialog.show(); let id, key, iv; // We need to be backwards compatible with old links that still use the query if (window.location.search.trim() != "") { const params = new URLSearchParams(window.location.search); id = params.get("id"); key = params.get("key"); iv = params.get("iv"); } else { // Need to remove leading "#" const hash = window.location.hash.substring(1); const split = hash.split(":"); id = split[0]; key = split[1]; iv = split[2]; } const exists = await hasPassword(id); if (!exists) { notFoundDialog.show(); return; } const shouldView = await confirmViewDialog.show(); if (!shouldView) { // This is needed for the redirect, otherwise the user won't get redirected setTimeout(() => { window.location.hash = ""; window.location.reload(); }, 0); return; } const encrypted = await getPassword(id); const password = await decryptPassword(encrypted, key, iv); viewDialog.show(password); } catch (error) { errorDialog.show(error); } finally { loadingDialog.close(); } } const enterPassword = document.querySelector("form#enter-password"); enterPassword.addEventListener("submit", async (ev) => { try { loadingDialog.show(); ev.preventDefault(); const data = new FormData(ev.target); const password = await encryptPassword(data.get("password")); const id = await uploadPassword( password.password, parseInt(data.get("expires-in")), ); const url = new URL(window.location); url.hash = [id, password.key, password.iv].join(":"); urlDialog.show(url.toString()); } catch (error) { errorDialog.show(error); } finally { loadingDialog.close(); } }); loadingDialog.init(); errorDialog.init(); urlDialog.init(); notFoundDialog.init(); viewDialog.init(); confirmViewDialog.init(); const hash = window.location.hash; if (hash.trim() != "") { viewPassword(); } // We need to be backwards compatible with the old links const query = window.location.search; if (query.trim() != "") { viewPassword(); }