UNPKG

@intuitionrobotics/push-pub-sub

Version:
184 lines 9.73 kB
"use strict"; /* * A typescript & react boilerplate with api call example * * Copyright (C) 2018 Intuition Robotics * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PushPubSubModule = exports.PushPubSubModule_Class = exports.pushSessionIdKey = exports.Command_SwToApp = void 0; const ts_common_1 = require("@intuitionrobotics/ts-common"); const frontend_1 = require("@intuitionrobotics/thunderstorm/frontend"); const thunderstorm_1 = require("@intuitionrobotics/thunderstorm"); const frontend_2 = require("@intuitionrobotics/firebase/frontend"); const NotificationModule_1 = require("./NotificationModule"); exports.Command_SwToApp = "SwToApp"; exports.pushSessionIdKey = "x-push-session-id"; const pushSessionId = new frontend_1.StorageKey(exports.pushSessionIdKey, false); class PushPubSubModule_Class extends ts_common_1.Module { constructor() { super("PushPubSubModule"); this.subscriptions = []; this.timeout = 800; this.registerServiceWorker = () => __awaiter(this, void 0, void 0, function* () { console.log("Registering service worker..."); return yield navigator.serviceWorker.register(`/${this.config.swFileName || "ts_service_worker.js"}`); }); this.initApp = () => { var _a; if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.publicKeyBase64)) throw new ts_common_1.ImplementationMissingException(`Please specify the right config for the 'PushPubSubModule'`); this.runAsync("Initializing Firebase SDK and registering SW", () => __awaiter(this, void 0, void 0, function* () { if ("serviceWorker" in navigator) { const asyncs = [ this.registerServiceWorker(), frontend_2.FirebaseModule.createSession() ]; const { 0: registration, 1: app } = yield Promise.all(asyncs); yield registration.update(); this.messaging = app.getMessaging(); // this.messaging.usePublicVapidKey(this.config.publicKeyBase64); // await this.messaging.useServiceWorker(registration); yield this.getToken({ vapidKey: this.config.publicKeyBase64, serviceWorkerRegistration: registration }); if (navigator.serviceWorker.controller) { console.log(`This page is currently controlled by: ${navigator.serviceWorker.controller}`); } navigator.serviceWorker.oncontrollerchange = function () { console.log("This page is now controlled by:", navigator.serviceWorker.controller); }; navigator.serviceWorker.onmessage = (event) => { this.processMessageFromSw(event.data); }; } })); }; // / need to call this from the login verified this.getToken = (options) => __awaiter(this, void 0, void 0, function* () { try { this.logVerbose("Checking/Requesting permission..."); const permission = yield Notification.requestPermission(); this.logVerbose(`Notification permission: ${permission}`); if (permission !== "granted") return; if (!this.messaging) throw new ts_common_1.BadImplementationException("I literally just set this!"); this.firebaseToken = yield this.messaging.getToken(options); if (!this.firebaseToken) return; this.messaging.onMessage((payload) => { if (!payload.data) return this.logInfo('No data passed to the message handler, I got this', payload); this.processMessage(payload.data); }); this.logVerbose("new token received: " + this.firebaseToken); // this.logWarning("I don't believe there is a good reason to register whenever an app starts.. before we have any information about user or app status!!") // this.logWarning("Convince me otherwise.. :)") // Race Condition in CC proved that I didnt register for push due to the getToken being async which ended after modules init // so I had subscriptions but didnt register them if (this.subscriptions.length > 0) this.register(); } catch (err) { this.logError("Unable to get token", err); } }); this.processMessageFromSw = (data) => { this.logInfo("Got data from SW: ", data); if (!data.command || !data.message || data.command !== exports.Command_SwToApp) return; this.processMessage(data.message); }; this.processMessage = (data) => { this.logInfo("process message", data); const arr = JSON.parse(data.messages); arr.forEach(s => { s.persistent && NotificationModule_1.NotificationsModule.addNotification(s); this.subscriptions .filter(d => d.pushKey === s.pushKey && (0, ts_common_1.compare)(s.props, d.props)) .forEach(d => d.callBack(s.data)); }); }; this.subscribe = (subscription) => { this.subscribeImpl(subscription); return this.register(); }; this.subscribeImpl = (subscription) => { const foundSubscription = this.subscriptions.find(d => d.pushKey === subscription.pushKey && (0, ts_common_1.compare)(subscription.props, d.props)); if (foundSubscription) { this.logError("Subscription already exists", subscription); return; } this.subscriptions.push(subscription); }; this.subscribeMulti = (subscriptions) => { subscriptions.forEach(subscription => this.subscribeImpl(subscription)); return this.register(); }; this.unsubscribe = (subscription) => { const idx = this.subscriptions.findIndex(d => d.pushKey === subscription.pushKey && (0, ts_common_1.compare)(subscription.props, d.props)); const foundSubscription = idx !== -1 ? this.subscriptions[idx] : undefined; if (foundSubscription) this.subscriptions.splice(idx, 1); return this.register(); }; this.register = () => { const firebaseToken = this.firebaseToken; if (!firebaseToken) return this.logWarning("No Firebase token..."); this.debounce(() => { const body = { firebaseToken, pushSessionId: this.getPushSessionId(), subscriptions: this.subscriptions.map(({ pushKey, props }) => ({ pushKey, props })) }; this.logDebug("Registering subscriptions"); for (const sub of this.subscriptions) { this.logDebug(`${sub.pushKey} => ${sub.props ? (0, ts_common_1.__stringify)(sub.props) : "no props"}`); } frontend_1.XhrHttpModule .createRequest(thunderstorm_1.HttpMethod.POST, "register-pub-sub-tab") .setRelativeUrl("/v1/push/register") .setJsonBody(body) .setOnError("Failed to register for push") .execute((response) => { NotificationModule_1.NotificationsModule.setNotificationList(response); this.logVerbose("Finished register PubSub"); }); }, "debounce-register", this.timeout); }; window.name = window.name || (0, ts_common_1.generateHex)(32); this.pushSessionId = pushSessionId.set(window.name); } init() { var _a; if (((_a = this.config) === null || _a === void 0 ? void 0 : _a.registerOnInit) === false) return; this.initApp(); } getPushSessionId() { return this.pushSessionId; } } exports.PushPubSubModule_Class = PushPubSubModule_Class; exports.PushPubSubModule = new PushPubSubModule_Class(); //# sourceMappingURL=PushPubSubModule.js.map