Major PWA and mobile UI improvements
- Fixed PWA installation on Android by correcting manifest.json icon configuration - Made UI mobile-friendly with compact layout and sticky record button - Implemented auto-translation after transcription stops - Updated branding from 'Voice Translator' to 'Talk2Me' throughout - Added reverse proxy support with ProxyFix middleware - Created diagnostic tools for PWA troubleshooting - Added proper HTTP headers for service worker and manifest - Improved mobile CSS with responsive design - Fixed JavaScript bundling with webpack configuration - Updated service worker cache versioning - Added comprehensive PWA documentation These changes ensure the app works properly as a PWA on Android devices and provides a better mobile user experience.
This commit is contained in:
168
check-pwa-status.html
Normal file
168
check-pwa-status.html
Normal file
@@ -0,0 +1,168 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PWA Installation Checker</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.check {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.pass {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
.fail {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
.info {
|
||||
background-color: #d1ecf1;
|
||||
color: #0c5460;
|
||||
}
|
||||
pre {
|
||||
background: #f4f4f4;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>PWA Installation Status Checker</h1>
|
||||
<div id="results"></div>
|
||||
|
||||
<script>
|
||||
const results = document.getElementById('results');
|
||||
|
||||
function addResult(message, status = 'info') {
|
||||
const div = document.createElement('div');
|
||||
div.className = `check ${status}`;
|
||||
div.innerHTML = message;
|
||||
results.appendChild(div);
|
||||
}
|
||||
|
||||
// Check HTTPS
|
||||
if (location.protocol === 'https:' || location.hostname === 'localhost') {
|
||||
addResult('✅ HTTPS/Localhost: ' + location.protocol + '//' + location.hostname, 'pass');
|
||||
} else {
|
||||
addResult('❌ Not HTTPS: PWAs require HTTPS (or localhost)', 'fail');
|
||||
}
|
||||
|
||||
// Check Service Worker support
|
||||
if ('serviceWorker' in navigator) {
|
||||
addResult('✅ Service Worker API supported', 'pass');
|
||||
|
||||
// Check registration
|
||||
navigator.serviceWorker.getRegistration().then(reg => {
|
||||
if (reg) {
|
||||
addResult('✅ Service Worker registered: ' + reg.scope, 'pass');
|
||||
addResult('Service Worker state: ' + (reg.active ? 'active' : 'not active'), 'info');
|
||||
} else {
|
||||
addResult('❌ No Service Worker registered', 'fail');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addResult('❌ Service Worker API not supported', 'fail');
|
||||
}
|
||||
|
||||
// Check manifest
|
||||
const manifestLink = document.querySelector('link[rel="manifest"]');
|
||||
if (manifestLink) {
|
||||
addResult('✅ Manifest link found: ' + manifestLink.href, 'pass');
|
||||
|
||||
// Fetch and validate manifest
|
||||
fetch(manifestLink.href)
|
||||
.then(response => response.json())
|
||||
.then(manifest => {
|
||||
addResult('Manifest loaded successfully', 'info');
|
||||
|
||||
// Check required fields
|
||||
const required = ['name', 'short_name', 'start_url', 'display', 'icons'];
|
||||
required.forEach(field => {
|
||||
if (manifest[field]) {
|
||||
addResult(`✅ Manifest has ${field}: ${JSON.stringify(manifest[field])}`, 'pass');
|
||||
} else {
|
||||
addResult(`❌ Manifest missing ${field}`, 'fail');
|
||||
}
|
||||
});
|
||||
|
||||
// Check icons
|
||||
if (manifest.icons && manifest.icons.length > 0) {
|
||||
const has192 = manifest.icons.some(icon => icon.sizes && icon.sizes.includes('192'));
|
||||
const has512 = manifest.icons.some(icon => icon.sizes && icon.sizes.includes('512'));
|
||||
|
||||
if (has192) addResult('✅ Has 192x192 icon', 'pass');
|
||||
else addResult('❌ Missing 192x192 icon', 'fail');
|
||||
|
||||
if (has512) addResult('✅ Has 512x512 icon', 'pass');
|
||||
else addResult('⚠️ Missing 512x512 icon (recommended)', 'info');
|
||||
|
||||
// Check icon purposes
|
||||
manifest.icons.forEach((icon, i) => {
|
||||
addResult(`Icon ${i + 1}: ${icon.sizes} - purpose: ${icon.purpose || 'not specified'}`, 'info');
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
addResult('❌ Failed to load manifest: ' + error.message, 'fail');
|
||||
});
|
||||
} else {
|
||||
addResult('❌ No manifest link found in HTML', 'fail');
|
||||
}
|
||||
|
||||
// Check installability
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
e.preventDefault();
|
||||
addResult('✅ Browser considers app installable (beforeinstallprompt fired)', 'pass');
|
||||
|
||||
// Show install criteria met
|
||||
const criteria = [
|
||||
'HTTPS or localhost',
|
||||
'Valid manifest with required fields',
|
||||
'Service Worker with fetch handler',
|
||||
'Icons (192x192 minimum)',
|
||||
'Not already installed'
|
||||
];
|
||||
|
||||
addResult('<strong>Installation criteria met:</strong><br>' + criteria.join('<br>'), 'info');
|
||||
});
|
||||
|
||||
// Check if already installed
|
||||
if (window.matchMedia('(display-mode: standalone)').matches) {
|
||||
addResult('✅ App is already installed (running in standalone mode)', 'pass');
|
||||
}
|
||||
|
||||
// Additional Chrome-specific checks
|
||||
if (navigator.userAgent.includes('Chrome')) {
|
||||
addResult('Chrome browser detected - checking Chrome-specific requirements', 'info');
|
||||
|
||||
setTimeout(() => {
|
||||
// If no beforeinstallprompt event fired after 3 seconds
|
||||
if (!window.installPromptFired) {
|
||||
addResult('⚠️ beforeinstallprompt event not fired after 3 seconds', 'info');
|
||||
addResult('Possible reasons:<br>' +
|
||||
'- App already installed<br>' +
|
||||
'- User dismissed install prompt recently<br>' +
|
||||
'- Missing PWA criteria<br>' +
|
||||
'- Chrome needs a user gesture to show prompt', 'info');
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Log all checks completed
|
||||
setTimeout(() => {
|
||||
addResult('<br><strong>All checks completed</strong>', 'info');
|
||||
console.log('PWA Status Check Complete');
|
||||
}, 4000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user