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 {
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
    color: #212529;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@keyframes pulse {
 | 
			
		||||
@@ -74,8 +74,8 @@
 | 
			
		||||
.twp-phone-selection label {
 | 
			
		||||
    display: block;
 | 
			
		||||
    margin-bottom: 8px;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
    color: #212529;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.twp-select {
 | 
			
		||||
@@ -85,7 +85,7 @@
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
    background: #fff;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    color: #212529;
 | 
			
		||||
    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-position: right 12px center;
 | 
			
		||||
@@ -289,8 +289,8 @@
 | 
			
		||||
    padding: 8px;
 | 
			
		||||
    background: #f8f9fa;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    color: #212529;
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Queue Management Section */
 | 
			
		||||
@@ -317,9 +317,10 @@
 | 
			
		||||
.queue-loading,
 | 
			
		||||
.no-queues {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    color: #6c757d;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
    padding: 20px;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.no-queues {
 | 
			
		||||
@@ -377,7 +378,7 @@
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    font-size: 0.9rem;
 | 
			
		||||
    color: #6c757d;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.queue-waiting {
 | 
			
		||||
@@ -418,7 +419,7 @@
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    gap: 20px;
 | 
			
		||||
    font-size: 0.9rem;
 | 
			
		||||
    color: #6c757d;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.queue-stats span {
 | 
			
		||||
@@ -552,27 +553,59 @@
 | 
			
		||||
/* Dark mode support */
 | 
			
		||||
@media (prefers-color-scheme: dark) {
 | 
			
		||||
    .twp-browser-phone-container {
 | 
			
		||||
        background: #2d3748;
 | 
			
		||||
        color: #e2e8f0;
 | 
			
		||||
        background: #1a202c;
 | 
			
		||||
        color: #f7fafc;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .twp-connection-status,
 | 
			
		||||
    .twp-call-info,
 | 
			
		||||
    .twp-queue-controls {
 | 
			
		||||
        background: #4a5568;
 | 
			
		||||
        border-color: #718096;
 | 
			
		||||
    .twp-queue-controls,
 | 
			
		||||
    .twp-queue-section {
 | 
			
		||||
        background: #2d3748;
 | 
			
		||||
        border-color: #4a5568;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .twp-select,
 | 
			
		||||
    #twp-dial-number,
 | 
			
		||||
    .twp-dial-btn {
 | 
			
		||||
        background: #4a5568;
 | 
			
		||||
        border-color: #718096;
 | 
			
		||||
        color: #e2e8f0;
 | 
			
		||||
        background: #2d3748;
 | 
			
		||||
        border-color: #4a5568;
 | 
			
		||||
        color: #f7fafc;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .call-status {
 | 
			
		||||
        background: #1a202c;
 | 
			
		||||
        color: #f7fafc;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .queue-item {
 | 
			
		||||
        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,32 +27,61 @@
 | 
			
		||||
        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
 | 
			
		||||
     */
 | 
			
		||||
    function initializeBrowserPhone() {
 | 
			
		||||
        updateStatus('connecting', 'Initializing...');
 | 
			
		||||
        
 | 
			
		||||
        // Generate capability token
 | 
			
		||||
        $.ajax({
 | 
			
		||||
            url: twp_frontend_ajax.ajax_url,
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            data: {
 | 
			
		||||
                action: 'twp_generate_capability_token',
 | 
			
		||||
                nonce: twp_frontend_ajax.nonce
 | 
			
		||||
            },
 | 
			
		||||
            success: function(response) {
 | 
			
		||||
                if (response.success) {
 | 
			
		||||
                    setupTwilioDevice(response.data.token);
 | 
			
		||||
                } else {
 | 
			
		||||
                    updateStatus('offline', 'Failed to initialize');
 | 
			
		||||
                    showMessage('Failed to initialize browser phone: ' + (response.data || 'Unknown error'), 'error');
 | 
			
		||||
        // Wait for Twilio SDK to load, then initialize
 | 
			
		||||
        waitForTwilioSDK(function() {
 | 
			
		||||
            // Generate capability token
 | 
			
		||||
            $.ajax({
 | 
			
		||||
                url: twp_frontend_ajax.ajax_url,
 | 
			
		||||
                method: 'POST',
 | 
			
		||||
                data: {
 | 
			
		||||
                    action: 'twp_generate_capability_token',
 | 
			
		||||
                    nonce: twp_frontend_ajax.nonce
 | 
			
		||||
                },
 | 
			
		||||
                success: function(response) {
 | 
			
		||||
                    if (response.success) {
 | 
			
		||||
                        setupTwilioDevice(response.data.token);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        updateStatus('offline', 'Failed to initialize');
 | 
			
		||||
                        showMessage('Failed to initialize browser phone: ' + (response.data || 'Unknown error'), 'error');
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                error: function() {
 | 
			
		||||
                    updateStatus('offline', 'Connection failed');
 | 
			
		||||
                    showMessage('Failed to connect to server', 'error');
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            error: function() {
 | 
			
		||||
                updateStatus('offline', 'Connection failed');
 | 
			
		||||
                showMessage('Failed to connect to server', 'error');
 | 
			
		||||
            }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
@@ -60,6 +89,14 @@
 | 
			
		||||
     * Setup Twilio Device
 | 
			
		||||
     */
 | 
			
		||||
    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 {
 | 
			
		||||
            twilioDevice = new Twilio.Device(token, {
 | 
			
		||||
                logLevel: 1,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ class TWP_Shortcodes {
 | 
			
		||||
                'https://sdk.twilio.com/js/voice/2.11.1/twilio.min.js',
 | 
			
		||||
                array(),
 | 
			
		||||
                '2.11.1',
 | 
			
		||||
                true
 | 
			
		||||
                false // Load in head to ensure it's available
 | 
			
		||||
            );
 | 
			
		||||
            
 | 
			
		||||
            // Enqueue our browser phone script
 | 
			
		||||
@@ -180,10 +180,8 @@ class TWP_Shortcodes {
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            
 | 
			
		||||
            <!-- Audio elements -->
 | 
			
		||||
            <audio id="twp-ringtone" preload="auto" loop>
 | 
			
		||||
                <source src="<?php echo TWP_PLUGIN_URL; ?>assets/audio/ringtone.mp3" type="audio/mpeg">
 | 
			
		||||
            </audio>
 | 
			
		||||
            <!-- Audio elements for incoming calls handled by browser -->
 | 
			
		||||
            <audio id="twp-ringtone" style="display: none;"></audio>
 | 
			
		||||
            
 | 
			
		||||
            <!-- Error/Success Messages -->
 | 
			
		||||
            <div class="twp-messages" id="twp-messages"></div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user