Skip to content
Snippets Groups Projects
subscriptions.js 2.78 KiB
Newer Older
import nextTick from "./utils/next-tick.js";

Greg Fodor's avatar
WIP
Greg Fodor committed
// Manages web push subscriptions
//
function urlBase64ToUint8Array(base64String) {
  const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
  const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");

  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

export default class Subscriptions {
  constructor(hubId) {
Greg Fodor's avatar
WIP
Greg Fodor committed
    this.hubId = hubId;
  }

  setHubChannel = hubChannel => {
Greg Fodor's avatar
WIP
Greg Fodor committed
    this.hubChannel = hubChannel;
  };

  setRegistration = registration => {
Greg Fodor's avatar
WIP
Greg Fodor committed
    this.registration = registration;
Greg Fodor's avatar
WIP
Greg Fodor committed

  setRegistrationFailed = () => {
    this.registration = null;
Greg Fodor's avatar
WIP
Greg Fodor committed
  };

  setVapidPublicKey = vapidPublicKey => {
    this.vapidPublicKey = vapidPublicKey;
  setSubscribed = isSubscribed => {
    this._isSubscribed = isSubscribed;
Greg Fodor's avatar
WIP
Greg Fodor committed
  isSubscribed = () => {
    return this._isSubscribed;
Greg Fodor's avatar
WIP
Greg Fodor committed
  };

  getCurrentEndpoint = async () => {
    if (!navigator.serviceWorker) return null;
Greg Fodor's avatar
WIP
Greg Fodor committed

    // registration becomes null if failed, non null if registered
    while (this.registration === undefined) await nextTick();
    if (!this.registration || !this.registration.pushManager) return null;

    while (this.vapidPublicKey === undefined) await nextTick();
    if (this.vapidPublicKey === null) return null;

    try {
      const convertedVapidKey = urlBase64ToUint8Array(this.vapidPublicKey);

      if (
        (await this.registration.pushManager.permissionState({
          userVisibleOnly: true,
          applicationServerKey: convertedVapidKey
        })) !== "granted"
      )
        return null;
    } catch (e) {
      return null; // Chrome can throw here complaining about userVisible if push is not right
    }
    const sub = await this.registration.pushManager.getSubscription();
    if (!sub) return null;
Greg Fodor's avatar
WIP
Greg Fodor committed

Greg Fodor's avatar
Greg Fodor committed
    return sub.endpoint;
    if (!this.registration) return;

    if (this._isSubscribed) {
      const pushSubscription = await this.registration.pushManager.getSubscription();
      const res = await this.hubChannel.unsubscribe(pushSubscription);
Greg Fodor's avatar
WIP
Greg Fodor committed

      if (res && res.has_remaining_subscriptions === false) {
        pushSubscription.unsubscribe();
Greg Fodor's avatar
WIP
Greg Fodor committed
      }
    } else {
      let pushSubscription = await this.registration.pushManager.getSubscription();
Greg Fodor's avatar
WIP
Greg Fodor committed

Greg Fodor's avatar
WIP
Greg Fodor committed
        const convertedVapidKey = urlBase64ToUint8Array(this.vapidPublicKey);

        pushSubscription = await this.registration.pushManager.subscribe({
Greg Fodor's avatar
WIP
Greg Fodor committed
          userVisibleOnly: true,
          applicationServerKey: convertedVapidKey
        });
      }

      this.hubChannel.subscribe(pushSubscription);
Greg Fodor's avatar
WIP
Greg Fodor committed
    }

    this._isSubscribed = !this._isSubscribed;
Greg Fodor's avatar
WIP
Greg Fodor committed
  };
}