Files
TrueNews/public/notifications.js
T

74 lines
4.4 KiB
JavaScript
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.
(async()=>{
const panel=document.querySelector('#push-prompt');
const toggle=document.querySelector('#push-toggle');
const enable=document.querySelector('#push-enable');
const dismiss=document.querySelector('#push-dismiss');
const message=document.querySelector('#push-message');
const status=document.querySelector('#push-status');
let registration;
let config;
let subscription;
const remember=()=>{try{localStorage.setItem('truenews-push-dismissed',String(Date.now()));}catch{}};
const dismissed=()=>{try{return Date.now()-Number(localStorage.getItem('truenews-push-dismissed')||0)<30*86400000;}catch{return false;}};
const api=async(action,value)=>{
const response=await fetch(`/api/push/${action}`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(value)});
if(!response.ok)throw new Error('Could not save your preference. Please try again.');
};
const show=()=>{panel.hidden=false;};
const update=()=>{
toggle.textContent=subscription?'Notifications on':'Get new stories';
enable.textContent=subscription?'Turn off notifications':'Enable notifications';
message.textContent=subscription?'You’ll get a notification when a new article is published.':'Get a browser notification when a new story is published. You can turn this off anytime.';
};
try {
const response=await fetch('/api/push/config');
if(!response.ok)return;
config=await response.json();
if(!config.enabled)return;
toggle.hidden=false;
const supported=window.isSecureContext && 'serviceWorker' in navigator && 'PushManager' in window && 'Notification' in window;
if(!supported){
const explain=()=>{
show();enable.hidden=true;
const apple=/iPad|iPhone|iPod/.test(navigator.userAgent)||(navigator.platform==='MacIntel'&&navigator.maxTouchPoints>1);
message.textContent=apple?'On iPhone or iPad, add TrueNews to your Home Screen, open it from there, then enable notifications.':'Notifications need a supported browser and a secure HTTPS connection.';
};
toggle.addEventListener('click',explain);
if((/iPad|iPhone|iPod/.test(navigator.userAgent)||(navigator.platform==='MacIntel'&&navigator.maxTouchPoints>1))&&!dismissed())explain();
dismiss.addEventListener('click',()=>{panel.hidden=true;remember();});
return;
}
registration=await navigator.serviceWorker.register('/sw.js');
await navigator.serviceWorker.ready;
subscription=await registration.pushManager.getSubscription();
if(subscription && Notification.permission==='granted') {
// Restore the server record if a device revisits after a transient failure.
await api('subscribe',subscription.toJSON()).catch(()=>{status.textContent='Could not sync notifications. You can retry or turn them off below.';});
}
update();
toggle.addEventListener('click',()=>{status.textContent='';update();show();});
dismiss.addEventListener('click',()=>{panel.hidden=true;remember();});
enable.addEventListener('click',async()=>{
enable.disabled=true;status.textContent='';
try {
if(subscription){
await api('unsubscribe',subscription.toJSON());
await subscription.unsubscribe();subscription=null;remember();update();status.textContent='Notifications turned off.';
}else{
// Permission must be requested directly from this user gesture.
const permission=await Notification.requestPermission();
if(permission!=='granted'){
remember();status.textContent=permission==='denied'?'Notifications are blocked. You can change this in your browser’s site settings.':'No problem. You can enable notifications here later.';return;
}
const key=Uint8Array.from(atob(config.publicKey.replace(/-/g,'+').replace(/_/g,'/')),c=>c.charCodeAt(0));
const created=await registration.pushManager.subscribe({userVisibleOnly:true,applicationServerKey:key});
try {await api('subscribe',created.toJSON());}catch(error){await created.unsubscribe();throw error;}
subscription=created;update();status.textContent='You’re subscribed. Watch for the next story.';
}
}catch(error){status.textContent=error.message || 'Could not update notifications. Please try again.';}
finally{enable.disabled=false;}
});
if(!subscription && Notification.permission==='default' && !dismissed()) show();
}catch{toggle.hidden=true;panel.hidden=true;}
})();