perf: Refactor menu item height synchronization to prevent layout thrashing and introduce a debounced resize listener.

This commit is contained in:
Kantine Wrapper
2026-03-12 11:28:32 +01:00
parent d1d355d3c2
commit b5568c964b
10 changed files with 186 additions and 57 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

21
dist/install.html vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1578,9 +1578,10 @@ function setLangMode(lang) {
/* harmony export */ OR: () => (/* binding */ renderVisibleWeeks),
/* harmony export */ Ux: () => (/* binding */ checkForUpdates),
/* harmony export */ gJ: () => (/* binding */ updateNextWeekBadge),
/* harmony export */ showErrorModal: () => (/* binding */ showErrorModal)
/* harmony export */ showErrorModal: () => (/* binding */ showErrorModal),
/* harmony export */ wy: () => (/* binding */ syncMenuItemHeights)
/* harmony export */ });
/* unused harmony exports syncMenuItemHeights, createDayCard, fetchVersions, updateCountdown, removeCountdown */
/* unused harmony exports createDayCard, fetchVersions, updateCountdown, removeCountdown */
/* harmony import */ var _state_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(901);
/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(413);
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521);
@@ -1738,23 +1739,39 @@ function renderVisibleWeeks() {
function syncMenuItemHeights(grid) {
const cards = grid.querySelectorAll('.menu-card');
if (cards.length === 0) return;
// 1. Gather all menu-item groups (rows) across cards
const itemRows = [];
let maxItems = 0;
cards.forEach(card => {
maxItems = Math.max(maxItems, card.querySelectorAll('.menu-item').length);
const cardItems = Array.from(cards).map(card => {
const items = Array.from(card.querySelectorAll('.menu-item'));
maxItems = Math.max(maxItems, items.length);
return items;
});
for (let i = 0; i < maxItems; i++) {
let maxHeight = 0;
const itemsAtPos = [];
cards.forEach(card => {
const items = card.querySelectorAll('.menu-item');
if (items[i]) {
items[i].style.height = 'auto';
maxHeight = Math.max(maxHeight, items[i].offsetHeight);
itemsAtPos.push(items[i]);
}
});
itemsAtPos.forEach(item => { item.style.height = `${maxHeight}px`; });
// Collect i-th item from each card (forming a "row")
itemRows[i] = cardItems.map(items => items[i]).filter(item => !!item);
}
// 2. Batch Reset (Write phase) - clear old heights to let them flow naturally
itemRows.flat().forEach(item => {
item.style.height = 'auto';
});
// 3. Batch Read (Read phase) - measure all heights in one pass to avoid layout thrashing
const rowMaxHeights = itemRows.map(row => {
return Math.max(...row.map(item => item.offsetHeight));
});
// 4. Batch Apply (Write phase) - set synchronized heights
itemRows.forEach((row, i) => {
const height = `${rowMaxHeights[i]}px`;
row.forEach(item => {
item.style.height = height;
});
});
}
function createDayCard(day) {
@@ -2329,6 +2346,7 @@ function updateAlarmBell() {
/* harmony export */ U4: () => (/* binding */ isNewer),
/* harmony export */ ZD: () => (/* binding */ escapeHtml),
/* harmony export */ gs: () => (/* binding */ getRelativeTime),
/* harmony export */ sg: () => (/* binding */ debounce),
/* harmony export */ sn: () => (/* binding */ getISOWeek)
/* harmony export */ });
/* unused harmony export splitLanguage */
@@ -2582,6 +2600,18 @@ function getLocalizedText(text) {
return split.de || split.raw;
}
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/***/ }
@@ -2884,6 +2914,8 @@ var constants = __webpack_require__(521);
var api = __webpack_require__(672);
// EXTERNAL MODULE: ./src/i18n.js
var i18n = __webpack_require__(646);
// EXTERNAL MODULE: ./src/utils.js
var utils = __webpack_require__(413);
;// ./src/events.js
@@ -2892,6 +2924,7 @@ var i18n = __webpack_require__(646);
/**
* Updates all static UI labels/tooltips to match the current language.
* Called when the user switches the language toggle.
@@ -3251,6 +3284,12 @@ function bindEvents() {
(0,actions/* updateAuthUI */.i_)();
(0,ui_helpers/* renderVisibleWeeks */.OR)();
});
// Sync heights on window resize (FR-Performance)
window.addEventListener('resize', (0,utils/* debounce */.sg)(() => {
const grid = document.querySelector('.days-grid');
if (grid) (0,ui_helpers/* syncMenuItemHeights */.wy)(grid);
}, 150));
}
;// ./src/index.js