Add automatic token refresh for browser phone to prevent timeouts
- Implement proactive token refresh 5 minutes before expiry (1-hour tokens) - Add call-safe refresh logic that postpones refresh during active calls - Replace fixed-interval refresh with smart scheduling based on token expiry - Add proper cleanup on page unload to prevent memory leaks - Enhance error handling with retry mechanisms for network failures - Apply to both admin browser phone page and frontend shortcode 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5691,6 +5691,8 @@ class TWP_Admin {
|
||||
var currentCall = null;
|
||||
var callTimer = null;
|
||||
var callStartTime = null;
|
||||
var tokenRefreshTimer = null;
|
||||
var tokenExpiry = null;
|
||||
|
||||
// Wait for SDK to load
|
||||
function waitForTwilioSDK(callback) {
|
||||
@@ -5718,6 +5720,9 @@ class TWP_Admin {
|
||||
if (response.success) {
|
||||
$('#browser-phone-error').hide();
|
||||
setupTwilioDevice(response.data.token);
|
||||
// Set token expiry and schedule refresh
|
||||
tokenExpiry = Date.now() + (response.data.expires_in || 3600) * 1000;
|
||||
scheduleTokenRefresh();
|
||||
} else {
|
||||
// WordPress wp_send_json_error sends the error message as response.data
|
||||
var errorMsg = response.data || response.error || 'Unknown error';
|
||||
@@ -5852,18 +5857,65 @@ class TWP_Admin {
|
||||
}
|
||||
|
||||
function refreshToken() {
|
||||
console.log('Refreshing capability token...');
|
||||
|
||||
// Don't refresh if currently in a call
|
||||
if (currentCall) {
|
||||
console.log('Currently in call, postponing token refresh');
|
||||
setTimeout(refreshToken, 60000); // Retry in 1 minute
|
||||
return;
|
||||
}
|
||||
|
||||
$.post(ajaxurl, {
|
||||
action: 'twp_generate_capability_token',
|
||||
nonce: '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>'
|
||||
}, function(response) {
|
||||
if (response.success && device) {
|
||||
console.log('Token refreshed successfully');
|
||||
device.updateToken(response.data.token);
|
||||
// Update token expiry and schedule next refresh
|
||||
tokenExpiry = Date.now() + (response.data.expires_in || 3600) * 1000;
|
||||
scheduleTokenRefresh();
|
||||
} else {
|
||||
console.error('Failed to refresh token:', response.data);
|
||||
showError('Failed to refresh connection. Please refresh the page.');
|
||||
}
|
||||
}).fail(function() {
|
||||
console.error('Failed to refresh token');
|
||||
console.error('Failed to refresh token - network error');
|
||||
// Retry in 30 seconds
|
||||
setTimeout(refreshToken, 30000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule token refresh
|
||||
* Refreshes token 5 minutes before expiry
|
||||
*/
|
||||
function scheduleTokenRefresh() {
|
||||
// Clear any existing timer
|
||||
if (tokenRefreshTimer) {
|
||||
clearTimeout(tokenRefreshTimer);
|
||||
}
|
||||
|
||||
if (!tokenExpiry) {
|
||||
console.error('Token expiry time not set');
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate time until refresh (5 minutes before expiry)
|
||||
var refreshBuffer = 5 * 60 * 1000; // 5 minutes in milliseconds
|
||||
var timeUntilRefresh = tokenExpiry - Date.now() - refreshBuffer;
|
||||
|
||||
if (timeUntilRefresh <= 0) {
|
||||
// Token needs refresh immediately
|
||||
refreshToken();
|
||||
} else {
|
||||
// Schedule refresh
|
||||
console.log('Scheduling token refresh in', Math.round(timeUntilRefresh / 1000), 'seconds');
|
||||
tokenRefreshTimer = setTimeout(refreshToken, timeUntilRefresh);
|
||||
}
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
$('#browser-phone-error').html('<p><strong>Error:</strong> ' + message + '</p>').show();
|
||||
$('#phone-status').text('Error').css('color', '#f44336');
|
||||
@@ -6005,8 +6057,15 @@ class TWP_Admin {
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Refresh token every 50 minutes (tokens expire in 1 hour)
|
||||
setInterval(initializeBrowserPhone, 50 * 60 * 1000);
|
||||
// Clean up on page unload
|
||||
$(window).on('beforeunload', function() {
|
||||
if (tokenRefreshTimer) {
|
||||
clearTimeout(tokenRefreshTimer);
|
||||
}
|
||||
if (device) {
|
||||
device.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// Mode switching functionality
|
||||
$('input[name="call_mode"]').on('change', function() {
|
||||
|
Reference in New Issue
Block a user