diff --git a/client/src/App.jsx b/client/src/App.jsx
index 54be3a2..2e64284 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -2,7 +2,6 @@ import { useState, useEffect } from 'react';
import useLiveKit from './hooks/useLiveKit';
import PTTButton from './components/PTTButton';
import UserList from './components/UserList';
-import AudioIndicator from './components/AudioIndicator';
import GroupSelector from './components/GroupSelector';
import './App.css';
@@ -241,14 +240,12 @@ function App() {
{/* Liste des participants */}
- {/* Indicateur audio */}
-
-
- {/* Bouton PTT principal */}
+ {/* Bouton PTT principal avec VU-mètre intégré */}
diff --git a/client/src/components/PTTButton.css b/client/src/components/PTTButton.css
index b550045..6bd0525 100644
--- a/client/src/components/PTTButton.css
+++ b/client/src/components/PTTButton.css
@@ -11,6 +11,24 @@
position: relative;
}
+/* Wrapper bouton + anneau VU-mètre */
+.ptt-button-wrapper {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* Anneau VU-mètre (SVG) */
+.audio-ring {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ pointer-events: none;
+ z-index: 0;
+}
+
.ptt-button {
width: 240px;
height: 240px;
@@ -27,6 +45,7 @@
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
position: relative;
overflow: hidden;
+ z-index: 1; /* Au-dessus de l'anneau */
/* Mobile touch optimizations */
touch-action: none;
@@ -189,6 +208,11 @@
height: 200px;
}
+ .audio-ring {
+ width: 240px;
+ height: 240px;
+ }
+
.ptt-icon {
width: 56px;
height: 56px;
@@ -210,6 +234,11 @@
height: 160px;
}
+ .audio-ring {
+ width: 200px;
+ height: 200px;
+ }
+
.ptt-icon {
width: 48px;
height: 48px;
diff --git a/client/src/components/PTTButton.jsx b/client/src/components/PTTButton.jsx
index bf977c9..2d1e5b8 100644
--- a/client/src/components/PTTButton.jsx
+++ b/client/src/components/PTTButton.jsx
@@ -7,8 +7,9 @@ import './PTTButton.css';
* Modes :
* - PTT classique : maintenir pour parler
* - Mode continu (lock) : glisser vers le haut pendant qu'on parle
+ * Inclut VU-mètre intégré (anneau autour du bouton)
*/
-export default function PTTButton({ isTalking, onPressStart, onPressEnd }) {
+export default function PTTButton({ isTalking, onPressStart, onPressEnd, audioLevel = 0 }) {
const buttonRef = useRef(null);
const isPressingRef = useRef(false);
const [isLockMode, setIsLockMode] = useState(false);
@@ -241,6 +242,25 @@ export default function PTTButton({ isTalking, onPressStart, onPressEnd }) {
}
};
+ // Calculer le niveau audio normalisé (0-100)
+ const normalizedLevel = Math.min(100, Math.max(0, audioLevel));
+
+ // Convertir le niveau en angle pour le cercle SVG (0-360°)
+ const levelAngle = (normalizedLevel / 100) * 360;
+
+ // Calculer le dasharray pour l'arc SVG
+ const radius = 130; // Rayon du cercle VU-mètre
+ const circumference = 2 * Math.PI * radius;
+ const dashOffset = circumference - (levelAngle / 360) * circumference;
+
+ // Déterminer la couleur selon le niveau
+ const getAudioColor = () => {
+ if (normalizedLevel > 90) return '#ef4444'; // Danger (rouge)
+ if (normalizedLevel > 75) return '#f59e0b'; // Warning (orange)
+ if (isTalking) return '#3b82f6'; // Talking (bleu)
+ return '#10b981'; // Normal (vert)
+ };
+
return (
{/* Zone de drag vers le haut (indicateur visuel) */}
@@ -253,15 +273,53 @@ export default function PTTButton({ isTalking, onPressStart, onPressEnd }) {