pwa manager in settings

This commit is contained in:
Dobromir Popov
2024-04-08 12:47:29 +03:00
parent 3ddb514d9c
commit ff97d441b1
2 changed files with 241 additions and 4 deletions

227
components/PwaManager.tsx Normal file
View File

@ -0,0 +1,227 @@
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/notification', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ subscription })
});
};
return (
<>
<div>
<h1>PWA Manager</h1>
{!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>App is running in standalone mode!</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>
</>
);
}
export default PwaManager;

View File

@ -6,6 +6,7 @@ import Link from "next/link";
import axiosInstance from '../../src/axiosSecure';
//import { getDate } from "date-fns";
import PwaManager from "../PwaManager";
import { monthNamesBG, GetTimeFormat, GetDateFormat } from "../../src/helpers/const"
import PublisherSearchBox from './PublisherSearchBox';
import AvailabilityList from "../availability/AvailabilityList";
@ -241,16 +242,28 @@ export default function PublisherForm({ item, me }) {
<input type="text" id="town" name="town" value={publisher.town} onChange={handleChange} className="textbox" placeholder="Град" autoFocus />
</div>
<div className="mb-4">
{/* notifications */}
<div className="form-check">
<input className="checkbox" type="checkbox" id="isSubscribedToCoverMe" name="isSubscribedToCoverMe" onChange={handleChange} checked={publisher.isSubscribedToCoverMe} autoComplete="off" />
<label className="label" htmlFor="isSubscribedToCoverMe">Абониран за имейли за заместване</label>
<input className="checkbox" type="checkbox" id="isSubscribedToReminders" name="isSubscribedToReminders" onChange={handleChange} checked={publisher.isSubscribedToReminders} autoComplete="off" />
<label className="label" htmlFor="isSubscribedToReminders">Абониран за напомняния (имейл)</label>
{/* prompt to install PWA */}
</div>
</div>
{/* button to install PWA */}
{/* <div className="mb-4">
<button className="button bg-blue-500 hover:bg-blue-700 focus:outline-none focus:shadow-outline" type="button" onClick={() => window.installPWA()}>
Инсталирай приложението
</div> */}
{/* ADMINISTRATORS ONLY */}
<ProtectedRoute allowedRoles={[UserRole.ADMIN]} deniedMessage=" " className="">
<PwaManager />
<div className="border border-blue-500 border-solid p-2">
<div className="mb-4">
<label className="label" htmlFor="type">Тип</label>
@ -292,10 +305,7 @@ export default function PublisherForm({ item, me }) {
{/* Add other roles as needed */}
</select>
</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>
</ProtectedRoute>
{/* ---------------------------- Actions --------------------------------- */}