Build Markdown news site with local AI generation and web push
This commit is contained in:
1 parent
ad30f12116
commit
199dec8a1e
26 files changed
+2277
-1
No files matched your search
@@ -0,0 +1,73 @@
|
||||
(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;}
|
||||
})();
|
||||
Reference in new issue
Block a user