diff --git a/src/App.vue b/src/App.vue index 78de2af..c9847e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -301,7 +301,34 @@ export default class App extends Vue { return this.askPermission() .then((permission) => { console.log("Permission granted:", permission); - // Initialize notifications here + + // Call the function and handle promises + this.subscribeToPush() + .then(() => { + console.log("Subscribed successfully."); + // Assuming the subscription object is available + return navigator.serviceWorker.ready; + }) + .then((registration) => { + // Fetch the existing subscription object from the registration + return registration.pushManager.getSubscription(); + }) + .then((subscription) => { + if (subscription) { + return this.sendSubscriptionToServer(subscription); + } else { + throw new Error("Subscription object is not available."); + } + }) + .then(() => { + console.log("Subscription data sent to server."); + }) + .catch((error) => { + console.error( + "Subscription or server communication failed:", + error, + ); + }); }) .catch((error) => { console.error("An error occurred:", error); @@ -309,6 +336,73 @@ export default class App extends Vue { }); } + // Function to convert URL base64 to Uint8Array + private urlBase64ToUint8Array(base64String: string): Uint8Array { + 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; + } + + // The subscribeToPush method + private subscribeToPush(): Promise { + return new Promise((resolve, reject) => { + if ("serviceWorker" in navigator && "PushManager" in window) { + navigator.serviceWorker + .register("/service-worker.js") + .then((registration) => { + const b64 = + "BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U"; + const applicationServerKey = this.urlBase64ToUint8Array(b64); + + const options: PushSubscriptionOptions = { + userVisibleOnly: true, + applicationServerKey: applicationServerKey, + }; + + return registration.pushManager.subscribe(options); + }) + .then((subscription) => { + console.log("Push subscription successful:", subscription); + resolve(); + }) + .catch((error) => { + console.error("Push subscription failed:", error); + reject(error); + }); + } else { + const errorMsg = "Push messaging is not supported"; + console.warn(errorMsg); + reject(new Error(errorMsg)); + } + }); + } + + private sendSubscriptionToServer( + subscription: PushSubscription, + ): Promise { + // Simulated API call + return fetch("/api/save-subscription", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(subscription), + }).then((response) => { + if (!response.ok) { + throw new Error("Failed to send subscription to server"); + } + console.log("Subscription sent to server successfully."); + }); + } + never(ID: string) { alert(ID); } diff --git a/src/db/tables/settings.ts b/src/db/tables/settings.ts index 8298dfe..e909533 100644 --- a/src/db/tables/settings.ts +++ b/src/db/tables/settings.ts @@ -5,7 +5,7 @@ export type BoundingBox = { westLong: number; }; -// a singleton +// Updated Settings type export type Settings = { id: number; // there's only one entry: MASTER_SETTINGS_KEY @@ -19,6 +19,9 @@ export type Settings = { bbox: BoundingBox; }>; showContactGivesInline?: boolean; + vapid?: string; // added VAPID field + reminderTime?: number; // Time in milliseconds since the UNIX epoch + reminderOn?: boolean; // Whether the reminder is on or off }; export const SettingsSchema = {