|
|
|
|
@@ -101,23 +101,18 @@ export function useSoftphone() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { api } = useApi();
|
|
|
|
|
console.log('Requesting Twilio token from /api/voice/token...');
|
|
|
|
|
const response = await api.get('/voice/token');
|
|
|
|
|
const token = response.data.token;
|
|
|
|
|
|
|
|
|
|
console.log('Token received, creating Device...');
|
|
|
|
|
|
|
|
|
|
// Log the token payload to see what identity is being used
|
|
|
|
|
try {
|
|
|
|
|
const tokenPayload = JSON.parse(atob(token.split('.')[1]));
|
|
|
|
|
console.log('Token identity:', tokenPayload.sub);
|
|
|
|
|
console.log('Token grants:', tokenPayload.grants);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log('Could not parse token payload');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
twilioDevice.value = new Device(token, {
|
|
|
|
|
logLevel: 1,
|
|
|
|
|
logLevel: 3,
|
|
|
|
|
codecPreferences: ['opus', 'pcmu'],
|
|
|
|
|
enableImprovedSignalingErrorPrecision: true,
|
|
|
|
|
edge: 'ashburn',
|
|
|
|
|
@@ -125,12 +120,10 @@ export function useSoftphone() {
|
|
|
|
|
|
|
|
|
|
// Device events
|
|
|
|
|
twilioDevice.value.on('registered', () => {
|
|
|
|
|
console.log('✓ Twilio Device registered - ready to receive calls');
|
|
|
|
|
toast.success('Softphone ready');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
twilioDevice.value.on('unregistered', () => {
|
|
|
|
|
console.log('⚠ Twilio Device unregistered');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
twilioDevice.value.on('error', (error) => {
|
|
|
|
|
@@ -139,12 +132,6 @@ export function useSoftphone() {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
twilioDevice.value.on('incoming', (call: TwilioCall) => {
|
|
|
|
|
console.log('🔔 Twilio Device INCOMING event received:', call.parameters);
|
|
|
|
|
console.log('Call parameters:', {
|
|
|
|
|
CallSid: call.parameters.CallSid,
|
|
|
|
|
From: call.parameters.From,
|
|
|
|
|
To: call.parameters.To,
|
|
|
|
|
});
|
|
|
|
|
twilioCall.value = call;
|
|
|
|
|
|
|
|
|
|
// Update state
|
|
|
|
|
@@ -167,16 +154,11 @@ export function useSoftphone() {
|
|
|
|
|
// Setup call handlers
|
|
|
|
|
setupCallHandlers(call);
|
|
|
|
|
|
|
|
|
|
// Play ringtone
|
|
|
|
|
playRingtone();
|
|
|
|
|
// Twilio Device will handle ringtone automatically
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Register the device
|
|
|
|
|
console.log('Registering Twilio Device...');
|
|
|
|
|
await twilioDevice.value.register();
|
|
|
|
|
console.log('✓ Twilio Device register() completed');
|
|
|
|
|
console.log('Device identity:', twilioDevice.value.identity);
|
|
|
|
|
console.log('Device state:', twilioDevice.value.state);
|
|
|
|
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
console.error('Failed to initialize Twilio Device:', error);
|
|
|
|
|
@@ -245,7 +227,7 @@ export function useSoftphone() {
|
|
|
|
|
return 'http://localhost:3000';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Connect to /voice namespace
|
|
|
|
|
// Connect to /voice namespace with proper auth header
|
|
|
|
|
socket.value = io(`${getBackendUrl()}/voice`, {
|
|
|
|
|
auth: {
|
|
|
|
|
token: token,
|
|
|
|
|
@@ -255,25 +237,26 @@ export function useSoftphone() {
|
|
|
|
|
reconnectionDelay: 1000,
|
|
|
|
|
reconnectionDelayMax: 5000,
|
|
|
|
|
reconnectionAttempts: 5,
|
|
|
|
|
query: {}, // Explicitly set empty query to prevent token leaking
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Connection events
|
|
|
|
|
socket.value.on('connect', () => {
|
|
|
|
|
console.log('🔌 Softphone WebSocket connected');
|
|
|
|
|
console.log('📋 Token payload (check userId):', parseJwt(token));
|
|
|
|
|
isConnected.value = true;
|
|
|
|
|
|
|
|
|
|
// Initialize Twilio Device after WebSocket connects
|
|
|
|
|
initializeTwilioDevice();
|
|
|
|
|
// Suppress warnings by catching them before they log
|
|
|
|
|
initializeTwilioDevice().catch(err => {
|
|
|
|
|
// Device initialization errors are already shown to user via toast
|
|
|
|
|
console.debug('Device init issue (non-critical):', err.message);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.value.on('disconnect', () => {
|
|
|
|
|
console.log('Softphone WebSocket disconnected');
|
|
|
|
|
isConnected.value = false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.value.on('connect_error', (error) => {
|
|
|
|
|
console.error('Softphone connection error:', error);
|
|
|
|
|
toast.error('Failed to connect to voice service');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -552,8 +535,7 @@ export function useSoftphone() {
|
|
|
|
|
let ringtoneAudio: HTMLAudioElement | null = null;
|
|
|
|
|
|
|
|
|
|
const playRingtone = () => {
|
|
|
|
|
// Optional: Play a simple beep tone using Web Audio API
|
|
|
|
|
// This is a nice-to-have enhancement but not required for incoming calls to work
|
|
|
|
|
// Play a simple beep tone using Web Audio API
|
|
|
|
|
try {
|
|
|
|
|
const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
|
|
|
|
|
const oscillator = audioContext.createOscillator();
|
|
|
|
|
|