Files
nebuleair_pro_4g/html/screen.html
PaulVua 5849190220 Fix: sidebar.html charge une seule fois au lieu de deux sur toutes les pages
Reduit de 3 a 2 les fetch au DOMContentLoaded, liberant un slot
de connexion HTTP. Corrige le blocage "pending" cause par la limite
de 6 connexions simultanees par domaine dans Chrome/Firefox.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:32:22 +01:00

182 lines
7.9 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Screen Control</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<style>
body {
overflow-x: hidden;
}
#sidebar a.nav-link {
position: relative;
display: flex;
align-items: center;
}
#sidebar a.nav-link:hover {
background-color: rgba(0, 0, 0, 0.5);
}
#sidebar a.nav-link svg {
margin-right: 8px;
/* Add spacing between icons and text */
}
#sidebar {
transition: transform 0.3s ease-in-out;
}
.offcanvas-backdrop {
z-index: 1040;
}
</style>
</head>
<body>
<!-- Topbar -->
<span id="topbar"></span>
<!-- Sidebar Offcanvas for Mobile -->
<div class="offcanvas offcanvas-start text-white bg-dark" tabindex="-1" id="sidebarOffcanvas"
aria-labelledby="sidebarOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="sidebarOffcanvasLabel">NebuleAir</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas"
aria-label="Close"></button>
</div>
<div class="offcanvas-body" id="sidebar_mobile">
</div>
</div>
<div class="container-fluid mt-5">
<div class="row">
<aside class="col-md-2 col-lg-1 d-none d-md-block vh-100 position-fixed bg-dark text-white" id="sidebar">
</aside>
<!-- Main content -->
<main class="col-md-9 ms-sm-auto col-lg-10 offset-md-3 offset-lg-2 px-md-4">
<h1 class="mt-4" data-i18n="screen.title">Contrôle de l'écran</h1>
<p data-i18n="screen.description">Gérer l'affichage sur l'écran HDMI.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Actions</h5>
<p class="card-text">Démarrer ou arrêter l'application d'affichage sur l'écran HDMI.</p>
<button id="startBtn" class="btn btn-success m-2" onclick="controlScreen('start')">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-play-fill" viewBox="0 0 16 16">
<path
d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z" />
</svg>
Démarrer
</button>
<button id="stopBtn" class="btn btn-danger m-2" onclick="controlScreen('stop')">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-stop-fill" viewBox="0 0 16 16">
<path
d="M5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11V5A1.5 1.5 0 0 1 5 3.5z" />
</svg>
Arrêter
</button>
</div>
</div>
</div>
</div>
<div id="status-message" class="mt-3 col-md-6"></div>
</main>
</div>
</div>
<!-- JAVASCRIPT -->
<!-- Link Ajax locally -->
<script src="assets/jquery/jquery-3.7.1.min.js"></script>
<!-- Link Bootstrap JS and Popper.js locally -->
<script src="assets/js/bootstrap.bundle.js"></script>
<!-- i18n translation system -->
<script src="assets/js/i18n.js"></script>
<script src="assets/js/topbar-logo.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Load topbar
fetch('topbar.html')
.then(r => r.text())
.then(data => {
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
fetch('sidebar.html')
.then(r => r.text())
.then(data => {
const sidebar = document.getElementById('sidebar');
const sidebarMobile = document.getElementById('sidebar_mobile');
sidebar.innerHTML = data;
sidebarMobile.innerHTML = data;
if (window.i18n && typeof window.i18n.applyTranslations === 'function') {
window.i18n.applyTranslations();
}
// Ensure the screen tab is visible in both sidebars
setTimeout(() => {
[sidebar, sidebarMobile].forEach(el => {
const navScreenElements = el.querySelectorAll('.nav-screen-item');
navScreenElements.forEach(item => item.style.display = 'flex');
});
}, 100);
})
.catch(e => console.error('Error loading sidebar:', e));
// Translation fallback for now if keys are missing
setTimeout(() => {
if (document.querySelector('[data-i18n="screen.title"]').innerText === "screen.title") {
document.querySelector('[data-i18n="screen.title"]').innerText = "Contrôle de l'écran";
}
if (document.querySelector('[data-i18n="screen.description"]').innerText === "screen.description") {
document.querySelector('[data-i18n="screen.description"]').innerText = "Gérer l'affichage sur l'écran HDMI.";
}
}, 500);
});
function controlScreen(action) {
console.log("Sending Screen Control Action:", action);
$.ajax({
url: 'launcher.php?type=screen_control&action=' + action,
dataType: 'text',
method: 'GET',
success: function (response) {
console.log("Server Response:", response);
if (action == 'start') {
$('#startBtn').removeClass('btn-success').addClass('btn-secondary').prop('disabled', true);
$('#stopBtn').removeClass('btn-secondary').addClass('btn-danger').prop('disabled', false);
$('#status-message').html('<div class="alert alert-success">L\'écran a été démarré. Réponse: ' + response + '</div>');
} else {
$('#startBtn').removeClass('btn-secondary').addClass('btn-success').prop('disabled', false);
$('#stopBtn').removeClass('btn-danger').addClass('btn-secondary').prop('disabled', true);
$('#status-message').html('<div class="alert alert-warning">L\'écran a été arrêté. Réponse: ' + response + '</div>');
}
},
error: function (xhr, status, error) {
console.error("AJAX Error:", status, error);
$('#status-message').html('<div class="alert alert-danger">Erreur: ' + error + '</div>');
}
});
}
</script>
</body>
</html>