Headless Hook
useThunderPhone હૂક તમને યુઝર ઇન્ટરફેસ પર સંપૂર્ણ નિયંત્રણ આપે છે, જ્યારે ThunderPhone વૉઇસ સેશન, ઑડિયો રૂટિંગ અને કનેક્શન સ્ટેટનું સંચાલન કરે છે. જ્યારે તમને સંપૂર્ણપણે કસ્ટમ UI જોઈએ ત્યારે તેનો ઉપયોગ કરો -- તમારા પોતાના બટનો, લેઆઉટ, એનિમેશન અને બ્રાન્ડિંગ સાથે -- જ્યારે ThunderPhone આંતરિક રીતે બધું સંભાળે છે.
હેડલેસ હૂકનો ઉપયોગ ક્યારે કરવો
પૂર્વનિર્મિત ThunderPhoneWidget કોમ્પોનેન્ટ મોટા ભાગના ઉપયોગના કેસ આવરી લે છે, પરંતુ જ્યારે તમને નીચેની જરૂર હોય ત્યારે હેડલેસ હૂકનો ઉપયોગ કરો:
- તમારી એપ્લિકેશનની ડિઝાઇન સિસ્ટમ સાથે મેળ ખાતું સંપૂર્ણપણે કસ્ટમ કૉલ UI
- રીઅલ-ટાઇમ ઑડિયો લેવલ દ્વારા સંચાલિત ઑડિયો-પ્રતિક્રિયાશીલ વિઝ્યુઅલાઇઝેશન (વેવફોર્મ્સ, ઓર્બ્સ, ધબકતા ઇન્ડિકેટર્સ)
- કસ્ટમ કૉલ ફ્લો, જેમ કે કૉલ પહેલાંના ફોર્મ, કૉલ પછીના સર્વે અથવા વૉઇસ સાથે ઇનલાઇન ચેટ
- હાલની કોમ્પોનેન્ટ લાઇબ્રેરીમાં એકીકરણ (Material UI, Chakra, Radix, વગેરે)
ઇન્સ્ટોલેશન
npm install @thunderphone/widget
મૂળભૂત ઉપયોગ
import { useThunderPhone } from '@thunderphone/widget'
function CustomCallButton() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
const handleClick = () => {
if (phone.state === 'connected') {
phone.disconnect()
} else {
phone.connect()
}
}
return (
<>
<button onClick={handleClick} disabled={phone.state === 'connecting'}>
{phone.state === 'connecting'
? 'Connecting...'
: phone.state === 'connected'
? 'End call'
: 'Start call'}
</button>
{phone.audio}
</>
)
}
વિકલ્પો
UseThunderPhoneOptions મારફતે આ વિકલ્પો useThunderPhone ને આપો:
| વિકલ્પ | પ્રકાર | આવશ્યક | ડિફૉલ્ટ | વર્ણન |
|---|---|---|---|---|
publishableKey | string | હા | -- | પબ્લિશેબલ API કી (pk_live_...). એજન્ટ કીની વિજેટ રૂપરેખાંકનમાંથી આપમેળે નક્કી થાય છે. |
apiBase | string | ના | 'https://api.thunderphone.com/v1' | API બેઝ URL ઓવરરાઇડ. |
language | string | ના | -- | પ્રતિ-સેશન ભાષા ઓવરરાઇડ -- en, es, અથવા fr-FR જેવા ભાષા કોડ અથવા લોકેલ. સેટ ન કરેલ હોય ત્યારે, એજન્ટની રૂપરેખાંકિત ભાષા લાગુ પડે છે. |
voice | string | ના | -- | પ્રતિ-સેશન વૉઇસ ઓવરરાઇડ -- maria જેવા વૉઇસ નામ. સેટ ન કરેલ હોય ત્યારે, એજન્ટનો રૂપરેખાંકિત વૉઇસ લાગુ પડે છે. |
context | string | ના | -- | એજન્ટને મોકલવામાં આવતો પ્રતિ-સેશન તથ્યાત્મક પેજ અથવા સાઇટ કોન્ટેક્સ્ટ. સર્વર-સાઇડ પર 12,000 અક્ષરો સુધી ટૂંકો કરવામાં આવે છે. |
onConnect | () => void | ના | -- | વૉઇસ સેશન કનેક્ટ થાય ત્યારે કૉલ થાય છે. |
onDisconnect | () => void | ના | -- | સેશન સમાપ્ત થાય ત્યારે કૉલ થાય છે. |
onError | (error) => void | ના | -- | ભૂલો થાય ત્યારે કૉલ થાય છે. ભૂલમાં error (કોડ) અને message ફીલ્ડ હોય છે. |
ringtone | boolean | string | ના | false | કનેક્ટ કરતી વખતે રિંગટોન વગાડો. ડિફૉલ્ટ રિંગટોન માટે true, અથવા કસ્ટમ ઑડિયો માટે URL સ્ટ્રિંગ. |
રિટર્ન વેલ્યુ
હૂક UseThunderPhoneReturn ઑબ્જેક્ટ રિટર્ન કરે છે:
| પ્રોપર્ટી | પ્રકાર | વર્ણન |
|---|---|---|
state | 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error' | વર્તમાન કનેક્શન સ્થિતિ. |
connect | () => void | વૉઇસ સેશન શરૂ કરો. |
disconnect | () => void | વર્તમાન સેશન સમાપ્ત કરો. |
toggleMute | () => void | માઇક્રોફોન મ્યૂટને ચાલુ/બંધ કરો. |
isMuted | boolean | માઇક્રોફોન હાલમાં મ્યૂટ છે કે નહીં. |
error | string | undefined | સ્થિતિ 'error' હોય ત્યારે એરર મેસેજ. |
agentName | string | undefined | કનેક્ટેડ એજન્ટનું ડિસ્પ્લે નામ. |
audioLevel | number | ડિપ્રિકેટેડ -- હંમેશા 0. બેકવર્ડ્સ કમ્પેટિબિલિટી માટે રાખવામાં આવેલો સ્થિર પ્લેસહોલ્ડર; તે ક્યારેય અપડેટ થતો નથી. તેના બદલે audioLevelRef.current વાંચો. |
audioLevelRef | React.RefObject<number> | રિયલ-ટાઇમ ઑડિયો લેવલ (0--1) ધરાવતો મ્યૂટેબલ ref -- એજન્ટના અવાજ અને વિઝિટરના માઇક્રોફોનમાંથી જે વધુ ઊંચો હોય તે -- Reactના રેન્ડર સાયકલની બહાર, દરેક એનિમેશન ફ્રેમ પર અપડેટ થાય છે. સ્મૂથ, જૅન્ક-મુક્ત એનિમેશન માટે requestAnimationFrame લૂપમાં audioLevelRef.current વાંચો, અથવા React સ્ટેટમાં વેલ્યુ જરૂરી હોય ત્યારે તેને નિયમિત અંતરે સેમ્પલ કરો. |
audio | ReactNode | ઑડિયો કનેક્શન હેન્ડલ કરતું અદૃશ્ય એલિમેન્ટ -- રેન્ડર કરવું આવશ્યક છે. |
ઑડિયો-પ્રતિક્રિયાશીલ UI
audioLevelRef ref તમને React રિ-રેન્ડર ટ્રિગર કર્યા વિના ફ્રેમ-રેટ ઑડિયો લેવલ આપે છે, જેથી તે સરળ વેવફોર્મ વિઝ્યુઅલાઇઝેશન, પલ્સ થતા ઓર્બ્સ અથવા વાતચીત સાથે જોડાયેલા કોઈપણ એનિમેશન ચલાવવા માટે આદર્શ બને છે. લેવલ એજન્ટના અવાજ અથવા મુલાકાતીના માઇક્રોફોનમાંથી જે વધુ ઊંચો હોય તે દર્શાવે છે.
વેવફોર્મ ઉદાહરણ
import { useRef, useEffect } from 'react'
import { useThunderPhone } from '@thunderphone/widget'
function WaveformCall() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
if (phone.state !== 'connected') return
const canvas = canvasRef.current
if (!canvas) return
const ctx = canvas.getContext('2d')!
let animId: number
const draw = () => {
const level = phone.audioLevelRef.current ?? 0
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Draw bars that react to audio level
const barCount = 24
const barWidth = canvas.width / barCount
for (let i = 0; i < barCount; i++) {
const distance = Math.abs(i - barCount / 2) / (barCount / 2)
const height = level * canvas.height * (1 - distance * 0.6)
const y = (canvas.height - height) / 2
ctx.fillStyle = '#0ea5e9'
ctx.fillRect(i * barWidth + 1, y, barWidth - 2, height)
}
animId = requestAnimationFrame(draw)
}
animId = requestAnimationFrame(draw)
return () => cancelAnimationFrame(animId)
}, [phone.state, phone.audioLevelRef])
return (
<div>
{phone.state === 'connected' && (
<canvas ref={canvasRef} width={240} height={80} />
)}
<button
onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
disabled={phone.state === 'connecting'}
>
{phone.state === 'connected' ? 'End call' : 'Start call'}
</button>
{phone.audio}
</div>
)
}
પલ્સિંગ ઓર્બ ઉદાહરણ
import { useRef, useEffect } from 'react'
import { useThunderPhone } from '@thunderphone/widget'
function PulsingOrb() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
const orbRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (phone.state !== 'connected') return
let animId: number
const animate = () => {
const level = phone.audioLevelRef.current ?? 0
if (orbRef.current) {
const scale = 1 + level * 0.5
orbRef.current.style.transform = `scale(${scale})`
orbRef.current.style.opacity = `${0.6 + level * 0.4}`
}
animId = requestAnimationFrame(animate)
}
animId = requestAnimationFrame(animate)
return () => cancelAnimationFrame(animId)
}, [phone.state, phone.audioLevelRef])
return (
<div style={{ textAlign: 'center' }}>
<div
ref={orbRef}
style={{
width: 80,
height: 80,
borderRadius: '50%',
background: '#0ea5e9',
margin: '20px auto',
transition: 'transform 0.05s ease-out',
}}
/>
<button
onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
disabled={phone.state === 'connecting'}
>
{phone.state === 'connected' ? 'End call' : 'Call'}
</button>
{phone.audio}
</div>
)
}
બોલવાનું સૂચક ઉદાહરણ
વોલ્યુમ સાથે બદલાતા React-રેન્ડર કરેલા UI માટે -- જેમ કે થ્રેશોલ્ડ-આધારિત "બોલી રહ્યા છે" બેજ -- audioLevelRef.current ને નિયમિત અંતરાલે સેમ્પલ કરો અને પરિણામને state માં સંગ્રહિત કરો:
import { useEffect, useState } from 'react'
import { useThunderPhone } from '@thunderphone/widget'
function SpeakingBadge() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
const [speaking, setSpeaking] = useState(false)
useEffect(() => {
if (phone.state !== 'connected') {
setSpeaking(false)
return
}
const interval = setInterval(() => {
setSpeaking((phone.audioLevelRef.current ?? 0) > 0.1)
}, 100)
return () => clearInterval(interval)
}, [phone.state, phone.audioLevelRef])
return (
<div>
{phone.state === 'connected' && (
<span>{speaking ? 'Speaking' : 'Listening'}</span>
)}
<button onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}>
{phone.state === 'connected' ? 'End call' : 'Start call'}
</button>
{phone.audio}
</div>
)
}
સ્થિતિ મશીન
state પ્રોપર્ટી આ જીવનચક્રને અનુસરે છે:
idle --> connecting --> connected --> disconnected --> idle (after 1.5s)
\
--> error (stays until connect() is called again)
| સ્થિતિ | વર્ણન |
|---|---|
idle | કોઈ સક્રિય સેશન નથી. connect() કૉલ કરવા માટે તૈયાર છે. |
connecting | સેશન સ્થાપિત થઈ રહ્યું છે. આ સ્થિતિ દરમિયાન કોલ બટન નિષ્ક્રિય કરો. |
connected | વૉઇસ સેશન સક્રિય છે. વપરાશકર્તા એજન્ટ સાથે વાત કરી રહ્યા છે. |
disconnected | સેશન સ્વચ્છ રીતે સમાપ્ત થયું છે. 1.5 સેકન્ડ પછી આપમેળે પાછું idle પર જાય છે. |
error | કંઈક ખોટું થયું છે. સંદેશ માટે phone.error તપાસો. સ્થિતિ પોતાની મેળે સાફ થતી નથી -- ફરીથી connect() કૉલ કરવાથી નવો પ્રયાસ શરૂ થાય છે અને ભૂલ રીસેટ થાય છે. |
ઉદાહરણો
મ્યૂટ નિયંત્રણ સાથે
import { useThunderPhone } from '@thunderphone/widget'
function CallWithMute() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
return (
<div>
{phone.state === 'connected' && (
<div>
<p>Talking to {phone.agentName ?? 'Agent'}</p>
<button onClick={phone.toggleMute}>
{phone.isMuted ? 'Unmute' : 'Mute'}
</button>
<button onClick={phone.disconnect}>End call</button>
</div>
)}
{phone.state !== 'connected' && (
<button
onClick={phone.connect}
disabled={phone.state === 'connecting'}
>
{phone.state === 'connecting' ? 'Connecting...' : 'Call support'}
</button>
)}
{phone.state === 'error' && (
<p style={{ color: 'red' }}>{phone.error}</p>
)}
{phone.audio}
</div>
)
}
રિંગટોન સાથે
ફોન કૉલનું અનુકરણ કરવા માટે કનેક્ટ કરતી વખતે રિંગિંગ અવાજ વગાડો:
import { useThunderPhone } from '@thunderphone/widget'
function PhoneCallButton() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
ringtone: true, // or a custom URL: 'https://example.com/ringtone.mp3'
})
return (
<>
<button
onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
disabled={phone.state === 'connecting'}
>
{phone.state === 'connecting'
? 'Ringing...'
: phone.state === 'connected'
? 'Hang up'
: 'Call'}
</button>
{phone.audio}
</>
)
}
રિંગટોન connecting સ્થિતિ દરમિયાન સતત વાગે છે અને એજન્ટ કનેક્ટ થાય ત્યારે ધીમે ધીમે બંધ થાય છે. બિલ્ટ-ઇન ડિફૉલ્ટ રિંગટોન માટે true પાસ કરો અથવા તમારી પોતાની ઑડિયો ફાઇલ વાપરવા માટે URL સ્ટ્રિંગ પાસ કરો.
ઇવેન્ટ કૉલબૅક સાથે
import { useThunderPhone } from '@thunderphone/widget'
function TrackedCallButton() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
onConnect: () => {
analytics.track('call_started')
},
onDisconnect: () => {
analytics.track('call_ended')
},
onError: (error) => {
analytics.track('call_error', { code: error.error, message: error.message })
},
})
return (
<>
<button
onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}
disabled={phone.state === 'connecting'}
>
{phone.state === 'connected' ? 'Hang up' : 'Talk to AI'}
</button>
{phone.audio}
</>
)
}
સંપૂર્ણ કસ્ટમ UI
import { useThunderPhone } from '@thunderphone/widget'
function FullCustomUI() {
const phone = useThunderPhone({
publishableKey: 'pk_live_your_publishable_key',
})
return (
<div className="call-panel">
<div className="call-status">
{phone.state === 'idle' && <span>Ready</span>}
{phone.state === 'connecting' && <span className="pulse">Connecting...</span>}
{phone.state === 'connected' && (
<span>On call with {phone.agentName}</span>
)}
{phone.state === 'error' && <span className="error">{phone.error}</span>}
</div>
<div className="call-controls">
{phone.state === 'connected' ? (
<>
<button className="mute-btn" onClick={phone.toggleMute}>
{phone.isMuted ? 'Unmute' : 'Mute'}
</button>
<button className="end-btn" onClick={phone.disconnect}>
End
</button>
</>
) : (
<button
className="start-btn"
onClick={phone.connect}
disabled={phone.state === 'connecting'}
>
Start call
</button>
)}
</div>
{/* Required -- handles audio under the hood */}
{phone.audio}
</div>
)
}
સૂચનાઓ
હંમેશા phone.audio રેન્ડર કરો
phone.audio એલિમેન્ટ અદૃશ્ય છે, પરંતુ જરૂરી છે. તેને તમારા JSX માં ગમે ત્યાં મૂકો -- તે કોઈ દૃશ્યમાન DOM રેન્ડર કરતું નથી, પરંતુ અંદરથી WebRTC ઑડિયો કનેક્શનનું સંચાલન કરે છે.
કનેક્ટ કરતી વખતે બટન અક્ષમ કરો
connecting સ્થિતિ 1-3 સેકન્ડ સુધી રહી શકે છે. ડુપ્લિકેટ કનેક્શન પ્રયાસો અટકાવવા માટે આ સ્થિતિ દરમિયાન કૉલ બટન અક્ષમ કરો.
ભૂલની સ્થિતિને સુવ્યવસ્થિત રીતે હેન્ડલ કરો
જ્યારે સ્થિતિ error હોય, ત્યારે વપરાશકર્તાને phone.error દર્શાવો અને તમારું કૉલ બટન સક્ષમ રાખો. હૂક પોતાની મેળે error સ્થિતિ છોડતું નથી -- ફરીથી connect() કૉલ કરવાથી નવો પ્રયાસ શરૂ થાય છે અને અગાઉની ભૂલ દૂર થાય છે.
સાઇડ ઇફેક્ટ્સ માટે કૉલબૅક્સનો ઉપયોગ કરો
onConnect, onDisconnect, અને onError કૉલબૅક્સ સ્થિતિને પોલ કર્યા વિના એનાલિટિક્સ, લૉગિંગ અથવા અન્ય એપ્લિકેશન લૉજિક ટ્રિગર કરવા માટે આદર્શ છે.
audioLevelRef માંથી ઑડિયો લેવલ વાંચો
audioLevelRef એકમાત્ર લાઇવ ઑડિયો-લેવલ સ્રોત છે. વેવફોર્મ જેવી સરળ એનિમેશન માટે requestAnimationFrame ની અંદર audioLevelRef.current વાંચો (ref વાંચવાથી ફરીથી રેન્ડર થતું નથી), અથવા તેને નિયમિત અંતરાલે સેમ્પલ કરીને React-રેન્ડર કરેલા UI માટે પરિણામને state માં સંગ્રહો. audioLevel નંબર ડિપ્રિકેટેડ છે અને હંમેશા 0 હોય છે -- તેના પર લૉજિક બનાવશો નહીં.