Fix critical browser phone shortcode issues
Issues Fixed: 1. 🎵 Audio Error: Removed missing ringtone.mp3 causing 404 error 2. 📡 Twilio SDK Loading: Added proper SDK availability checking and retry mechanism 3. 🎨 Contrast Issues: Improved readability with darker text colors Technical Changes: - Removed hardcoded ringtone.mp3 reference causing 404 errors - Added waitForTwilioSDK() function with 5-second timeout and retry logic - Changed Twilio SDK loading to head (false flag) for better availability - Enhanced error handling with specific Twilio SDK load failure messages - Improved text contrast: #6c757d → #495057, #495057 → #212529 - Enhanced dark mode colors for better accessibility UI Improvements: - Status text: font-weight 600, color #212529 for better visibility - Labels and selects: improved contrast ratios - Queue info: better text color for mobile readability - Call status: font-weight 600 for prominence - Dark mode: complete color scheme overhaul with proper contrast Error Handling: - Graceful SDK loading with visual feedback - Clear error messages for troubleshooting - Automatic retry mechanism for network issues - Timeout handling for slow connections 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -56,8 +56,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-text {
|
.status-text {
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #495057;
|
color: #212529;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
@@ -74,8 +74,8 @@
|
|||||||
.twp-phone-selection label {
|
.twp-phone-selection label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #495057;
|
color: #212529;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twp-select {
|
.twp-select {
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #495057;
|
color: #212529;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||||
background-position: right 12px center;
|
background-position: right 12px center;
|
||||||
@@ -289,8 +289,8 @@
|
|||||||
padding: 8px;
|
padding: 8px;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #495057;
|
color: #212529;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queue Management Section */
|
/* Queue Management Section */
|
||||||
@@ -317,9 +317,10 @@
|
|||||||
.queue-loading,
|
.queue-loading,
|
||||||
.no-queues {
|
.no-queues {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #6c757d;
|
color: #495057;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-queues {
|
.no-queues {
|
||||||
@@ -377,7 +378,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: #6c757d;
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-waiting {
|
.queue-waiting {
|
||||||
@@ -418,7 +419,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: #6c757d;
|
color: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-stats span {
|
.queue-stats span {
|
||||||
@@ -552,27 +553,59 @@
|
|||||||
/* Dark mode support */
|
/* Dark mode support */
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.twp-browser-phone-container {
|
.twp-browser-phone-container {
|
||||||
background: #2d3748;
|
background: #1a202c;
|
||||||
color: #e2e8f0;
|
color: #f7fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twp-connection-status,
|
.twp-connection-status,
|
||||||
.twp-call-info,
|
.twp-call-info,
|
||||||
.twp-queue-controls {
|
.twp-queue-controls,
|
||||||
background: #4a5568;
|
.twp-queue-section {
|
||||||
border-color: #718096;
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twp-select,
|
.twp-select,
|
||||||
#twp-dial-number,
|
#twp-dial-number,
|
||||||
.twp-dial-btn {
|
.twp-dial-btn {
|
||||||
background: #4a5568;
|
background: #2d3748;
|
||||||
border-color: #718096;
|
border-color: #4a5568;
|
||||||
color: #e2e8f0;
|
color: #f7fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.call-status {
|
.call-status {
|
||||||
|
background: #1a202c;
|
||||||
|
color: #f7fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item {
|
||||||
background: #2d3748;
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
|
color: #f7fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item:hover,
|
||||||
|
.queue-item.selected {
|
||||||
|
background: #4a5568;
|
||||||
|
border-color: #63b3ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-name,
|
||||||
|
.status-text,
|
||||||
|
.twp-phone-selection label {
|
||||||
|
color: #f7fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-info,
|
||||||
|
.queue-stats,
|
||||||
|
.queue-loading,
|
||||||
|
.no-queues {
|
||||||
|
color: #cbd5e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-queues {
|
||||||
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,12 +27,40 @@
|
|||||||
loadUserQueues();
|
loadUserQueues();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for Twilio SDK to load
|
||||||
|
*/
|
||||||
|
function waitForTwilioSDK(callback) {
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 50; // 5 seconds max
|
||||||
|
|
||||||
|
function checkTwilio() {
|
||||||
|
if (typeof Twilio !== 'undefined' && Twilio.Device) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts++;
|
||||||
|
if (attempts >= maxAttempts) {
|
||||||
|
updateStatus('offline', 'SDK load timeout');
|
||||||
|
showMessage('Twilio SDK failed to load within 5 seconds. Please check your internet connection and refresh the page.', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(checkTwilio, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTwilio();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the browser phone
|
* Initialize the browser phone
|
||||||
*/
|
*/
|
||||||
function initializeBrowserPhone() {
|
function initializeBrowserPhone() {
|
||||||
updateStatus('connecting', 'Initializing...');
|
updateStatus('connecting', 'Initializing...');
|
||||||
|
|
||||||
|
// Wait for Twilio SDK to load, then initialize
|
||||||
|
waitForTwilioSDK(function() {
|
||||||
// Generate capability token
|
// Generate capability token
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: twp_frontend_ajax.ajax_url,
|
url: twp_frontend_ajax.ajax_url,
|
||||||
@@ -54,12 +82,21 @@
|
|||||||
showMessage('Failed to connect to server', 'error');
|
showMessage('Failed to connect to server', 'error');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup Twilio Device
|
* Setup Twilio Device
|
||||||
*/
|
*/
|
||||||
function setupTwilioDevice(token) {
|
function setupTwilioDevice(token) {
|
||||||
|
// Check if Twilio SDK is loaded
|
||||||
|
if (typeof Twilio === 'undefined' || !Twilio.Device) {
|
||||||
|
updateStatus('offline', 'Twilio SDK not loaded');
|
||||||
|
showMessage('Twilio SDK failed to load. Please refresh the page.', 'error');
|
||||||
|
console.error('Twilio SDK is not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
twilioDevice = new Twilio.Device(token, {
|
twilioDevice = new Twilio.Device(token, {
|
||||||
logLevel: 1,
|
logLevel: 1,
|
||||||
|
@@ -32,7 +32,7 @@ class TWP_Shortcodes {
|
|||||||
'https://sdk.twilio.com/js/voice/2.11.1/twilio.min.js',
|
'https://sdk.twilio.com/js/voice/2.11.1/twilio.min.js',
|
||||||
array(),
|
array(),
|
||||||
'2.11.1',
|
'2.11.1',
|
||||||
true
|
false // Load in head to ensure it's available
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enqueue our browser phone script
|
// Enqueue our browser phone script
|
||||||
@@ -180,10 +180,8 @@ class TWP_Shortcodes {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Audio elements -->
|
<!-- Audio elements for incoming calls handled by browser -->
|
||||||
<audio id="twp-ringtone" preload="auto" loop>
|
<audio id="twp-ringtone" style="display: none;"></audio>
|
||||||
<source src="<?php echo TWP_PLUGIN_URL; ?>assets/audio/ringtone.mp3" type="audio/mpeg">
|
|
||||||
</audio>
|
|
||||||
|
|
||||||
<!-- Error/Success Messages -->
|
<!-- Error/Success Messages -->
|
||||||
<div class="twp-messages" id="twp-messages"></div>
|
<div class="twp-messages" id="twp-messages"></div>
|
||||||
|
Reference in New Issue
Block a user