74 lines
4.4 KiB
JavaScript
74 lines
4.4 KiB
JavaScript
(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;}
|
||
})();
|