201 lines
12 KiB
HTML
201 lines
12 KiB
HTML
<!doctype html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="theme-color" content="#202326">
|
||
<title>{{ name }}</title>
|
||
<link rel="stylesheet" href="/static/css/alfred.css">
|
||
<link rel="stylesheet" href="/static/css/alfred-controls.css">
|
||
<link rel="stylesheet" href="/static/css/alfred-views.css">
|
||
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
|
||
<link rel="stylesheet" href="/static/css/alfred-camera-popup.css">
|
||
<link rel="stylesheet" href="/static/css/alfred-features.css?v=45">
|
||
<link rel="stylesheet" href="/static/css/alfred-timers-context.css">
|
||
<!-- ALFRED_MAIN_VISUAL_V1 -->
|
||
<link rel="stylesheet" href="/static/css/alfred-main-v1.css?v=1">
|
||
<!-- ALFRED_LISTES_GLASS_V1 -->
|
||
<link rel="stylesheet" href="/static/css/alfred-listes-glass.css?v=1">
|
||
<!-- ALFRED_GLASS_V2 -->
|
||
<link rel="stylesheet" href="/static/css/alfred-main-v2.css?v=2">
|
||
</head>
|
||
<body>
|
||
<main class="alfred-shell">
|
||
<header class="topbar">
|
||
<!-- Le statut remplace l'ancien titre « Alfred ». -->
|
||
<div class="status" role="status" aria-live="polite">
|
||
<span id="statusDot" class="status-dot" data-mode="idle" aria-hidden="true"></span>
|
||
<span id="mode" data-mode="idle">En attente</span>
|
||
</div>
|
||
|
||
<div class="header-actions" aria-label="Navigation et commandes audio">
|
||
<!-- ALFRED_ADMIN_NAV_V1 : pages d’administration séparées -->
|
||
<a class="icon-button" style="text-decoration:none" href="/config" title="Configuration complète" aria-label="Configuration complète">⚙</a>
|
||
<a class="icon-button" style="text-decoration:none" href="/surveillance" title="Surveillance des services" aria-label="Surveillance des services">▤</a>
|
||
<button id="viewHome" class="icon-button" type="button" title="Accueil" aria-label="Accueil">⌂</button>
|
||
<button id="viewCalendar" class="icon-button" type="button" title="Agenda" aria-label="Agenda">▦</button>
|
||
<button id="viewWeather" class="icon-button" type="button" title="Météo Home Assistant" aria-label="Météo Home Assistant">☀</button>
|
||
<button id="viewTemperatures" class="icon-button" type="button" title="Températures" aria-label="Températures">°</button>
|
||
<button id="viewCameras" class="icon-button" type="button" title="Caméras Home Assistant" aria-label="Caméras Home Assistant">▣</button>
|
||
|
||
<!-- ALFRED_CAMERA_POPUP_V1 -->
|
||
<button id="cameraPopupButton" class="icon-button" type="button"
|
||
title="Afficher la caméra" aria-label="Afficher la caméra"
|
||
aria-haspopup="dialog" aria-controls="cameraPopup" aria-expanded="false">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"
|
||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<rect x="2.5" y="5" width="14" height="14" rx="3"/>
|
||
<path d="m16.5 10 5-3v10l-5-3"/>
|
||
</svg>
|
||
</button>
|
||
<button id="audioSettingsButton" class="icon-button" type="button"
|
||
aria-label="Réglages audio et caméra" aria-haspopup="dialog" aria-expanded="false"
|
||
aria-controls="audioSettingsPanel" title="Réglages audio et caméra">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<path d="M4 7h16M4 17h16"/><circle cx="9" cy="7" r="2.5" fill="#272b30"/><circle cx="16" cy="17" r="2.5" fill="#272b30"/>
|
||
</svg>
|
||
</button>
|
||
<button id="micMute" class="icon-button" type="button"
|
||
aria-label="Couper le microphone" aria-pressed="false" title="Couper le microphone">
|
||
<svg class="mic-on-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<rect x="9" y="2.5" width="6" height="12" rx="3"/>
|
||
<path d="M5.5 10.5v1.5a6.5 6.5 0 0 0 13 0v-1.5M12 18.5v3M8 21.5h8"/>
|
||
</svg>
|
||
<svg class="mic-off-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<path d="M9.2 5.3V5.5a3 3 0 0 1 5.5-1.4M15 10.6v.9c0 .5-.1 1-.3 1.5M9 9.5v2A3 3 0 0 0 13.6 14"/>
|
||
<path d="M5.5 10.5V12a6.5 6.5 0 0 0 11.5 4.1M12 18.5v3M8 21.5h8M3 3l18 18"/>
|
||
</svg>
|
||
</button>
|
||
<button id="speakerMuteQuick" class="icon-button" type="button"
|
||
aria-label="Couper le son" aria-pressed="false" title="Couper le son">
|
||
<svg class="speaker-on-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<path d="m11 5-5 4H3v6h3l5 4V5Z"/><path d="M15 9a4 4 0 0 1 0 6M18 6a8 8 0 0 1 0 12"/>
|
||
</svg>
|
||
<svg class="speaker-off-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<path d="m11 5-5 4H3v6h3l5 4V5Z"/><path d="m16 9 5 6m0-6-5 6"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Pop-up : commandes connectées à /api/audio/settings -->
|
||
<div id="audioSettingsPanel" class="audio-popover" role="dialog"
|
||
aria-label="Réglages audio et caméra" aria-modal="false" hidden>
|
||
<div class="popover-heading">
|
||
<strong>Réglages</strong>
|
||
<button id="closeAudioSettings" class="icon-button mini" type="button" aria-label="Fermer les réglages">×</button>
|
||
</div>
|
||
<div class="settings-tabs" role="tablist" aria-label="Catégories de réglages">
|
||
<button id="audioTab" class="settings-tab" type="button" role="tab" aria-selected="true" aria-controls="audioSettingsSection">Audio</button>
|
||
<button id="cameraTab" class="settings-tab" type="button" role="tab" aria-selected="false" aria-controls="cameraSettingsSection">Caméra</button>
|
||
</div>
|
||
<div id="audioSettingsSection" role="tabpanel" aria-labelledby="audioTab">
|
||
<div class="setting-row">
|
||
<label for="volumeSlider">Volume du haut-parleur</label>
|
||
<output id="volumeValue" for="volumeSlider">70 %</output>
|
||
</div>
|
||
<input id="volumeSlider" type="range" min="0" max="100" value="70" step="1">
|
||
<div class="setting-row">
|
||
<label for="micGainSlider">Sensibilité du microphone</label>
|
||
<output id="micGainValue" for="micGainSlider">—</output>
|
||
</div>
|
||
<input id="micGainSlider" type="range" min="0" max="100" value="50" step="1">
|
||
<p id="audioSettingsMessage" class="settings-message" role="status" aria-live="polite"></p>
|
||
</div>
|
||
<div id="cameraSettingsSection" role="tabpanel" aria-labelledby="cameraTab" hidden>
|
||
<p class="camera-settings-note">Webcam locale · réglages matériels V4L2.<br>Tu peux voir le résultat via le bouton Caméra en haut de l’écran.</p>
|
||
<div id="cameraSettingsItems" class="camera-settings-items" aria-live="off"></div>
|
||
<div class="camera-settings-actions">
|
||
<button id="cameraSettingsReload" class="camera-settings-action" type="button">Actualiser</button>
|
||
<button id="cameraSettingsReset" class="camera-settings-action reset" type="button">Valeurs d’usine</button>
|
||
</div>
|
||
<p id="cameraSettingsMessage" class="settings-message" role="status" aria-live="polite"></p>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="cameraPopup" class="camera-popup-overlay" role="dialog"
|
||
aria-label="Prévisualisation caméra" aria-modal="true" hidden>
|
||
<div class="camera-popup-frame">
|
||
<div class="camera-popup-titlebar">
|
||
<strong class="camera-popup-title">Caméra en direct</strong>
|
||
<button id="cameraPopupClose" class="camera-popup-close" type="button"
|
||
aria-label="Fermer la caméra" title="Fermer">×</button>
|
||
</div>
|
||
<aside class="camera-panel camera-popup-body" aria-label="Prévisualisation caméra">
|
||
<div class="panel-heading">
|
||
<span class="panel-title"><span class="panel-indicator"></span> CAMÉRA</span>
|
||
<button id="cameraToggle" class="panel-action" type="button" aria-pressed="false">Activer</button>
|
||
</div>
|
||
<div class="camera-viewport">
|
||
<img id="cameraFeed" alt="Vidéo en direct de la caméra d'Alfred" hidden>
|
||
<div id="cameraPlaceholder" class="camera-placeholder">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true">
|
||
<rect x="2.5" y="5" width="14" height="14" rx="3"/><path d="m16.5 10 5-3v10l-5-3"/>
|
||
</svg>
|
||
<span id="cameraMessage">Caméra désactivée</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
<p class="camera-popup-footnote">Le flux est interrompu à la fermeture pour laisser la webcam disponible aux autres fonctions d’Alfred.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="stage" aria-label="Réponse d'Alfred">
|
||
<div id="content"><h1>Bonjour.</h1><p>À votre écoute.</p></div>
|
||
</section>
|
||
|
||
<section id="wave" aria-hidden="true"><canvas id="waveCanvas"></canvas></section>
|
||
|
||
|
||
|
||
<!-- Affiche les résultats partiels ET définitifs de la reconnaissance Vosk. -->
|
||
<aside class="transcript-panel" aria-label="Transcription vocale">
|
||
<div class="panel-heading">
|
||
<span class="panel-title"><span class="panel-indicator stt-indicator"></span> RECONNAISSANCE VOCALE · VOSK</span>
|
||
<span id="transcriptState" class="transcript-state">En attente</span>
|
||
</div>
|
||
<p id="transcriptText" class="transcript-text" aria-live="polite">La dernière phrase reconnue s'affichera ici.</p>
|
||
</aside>
|
||
</main>
|
||
|
||
<script src="/static/js/alfred.js"></script>
|
||
<script src="/static/js/alfred-views.js"></script>
|
||
<script src="/static/js/alfred-controls.js"></script>
|
||
<script src="/static/js/alfred-camera.js"></script>
|
||
<script src="/static/js/alfred-camera-settings.js"></script>
|
||
<script src="/static/js/alfred-camera-popup.js"></script>
|
||
<script defer src="/static/js/alfred-features.js?v=45"></script>
|
||
|
||
<!-- ALFRED_TIMERS_CONTEXT_V1 : chronos/minuteurs dans le coin inférieur gauche -->
|
||
<aside id="alfredTimersDock" role="region" aria-label="Minuteurs et chronomètres" hidden>
|
||
<div class="alfred-time-head">⏱ MINUTEURS ET CHRONOMÈTRES</div>
|
||
<div id="alfredTimersList"></div>
|
||
</aside>
|
||
<div id="alfredTimerToast" role="alert" aria-live="assertive" hidden></div>
|
||
|
||
<div id="alfredContextPopup" role="dialog" aria-label="Illustration de la réponse"
|
||
aria-modal="true" hidden>
|
||
<article class="alfred-context-card">
|
||
<button id="alfredContextClose" class="alfred-context-close" type="button"
|
||
aria-label="Fermer l'illustration" title="Fermer">×</button>
|
||
<img id="alfredContextImage" alt="Illustration contextuelle de la réponse" />
|
||
<div class="alfred-context-details">
|
||
<h2 id="alfredContextTitle"></h2>
|
||
<p id="alfredContextText"></p>
|
||
<a id="alfredContextSource" href="#" target="_blank" rel="noopener noreferrer">Source Wikipédia</a>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
<script src="/static/js/alfred-timers-context.js"></script>
|
||
<!-- ALFRED_HIDE_HERMES_ACTIVITY_V2 -->
|
||
<script src="/static/js/alfred-hide-hermes-activity.js?v=2" defer></script>
|
||
<script src="/static/js/alfred-main-v1.js?v=1"></script>
|
||
<!-- ALFRED_ADMIN_GLASS_MAISON_V1 -->
|
||
<script src="/static/js/alfred-maison-card.js?v=1"></script>
|
||
<script src="/static/js/alfred-listes-glass.js?v=1"></script>
|
||
<script src="/static/js/alfred-main-v2.js?v=2"></script>
|
||
<!-- ALFRED_IDENTITY_GLASS_V1 -->
|
||
<script src="/static/js/alfred-name-dynamic.js?v=1" defer></script>
|
||
</body>
|
||
</html>
|