Revert optimisations sidebar/fetch qui causaient des blocages navigateur

Retour a l'etat 408ab76. Les tentatives d'optimisation du nombre
de fetch (sidebar unique, config partagee, sequencement) causaient
des blocages sur Chrome/Firefox. On garde les features (forget wifi,
hotspot badge, UI wifi) mais on revient au chargement d'origine.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
PaulVua
2026-03-17 18:48:38 +01:00
parent ffead8597a
commit 8f88eae575
11 changed files with 255 additions and 219 deletions

View File

@@ -412,20 +412,23 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
}) element.innerHTML = data;
.catch(e => console.error('Error loading sidebar:', e)); }
})
.catch(error => console.error(`Error loading ${file}:`, error));
});
}); });
//end document.addEventListener //end document.addEventListener

View File

@@ -5,31 +5,25 @@
* - Shows/Hides "Screen" sidebar tab based on device type * - Shows/Hides "Screen" sidebar tab based on device type
* - Updates sidebar device name * - Updates sidebar device name
* - Shows hotspot badge in sidebar when in hotspot mode * - Shows hotspot badge in sidebar when in hotspot mode
*
* Fetches config at window.onload (not DOMContentLoaded) to avoid
* saturating the browser's 6-connection-per-domain limit.
*/ */
(function() { document.addEventListener('DOMContentLoaded', () => {
let config = null; let config = null;
// Observe DOM changes to apply config when sidebar/topbar are loaded // Fetch config once
fetch('launcher.php?type=get_config_sqlite')
.then(response => response.json())
.then(data => {
config = data;
applyConfig(); // Apply immediately if elements are ready
})
.catch(error => console.error('Error loading config:', error));
// Observe DOM changes to handle dynamically loaded elements (sidebar, topbar)
const observer = new MutationObserver(() => { const observer = new MutationObserver(() => {
if (config) applyConfig(); if (config) applyConfig();
}); });
observer.observe(document.body, { childList: true, subtree: true });
// Fetch config after all initial resources are loaded observer.observe(document.body, { childList: true, subtree: true });
window.addEventListener('load', () => {
fetch('launcher.php?type=get_config_sqlite')
.then(response => response.json())
.then(data => {
config = data;
window._nebuleairConfig = data;
applyConfig();
document.dispatchEvent(new CustomEvent('nebuleair-config-ready', { detail: data }));
})
.catch(error => console.error('Error loading config:', error));
});
function applyConfig() { function applyConfig() {
if (!config) return; if (!config) return;
@@ -39,12 +33,13 @@
// 1. Topbar Logo Logic // 1. Topbar Logo Logic
const logo = document.getElementById('topbar-logo'); const logo = document.getElementById('topbar-logo');
if (logo && isModuleAirPro) { if (logo && isModuleAirPro) {
// prevent unnecessary re-assignments
if (!logo.src.includes('logoModuleAir.png')) { if (!logo.src.includes('logoModuleAir.png')) {
logo.src = 'assets/img/logoModuleAir.png'; logo.src = 'assets/img/logoModuleAir.png';
} }
} }
// 2. Sidebar Screen Tab Logic // 2. Sidebar Screen Tab Logic - Use class since ID might be duplicated (desktop/mobile)
const navScreenElements = document.querySelectorAll('.nav-screen-item'); const navScreenElements = document.querySelectorAll('.nav-screen-item');
if (navScreenElements.length > 0) { if (navScreenElements.length > 0) {
navScreenElements.forEach(navScreen => { navScreenElements.forEach(navScreen => {
@@ -73,4 +68,4 @@
badge.style.display = (config.WIFI_status === 'hotspot') ? '' : 'none'; badge.style.display = (config.WIFI_status === 'hotspot') ? '' : 'none';
}); });
} }
})(); });

View File

@@ -181,6 +181,15 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
console.log("DOMContentLoaded"); console.log("DOMContentLoaded");
const elementsToLoad = [
{ id: 'topbar', file: 'topbar.html' },
{ id: 'sidebar', file: 'sidebar.html' },
{ id: 'sidebar_mobile', file: 'sidebar.html' }
];
let loadedCount = 0;
const totalElements = elementsToLoad.length;
function applyTranslationsWhenReady() { function applyTranslationsWhenReady() {
if (typeof i18n !== 'undefined' && i18n.translations && Object.keys(i18n.translations).length > 0) { if (typeof i18n !== 'undefined' && i18n.translations && Object.keys(i18n.translations).length > 0) {
console.log("Applying translations to dynamically loaded content"); console.log("Applying translations to dynamically loaded content");
@@ -191,28 +200,23 @@
} }
} }
let loadedCount = 0; elementsToLoad.forEach(({ id, file }) => {
fetch(file)
.then(response => response.text())
.then(data => {
const element = document.getElementById(id);
if (element) {
element.innerHTML = data;
}
loadedCount++;
// Load topbar // Re-apply translations after all dynamic content is loaded
fetch('topbar.html') if (loadedCount === totalElements) {
.then(r => r.text()) applyTranslationsWhenReady();
.then(data => { }
document.getElementById('topbar').innerHTML = data; })
loadedCount++; .catch(error => console.error(`Error loading ${file}:`, error));
if (loadedCount === 2) applyTranslationsWhenReady(); });
})
.catch(e => console.error('Error loading topbar:', e));
// Load sidebar once, reuse for desktop + mobile
fetch('sidebar.html')
.then(r => r.text())
.then(data => {
document.getElementById('sidebar').innerHTML = data;
document.getElementById('sidebar_mobile').innerHTML = data;
loadedCount++;
if (loadedCount === 2) applyTranslationsWhenReady();
})
.catch(e => console.error('Error loading sidebar:', e));
// Also listen for language change events to re-apply translations // Also listen for language change events to re-apply translations
document.addEventListener('languageChanged', function() { document.addEventListener('languageChanged', function() {

View File

@@ -136,28 +136,27 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { { id: 'sidebar_mobile', file: 'sidebar.html' }
document.getElementById('topbar').innerHTML = data; ];
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
})
.catch(e => console.error('Error loading topbar:', e));
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
if (window.i18n && typeof window.i18n.applyTranslations === 'function') { element.innerHTML = data;
window.i18n.applyTranslations(); // Apply translations after loading dynamic content
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
} }
}) })
.catch(e => console.error('Error loading sidebar:', e)); .catch(error => console.error(`Error loading ${file}:`, error));
});
}); });

View File

@@ -96,20 +96,23 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
}) element.innerHTML = data;
.catch(e => console.error('Error loading sidebar:', e)); }
})
.catch(error => console.error(`Error loading ${file}:`, error));
});
const loop_card_content = document.getElementById('card_loop_content'); const loop_card_content = document.getElementById('card_loop_content');
const boot_card_content = document.getElementById('card_boot_content'); const boot_card_content = document.getElementById('card_boot_content');

View File

@@ -121,20 +121,23 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
}) element.innerHTML = data;
.catch(e => console.error('Error loading sidebar:', e)); }
})
.catch(error => console.error(`Error loading ${file}:`, error));
});

View File

@@ -397,20 +397,23 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
}) element.innerHTML = data;
.catch(e => console.error('Error loading sidebar:', e)); }
})
.catch(error => console.error(`Error loading ${file}:`, error));
});
//OLD way to retreive data from JSON //OLD way to retreive data from JSON
/* /*

View File

@@ -108,37 +108,34 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { { id: 'sidebar_mobile', file: 'sidebar.html' }
document.getElementById('topbar').innerHTML = data; ];
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
})
.catch(e => console.error('Error loading topbar:', e));
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
const sidebar = document.getElementById('sidebar'); const element = document.getElementById(id);
const sidebarMobile = document.getElementById('sidebar_mobile'); if (element) {
sidebar.innerHTML = data; element.innerHTML = data;
sidebarMobile.innerHTML = data; // Apply translations after loading dynamic content
if (window.i18n && typeof window.i18n.applyTranslations === 'function') { if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations(); window.i18n.applyTranslations();
} }
// Ensure the screen tab is visible in both sidebars // Ensure the screen tab is visible here as well
setTimeout(() => { if (id.includes('sidebar')) {
[sidebar, sidebarMobile].forEach(el => { setTimeout(() => {
const navScreenElements = el.querySelectorAll('.nav-screen-item'); const navScreenElements = element.querySelectorAll('.nav-screen-item');
navScreenElements.forEach(item => item.style.display = 'flex'); navScreenElements.forEach(el => el.style.display = 'flex');
}); }, 100);
}, 100); }
}) }
.catch(e => console.error('Error loading sidebar:', e)); })
.catch(error => console.error(`Error loading ${file}:`, error));
});
// Translation fallback for now if keys are missing // Translation fallback for now if keys are missing
setTimeout(() => { setTimeout(() => {

View File

@@ -89,28 +89,27 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { { id: 'sidebar_mobile', file: 'sidebar.html' }
document.getElementById('topbar').innerHTML = data; ];
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
})
.catch(e => console.error('Error loading topbar:', e));
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
if (window.i18n && typeof window.i18n.applyTranslations === 'function') { element.innerHTML = data;
window.i18n.applyTranslations(); // Apply translations after loading dynamic content
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
} }
}) })
.catch(e => console.error('Error loading sidebar:', e)); .catch(error => console.error(`Error loading ${file}:`, error));
});
}); });
function getNPM_values(port) { function getNPM_values(port) {

View File

@@ -179,20 +179,23 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
element.innerHTML = data;
}
}) })
.catch(e => console.error('Error loading sidebar:', e)); .catch(error => console.error(`Error loading ${file}:`, error));
});
// Initialize elements // Initialize elements
initializeElements(); initializeElements();

View File

@@ -215,24 +215,23 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
console.log("DOMContentLoaded"); console.log("DOMContentLoaded");
// Load topbar const elementsToLoad = [
fetch('topbar.html') { id: 'topbar', file: 'topbar.html' },
.then(r => r.text()) { id: 'sidebar', file: 'sidebar.html' },
.then(data => { document.getElementById('topbar').innerHTML = data; }) { id: 'sidebar_mobile', file: 'sidebar.html' }
.catch(e => console.error('Error loading topbar:', e)); ];
// Load sidebar once, reuse for desktop + mobile elementsToLoad.forEach(({ id, file }) => {
fetch('sidebar.html') fetch(file)
.then(r => r.text()) .then(response => response.text())
.then(data => { .then(data => {
document.getElementById('sidebar').innerHTML = data; const element = document.getElementById(id);
document.getElementById('sidebar_mobile').innerHTML = data; if (element) {
// Re-apply translations to dynamically loaded sidebar element.innerHTML = data;
if (typeof i18n !== 'undefined' && i18n.translations) { }
i18n.applyTranslations(); })
} .catch(error => console.error(`Error loading ${file}:`, error));
}) });
.catch(e => console.error('Error loading sidebar:', e));
}); });
@@ -564,40 +563,68 @@ function get_internet(){
// Wait for config loaded by topbar-logo.js (fires after window.onload) window.onload = function() {
document.addEventListener('nebuleair-config-ready', function(e) { $.ajax({
const data = e.detail; url: 'launcher.php?type=get_config_sqlite',
console.log("Config loaded (wifi page):"); dataType: 'json',
console.log(data); method: 'GET',
success: function(data) {
console.log("Getting SQLite config table (wifi page):");
console.log(data);
const WIFI_statusElement = document.getElementById("wifi-status"); // WiFi connection status — toggle cards
console.log("WIFI is: " + data.WIFI_status); const WIFI_statusElement = document.getElementById("wifi-status");
console.log("WIFI is: " + data.WIFI_status);
if (data.WIFI_status === "connected") { if (data.WIFI_status === "connected") {
WIFI_statusElement.textContent = "Connected"; WIFI_statusElement.textContent = "Connected";
WIFI_statusElement.className = "badge text-bg-success"; WIFI_statusElement.className = "badge text-bg-success";
document.getElementById('btn-forget-wifi').style.display = 'inline-block'; document.getElementById('btn-forget-wifi').style.display = 'inline-block';
document.getElementById('card-connection-info').style.display = ''; document.getElementById('card-connection-info').style.display = '';
document.getElementById('card-hotspot-info').style.display = 'none'; document.getElementById('card-hotspot-info').style.display = 'none';
document.getElementById('card-wifi-scan').style.display = 'none'; document.getElementById('card-wifi-scan').style.display = 'none';
get_internet(); // Auto-load connection details
} else if (data.WIFI_status === "hotspot") { get_internet();
WIFI_statusElement.textContent = "Hotspot"; } else if (data.WIFI_status === "hotspot") {
WIFI_statusElement.className = "badge text-bg-warning"; WIFI_statusElement.textContent = "Hotspot";
document.getElementById('btn-forget-wifi').style.display = 'none'; WIFI_statusElement.className = "badge text-bg-warning";
document.getElementById('card-connection-info').style.display = 'none'; document.getElementById('btn-forget-wifi').style.display = 'none';
document.getElementById('card-hotspot-info').style.display = ''; document.getElementById('card-connection-info').style.display = 'none';
document.getElementById('card-wifi-scan').style.display = ''; document.getElementById('card-hotspot-info').style.display = '';
wifi_scan(); document.getElementById('card-wifi-scan').style.display = '';
} else { // Auto-load cached scan results in hotspot mode
WIFI_statusElement.textContent = "Unknown"; wifi_scan();
WIFI_statusElement.className = "badge text-bg-secondary"; } else {
document.getElementById('btn-forget-wifi').style.display = 'none'; WIFI_statusElement.textContent = "Unknown";
document.getElementById('card-connection-info').style.display = 'none'; WIFI_statusElement.className = "badge text-bg-secondary";
document.getElementById('card-hotspot-info').style.display = 'none'; document.getElementById('btn-forget-wifi').style.display = 'none';
document.getElementById('card-wifi-scan').style.display = ''; document.getElementById('card-connection-info').style.display = 'none';
} document.getElementById('card-hotspot-info').style.display = 'none';
}); document.getElementById('card-wifi-scan').style.display = '';
}
// Always load ethernet info
load_ethernet_info();
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
// Load RTC time
$.ajax({
url: 'launcher.php?type=RTC_time',
dataType: 'text',
method: 'GET',
success: function(response) {
const RTC_Element = document.getElementById("RTC_time");
if (RTC_Element) RTC_Element.textContent = response;
},
error: function(xhr, status, error) {
console.error('AJAX request failed:', status, error);
}
});
}
</script> </script>