Files
twilio-wp-plugin/includes/class-twp-shortcodes.php
Josh Knapp 872182a393 Fix browser phone issues and improve UI organization
- Fix 403 Forbidden error in voicemail AJAX by correcting nonce validation
- Create accordion-style collapsible voicemail section with persistent state
- Restructure queue controls to show alert toggle button consistently
- Add global queue actions always visible when user has assigned queues
- Implement smooth slide animations and localStorage state management
- Update dark mode support for new UI elements and improved accessibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 09:56:04 -07:00

250 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Handle plugin shortcodes
*/
class TWP_Shortcodes {
/**
* Initialize shortcodes
*/
public static function init() {
add_action('init', array(__CLASS__, 'register_shortcodes'));
add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_frontend_assets'));
}
/**
* Register all shortcodes
*/
public static function register_shortcodes() {
add_shortcode('twp_browser_phone', array(__CLASS__, 'browser_phone_shortcode'));
}
/**
* Enqueue frontend assets when shortcode is present
*/
public static function enqueue_frontend_assets() {
global $post;
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'twp_browser_phone')) {
// Enqueue Twilio Voice SDK from unpkg CDN (same as backend)
wp_enqueue_script(
'twilio-voice-sdk',
'https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js',
array(),
'2.11.0',
false // Load in head to ensure it's available
);
// Add backup SDK loading
wp_add_inline_script('twilio-voice-sdk', "
window.twpLoadTwilioSDK = function() {
if (typeof Twilio === 'undefined') {
console.warn('Primary Twilio SDK failed, attempting fallback load');
var script = document.createElement('script');
script.src = 'https://unpkg.com/@twilio/voice-sdk@2.11.0/dist/twilio.min.js';
script.onload = function() { console.log('Fallback Twilio SDK loaded'); };
script.onerror = function() { console.error('Fallback Twilio SDK failed'); };
document.head.appendChild(script);
}
};
// Try loading after a delay if not available
setTimeout(window.twpLoadTwilioSDK, 2000);
", 'after');
// Enqueue our browser phone script
wp_enqueue_script(
'twp-browser-phone-frontend',
TWP_PLUGIN_URL . 'assets/js/browser-phone-frontend.js',
array('jquery', 'twilio-voice-sdk'),
TWP_VERSION,
true
);
// Enqueue mobile-friendly styles
wp_enqueue_style(
'twp-browser-phone-frontend',
TWP_PLUGIN_URL . 'assets/css/browser-phone-frontend.css',
array(),
TWP_VERSION
);
// Localize script with AJAX data
wp_localize_script('twp-browser-phone-frontend', 'twp_frontend_ajax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'admin_url' => admin_url(),
'nonce' => wp_create_nonce('twp_frontend_nonce'),
'user_id' => get_current_user_id(),
'is_logged_in' => is_user_logged_in()
));
}
}
/**
* Browser phone shortcode handler
*/
public static function browser_phone_shortcode($atts) {
// Check if user is logged in
if (!is_user_logged_in()) {
return '<div class="twp-error">You must be logged in to access the browser phone.</div>';
}
// Check if user has permission
if (!current_user_can('twp_access_browser_phone') && !current_user_can('manage_options')) {
return '<div class="twp-error">You don\'t have permission to access the browser phone.</div>';
}
// Parse shortcode attributes
$atts = shortcode_atts(array(
'title' => 'Browser Phone',
'show_title' => 'true',
'compact' => 'false'
), $atts, 'twp_browser_phone');
$show_title = ($atts['show_title'] === 'true');
$compact_mode = ($atts['compact'] === 'true');
ob_start();
?>
<div id="twp-frontend-browser-phone" class="twp-browser-phone-container <?php echo $compact_mode ? 'compact' : ''; ?>">
<?php if ($show_title): ?>
<h3 class="twp-browser-phone-title"><?php echo esc_html($atts['title']); ?></h3>
<?php endif; ?>
<!-- Connection Status -->
<div class="twp-connection-status">
<span class="status-indicator offline" id="twp-status-indicator"></span>
<span class="status-text" id="twp-status-text">Connecting...</span>
</div>
<!-- Phone Number Selection -->
<div class="twp-phone-selection">
<label for="twp-caller-id">Caller ID:</label>
<select id="twp-caller-id" class="twp-select">
<option value="">Loading...</option>
</select>
</div>
<!-- Dial Pad -->
<div class="twp-dialpad">
<div class="twp-number-display">
<input type="tel" id="twp-dial-number" placeholder="Enter number to dial" />
<button id="twp-clear-number" class="twp-btn-clear" title="Clear">×</button>
</div>
<div class="twp-dial-grid">
<button class="twp-dial-btn" data-digit="1">1<span></span></button>
<button class="twp-dial-btn" data-digit="2">2<span>ABC</span></button>
<button class="twp-dial-btn" data-digit="3">3<span>DEF</span></button>
<button class="twp-dial-btn" data-digit="4">4<span>GHI</span></button>
<button class="twp-dial-btn" data-digit="5">5<span>JKL</span></button>
<button class="twp-dial-btn" data-digit="6">6<span>MNO</span></button>
<button class="twp-dial-btn" data-digit="7">7<span>PQRS</span></button>
<button class="twp-dial-btn" data-digit="8">8<span>TUV</span></button>
<button class="twp-dial-btn" data-digit="9">9<span>WXYZ</span></button>
<button class="twp-dial-btn" data-digit="*">*</button>
<button class="twp-dial-btn" data-digit="0">0<span>+</span></button>
<button class="twp-dial-btn" data-digit="#">#</button>
</div>
</div>
<!-- Call Controls -->
<div class="twp-call-controls">
<button id="twp-call-btn" class="twp-btn twp-btn-primary">
<span class="call-icon">📞</span>
<span class="call-text">Call</span>
</button>
<button id="twp-hangup-btn" class="twp-btn twp-btn-danger" style="display: none;">
<span class="hangup-icon">📞</span>
<span class="hangup-text">Hang Up</span>
</button>
</div>
<!-- Call Info -->
<div class="twp-call-info" id="twp-call-info" style="display: none;">
<div class="call-timer">
<span class="timer-label">Call Duration:</span>
<span class="timer-value" id="twp-call-timer">00:00</span>
</div>
<div class="call-status">
<span id="twp-call-status">Connecting...</span>
</div>
</div>
<!-- Queue Management Section -->
<div class="twp-queue-section" id="twp-queue-section">
<h4>Your Queues</h4>
<div class="twp-queue-list" id="twp-queue-list">
<div class="queue-loading">Loading queues...</div>
</div>
<!-- Queue Actions (Always Visible) -->
<div class="queue-global-actions" id="twp-queue-global-actions" style="display: none;">
<div class="global-queue-actions">
<button id="twp-refresh-queues" class="twp-btn twp-btn-secondary">
Refresh
</button>
<button id="twp-alert-toggle" class="twp-btn twp-btn-secondary alert-off">
🔕 Alerts OFF
</button>
</div>
</div>
<!-- Queue Controls (Only When Call Selected) -->
<div class="twp-queue-controls" id="twp-queue-controls" style="display: none;">
<div class="selected-queue-info">
<h5 id="selected-queue-name">No queue selected</h5>
<div class="queue-stats">
<span class="waiting-count">Waiting: <span id="twp-waiting-count">0</span></span>
<span class="queue-size">Max: <span id="twp-queue-max-size">-</span></span>
</div>
</div>
<div class="queue-actions">
<button id="twp-accept-queue-call" class="twp-btn twp-btn-success">
Accept Next Call
</button>
</div>
</div>
</div>
<!-- Voicemail Section -->
<div class="twp-voicemail-section" id="twp-voicemail-section">
<div class="voicemail-header" id="twp-voicemail-header">
<h4>Recent Voicemails</h4>
<div class="voicemail-summary">
<span class="summary-stats">
Total: <span id="twp-total-voicemails">0</span> |
Today: <span id="twp-today-voicemails">0</span>
</span>
<button class="voicemail-toggle" id="twp-voicemail-toggle">
<span class="toggle-icon">▼</span>
</button>
</div>
</div>
<div class="voicemail-content" id="twp-voicemail-content" style="display: none;">
<div class="twp-voicemail-list" id="twp-voicemail-list">
<div class="voicemail-loading">Loading voicemails...</div>
</div>
<div class="voicemail-actions">
<button id="twp-refresh-voicemails" class="twp-btn twp-btn-secondary">
Refresh
</button>
<button id="twp-view-all-voicemails" class="twp-btn twp-btn-secondary">
View All
</button>
</div>
</div>
</div>
<!-- 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>
</div>
<?php
return ob_get_clean();
}
}