Files
mwitnessing/components/PwaManager.tsx
Dobromir Popov 348e404565 fix typo
2024-04-17 01:37:00 +03:00

233 lines
8.8 KiB
TypeScript
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.

import React, { useEffect, useState } from 'react';
import common from '../src/helpers/common'; // Ensure this path is correct
function PwaManager() {
const [deferredPrompt, setDeferredPrompt] = useState(null);
const [isPWAInstalled, setIsPWAInstalled] = useState(false);
const [isStandAlone, setIsStandAlone] = useState(false);
const [isSubscribed, setIsSubscribed] = useState(false);
const [subscription, setSubscription] = useState(null);
const [registration, setRegistration] = useState(null);
const [notificationPermission, setNotificationPermission] = useState(Notification.permission);
// Handle PWA installation
useEffect(() => {
setNotificationPermission(Notification.permission);
// Handle Push Notification Subscription
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.ready.then(reg => {
reg.pushManager.getSubscription().then(sub => {
if (sub) {
setSubscription(sub);
setIsSubscribed(true);
}
});
setRegistration(reg);
});
}
// Check if the app is running in standalone mode
if (window.matchMedia('(display-mode: standalone)').matches) {
setIsStandAlone(true);
}
const handleBeforeInstallPrompt = (e) => {
e.preventDefault();
setDeferredPrompt(e);
};
const handleAppInstalled = () => {
setIsPWAInstalled(true);
};
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
window.addEventListener('appinstalled', handleAppInstalled);
return () => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
window.removeEventListener('appinstalled', handleAppInstalled);
};
}, []);
const installPWA = async (e) => {
e.preventDefault();
if (deferredPrompt) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
setIsPWAInstalled(true);
}
setDeferredPrompt(null);
}
};
// Utility function for converting base64 string to Uint8Array
const base64ToUint8Array = base64 => {
const padding = '='.repeat((4 - (base64.length % 4)) % 4);
const b64 = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(b64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
const subscribeToNotifications = async (e) => {
try {
e.preventDefault();
if (!registration) {
console.error('Service worker registration not found.');
registration
return;
}
const sub = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: base64ToUint8Array(process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY)
});
// Call your API to save subscription data on server
setSubscription(sub);
setIsSubscribed(true);
console.log('Web push subscribed!');
console.log(sub);
} catch (error) {
console.error('Error subscribing to notifications:', error);
}
};
const unsubscribeFromNotifications = async (e) => {
try {
e.preventDefault();
await subscription.unsubscribe();
// Call your API to delete or invalidate subscription data on server
setSubscription(null);
setIsSubscribed(false);
console.log('Web push unsubscribed!');
} catch (error) {
console.error('Error unsubscribing from notifications:', error);
}
};
// Function to request push notification permission
const requestNotificationPermission = async (e) => {
e.preventDefault();
const permission = await Notification.requestPermission();
setNotificationPermission(permission);
if (permission === "granted") {
// User granted permission
subscribeToNotifications(null); // Pass the required argument here
} else {
// User denied or dismissed permission
console.log("Push notifications permission denied.");
}
};
// Function to toggle push notifications
const togglePushNotifications = async (e) => {
e.preventDefault();
if (notificationPermission === "granted") {
// If already subscribed, unsubscribe
unsubscribeFromNotifications(null); // Pass null as the argument
} else if (notificationPermission === "default" || notificationPermission === "denied") {
// Request permission if not already granted
await requestNotificationPermission(e);
}
};
const sendTestNotification = async (e) => {
e.preventDefault();
if (!subscription) {
console.error('Web push not subscribed');
return;
}
await fetch('/api/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ subscription })
});
};
return (
<>
<div>
<h1>PWA Manager</h1>
{!isStandAlone && !isPWAInstalled && (
<button
onClick={installPWA}
className="bg-blue-500 hover:bg-blue-700 text-white text-xs py-1 px-2 rounded-full focus:outline-none focus:shadow-outline transition duration-150 ease-in-out"
>
Install PWA
</button>
)}
{isPWAInstalled && <p>App is installed!</p>}
{isStandAlone && <p>PWA App</p>}
<button
onClick={subscribeToNotifications}
disabled={isSubscribed}
className={`text-xs py-1 px-2 rounded-full focus:outline-none transition duration-150 ease-in-out ${isSubscribed ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-green-500 hover:bg-green-700 text-white'
}`}
>
Subscribe to Notifications
</button>
<button
onClick={unsubscribeFromNotifications}
disabled={!isSubscribed}
className={`text-xs py-1 px-2 rounded-full focus:outline-none transition duration-150 ease-in-out ${!isSubscribed ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-red-500 hover:bg-red-700 text-white'
}`}
>
Unsubscribe from Notifications
</button>
</div>
<div>
<button
onClick={sendTestNotification}
disabled={!isSubscribed}
className={`text-xs py-1 px-2 rounded-full focus:outline-none transition duration-150 ease-in-out ${!isSubscribed ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-yellow-500 hover:bg-yellow-600 text-white'
}`}
>
Send Test Notification
</button>
{notificationPermission !== "granted" && (
<button
onClick={togglePushNotifications}
className={`text-xs py-1 px-2 rounded-full focus:outline-none transition duration-150 ease-in-out ${notificationPermission === "denied" ? 'bg-red-500 hover:bg-red-700 text-white' : 'bg-green-500 hover:bg-green-700 text-white'
}`}
>
{notificationPermission === "denied" ? 'Notifications Denied!' : 'Enable Notifications'}
</button>
)}
</div>
<div>
<a href="https://t.me/mwhitnessing_bot" className="inline-flex items-center ml-4" target="_blank">
<img src="/content/icons/telegram-svgrepo-com.svg" alt="Телеграм" width="32" height="32" className="align-middle" />
<span className="align-middle">Телеграм</span>
</a>
</div>
<div>
<a href="/api/auth/apple-signin" className="inline-flex items-center ml-4" target="_blank">
<span className="align-middle">Apple sign-in</span>
</a>
</div>
</>
);
}
export default PwaManager;