@notificationapi/react 1.1.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,26 @@
1
- import { jsx as Q } from "react/jsx-runtime";
2
- import { useState as I, useCallback as m, useMemo as X, useRef as U, useEffect as y, useContext as Y } from "react";
3
- import { NotificationAPIContext as H } from "./context.js";
4
- const Z = async (e, c, i, a, f, b, h) => {
5
- const l = ee(a, f, b), g = await fetch(
6
- `https://${c}/${a}/users/${encodeURIComponent(
7
- f
8
- )}/${i}`,
1
+ import { jsx as te } from "react/jsx-runtime";
2
+ import { useMemo as B, useState as b, useCallback as N, useRef as R, useEffect as y, useContext as oe } from "react";
3
+ import { NotificationAPIContext as V } from "./context.js";
4
+ import { createDebugLogger as ie, formatApiCall as k } from "../../utils/debug.js";
5
+ const ne = async (i, e, g, s, c, p, w) => {
6
+ const h = re(s, c, p), f = await fetch(
7
+ `https://${e}/${s}/users/${encodeURIComponent(
8
+ c
9
+ )}/${g}`,
9
10
  {
10
- method: e,
11
- body: JSON.stringify(h),
11
+ method: i,
12
+ body: JSON.stringify(w),
12
13
  headers: {
13
- Authorization: `Basic ${l}`
14
+ Authorization: `Basic ${h}`
14
15
  }
15
16
  }
16
17
  );
17
18
  try {
18
- return await g.json();
19
+ return await f.json();
19
20
  } catch {
20
21
  return;
21
22
  }
22
- }, ee = (e, c, i) => btoa(i ? e + ":" + c + ":" + i : e + ":" + c), q = {
23
+ }, re = (i, e, g) => btoa(g ? i + ":" + e + ":" + g : i + ":" + e), K = {
23
24
  host: "api.notificationapi.com",
24
25
  websocketHost: "ws.notificationapi.com",
25
26
  userId: "",
@@ -32,79 +33,79 @@ const Z = async (e, c, i, a, f, b, h) => {
32
33
  onNewInAppNotifications: void 0,
33
34
  keepWebSocketAliveForSeconds: 86400
34
35
  // 24 hours
35
- }, o = {
36
- config: q,
37
- init: function(e) {
38
- return this.config = { ...q, ...e }, {
36
+ }, a = {
37
+ config: K,
38
+ init: function(i) {
39
+ return this.config = { ...K, ...i }, {
39
40
  ...this
40
41
  };
41
42
  },
42
43
  rest: {
43
- generic: function(e, c, i) {
44
- return Z(
44
+ generic: function(i, e, g) {
45
+ return ne(
46
+ i,
47
+ a.config.host,
45
48
  e,
46
- o.config.host,
47
- c,
48
- o.config.clientId,
49
- o.config.userId,
50
- o.config.hashedUserId,
51
- i
49
+ a.config.clientId,
50
+ a.config.userId,
51
+ a.config.hashedUserId,
52
+ g
52
53
  );
53
54
  },
54
55
  // The functions below are nice wrappers over the generic
55
56
  // rest api function above. They must follow REST API naming:
56
57
  // Method + Resource, representing the end-point.
57
- getNotifications: function(e, c) {
58
- return o.rest.generic(
58
+ getNotifications: function(i, e) {
59
+ return a.rest.generic(
59
60
  "GET",
60
- `notifications/INAPP_WEB?count=${c}&before=${e}`
61
+ `notifications/INAPP_WEB?count=${e}&before=${i}`
61
62
  );
62
63
  },
63
- patchNotifications: function(e) {
64
- return o.rest.generic(
64
+ patchNotifications: function(i) {
65
+ return a.rest.generic(
65
66
  "PATCH",
66
67
  "notifications/INAPP_WEB",
67
- e
68
+ i
68
69
  );
69
70
  },
70
71
  getPreferences: function() {
71
- return o.rest.generic("GET", "preferences");
72
+ return a.rest.generic("GET", "preferences");
72
73
  },
73
- postPreferences: function(e) {
74
- return o.rest.generic(
74
+ postPreferences: function(i) {
75
+ return a.rest.generic(
75
76
  "POST",
76
77
  "preferences",
77
- e
78
+ i
78
79
  );
79
80
  },
80
- postUser: function(e) {
81
- return o.rest.generic("POST", "", e);
81
+ postUser: function(i) {
82
+ return a.rest.generic("POST", "", i);
82
83
  },
83
84
  getUserAccountMetadata: function() {
84
- return o.rest.generic("GET", "account_metadata");
85
+ return a.rest.generic("GET", "account_metadata");
85
86
  }
86
87
  },
87
88
  websocket: {
88
89
  object: void 0,
89
90
  connect: function() {
90
- let e = `wss://${o.config.websocketHost}?userId=${encodeURIComponent(o.config.userId)}&envId=${o.config.clientId}`;
91
- return o.config.hashedUserId && (e += `&userIdHash=${encodeURIComponent(o.config.hashedUserId)}`), o.websocket.object = new WebSocket(e), o.websocket.object.onmessage = (c) => {
92
- const i = JSON.parse(c.data);
93
- if (!(!i || !i.route) && i.route === "inapp_web/new_notifications") {
94
- const a = i;
95
- o.config.onNewInAppNotifications && o.config.onNewInAppNotifications(
96
- a.payload.notifications
91
+ let i = `wss://${a.config.websocketHost}?userId=${encodeURIComponent(a.config.userId)}&envId=${a.config.clientId}`;
92
+ return a.config.hashedUserId && (i += `&userIdHash=${encodeURIComponent(a.config.hashedUserId)}`), a.websocket.object = new WebSocket(i), a.websocket.object.onmessage = (e) => {
93
+ const g = JSON.parse(e.data);
94
+ if (!(!g || !g.route) && g.route === "inapp_web/new_notifications") {
95
+ const s = g;
96
+ a.config.onNewInAppNotifications && a.config.onNewInAppNotifications(
97
+ s.payload.notifications
97
98
  );
98
99
  }
99
- }, o.websocket.object;
100
+ }, a.websocket.object;
100
101
  },
101
- disconnect: function(e) {
102
- var c;
103
- o.websocket.object && ((c = o.websocket.object) == null || c.close(), e && e(o.websocket.object));
102
+ disconnect: function(i) {
103
+ var e;
104
+ a.websocket.object && ((e = a.websocket.object) == null || e.close(), i && i(a.websocket.object));
104
105
  }
105
106
  },
106
107
  openWebSocket: function() {
107
- return o.websocket.connect(() => {
108
+ return a.websocket.connect(() => {
108
109
  setTimeout(
109
110
  () => {
110
111
  this.websocket.disconnect(() => {
@@ -118,45 +119,55 @@ const Z = async (e, c, i, a, f, b, h) => {
118
119
  // These functions are developer friendly wrappers over the rest APIs
119
120
  // They may or may not do additional tasks.
120
121
  // e.g. identify simply maps to postUsers
121
- getInAppNotifications: async (e) => {
122
- const c = e.maxCountNeeded || o.config.getInAppDefaultCount, i = e.oldestNeeded || o.config.getInAppDefaultOldest;
123
- let a = [], f = e.before, b = !0, h = !0;
124
- for (; h; ) {
125
- const l = (await o.rest.getNotifications(
126
- f,
127
- c
122
+ getInAppNotifications: async (i) => {
123
+ const e = i.maxCountNeeded || a.config.getInAppDefaultCount, g = i.oldestNeeded || a.config.getInAppDefaultOldest;
124
+ let s = [], c = i.before, p = !0, w = !0;
125
+ for (; w; ) {
126
+ const h = (await a.rest.getNotifications(
127
+ c,
128
+ e
128
129
  )).notifications.filter(
129
- (g) => !a.find((w) => w.id === g.id)
130
+ (f) => !s.find((I) => I.id === f.id)
130
131
  );
131
- f = l.reduce(
132
- (g, w) => g < w.date ? g : w.date,
133
- e.before
134
- ), a = [...a, ...l], b = l.length > 0, h = !0, (!b || a.length >= c || f < i) && (h = !1);
132
+ c = h.reduce(
133
+ (f, I) => f < I.date ? f : I.date,
134
+ i.before
135
+ ), s = [...s, ...h], p = h.length > 0, w = !0, (!p || s.length >= e || c < g) && (w = !1);
135
136
  }
136
137
  return {
137
- items: a,
138
- hasMore: b,
139
- oldestReceived: f
138
+ items: s,
139
+ hasMore: p,
140
+ oldestReceived: c
140
141
  };
141
142
  },
142
- updateInAppNotifications: async (e) => {
143
- const c = {
144
- trackingIds: e.ids
143
+ updateInAppNotifications: async (i) => {
144
+ const e = {
145
+ trackingIds: i.ids
145
146
  };
146
- return e.archived === !0 ? c.archived = (/* @__PURE__ */ new Date()).toISOString() : e.archived === !1 && (c.archived = null), e.clicked === !0 ? c.clicked = (/* @__PURE__ */ new Date()).toISOString() : e.clicked === !1 && (c.clicked = null), e.opened === !0 ? c.opened = (/* @__PURE__ */ new Date()).toISOString() : e.opened === !1 && (c.opened = null), o.rest.patchNotifications(c);
147
+ return i.archived === !0 ? e.archived = (/* @__PURE__ */ new Date()).toISOString() : i.archived === !1 && (e.archived = null), i.clicked === !0 ? e.clicked = (/* @__PURE__ */ new Date()).toISOString() : i.clicked === !1 && (e.clicked = null), i.opened === !0 ? e.opened = (/* @__PURE__ */ new Date()).toISOString() : i.opened === !1 && (e.opened = null), a.rest.patchNotifications(e);
147
148
  },
148
- getPreferences: async () => o.rest.getPreferences(),
149
- updateDeliveryOption: async (e) => o.rest.postPreferences([e]),
150
- identify: async (e) => {
151
- if (e.id && e.id !== o.config.userId)
149
+ getPreferences: async () => a.rest.getPreferences(),
150
+ updateDeliveryOption: async (i) => a.rest.postPreferences([i]),
151
+ identify: async (i) => {
152
+ if (i.id && i.id !== a.config.userId)
152
153
  throw new Error(
153
154
  "The id in the parameters does not match the initialized userId."
154
155
  );
155
- return o.rest.postUser(e);
156
+ return a.rest.postUser(i);
156
157
  },
157
- getUserAccountMetadata: async () => o.rest.getUserAccountMetadata()
158
- }, F = typeof window < "u", te = (e) => {
159
- const i = {
158
+ getUserAccountMetadata: async () => a.rest.getUserAccountMetadata()
159
+ }, G = typeof window < "u", se = (i) => {
160
+ const e = B(
161
+ () => ie(i.debug || !1),
162
+ [i.debug]
163
+ );
164
+ e.log("NotificationAPI Provider initializing", {
165
+ clientId: i.clientId,
166
+ userId: "userId" in i ? i.userId : i.user.id,
167
+ debug: i.debug || !1,
168
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
169
+ });
170
+ const s = {
160
171
  ...{
161
172
  apiURL: "api.notificationapi.com",
162
173
  wsURL: "ws.notificationapi.com",
@@ -167,153 +178,313 @@ const Z = async (e, c, i, a, f, b, h) => {
167
178
  webPushOptInMessage: "AUTOMATIC",
168
179
  customServiceWorkerPath: "/notificationapi-service-worker.js"
169
180
  },
170
- ...e,
171
- user: "userId" in e ? { id: e.userId } : e.user
172
- }, [a, f] = I(), [b, h] = I(), [l, g] = I(), [w, S] = I(!1), [k, T] = I((/* @__PURE__ */ new Date()).toISOString()), [A, C] = I(!0), [v, N] = I(i.webPushOptInMessage), [L, J] = I(!1), W = m(() => {
173
- i.playSoundOnNewNotification && new Audio(i.newNotificationSoundPath).play().catch((s) => {
174
- console.log("Failed to play new notification sound:", s);
175
- });
176
- }, [i.newNotificationSoundPath, i.playSoundOnNewNotification]), P = m((t) => {
177
- const s = (/* @__PURE__ */ new Date()).toISOString();
178
- f((n) => (t = Array.isArray(t) ? t : [], t = t.filter((d) => {
179
- const p = d.expDate && new Date(d.expDate).toISOString() > s, D = new Date(d.date).getTime() > new Date(s).getTime() + 1e3;
180
- return !p && !D;
181
- }), n = Array.isArray(n) ? n : [], [
182
- ...t.filter((d) => !n.find((D) => D.id === d.id)),
183
- ...n
184
- ]));
185
- }, []), u = X(() => {
186
- const t = e.client ? e.client : o.init({
187
- clientId: i.clientId,
188
- userId: i.user.id,
189
- hashedUserId: i.hashedUserId,
190
- onNewInAppNotifications: (s) => {
191
- W(), P(s);
192
- },
193
- host: i.apiURL,
194
- websocketHost: i.wsURL
195
- });
196
- return t.identify({
197
- email: i.user.email,
198
- number: i.user.number
199
- }), t;
181
+ ...i,
182
+ user: "userId" in i ? { id: i.userId } : i.user
183
+ };
184
+ e.log("Configuration loaded", s);
185
+ const [c, p] = b(), [w, h] = b(), [f, I] = b(), [E, C] = b(!1), [O, F] = b((/* @__PURE__ */ new Date()).toISOString()), [M, x] = b(!0), [P, m] = b(s.webPushOptInMessage), [S, J] = b(!1), q = N(() => {
186
+ s.playSoundOnNewNotification && (e.log("Playing notification sound", {
187
+ soundPath: s.newNotificationSoundPath
188
+ }), new Audio(s.newNotificationSoundPath).play().catch((n) => {
189
+ e.error("Failed to play new notification sound", n), console.log("Failed to play new notification sound:", n);
190
+ }));
200
191
  }, [
201
- i.clientId,
202
- i.user.id,
203
- i.user.email,
204
- i.user.number,
205
- i.hashedUserId,
206
- P,
207
- W,
208
- e.client,
209
- i.apiURL,
210
- i.wsURL
211
- ]), x = m(
212
- async (t, s) => {
213
- const n = await u.rest.getNotifications(t, s);
214
- T(n.oldestReceived), C(n.couldLoadMore), P(n.notifications);
192
+ s.newNotificationSoundPath,
193
+ s.playSoundOnNewNotification,
194
+ e
195
+ ]), A = N(
196
+ (t) => {
197
+ e.group("Adding notifications to state"), e.log("Received notifications", {
198
+ count: (t == null ? void 0 : t.length) || 0,
199
+ notifications: t
200
+ });
201
+ const n = (/* @__PURE__ */ new Date()).toISOString();
202
+ p((o) => {
203
+ const r = (o == null ? void 0 : o.length) || 0;
204
+ e.log("Current notifications count", r), t = Array.isArray(t) ? t : [], t = t.filter((u) => {
205
+ const v = u.expDate && new Date(u.expDate).toISOString() > n, T = new Date(u.date).getTime() > new Date(n).getTime() + 1e3, z = !v && !T;
206
+ return z || e.log("Filtering out notification", {
207
+ id: u.id,
208
+ reason: v ? "expired" : "future",
209
+ expDate: u.expDate,
210
+ date: u.date
211
+ }), z;
212
+ }), o = Array.isArray(o) ? o : [];
213
+ const d = [
214
+ ...t.filter((u) => {
215
+ const v = o.find((T) => T.id === u.id);
216
+ return v && e.log("Filtering out duplicate notification", { id: u.id }), !v;
217
+ }),
218
+ ...o
219
+ ];
220
+ return e.log("State updated", {
221
+ previousCount: r,
222
+ newCount: d.length,
223
+ addedCount: t.length
224
+ }), e.groupEnd(), d;
225
+ });
215
226
  },
216
- [P, u.rest]
217
- ), E = U(A), R = U(w), $ = U(k);
227
+ [e]
228
+ ), l = B(() => {
229
+ e.group("Initializing NotificationAPI client");
230
+ const t = {
231
+ clientId: s.clientId,
232
+ userId: s.user.id,
233
+ hashedUserId: s.hashedUserId,
234
+ host: s.apiURL,
235
+ websocketHost: s.wsURL
236
+ };
237
+ e.log("Client configuration", t);
238
+ const n = i.client ? i.client : a.init({
239
+ ...t,
240
+ onNewInAppNotifications: (r) => {
241
+ e.log("Received new in-app notifications via WebSocket", {
242
+ count: (r == null ? void 0 : r.length) || 0,
243
+ notifications: r
244
+ }), q(), A(r);
245
+ }
246
+ }), o = {
247
+ email: s.user.email,
248
+ number: s.user.number
249
+ };
250
+ return e.log("Identifying user", o), n.identify(o), e.groupEnd(), n;
251
+ }, [
252
+ s.clientId,
253
+ s.user.id,
254
+ s.user.email,
255
+ s.user.number,
256
+ s.hashedUserId,
257
+ A,
258
+ q,
259
+ i.client,
260
+ s.apiURL,
261
+ s.wsURL,
262
+ e
263
+ ]), $ = N(
264
+ async (t, n) => {
265
+ var o;
266
+ e.group("Fetching notifications"), e.log(
267
+ "Fetch parameters",
268
+ k("GET", "/notifications", { date: t, count: n })
269
+ );
270
+ try {
271
+ const r = await l.rest.getNotifications(t, n);
272
+ e.log("Fetch successful", {
273
+ notificationsCount: ((o = r.notifications) == null ? void 0 : o.length) || 0,
274
+ oldestReceived: r.oldestReceived,
275
+ couldLoadMore: r.couldLoadMore
276
+ }), F(r.oldestReceived), x(r.couldLoadMore), A(r.notifications), e.groupEnd();
277
+ } catch (r) {
278
+ throw e.error("Failed to fetch notifications", r, { date: t, count: n }), e.groupEnd(), r;
279
+ }
280
+ },
281
+ [A, l.rest, e]
282
+ ), U = R(M), D = R(E), j = R(O);
218
283
  y(() => {
219
- E.current = A, R.current = w, $.current = k;
220
- }, [A, w, k]);
221
- const O = m(
284
+ U.current = M, D.current = E, j.current = O;
285
+ }, [M, E, O]);
286
+ const L = N(
222
287
  async (t) => {
223
- if (!(!t && (!E.current || R.current))) {
224
- S(!0);
225
- try {
226
- await x(
227
- t ? (/* @__PURE__ */ new Date()).toISOString() : $.current,
228
- t ? i.initialLoadMaxCount : 1e3
229
- );
230
- } finally {
231
- S(!1);
232
- }
288
+ if (e.group(`Loading notifications (${t ? "initial" : "more"})`), e.log("Load conditions", {
289
+ initial: t,
290
+ hasMore: U.current,
291
+ loading: D.current
292
+ }), !t && (!U.current || D.current)) {
293
+ e.log("Skipping load - conditions not met"), e.groupEnd();
294
+ return;
295
+ }
296
+ C(!0), e.log("Loading started");
297
+ try {
298
+ await $(
299
+ t ? (/* @__PURE__ */ new Date()).toISOString() : j.current,
300
+ t ? s.initialLoadMaxCount : 1e3
301
+ ), e.log("Loading completed successfully");
302
+ } catch (n) {
303
+ throw e.error("Loading failed", n), n;
304
+ } finally {
305
+ C(!1), e.groupEnd();
233
306
  }
234
307
  },
235
- [i.initialLoadMaxCount, x]
236
- ), B = async (t) => {
237
- if (!a) return;
238
- const s = (/* @__PURE__ */ new Date()).toISOString(), n = a.filter((r) => t.includes(r.id) && !r.clicked).map((r) => r.id);
239
- u.updateInAppNotifications({ ids: n, clicked: !0 }), f((r) => {
240
- if (!r) return [];
241
- const d = [...r];
242
- return d.filter((p) => n.includes(p.id)).forEach((p) => {
243
- p.clicked = s;
244
- }), d;
245
- });
246
- }, G = async () => {
247
- if (!a) return;
248
- const t = (/* @__PURE__ */ new Date()).toISOString(), s = a.filter((n) => !n.opened || !n.seen).map((n) => n.id);
249
- s.length !== 0 && (u.updateInAppNotifications({
250
- ids: s,
251
- opened: !0
252
- }), f((n) => {
253
- if (!n) return [];
254
- const r = [...n];
255
- return r.filter((d) => s.includes(d.id)).forEach((d) => {
256
- d.opened = t, d.seen = !0;
257
- }), r;
258
- }));
259
- }, K = async (t) => {
260
- if (!a) return;
261
- const s = a.filter((n) => n.archived && (t === "ALL" || t.includes(n.id))).map((n) => n.id);
262
- s.length !== 0 && (u.updateInAppNotifications({
263
- ids: s,
264
- archived: !1
265
- }), f((n) => {
266
- if (!n) return [];
267
- const r = [...n];
268
- return r.filter((d) => s.includes(d.id)).forEach((d) => {
269
- d.archived = void 0;
270
- }), r;
271
- }));
272
- }, V = async (t) => {
273
- if (!a) return;
274
- const s = (/* @__PURE__ */ new Date()).toISOString(), n = a.filter((r) => !r.archived && (t === "ALL" || t.includes(r.id))).map((r) => r.id);
275
- n.length !== 0 && (u.updateInAppNotifications({ ids: n, archived: !0 }), f((r) => {
276
- if (!r) return [];
277
- const d = [...r];
278
- return d.filter((p) => n.includes(p.id)).forEach((p) => {
279
- p.archived = s;
280
- }), d;
281
- }));
282
- }, _ = (t, s, n, r) => j([
308
+ [s.initialLoadMaxCount, $, e]
309
+ ), Q = async (t) => {
310
+ if (e.group("Marking notifications as clicked"), e.log("Requested IDs", t), !c) {
311
+ e.warn("No notifications available"), e.groupEnd();
312
+ return;
313
+ }
314
+ const n = (/* @__PURE__ */ new Date()).toISOString(), o = c.filter((r) => t.includes(r.id) && !r.clicked).map((r) => r.id);
315
+ if (e.log("Filtered IDs for update", {
316
+ requestedCount: t.length,
317
+ actualCount: o.length,
318
+ ids: o
319
+ }), o.length === 0) {
320
+ e.log("No notifications to update"), e.groupEnd();
321
+ return;
322
+ }
323
+ try {
324
+ e.log(
325
+ "Updating notifications via API",
326
+ k("PUT", "/notifications/clicked", { ids: o })
327
+ ), l.updateInAppNotifications({ ids: o, clicked: !0 }), p((r) => {
328
+ if (!r) return [];
329
+ const d = [...r];
330
+ return d.filter((u) => o.includes(u.id)).forEach((u) => {
331
+ u.clicked = n;
332
+ }), e.log("Local state updated", { updatedCount: o.length }), d;
333
+ }), e.groupEnd();
334
+ } catch (r) {
335
+ throw e.error("Failed to mark notifications as clicked", r, { ids: o }), e.groupEnd(), r;
336
+ }
337
+ }, X = async () => {
338
+ if (e.group("Marking notifications as opened"), !c) {
339
+ e.warn("No notifications available"), e.groupEnd();
340
+ return;
341
+ }
342
+ const t = (/* @__PURE__ */ new Date()).toISOString(), n = c.filter((o) => !o.opened || !o.seen).map((o) => o.id);
343
+ if (e.log("Notifications to mark as opened", { count: n.length, ids: n }), n.length === 0) {
344
+ e.log("All notifications already opened"), e.groupEnd();
345
+ return;
346
+ }
347
+ try {
348
+ e.log(
349
+ "Updating notifications via API",
350
+ k("PUT", "/notifications/opened", { ids: n })
351
+ ), l.updateInAppNotifications({
352
+ ids: n,
353
+ opened: !0
354
+ }), p((o) => {
355
+ if (!o) return [];
356
+ const r = [...o];
357
+ return r.filter((d) => n.includes(d.id)).forEach((d) => {
358
+ d.opened = t, d.seen = !0;
359
+ }), e.log("Local state updated", { updatedCount: n.length }), r;
360
+ }), e.groupEnd();
361
+ } catch (o) {
362
+ throw e.error("Failed to mark notifications as opened", o, { ids: n }), e.groupEnd(), o;
363
+ }
364
+ }, Y = async (t) => {
365
+ if (e.group("Marking notifications as unarchived"), e.log("Requested operation", { ids: t }), !c) {
366
+ e.warn("No notifications available"), e.groupEnd();
367
+ return;
368
+ }
369
+ const n = c.filter((o) => o.archived && (t === "ALL" || t.includes(o.id))).map((o) => o.id);
370
+ if (e.log("Filtered notifications for unarchiving", {
371
+ count: n.length,
372
+ ids: n
373
+ }), n.length === 0) {
374
+ e.log("No archived notifications to unarchive"), e.groupEnd();
375
+ return;
376
+ }
377
+ try {
378
+ e.log(
379
+ "Updating notifications via API",
380
+ k("PUT", "/notifications/unarchived", { ids: n })
381
+ ), l.updateInAppNotifications({
382
+ ids: n,
383
+ archived: !1
384
+ }), p((o) => {
385
+ if (!o) return [];
386
+ const r = [...o];
387
+ return r.filter((d) => n.includes(d.id)).forEach((d) => {
388
+ d.archived = void 0;
389
+ }), e.log("Local state updated", { unarchivedCount: n.length }), r;
390
+ }), e.groupEnd();
391
+ } catch (o) {
392
+ throw e.error("Failed to unarchive notifications", o, { ids: n }), e.groupEnd(), o;
393
+ }
394
+ }, Z = async (t) => {
395
+ if (e.group("Marking notifications as archived"), e.log("Requested operation", { ids: t }), !c) {
396
+ e.warn("No notifications available"), e.groupEnd();
397
+ return;
398
+ }
399
+ const n = (/* @__PURE__ */ new Date()).toISOString(), o = c.filter((r) => !r.archived && (t === "ALL" || t.includes(r.id))).map((r) => r.id);
400
+ if (e.log("Filtered notifications for archiving", {
401
+ count: o.length,
402
+ ids: o
403
+ }), o.length === 0) {
404
+ e.log("No unarchived notifications to archive"), e.groupEnd();
405
+ return;
406
+ }
407
+ try {
408
+ e.log(
409
+ "Updating notifications via API",
410
+ k("PUT", "/notifications/archived", { ids: o })
411
+ ), l.updateInAppNotifications({ ids: o, archived: !0 }), p((r) => {
412
+ if (!r) return [];
413
+ const d = [...r];
414
+ return d.filter((u) => o.includes(u.id)).forEach((u) => {
415
+ u.archived = n;
416
+ }), e.log("Local state updated", { archivedCount: o.length }), d;
417
+ }), e.groupEnd();
418
+ } catch (r) {
419
+ throw e.error("Failed to archive notifications", r, { ids: o }), e.groupEnd(), r;
420
+ }
421
+ }, _ = (t, n, o, r) => (e.log("Updating single delivery preference", {
422
+ notificationId: t,
423
+ channel: n,
424
+ delivery: o,
425
+ subNotificationId: r
426
+ }), H([
283
427
  {
284
428
  notificationId: t,
285
- channel: s,
286
- delivery: n,
429
+ channel: n,
430
+ delivery: o,
287
431
  subNotificationId: r
288
432
  }
289
- ]), j = (t) => {
290
- u.rest.postPreferences(t).then(() => {
291
- u.getPreferences().then((s) => {
292
- h(s);
433
+ ])), H = (t) => {
434
+ e.group("Updating delivery preferences"), e.log("Preference updates", { count: t.length, params: t });
435
+ try {
436
+ l.rest.postPreferences(t).then(() => {
437
+ e.log(
438
+ "Preferences updated successfully, fetching latest preferences"
439
+ ), l.getPreferences().then((n) => {
440
+ var o, r, d;
441
+ e.log("Latest preferences fetched", {
442
+ preferencesCount: ((o = n.preferences) == null ? void 0 : o.length) || 0,
443
+ notificationsCount: ((r = n.notifications) == null ? void 0 : r.length) || 0,
444
+ subNotificationsCount: ((d = n.subNotifications) == null ? void 0 : d.length) || 0
445
+ }), h(n), e.groupEnd();
446
+ }).catch((n) => {
447
+ e.error("Failed to fetch updated preferences", n), e.groupEnd();
448
+ });
449
+ }).catch((n) => {
450
+ e.error("Failed to update preferences", n, { params: t }), e.groupEnd();
293
451
  });
294
- });
295
- }, M = m(() => {
296
- "serviceWorker" in navigator && navigator.serviceWorker.register(i.customServiceWorkerPath).then(async (t) => {
297
- N(!1), ne().then(async (s) => {
298
- s === "granted" ? await t.pushManager.subscribe({
452
+ } catch (n) {
453
+ throw e.error("Error in updateDeliveries", n, { params: t }), e.groupEnd(), n;
454
+ }
455
+ }, W = N(() => {
456
+ e.group("Requesting web push permission"), e.log("Service worker support check", {
457
+ supported: "serviceWorker" in navigator,
458
+ customServiceWorkerPath: s.customServiceWorkerPath
459
+ }), "serviceWorker" in navigator ? (e.log("Registering service worker"), navigator.serviceWorker.register(s.customServiceWorkerPath).then(async (t) => {
460
+ e.log("Service worker registered successfully"), m(!1), ce().then(async (n) => {
461
+ e.log("Notification permission result", { permission: n }), n === "granted" ? (e.log("Permission granted, subscribing to push manager"), await t.pushManager.subscribe({
299
462
  userVisibleOnly: !0,
300
- applicationServerKey: l == null ? void 0 : l.userAccountMetadata.environmentVapidPublicKey
301
- }).then(async (n) => {
463
+ applicationServerKey: f == null ? void 0 : f.userAccountMetadata.environmentVapidPublicKey
464
+ }).then(async (o) => {
465
+ e.log("Push subscription successful");
302
466
  const r = {
303
467
  webPushTokens: [
304
468
  {
305
469
  sub: {
306
- endpoint: n.toJSON().endpoint,
307
- keys: n.toJSON().keys
470
+ endpoint: o.toJSON().endpoint,
471
+ keys: o.toJSON().keys
308
472
  }
309
473
  }
310
474
  ]
311
475
  };
312
- await u.identify(r), localStorage.setItem("hideWebPushOptInMessage", "true");
313
- }) : s === "denied" && console.log("Permission for notifications was denied");
476
+ e.log("Identifying user with web push tokens"), await l.identify(r), localStorage.setItem("hideWebPushOptInMessage", "true"), e.log("Web push setup completed successfully"), e.groupEnd();
477
+ })) : n === "denied" && (e.warn("Permission for notifications was denied"), console.log("Permission for notifications was denied"), e.groupEnd());
314
478
  });
315
479
  }).catch((t) => {
316
- t.code === 18 ? console.error(
480
+ e.error(
481
+ "Service worker registration or push subscription failed",
482
+ t,
483
+ {
484
+ errorCode: t.code,
485
+ customServiceWorkerPath: s.customServiceWorkerPath
486
+ }
487
+ ), t.code === 18 ? console.error(
317
488
  "NotificationAPI guide: Probably you are not setup the service worker correctly. Please check the documentation at https://docs.notificationapi.com/guides/web-push#step-by-step-implementation Step 3: Service Worker Setup."
318
489
  ) : t.code === 19 ? console.error(
319
490
  "The operation is aborted. This can happen if the user denies the permission request."
@@ -323,62 +494,95 @@ const Z = async (e, c, i, a, f, b, h) => {
323
494
  "The operation is not allowed. This can happen if the user has blocked notifications for the site. Please check your browser site settings Notifications part."
324
495
  ) : t.code === 22 ? console.error(
325
496
  "The operation is not supported. This can occur if the browser does not support the required features."
326
- ) : console.error(t);
327
- });
497
+ ) : console.error(t), e.groupEnd();
498
+ })) : (e.warn("Service worker not supported in this browser"), e.groupEnd());
328
499
  }, [
329
- u,
330
- i.customServiceWorkerPath,
331
- l == null ? void 0 : l.userAccountMetadata.environmentVapidPublicKey
500
+ l,
501
+ s.customServiceWorkerPath,
502
+ f == null ? void 0 : f.userAccountMetadata.environmentVapidPublicKey,
503
+ e
332
504
  ]);
333
505
  y(() => {
334
- f([]), S(!1), h(void 0), T((/* @__PURE__ */ new Date()).toISOString()), C(!0), O(!0), u.openWebSocket(), u.getPreferences().then((t) => {
335
- h(t);
506
+ e.group("Provider initialization effect"), e.log("Resetting state and loading initial data"), p([]), C(!1), h(void 0), F((/* @__PURE__ */ new Date()).toISOString()), x(!0), L(!0), e.log("Opening WebSocket connection"), l.openWebSocket(), e.log("Fetching user preferences"), l.getPreferences().then((t) => {
507
+ var n, o, r;
508
+ e.log("Initial preferences loaded", {
509
+ preferencesCount: ((n = t.preferences) == null ? void 0 : n.length) || 0,
510
+ notificationsCount: ((o = t.notifications) == null ? void 0 : o.length) || 0,
511
+ subNotificationsCount: ((r = t.subNotifications) == null ? void 0 : r.length) || 0
512
+ }), h(t), e.groupEnd();
513
+ }).catch((t) => {
514
+ e.error("Failed to fetch initial preferences", t), e.groupEnd();
336
515
  });
337
- }, [u, O, M]), y(() => {
338
- u.getUserAccountMetadata().then((t) => {
339
- g(t), F && "Notification" in window && typeof Notification.requestPermission == "function" ? Notification.permission !== "default" && N(!1) : N(t.userAccountMetadata.hasWebPushEnabled);
516
+ }, [l, L, W, e]), y(() => {
517
+ e.group("Fetching user account metadata"), l.getUserAccountMetadata().then((t) => {
518
+ e.log("User account metadata loaded", {
519
+ hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled,
520
+ environmentVapidPublicKey: t.userAccountMetadata.environmentVapidPublicKey ? "present" : "missing"
521
+ }), I(t), G && "Notification" in window && typeof Notification.requestPermission == "function" ? (e.log("Browser notification support detected", {
522
+ permission: Notification.permission
523
+ }), Notification.permission !== "default" && (e.log(
524
+ "Setting webPushOptInMessage to false (permission already set)"
525
+ ), m(!1))) : (e.log(
526
+ "Browser notification not supported, using server setting",
527
+ {
528
+ hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled
529
+ }
530
+ ), m(t.userAccountMetadata.hasWebPushEnabled)), e.groupEnd();
531
+ }).catch((t) => {
532
+ e.error("Failed to fetch user account metadata", t), e.groupEnd();
340
533
  });
341
- }, [u]), y(() => {
342
- v === "AUTOMATIC" && N(
343
- localStorage.getItem("hideWebPushOptInMessage") !== "true"
344
- );
345
- }, [v]), y(() => {
346
- L && M();
347
- }, [L, M]);
348
- const z = {
349
- notifications: a,
350
- preferences: b,
351
- userAccountMetaData: l,
352
- webPushOptInMessage: v,
353
- loadNotifications: O,
354
- markAsOpened: G,
355
- markAsArchived: V,
356
- markAsUnarchived: K,
357
- markAsClicked: B,
534
+ }, [l, e]), y(() => {
535
+ if (e.group("Handling webPushOptInMessage state"), e.log("webPushOptInMessage value", P), P === "AUTOMATIC") {
536
+ const t = localStorage.getItem("hideWebPushOptInMessage") === "true";
537
+ e.log("Automatic mode - checking localStorage", {
538
+ hideMessage: t,
539
+ shouldShow: !t
540
+ }), m(!t);
541
+ }
542
+ e.groupEnd();
543
+ }, [P, e]), y(() => {
544
+ e.group("Handling webPushOptIn state"), e.log("webPushOptIn state", S), S && (e.log("User opted in for web push, requesting permission"), W()), e.groupEnd();
545
+ }, [S, W, e]);
546
+ const ee = {
547
+ notifications: c,
548
+ preferences: w,
549
+ userAccountMetaData: f,
550
+ webPushOptInMessage: P,
551
+ loadNotifications: L,
552
+ markAsOpened: X,
553
+ markAsArchived: Z,
554
+ markAsUnarchived: Y,
555
+ markAsClicked: Q,
358
556
  updateDelivery: _,
359
- updateDeliveries: j,
360
- getClient: () => u,
361
- setWebPushOptInMessage: N,
557
+ updateDeliveries: H,
558
+ getClient: () => l,
559
+ setWebPushOptInMessage: m,
362
560
  setWebPushOptIn: J
363
561
  };
364
- return /* @__PURE__ */ Q(H.Provider, { value: z, children: e.children });
365
- }, ie = () => {
366
- const e = Y(H);
367
- if (!e)
562
+ return e.log("NotificationAPI Provider rendering", {
563
+ notificationsCount: (c == null ? void 0 : c.length) || 0,
564
+ hasPreferences: !!w,
565
+ hasUserAccountMetaData: !!f,
566
+ webPushOptInMessage: P,
567
+ webPushOptIn: S
568
+ }), /* @__PURE__ */ te(V.Provider, { value: ee, children: i.children });
569
+ }, ae = () => {
570
+ const i = oe(V);
571
+ if (!i)
368
572
  throw new Error("useMyContext must be used within a MyProvider");
369
- return e;
573
+ return i;
370
574
  };
371
- te.useNotificationAPIContext = ie;
372
- const ne = async () => {
373
- if (F && "Notification" in window && typeof Notification.requestPermission == "function")
575
+ se.useNotificationAPIContext = ae;
576
+ const ce = async () => {
577
+ if (G && "Notification" in window && typeof Notification.requestPermission == "function")
374
578
  try {
375
579
  return await Notification.requestPermission();
376
- } catch (e) {
377
- return console.error("Error requesting notification permission:", e), "default";
580
+ } catch (i) {
581
+ return console.error("Error requesting notification permission:", i), "default";
378
582
  }
379
583
  else
380
584
  return console.warn("Web Push Notifications are not supported in this browser."), "default";
381
585
  };
382
586
  export {
383
- te as NotificationAPIProvider
587
+ se as NotificationAPIProvider
384
588
  };