Release Nouri 1.3.0 with improved food states and quick entry flow

This commit is contained in:
2026-04-15 11:29:19 +02:00
parent 06be1371d3
commit 5e9beb1d98
22 changed files with 423 additions and 38 deletions
+115
View File
@@ -1,4 +1,62 @@
(() => {
const scrollStorageKey = () => `nouri-scroll:${window.location.pathname}${window.location.search}`;
const initPostFormScrollMemory = () => {
const restoreFromUrl = () => {
const currentUrl = new URL(window.location.href);
const rawScroll = currentUrl.searchParams.get("_scroll");
if (!rawScroll) return false;
const scrollValue = Number.parseInt(rawScroll, 10);
currentUrl.searchParams.delete("_scroll");
window.requestAnimationFrame(() => {
if (Number.isFinite(scrollValue)) {
window.scrollTo({ top: scrollValue, left: 0, behavior: "auto" });
}
window.history.replaceState({}, "", currentUrl.toString());
});
return true;
};
const restoreFromStorage = () => {
const savedScroll = sessionStorage.getItem(scrollStorageKey());
if (!savedScroll) return;
sessionStorage.removeItem(scrollStorageKey());
const scrollValue = Number.parseInt(savedScroll, 10);
if (!Number.isFinite(scrollValue)) return;
window.requestAnimationFrame(() => {
window.scrollTo({ top: scrollValue, left: 0, behavior: "auto" });
});
};
if (!restoreFromUrl()) {
restoreFromStorage();
}
document.addEventListener("submit", (event) => {
const form = event.target;
if (!(form instanceof HTMLFormElement)) return;
const method = (form.getAttribute("method") || "get").toLowerCase();
if (method !== "post") return;
const scrollValue = String(Math.round(window.scrollY));
sessionStorage.setItem(scrollStorageKey(), scrollValue);
let scrollInput = form.querySelector('input[name="_scroll"]');
if (!(scrollInput instanceof HTMLInputElement)) {
scrollInput = document.createElement("input");
scrollInput.type = "hidden";
scrollInput.name = "_scroll";
form.appendChild(scrollInput);
}
scrollInput.value = scrollValue;
});
};
const initMobileSheet = () => {
const sheet = document.querySelector("[data-mobile-sheet]");
const navStack = document.querySelector("[data-mobile-nav-stack]");
@@ -153,9 +211,66 @@
}, { passive: false });
};
const initDialogs = () => {
document.addEventListener("click", (event) => {
const openButton = event.target.closest("[data-dialog-open]");
if (openButton instanceof HTMLElement) {
const dialogId = openButton.getAttribute("data-dialog-open");
if (!dialogId) return;
const dialog = document.getElementById(dialogId);
if (dialog instanceof HTMLDialogElement) {
dialog.showModal();
}
return;
}
const closeButton = event.target.closest("[data-dialog-close]");
if (closeButton instanceof HTMLElement) {
const dialog = closeButton.closest("dialog");
if (dialog instanceof HTMLDialogElement) {
dialog.close();
}
}
});
document.addEventListener("keydown", (event) => {
const target = event.target;
if (!(target instanceof HTMLElement)) return;
const openButton = target.closest("[data-dialog-open]");
if (!(openButton instanceof HTMLElement)) return;
if (event.key !== "Enter" && event.key !== " ") return;
event.preventDefault();
const dialogId = openButton.getAttribute("data-dialog-open");
if (!dialogId) return;
const dialog = document.getElementById(dialogId);
if (dialog instanceof HTMLDialogElement) {
dialog.showModal();
}
});
document.querySelectorAll("dialog").forEach((dialog) => {
dialog.addEventListener("click", (event) => {
if (event.target === dialog && dialog instanceof HTMLDialogElement) {
dialog.close();
}
});
});
document.addEventListener("keydown", (event) => {
if (event.key !== "Escape") return;
document.querySelectorAll("dialog[open]").forEach((dialog) => {
if (dialog instanceof HTMLDialogElement) {
dialog.close();
}
});
});
};
document.addEventListener("DOMContentLoaded", () => {
initPostFormScrollMemory();
initMobileSheet();
initFilterInputs();
initIosPullToRefresh();
initDialogs();
});
})();