belaudiobooks / website

Catalog of belarusian audiobooks
GNU General Public License v3.0
33 stars 6 forks source link

Push notifications #94

Open nbeloglazov opened 1 year ago

nbeloglazov commented 1 year ago

Push notifications can help users to get notified when new books are added to the catalog. Convenient if someone doesn't want to subscribe to any of our social networks . Push notifications should not be intrusive and we shouldn't automatically suggest user to enable notifications when they visit the website. Instead we can add a button/link next to "Навінкі" category on the main page. For example add "падпісацца" link in smaller font. We should also explain user when they are enabling.

Push API https://developer.mozilla.org/en-US/docs/Web/API/Push_API https://web.dev/push-notifications-overview/

frombrest commented 1 year ago

I did a little research and found some libraries...

Most interesting for me is:

django-webpush                          https://github.com/safwanrahman/django-webpush

There are two another:

django-push-notifications               https://github.com/jazzband/django-push-notifications
django-pwa-webpush                      https://github.com/avryhof/django-pwa-webpush

@nbeloglazov Please take a look at them and let me know if you don't mind trying django-webpush.

nbeloglazov commented 1 year ago

Thank you. django-webpush indeed seems to be the most comprehensible. Though I'n not sure how customizable it is. Looking at their "Subscribe" button - it has hardcoded text: https://github.com/safwanrahman/django-webpush/blob/6f04208ae1878920787cf6d08d77a3bac9348947/webpush/templates/webpush_button.html#L4 But maybe we can just re-implement it ourselves.

Also I haven't read webpush docs carefully. Seems like it involves 3rd party service that actually handles pushes. So it's a bit more complicated than I thought.

frombrest commented 1 year ago

Yes, I think button is customizable, otherwise nobody would use this library )

If you are talking about (Notification Service) VAPID keys provider, I think this is standard practice for all kinds of push notifications browser or mobile. Even articles you have mentioned in issue description reference to such services. There are many providers, but most suitable one in our case is Firebase since entire application is backed by Google platform. As far as I know it is free service, details on how to get key-pair you can find here: https://firebase.google.com/docs/cloud-messaging/js/client#generate_a_new_key_pair

There is one more thing I would like to highlight that notifications have TTL time.(max 1000 sec = 16 min) Means if user is offline during that time after sending he will not receive notification.

so, are we good to go with ⬆️ ?

nbeloglazov commented 1 year ago

I have a bunch of questions, but not sure whether they are about this library or push API in general.

  1. Does push API provides a way to check whether user enabled notifications? Ideally I'd like to show "subscribe" or "unsubcribe" button depending on user status.
  2. Do we need to start saving data in session? Ideally no.
  3. How would we organize sending a push notification? Should we add a field to book model with a boolean indicating whether it was pushed already? So that we don't spam users. Probably should add a special page/button in admin for that.
frombrest commented 1 year ago
  1. Does push API provides a way to check whether user enabled notifications? Ideally I'd like to show "subscribe" or "unsubcribe" button depending on user status.

Yes technically it is possible. To get current notification permission status there is Notification API and permission property with status. Example: https://developer.mozilla.org/en-US/docs/Web/API/Notification/permission_static#examples

We will be able to show button subscribe.. it will call Notification.requestPermission() static method. But this method shows browser notification with Allow and Block buttons. (User has to click twice to subscribe)

ChatGPT helped me to find a way to provide user ability to unsubscribe from web push notifications:

// Check if the browser supports the necessary APIs
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    // Get the active subscription
    serviceWorkerRegistration.pushManager.getSubscription().then(function(subscription) {
      if (subscription) {
        // Unsubscribe the user
        subscription.unsubscribe().then(function(successful) {
          if (successful) {
            // Update UI to reflect unsubscription
            console.log('Unsubscribed from push notifications.');
          }
        }).catch(function(error) {
          console.error('Error unsubscribing:', error);
        });
      } else {
        console.log('No subscription found.');
      }
    });
  });
}

so the page can determine does user have subscription or not and display appropriate button.

Such thing will require significant customization of django-webpush lib... I am not sure that I enough experienced to be able to adjust js part.

  1. Do we need to start saving data in session? Ideally no.

No. Subscriptions does not use session data. As ChatGPT said:

When a user subscribes to web push notifications on a website, the subscription information is stored by the browser and persists even after the user's session ends or they close the browser. This allows the website to send push notifications to the user even when they are not actively on the site.

But more details about Push API and Notification API mechanisms you can read here: Web Push Notifications: https://medium.com/sessionstack-blog/how-javascript-works-the-mechanics-of-web-push-notifications-290176c5c55d Service worker: https://medium.com/sessionstack-blog/how-javascript-works-service-workers-their-life-cycle-and-use-cases-52b19ad98b58

If you are thinking about personal security of users, that may be the question, because it is possible to understand that user agreed on receiving notifications from site by checking browser settings: chrome://settings/content/notifications (Not session data)

  1. How would we organize sending a push notification? Should we add a field to book model with a boolean indicating whether it was pushed already? So that we don't spam users. Probably should add a special page/button in admin for that.

Separated model notification with FK to book and cron job to poll notification table to find one with READY_TO_SEND status to send and change status to DONE?