generated from cameronking4/VapiBlocks
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathclassic.tsx
105 lines (98 loc) · 3.5 KB
/
classic.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import React, { useEffect, useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import useWebRTCAudioSession from '@/hooks/use-webrtc';
import { Button } from '@/components/ui/button';
import { MicIcon, PhoneOff } from 'lucide-react';
const Visualizer: React.FC = () => {
const { currentVolume, isSessionActive, handleStartStopClick } = useWebRTCAudioSession('alloy');
const [bars, setBars] = useState(Array(50).fill(5));
useEffect(() => {
if (isSessionActive) {
updateBars(currentVolume);
} else {
resetBars();
}
}, [currentVolume, isSessionActive]);
const updateBars = (volume: number) => {
if (volume > 0.002) {
setBars(bars.map(() => Math.random() * volume * 500));
} else {
setBars(Array(50).fill(5));
}
};
const resetBars = () => {
setBars(Array(50).fill(5));
};
const micPulseAnimation = {
scale: [1, 1.2, 1],
opacity: [1, 0.8, 1],
transition: { duration: 0.8, repeat: Infinity }
};
return (
<div className="flex flex-col items-center justify-center p-6 rounded">
<AnimatePresence>
{isSessionActive && (
<motion.div
className="flex items-center justify-center w-full h-full"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5 }}
>
<svg width="100%" height="100%" viewBox="0 0 1000 200" preserveAspectRatio="xMidYMid meet">
{bars.map((height, index) => (
<React.Fragment key={index}>
<rect
x={500 + index * 20 - 490}
y={100 - height / 2}
width="10"
height={height}
className={`fill-current ${isSessionActive ? 'text-black dark:text-white opacity-70' : 'text-gray-400 opacity-30'}`}
/>
<rect
x={500 - index * 20 - 10}
y={100 - height / 2}
width="10"
height={height}
className={`fill-current ${isSessionActive ? 'text-black dark:text-white opacity-70' : 'text-gray-400 opacity-30'}`}
/>
</React.Fragment>
))}
</svg>
</motion.div>
)}
</AnimatePresence>
<motion.div
className="mt-4"
animate={isSessionActive && currentVolume === 0 ? micPulseAnimation : {}}
>
<Button onClick={handleStartStopClick} className="flex items-center justify-center w-12 h-12 rounded-full shadow-lg">
<AnimatePresence>
{isSessionActive ? (
<motion.div
key="phone-off"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3 }}
>
<PhoneOff size={24} />
</motion.div>
) : (
<motion.div
key="mic-icon"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ duration: 0.3 }}
>
<MicIcon size={24} />
</motion.div>
)}
</AnimatePresence>
</Button>
</motion.div>
</div>
);
};
export default Visualizer;