Add wake lock and device keepalive for reliable mobile calls
Prevents screen sleep during calls and auto-reconnects the Twilio device after app backgrounding. JS handles Screen Wake Lock API and 30s keepalive polling; Flutter coordinates via WakelockPlus and synthetic visibilitychange events on app resume. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -110,6 +110,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
var serviceWorkerRegistration = null;
|
||||
var currentCallDirection = null;
|
||||
var callHistory = [];
|
||||
var wakeLock = null;
|
||||
var deviceKeepaliveTimer = null;
|
||||
|
||||
// ============================================================
|
||||
// AudioContext & Ringtone
|
||||
@@ -193,13 +195,79 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Screen Wake Lock
|
||||
// ============================================================
|
||||
async function requestWakeLock() {
|
||||
if (!('wakeLock' in navigator)) return;
|
||||
try {
|
||||
wakeLock = await navigator.wakeLock.request('screen');
|
||||
console.log('TWP: Wake lock acquired');
|
||||
wakeLock.addEventListener('release', function() {
|
||||
console.log('TWP: Wake lock released');
|
||||
wakeLock = null;
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('TWP: Wake lock request failed:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function releaseWakeLock() {
|
||||
if (wakeLock) {
|
||||
wakeLock.release().catch(function() {});
|
||||
wakeLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Device Keepalive Monitor
|
||||
// ============================================================
|
||||
function startDeviceKeepalive() {
|
||||
stopDeviceKeepalive();
|
||||
deviceKeepaliveTimer = setInterval(function() {
|
||||
if (device && deviceConnectionState !== 'connected' && !currentCall) {
|
||||
console.log('TWP: Keepalive — device disconnected, re-registering');
|
||||
device.register().catch(function(e) {
|
||||
console.warn('TWP: Keepalive re-register failed:', e.message);
|
||||
});
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
|
||||
function stopDeviceKeepalive() {
|
||||
if (deviceKeepaliveTimer) {
|
||||
clearInterval(deviceKeepaliveTimer);
|
||||
deviceKeepaliveTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Page Visibility
|
||||
// ============================================================
|
||||
function setupPageVisibility() {
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
isPageVisible = !document.hidden;
|
||||
if (isPageVisible && audioContext) initializeAudioContext();
|
||||
if (isPageVisible) {
|
||||
console.log('TWP: Page visible — checking connections');
|
||||
// Resume audio
|
||||
if (audioContext) initializeAudioContext();
|
||||
// Re-request wake lock (auto-released when tab hidden)
|
||||
requestWakeLock();
|
||||
// Check token expiry — refresh if expired or within 2 minutes
|
||||
if (tokenExpiry && (Date.now() > tokenExpiry - 2 * 60 * 1000)) {
|
||||
console.log('TWP: Token expired or expiring soon, refreshing');
|
||||
refreshToken();
|
||||
}
|
||||
// Check device registration
|
||||
if (device && deviceConnectionState !== 'connected' && !currentCall) {
|
||||
console.log('TWP: Device disconnected, re-registering');
|
||||
device.register().catch(function(e) {
|
||||
console.warn('TWP: Visibility re-register failed:', e.message);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('TWP: Page hidden — wake lock auto-released by browser');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -352,6 +420,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
device.on('tokenWillExpire', function() { refreshToken(); });
|
||||
|
||||
await device.register();
|
||||
requestWakeLock();
|
||||
startDeviceKeepalive();
|
||||
} catch (error) {
|
||||
showError('Failed to setup device: ' + error.message);
|
||||
}
|
||||
@@ -363,6 +433,7 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
function setupCallHandlers(call) {
|
||||
call.on('accept', function() {
|
||||
stopRingtone();
|
||||
requestWakeLock();
|
||||
$('#phone-status').text('Connected').css('color', 'var(--accent)');
|
||||
$('#call-btn').hide();
|
||||
$('#answer-btn').hide();
|
||||
@@ -1041,6 +1112,8 @@ var twpTwilioEdge = window.twpConfig.twilioEdge;
|
||||
// ============================================================
|
||||
$(window).on('beforeunload', function() {
|
||||
if (tokenRefreshTimer) clearTimeout(tokenRefreshTimer);
|
||||
releaseWakeLock();
|
||||
stopDeviceKeepalive();
|
||||
if (device) device.destroy();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user