PWA-implementation
This commit is contained in:
205
LittleShop/wwwroot/js/pwa.js
Normal file
205
LittleShop/wwwroot/js/pwa.js
Normal file
@@ -0,0 +1,205 @@
|
||||
// Progressive Web App functionality
|
||||
// Handles service worker registration and PWA features
|
||||
|
||||
class PWAManager {
|
||||
constructor() {
|
||||
this.swRegistration = null;
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
console.log('PWA: Initializing PWA Manager...');
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
this.swRegistration = await navigator.serviceWorker.register('/sw.js');
|
||||
console.log('SW: Service Worker registered successfully');
|
||||
|
||||
// Listen for updates
|
||||
this.swRegistration.addEventListener('updatefound', () => {
|
||||
console.log('SW: New version available');
|
||||
this.showUpdateNotification();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log('SW: Service Worker registration failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup PWA install prompt
|
||||
this.setupInstallPrompt();
|
||||
|
||||
// Setup notifications (if enabled)
|
||||
this.setupNotifications();
|
||||
|
||||
// Show manual install option after 3 seconds if no prompt appeared
|
||||
setTimeout(() => {
|
||||
if (!document.getElementById('pwa-install-btn')) {
|
||||
this.showManualInstallButton();
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
setupInstallPrompt() {
|
||||
let deferredPrompt;
|
||||
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
console.log('PWA: beforeinstallprompt event fired');
|
||||
// Prevent Chrome 67 and earlier from automatically showing the prompt
|
||||
e.preventDefault();
|
||||
deferredPrompt = e;
|
||||
|
||||
// Show custom install button
|
||||
this.showInstallButton(deferredPrompt);
|
||||
});
|
||||
|
||||
window.addEventListener('appinstalled', () => {
|
||||
console.log('PWA: App was installed');
|
||||
this.hideInstallButton();
|
||||
});
|
||||
|
||||
// Debug: Check if app is already installed
|
||||
if (this.isInstalled()) {
|
||||
console.log('PWA: App is already installed (standalone mode)');
|
||||
} else {
|
||||
console.log('PWA: App is not installed, waiting for install prompt...');
|
||||
}
|
||||
}
|
||||
|
||||
showInstallButton(deferredPrompt) {
|
||||
// Create install button
|
||||
const installBtn = document.createElement('button');
|
||||
installBtn.id = 'pwa-install-btn';
|
||||
installBtn.className = 'btn btn-primary btn-sm';
|
||||
installBtn.innerHTML = '<i class="fas fa-download"></i> Install App';
|
||||
installBtn.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
|
||||
`;
|
||||
|
||||
installBtn.addEventListener('click', async () => {
|
||||
if (deferredPrompt) {
|
||||
deferredPrompt.prompt();
|
||||
const { outcome } = await deferredPrompt.userChoice;
|
||||
console.log('PWA: User response to install prompt:', outcome);
|
||||
deferredPrompt = null;
|
||||
this.hideInstallButton();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.appendChild(installBtn);
|
||||
}
|
||||
|
||||
hideInstallButton() {
|
||||
const installBtn = document.getElementById('pwa-install-btn');
|
||||
if (installBtn) {
|
||||
installBtn.remove();
|
||||
}
|
||||
}
|
||||
|
||||
showUpdateNotification() {
|
||||
// Show update available notification
|
||||
const notification = document.createElement('div');
|
||||
notification.className = 'alert alert-info alert-dismissible';
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1050;
|
||||
max-width: 300px;
|
||||
`;
|
||||
|
||||
notification.innerHTML = `
|
||||
<strong>Update Available!</strong><br>
|
||||
A new version of the app is ready.
|
||||
<button type="button" class="btn btn-sm btn-outline-info ms-2" id="update-btn">
|
||||
Update Now
|
||||
</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Handle update
|
||||
document.getElementById('update-btn').addEventListener('click', () => {
|
||||
if (this.swRegistration && this.swRegistration.waiting) {
|
||||
this.swRegistration.waiting.postMessage({ type: 'SKIP_WAITING' });
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async setupNotifications() {
|
||||
// Check if notifications are supported and get permission
|
||||
if ('Notification' in window) {
|
||||
const permission = await this.requestNotificationPermission();
|
||||
console.log('Notifications permission:', permission);
|
||||
}
|
||||
}
|
||||
|
||||
async requestNotificationPermission() {
|
||||
if (Notification.permission === 'default') {
|
||||
// Only request permission when user interacts with a relevant feature
|
||||
// For now, just return the current status
|
||||
return Notification.permission;
|
||||
}
|
||||
return Notification.permission;
|
||||
}
|
||||
|
||||
// Show notification (if permission granted)
|
||||
showNotification(title, options = {}) {
|
||||
if (Notification.permission === 'granted') {
|
||||
const notification = new Notification(title, {
|
||||
icon: '/icons/icon-192x192.png',
|
||||
badge: '/icons/icon-72x72.png',
|
||||
tag: 'littleshop-admin',
|
||||
...options
|
||||
});
|
||||
|
||||
// Auto-close after 5 seconds
|
||||
setTimeout(() => {
|
||||
notification.close();
|
||||
}, 5000);
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
|
||||
// Show manual install button for browsers that don't auto-prompt
|
||||
showManualInstallButton() {
|
||||
console.log('PWA: Showing manual install button');
|
||||
const installBtn = document.createElement('button');
|
||||
installBtn.id = 'pwa-install-btn';
|
||||
installBtn.className = 'btn btn-primary btn-sm';
|
||||
installBtn.innerHTML = '<i class="fas fa-mobile-alt"></i> Install as App';
|
||||
installBtn.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
|
||||
`;
|
||||
|
||||
installBtn.addEventListener('click', () => {
|
||||
alert('To install this app:\\n\\n1. Click the browser menu (⋮)\\n2. Select "Install LittleShop Admin"\\n\\nOr look for the install icon in the address bar!');
|
||||
});
|
||||
|
||||
document.body.appendChild(installBtn);
|
||||
}
|
||||
|
||||
// Check if app is installed
|
||||
isInstalled() {
|
||||
return window.matchMedia('(display-mode: standalone)').matches ||
|
||||
window.navigator.standalone === true;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize PWA Manager
|
||||
const pwaManager = new PWAManager();
|
||||
window.pwaManager = pwaManager;
|
||||
|
||||
// Expose notification function globally
|
||||
window.showNotification = (title, options) => pwaManager.showNotification(title, options);
|
||||
Reference in New Issue
Block a user