@notificationapi/react 1.2.0 → 1.4.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.
- package/README.md +19 -1
- package/dist/components/Provider/index.d.ts +1 -0
- package/dist/components/Provider/index.js +553 -256
- package/dist/main.d.ts +1 -0
- package/dist/main.js +8 -6
- package/dist/utils/debug.d.ts +26 -0
- package/dist/utils/debug.js +61 -0
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -6,6 +6,22 @@ The React SDK is mainly used for displaying In-App Notifications, allowing users
|
|
|
6
6
|
|
|
7
7
|
Please refer to our [documentations](https://docs.notificationapi.com).
|
|
8
8
|
|
|
9
|
+
# Debug Mode
|
|
10
|
+
|
|
11
|
+
The SDK includes a comprehensive debug mode to help troubleshoot issues and understand SDK behavior. Enable it by adding the `debug` prop:
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
<NotificationAPIProvider
|
|
15
|
+
clientId="your-client-id"
|
|
16
|
+
userId="your-user-id"
|
|
17
|
+
debug={true}
|
|
18
|
+
>
|
|
19
|
+
{/* Your app components */}
|
|
20
|
+
</NotificationAPIProvider>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For detailed information about debug mode, see [DEBUG.md](./DEBUG.md).
|
|
24
|
+
|
|
9
25
|
# Development
|
|
10
26
|
|
|
11
27
|
1. Install dependencies:
|
|
@@ -20,6 +36,8 @@ npm install
|
|
|
20
36
|
npm run dev
|
|
21
37
|
```
|
|
22
38
|
|
|
39
|
+
The example application includes a debug mode toggle to demonstrate the feature.
|
|
40
|
+
|
|
23
41
|
# React + TypeScript + Vite
|
|
24
42
|
|
|
25
43
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
@@ -100,7 +118,7 @@ We welcome contributions! To ensure smooth collaboration, please follow these st
|
|
|
100
118
|
|
|
101
119
|
5. **Commit and Push**
|
|
102
120
|
|
|
103
|
-
- Once you
|
|
121
|
+
- Once you've made and tested your changes, commit them with a meaningful message:
|
|
104
122
|
|
|
105
123
|
```bash
|
|
106
124
|
git add .
|
|
@@ -19,6 +19,7 @@ type Props = ({
|
|
|
19
19
|
client?: typeof NotificationAPIClientSDK;
|
|
20
20
|
webPushOptInMessage?: 'AUTOMATIC' | boolean;
|
|
21
21
|
customServiceWorkerPath?: string;
|
|
22
|
+
debug?: boolean;
|
|
22
23
|
};
|
|
23
24
|
export declare const NotificationAPIProvider: React.FunctionComponent<PropsWithChildren<Props>> & {
|
|
24
25
|
useNotificationAPIContext: typeof useNotificationAPIContext;
|
|
@@ -1,25 +1,59 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import {
|
|
3
|
-
import { NotificationAPIContext as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
);
|
|
1
|
+
import { jsx as oe } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as z, useState as N, useCallback as A, useRef as F, useEffect as E, useContext as ie } from "react";
|
|
3
|
+
import { NotificationAPIContext as V } from "./context.js";
|
|
4
|
+
import { createDebugLogger as ne, formatApiCall as C } from "../../utils/debug.js";
|
|
5
|
+
const re = async (o, e, u, a, c, h, I, l) => {
|
|
6
|
+
const p = se(a, c, h), b = `https://${e}/${a}/users/${encodeURIComponent(
|
|
7
|
+
c
|
|
8
|
+
)}/${u}`, w = {
|
|
9
|
+
Authorization: `Basic ${p}`
|
|
10
|
+
};
|
|
11
|
+
l && l.log("HTTP Request:", {
|
|
12
|
+
method: o,
|
|
13
|
+
host: e,
|
|
14
|
+
url: b,
|
|
15
|
+
body: I
|
|
16
|
+
});
|
|
17
|
+
const v = Date.now();
|
|
17
18
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const m = await fetch(b, {
|
|
20
|
+
method: o,
|
|
21
|
+
body: JSON.stringify(I),
|
|
22
|
+
headers: w
|
|
23
|
+
});
|
|
24
|
+
l && l.log("HTTP Response:", m);
|
|
25
|
+
try {
|
|
26
|
+
const P = await m.json();
|
|
27
|
+
return l && l.log("Response Data:", P), P;
|
|
28
|
+
} catch (P) {
|
|
29
|
+
l && l.warn("Failed to parse response as JSON:", P);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
} catch (m) {
|
|
33
|
+
const P = Date.now() - v;
|
|
34
|
+
throw l && l.error("HTTP Request Failed:", {
|
|
35
|
+
error: m,
|
|
36
|
+
url: b,
|
|
37
|
+
headers: w,
|
|
38
|
+
duration: `${P}ms`
|
|
39
|
+
}), m;
|
|
40
|
+
}
|
|
41
|
+
}, se = (o, e, u) => btoa(u ? o + ":" + e + ":" + u : o + ":" + e);
|
|
42
|
+
class B {
|
|
43
|
+
constructor(e = !1) {
|
|
44
|
+
this.debug = e;
|
|
21
45
|
}
|
|
22
|
-
|
|
46
|
+
log(...e) {
|
|
47
|
+
this.debug && console.log("[NotificationAPI js core SDK Debug]", ...e);
|
|
48
|
+
}
|
|
49
|
+
warn(...e) {
|
|
50
|
+
this.debug && console.warn("[NotificationAPI js core SDK Debug]", ...e);
|
|
51
|
+
}
|
|
52
|
+
error(...e) {
|
|
53
|
+
this.debug && console.error("[NotificationAPI js core SDK Debug]", ...e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const J = {
|
|
23
57
|
host: "api.notificationapi.com",
|
|
24
58
|
websocketHost: "ws.notificationapi.com",
|
|
25
59
|
userId: "",
|
|
@@ -27,84 +61,114 @@ const Z = async (e, c, i, a, f, b, h) => {
|
|
|
27
61
|
hashedUserId: "",
|
|
28
62
|
getInAppDefaultCount: 100,
|
|
29
63
|
getInAppDefaultOldest: new Date(
|
|
30
|
-
Date.now() -
|
|
64
|
+
Date.now() - 30 * 24 * 60 * 60 * 1e3
|
|
31
65
|
).toISOString(),
|
|
32
66
|
onNewInAppNotifications: void 0,
|
|
33
|
-
keepWebSocketAliveForSeconds:
|
|
67
|
+
keepWebSocketAliveForSeconds: 24 * 60 * 60,
|
|
34
68
|
// 24 hours
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
debug: !1
|
|
70
|
+
}, s = {
|
|
71
|
+
config: J,
|
|
72
|
+
logger: new B(!1),
|
|
73
|
+
init: function(o) {
|
|
74
|
+
return this.config = { ...J, ...o }, this.logger = new B(this.config.debug), this.logger.log("Initialized with config:", {
|
|
75
|
+
userId: this.config.userId,
|
|
76
|
+
clientId: this.config.clientId,
|
|
77
|
+
host: this.config.host,
|
|
78
|
+
websocketHost: this.config.websocketHost,
|
|
79
|
+
debug: this.config.debug,
|
|
80
|
+
hasHashedUserId: !!this.config.hashedUserId
|
|
81
|
+
}), {
|
|
39
82
|
...this
|
|
40
83
|
};
|
|
41
84
|
},
|
|
42
85
|
rest: {
|
|
43
|
-
generic: function(
|
|
44
|
-
return
|
|
86
|
+
generic: function(o, e, u) {
|
|
87
|
+
return s.logger.log(
|
|
88
|
+
`API Call: ${o} ${e}`,
|
|
89
|
+
u ? { body: u } : ""
|
|
90
|
+
), re(
|
|
91
|
+
o,
|
|
92
|
+
s.config.host,
|
|
45
93
|
e,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
i
|
|
94
|
+
s.config.clientId,
|
|
95
|
+
s.config.userId,
|
|
96
|
+
s.config.hashedUserId,
|
|
97
|
+
u,
|
|
98
|
+
s.logger
|
|
52
99
|
);
|
|
53
100
|
},
|
|
54
101
|
// The functions below are nice wrappers over the generic
|
|
55
102
|
// rest api function above. They must follow REST API naming:
|
|
56
103
|
// Method + Resource, representing the end-point.
|
|
57
|
-
getNotifications: function(
|
|
58
|
-
return
|
|
104
|
+
getNotifications: function(o, e) {
|
|
105
|
+
return s.rest.generic(
|
|
59
106
|
"GET",
|
|
60
|
-
`notifications/INAPP_WEB?count=${
|
|
107
|
+
`notifications/INAPP_WEB?count=${e}&before=${o}`
|
|
61
108
|
);
|
|
62
109
|
},
|
|
63
|
-
patchNotifications: function(
|
|
64
|
-
return
|
|
110
|
+
patchNotifications: function(o) {
|
|
111
|
+
return s.rest.generic(
|
|
65
112
|
"PATCH",
|
|
66
113
|
"notifications/INAPP_WEB",
|
|
67
|
-
|
|
114
|
+
o
|
|
68
115
|
);
|
|
69
116
|
},
|
|
70
117
|
getPreferences: function() {
|
|
71
|
-
return
|
|
118
|
+
return s.rest.generic("GET", "preferences");
|
|
72
119
|
},
|
|
73
|
-
postPreferences: function(
|
|
74
|
-
return
|
|
120
|
+
postPreferences: function(o) {
|
|
121
|
+
return s.rest.generic(
|
|
75
122
|
"POST",
|
|
76
123
|
"preferences",
|
|
77
|
-
|
|
124
|
+
o
|
|
78
125
|
);
|
|
79
126
|
},
|
|
80
|
-
postUser: function(
|
|
81
|
-
return
|
|
127
|
+
postUser: function(o) {
|
|
128
|
+
return s.rest.generic("POST", "", o);
|
|
82
129
|
},
|
|
83
130
|
getUserAccountMetadata: function() {
|
|
84
|
-
return
|
|
131
|
+
return s.rest.generic("GET", "account_metadata");
|
|
85
132
|
}
|
|
86
133
|
},
|
|
87
134
|
websocket: {
|
|
88
135
|
object: void 0,
|
|
89
136
|
connect: function() {
|
|
90
|
-
let
|
|
91
|
-
return
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
137
|
+
let o = `wss://${s.config.websocketHost}?userId=${encodeURIComponent(s.config.userId)}&envId=${s.config.clientId}`;
|
|
138
|
+
return s.config.hashedUserId && (o += `&userIdHash=${encodeURIComponent(s.config.hashedUserId)}`), s.logger.log("WebSocket connecting to:", o), s.websocket.object = new WebSocket(o), s.websocket.object.onopen = () => {
|
|
139
|
+
s.logger.log("WebSocket connection opened");
|
|
140
|
+
}, s.websocket.object.onclose = (e) => {
|
|
141
|
+
s.logger.log("WebSocket connection closed:", {
|
|
142
|
+
code: e.code,
|
|
143
|
+
reason: e.reason,
|
|
144
|
+
wasClean: e.wasClean
|
|
145
|
+
});
|
|
146
|
+
}, s.websocket.object.onerror = (e) => {
|
|
147
|
+
s.logger.error("WebSocket error:", e);
|
|
148
|
+
}, s.websocket.object.onmessage = (e) => {
|
|
149
|
+
s.logger.log(
|
|
150
|
+
"WebSocket message received:",
|
|
151
|
+
e.data
|
|
152
|
+
);
|
|
153
|
+
const u = JSON.parse(e.data);
|
|
154
|
+
if (!(!u || !u.route) && u.route === "inapp_web/new_notifications") {
|
|
155
|
+
const a = u;
|
|
156
|
+
s.logger.log(
|
|
157
|
+
"New notifications received:",
|
|
158
|
+
a.payload.notifications
|
|
159
|
+
), s.config.onNewInAppNotifications && s.config.onNewInAppNotifications(
|
|
96
160
|
a.payload.notifications
|
|
97
161
|
);
|
|
98
162
|
}
|
|
99
|
-
},
|
|
163
|
+
}, s.websocket.object;
|
|
100
164
|
},
|
|
101
|
-
disconnect: function(
|
|
102
|
-
var
|
|
103
|
-
|
|
165
|
+
disconnect: function(o) {
|
|
166
|
+
var e;
|
|
167
|
+
s.websocket.object && (s.logger.log("WebSocket disconnecting"), (e = s.websocket.object) == null || e.close(), o && o(s.websocket.object));
|
|
104
168
|
}
|
|
105
169
|
},
|
|
106
170
|
openWebSocket: function() {
|
|
107
|
-
return
|
|
171
|
+
return s.websocket.connect(() => {
|
|
108
172
|
setTimeout(
|
|
109
173
|
() => {
|
|
110
174
|
this.websocket.disconnect(() => {
|
|
@@ -118,45 +182,83 @@ const Z = async (e, c, i, a, f, b, h) => {
|
|
|
118
182
|
// These functions are developer friendly wrappers over the rest APIs
|
|
119
183
|
// They may or may not do additional tasks.
|
|
120
184
|
// e.g. identify simply maps to postUsers
|
|
121
|
-
getInAppNotifications: async (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
185
|
+
getInAppNotifications: async (o) => {
|
|
186
|
+
s.logger.log(
|
|
187
|
+
"getInAppNotifications called with params:",
|
|
188
|
+
o
|
|
189
|
+
);
|
|
190
|
+
const e = o.maxCountNeeded || s.config.getInAppDefaultCount, u = o.oldestNeeded || s.config.getInAppDefaultOldest;
|
|
191
|
+
s.logger.log("Fetching notifications with:", {
|
|
192
|
+
maxCountNeeded: e,
|
|
193
|
+
oldestNeeded: u,
|
|
194
|
+
before: o.before
|
|
195
|
+
});
|
|
196
|
+
let a = [], c = o.before, h = !0, I = !0;
|
|
197
|
+
for (; I; ) {
|
|
198
|
+
const l = (await s.rest.getNotifications(
|
|
199
|
+
c,
|
|
200
|
+
e
|
|
201
|
+
)).notifications, p = l.filter(
|
|
202
|
+
(b) => !a.find((w) => w.id === b.id)
|
|
130
203
|
);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
204
|
+
s.logger.log(
|
|
205
|
+
`Received ${l.length} notifications, ${p.length} unique`
|
|
206
|
+
), c = p.reduce(
|
|
207
|
+
(b, w) => b < w.date ? b : w.date,
|
|
208
|
+
o.before
|
|
209
|
+
), a = [...a, ...p], h = p.length > 0, I = !0, (!h || a.length >= e || c < u) && (I = !1, s.logger.log("Stopping fetch loop:", {
|
|
210
|
+
hasMore: h,
|
|
211
|
+
totalResults: a.length,
|
|
212
|
+
maxCountNeeded: e,
|
|
213
|
+
oldestReceived: c,
|
|
214
|
+
oldestNeeded: u
|
|
215
|
+
}));
|
|
135
216
|
}
|
|
136
|
-
return {
|
|
217
|
+
return s.logger.log("getInAppNotifications completed:", {
|
|
218
|
+
totalItems: a.length,
|
|
219
|
+
hasMore: h,
|
|
220
|
+
oldestReceived: c
|
|
221
|
+
}), {
|
|
137
222
|
items: a,
|
|
138
|
-
hasMore:
|
|
139
|
-
oldestReceived:
|
|
223
|
+
hasMore: h,
|
|
224
|
+
oldestReceived: c
|
|
140
225
|
};
|
|
141
226
|
},
|
|
142
|
-
updateInAppNotifications: async (
|
|
143
|
-
|
|
144
|
-
|
|
227
|
+
updateInAppNotifications: async (o) => {
|
|
228
|
+
s.logger.log(
|
|
229
|
+
"updateInAppNotifications called with params:",
|
|
230
|
+
o
|
|
231
|
+
);
|
|
232
|
+
const e = {
|
|
233
|
+
trackingIds: o.ids
|
|
145
234
|
};
|
|
146
|
-
return
|
|
235
|
+
return o.archived === !0 ? e.archived = (/* @__PURE__ */ new Date()).toISOString() : o.archived === !1 && (e.archived = null), o.clicked === !0 ? e.clicked = (/* @__PURE__ */ new Date()).toISOString() : o.clicked === !1 && (e.clicked = null), o.opened === !0 ? e.opened = (/* @__PURE__ */ new Date()).toISOString() : o.opened === !1 && (e.opened = null), s.logger.log(
|
|
236
|
+
"Updating notifications with body:",
|
|
237
|
+
e
|
|
238
|
+
), s.rest.patchNotifications(e);
|
|
147
239
|
},
|
|
148
|
-
getPreferences: async () =>
|
|
149
|
-
updateDeliveryOption: async (
|
|
150
|
-
identify: async (
|
|
151
|
-
if (
|
|
240
|
+
getPreferences: async () => s.rest.getPreferences(),
|
|
241
|
+
updateDeliveryOption: async (o) => s.rest.postPreferences([o]),
|
|
242
|
+
identify: async (o) => {
|
|
243
|
+
if (o.id && o.id !== s.config.userId)
|
|
152
244
|
throw new Error(
|
|
153
245
|
"The id in the parameters does not match the initialized userId."
|
|
154
246
|
);
|
|
155
|
-
return
|
|
247
|
+
return s.rest.postUser(o);
|
|
156
248
|
},
|
|
157
|
-
getUserAccountMetadata: async () =>
|
|
158
|
-
},
|
|
159
|
-
const
|
|
249
|
+
getUserAccountMetadata: async () => s.rest.getUserAccountMetadata()
|
|
250
|
+
}, G = typeof window < "u", ae = (o) => {
|
|
251
|
+
const e = z(
|
|
252
|
+
() => ne(o.debug || !1),
|
|
253
|
+
[o.debug]
|
|
254
|
+
);
|
|
255
|
+
e.log("NotificationAPI Provider initializing", {
|
|
256
|
+
clientId: o.clientId,
|
|
257
|
+
userId: "userId" in o ? o.userId : o.user.id,
|
|
258
|
+
debug: o.debug || !1,
|
|
259
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
260
|
+
});
|
|
261
|
+
const a = {
|
|
160
262
|
...{
|
|
161
263
|
apiURL: "api.notificationapi.com",
|
|
162
264
|
wsURL: "ws.notificationapi.com",
|
|
@@ -167,153 +269,315 @@ const Z = async (e, c, i, a, f, b, h) => {
|
|
|
167
269
|
webPushOptInMessage: "AUTOMATIC",
|
|
168
270
|
customServiceWorkerPath: "/notificationapi-service-worker.js"
|
|
169
271
|
},
|
|
170
|
-
...
|
|
171
|
-
user: "userId" in
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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;
|
|
272
|
+
...o,
|
|
273
|
+
user: "userId" in o ? { id: o.userId } : o.user
|
|
274
|
+
};
|
|
275
|
+
e.log("Configuration loaded", a);
|
|
276
|
+
const [c, h] = N(), [I, l] = N(), [p, b] = N(), [w, v] = N(!1), [m, P] = N((/* @__PURE__ */ new Date()).toISOString()), [D, x] = N(!0), [k, y] = N(a.webPushOptInMessage), [M, Q] = N(!1), $ = A(() => {
|
|
277
|
+
a.playSoundOnNewNotification && (e.log("Playing notification sound", {
|
|
278
|
+
soundPath: a.newNotificationSoundPath
|
|
279
|
+
}), new Audio(a.newNotificationSoundPath).play().catch((n) => {
|
|
280
|
+
e.error("Failed to play new notification sound", n), console.log("Failed to play new notification sound:", n);
|
|
281
|
+
}));
|
|
200
282
|
}, [
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
283
|
+
a.newNotificationSoundPath,
|
|
284
|
+
a.playSoundOnNewNotification,
|
|
285
|
+
e
|
|
286
|
+
]), O = A(
|
|
287
|
+
(t) => {
|
|
288
|
+
e.group("Adding notifications to state"), e.log("Received notifications", {
|
|
289
|
+
count: (t == null ? void 0 : t.length) || 0,
|
|
290
|
+
notifications: t
|
|
291
|
+
});
|
|
292
|
+
const n = (/* @__PURE__ */ new Date()).toISOString();
|
|
293
|
+
h((i) => {
|
|
294
|
+
const r = (i == null ? void 0 : i.length) || 0;
|
|
295
|
+
e.log("Current notifications count", r), t = Array.isArray(t) ? t : [], t = t.filter((g) => {
|
|
296
|
+
const S = g.expDate && new Date(g.expDate).toISOString() > n, L = new Date(g.date).getTime() > new Date(n).getTime() + 1e3, K = !S && !L;
|
|
297
|
+
return K || e.log("Filtering out notification", {
|
|
298
|
+
id: g.id,
|
|
299
|
+
reason: S ? "expired" : "future",
|
|
300
|
+
expDate: g.expDate,
|
|
301
|
+
date: g.date
|
|
302
|
+
}), K;
|
|
303
|
+
}), i = Array.isArray(i) ? i : [];
|
|
304
|
+
const d = [
|
|
305
|
+
...t.filter((g) => {
|
|
306
|
+
const S = i.find((L) => L.id === g.id);
|
|
307
|
+
return S && e.log("Filtering out duplicate notification", { id: g.id }), !S;
|
|
308
|
+
}),
|
|
309
|
+
...i
|
|
310
|
+
];
|
|
311
|
+
return e.log("State updated", {
|
|
312
|
+
previousCount: r,
|
|
313
|
+
newCount: d.length,
|
|
314
|
+
addedCount: t.length
|
|
315
|
+
}), e.groupEnd(), d;
|
|
316
|
+
});
|
|
317
|
+
},
|
|
318
|
+
[e]
|
|
319
|
+
), f = z(() => {
|
|
320
|
+
e.group("Initializing NotificationAPI client");
|
|
321
|
+
const t = {
|
|
322
|
+
clientId: a.clientId,
|
|
323
|
+
userId: a.user.id,
|
|
324
|
+
hashedUserId: a.hashedUserId,
|
|
325
|
+
host: a.apiURL,
|
|
326
|
+
websocketHost: a.wsURL,
|
|
327
|
+
debug: a.debug
|
|
328
|
+
};
|
|
329
|
+
e.log("Client configuration", t);
|
|
330
|
+
const n = o.client ? o.client : s.init({
|
|
331
|
+
...t,
|
|
332
|
+
onNewInAppNotifications: (r) => {
|
|
333
|
+
e.log("Received new in-app notifications via WebSocket", {
|
|
334
|
+
count: (r == null ? void 0 : r.length) || 0,
|
|
335
|
+
notifications: r
|
|
336
|
+
}), $(), O(r);
|
|
337
|
+
}
|
|
338
|
+
}), i = {
|
|
339
|
+
email: a.user.email,
|
|
340
|
+
number: a.user.number
|
|
341
|
+
};
|
|
342
|
+
return e.log("Identifying user", i), n.identify(i), e.groupEnd(), n;
|
|
343
|
+
}, [
|
|
344
|
+
a.clientId,
|
|
345
|
+
a.user.id,
|
|
346
|
+
a.user.email,
|
|
347
|
+
a.user.number,
|
|
348
|
+
a.hashedUserId,
|
|
349
|
+
a.debug,
|
|
350
|
+
O,
|
|
351
|
+
$,
|
|
352
|
+
o.client,
|
|
353
|
+
a.apiURL,
|
|
354
|
+
a.wsURL,
|
|
355
|
+
e
|
|
356
|
+
]), j = A(
|
|
357
|
+
async (t, n) => {
|
|
358
|
+
var i;
|
|
359
|
+
e.group("Fetching notifications"), e.log(
|
|
360
|
+
"Fetch parameters",
|
|
361
|
+
C("GET", "/notifications", { date: t, count: n })
|
|
362
|
+
);
|
|
363
|
+
try {
|
|
364
|
+
const r = await f.rest.getNotifications(t, n);
|
|
365
|
+
e.log("Fetch successful", {
|
|
366
|
+
notificationsCount: ((i = r.notifications) == null ? void 0 : i.length) || 0,
|
|
367
|
+
oldestReceived: r.oldestReceived,
|
|
368
|
+
couldLoadMore: r.couldLoadMore
|
|
369
|
+
}), P(r.oldestReceived), x(r.couldLoadMore), O(r.notifications), e.groupEnd();
|
|
370
|
+
} catch (r) {
|
|
371
|
+
throw e.error("Failed to fetch notifications", r, { date: t, count: n }), e.groupEnd(), r;
|
|
372
|
+
}
|
|
215
373
|
},
|
|
216
|
-
[
|
|
217
|
-
),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}, [
|
|
221
|
-
const
|
|
374
|
+
[O, f.rest, e]
|
|
375
|
+
), U = F(D), W = F(w), q = F(m);
|
|
376
|
+
E(() => {
|
|
377
|
+
U.current = D, W.current = w, q.current = m;
|
|
378
|
+
}, [D, w, m]);
|
|
379
|
+
const T = A(
|
|
222
380
|
async (t) => {
|
|
223
|
-
if (
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
381
|
+
if (e.group(`Loading notifications (${t ? "initial" : "more"})`), e.log("Load conditions", {
|
|
382
|
+
initial: t,
|
|
383
|
+
hasMore: U.current,
|
|
384
|
+
loading: W.current
|
|
385
|
+
}), !t && (!U.current || W.current)) {
|
|
386
|
+
e.log("Skipping load - conditions not met"), e.groupEnd();
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
v(!0), e.log("Loading started");
|
|
390
|
+
try {
|
|
391
|
+
await j(
|
|
392
|
+
t ? (/* @__PURE__ */ new Date()).toISOString() : q.current,
|
|
393
|
+
t ? a.initialLoadMaxCount : 1e3
|
|
394
|
+
), e.log("Loading completed successfully");
|
|
395
|
+
} catch (n) {
|
|
396
|
+
throw e.error("Loading failed", n), n;
|
|
397
|
+
} finally {
|
|
398
|
+
v(!1), e.groupEnd();
|
|
233
399
|
}
|
|
234
400
|
},
|
|
235
|
-
[
|
|
236
|
-
),
|
|
237
|
-
if (!
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
401
|
+
[a.initialLoadMaxCount, j, e]
|
|
402
|
+
), X = async (t) => {
|
|
403
|
+
if (e.group("Marking notifications as clicked"), e.log("Requested IDs", t), !c) {
|
|
404
|
+
e.warn("No notifications available"), e.groupEnd();
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const n = (/* @__PURE__ */ new Date()).toISOString(), i = c.filter((r) => t.includes(r.id) && !r.clicked).map((r) => r.id);
|
|
408
|
+
if (e.log("Filtered IDs for update", {
|
|
409
|
+
requestedCount: t.length,
|
|
410
|
+
actualCount: i.length,
|
|
411
|
+
ids: i
|
|
412
|
+
}), i.length === 0) {
|
|
413
|
+
e.log("No notifications to update"), e.groupEnd();
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
e.log(
|
|
418
|
+
"Updating notifications via API",
|
|
419
|
+
C("PUT", "/notifications/clicked", { ids: i })
|
|
420
|
+
), f.updateInAppNotifications({ ids: i, clicked: !0 }), h((r) => {
|
|
421
|
+
if (!r) return [];
|
|
422
|
+
const d = [...r];
|
|
423
|
+
return d.filter((g) => i.includes(g.id)).forEach((g) => {
|
|
424
|
+
g.clicked = n;
|
|
425
|
+
}), e.log("Local state updated", { updatedCount: i.length }), d;
|
|
426
|
+
}), e.groupEnd();
|
|
427
|
+
} catch (r) {
|
|
428
|
+
throw e.error("Failed to mark notifications as clicked", r, { ids: i }), e.groupEnd(), r;
|
|
429
|
+
}
|
|
430
|
+
}, Y = async () => {
|
|
431
|
+
if (e.group("Marking notifications as opened"), !c) {
|
|
432
|
+
e.warn("No notifications available"), e.groupEnd();
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const t = (/* @__PURE__ */ new Date()).toISOString(), n = c.filter((i) => !i.opened || !i.seen).map((i) => i.id);
|
|
436
|
+
if (e.log("Notifications to mark as opened", { count: n.length, ids: n }), n.length === 0) {
|
|
437
|
+
e.log("All notifications already opened"), e.groupEnd();
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
try {
|
|
441
|
+
e.log(
|
|
442
|
+
"Updating notifications via API",
|
|
443
|
+
C("PUT", "/notifications/opened", { ids: n })
|
|
444
|
+
), f.updateInAppNotifications({
|
|
445
|
+
ids: n,
|
|
446
|
+
opened: !0
|
|
447
|
+
}), h((i) => {
|
|
448
|
+
if (!i) return [];
|
|
449
|
+
const r = [...i];
|
|
450
|
+
return r.filter((d) => n.includes(d.id)).forEach((d) => {
|
|
451
|
+
d.opened = t, d.seen = !0;
|
|
452
|
+
}), e.log("Local state updated", { updatedCount: n.length }), r;
|
|
453
|
+
}), e.groupEnd();
|
|
454
|
+
} catch (i) {
|
|
455
|
+
throw e.error("Failed to mark notifications as opened", i, { ids: n }), e.groupEnd(), i;
|
|
456
|
+
}
|
|
457
|
+
}, Z = async (t) => {
|
|
458
|
+
if (e.group("Marking notifications as unarchived"), e.log("Requested operation", { ids: t }), !c) {
|
|
459
|
+
e.warn("No notifications available"), e.groupEnd();
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
const n = c.filter((i) => i.archived && (t === "ALL" || t.includes(i.id))).map((i) => i.id);
|
|
463
|
+
if (e.log("Filtered notifications for unarchiving", {
|
|
464
|
+
count: n.length,
|
|
465
|
+
ids: n
|
|
466
|
+
}), n.length === 0) {
|
|
467
|
+
e.log("No archived notifications to unarchive"), e.groupEnd();
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
try {
|
|
471
|
+
e.log(
|
|
472
|
+
"Updating notifications via API",
|
|
473
|
+
C("PUT", "/notifications/unarchived", { ids: n })
|
|
474
|
+
), f.updateInAppNotifications({
|
|
475
|
+
ids: n,
|
|
476
|
+
archived: !1
|
|
477
|
+
}), h((i) => {
|
|
478
|
+
if (!i) return [];
|
|
479
|
+
const r = [...i];
|
|
480
|
+
return r.filter((d) => n.includes(d.id)).forEach((d) => {
|
|
481
|
+
d.archived = void 0;
|
|
482
|
+
}), e.log("Local state updated", { unarchivedCount: n.length }), r;
|
|
483
|
+
}), e.groupEnd();
|
|
484
|
+
} catch (i) {
|
|
485
|
+
throw e.error("Failed to unarchive notifications", i, { ids: n }), e.groupEnd(), i;
|
|
486
|
+
}
|
|
487
|
+
}, _ = async (t) => {
|
|
488
|
+
if (e.group("Marking notifications as archived"), e.log("Requested operation", { ids: t }), !c) {
|
|
489
|
+
e.warn("No notifications available"), e.groupEnd();
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const n = (/* @__PURE__ */ new Date()).toISOString(), i = c.filter((r) => !r.archived && (t === "ALL" || t.includes(r.id))).map((r) => r.id);
|
|
493
|
+
if (e.log("Filtered notifications for archiving", {
|
|
494
|
+
count: i.length,
|
|
495
|
+
ids: i
|
|
496
|
+
}), i.length === 0) {
|
|
497
|
+
e.log("No unarchived notifications to archive"), e.groupEnd();
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
try {
|
|
501
|
+
e.log(
|
|
502
|
+
"Updating notifications via API",
|
|
503
|
+
C("PUT", "/notifications/archived", { ids: i })
|
|
504
|
+
), f.updateInAppNotifications({ ids: i, archived: !0 }), h((r) => {
|
|
505
|
+
if (!r) return [];
|
|
506
|
+
const d = [...r];
|
|
507
|
+
return d.filter((g) => i.includes(g.id)).forEach((g) => {
|
|
508
|
+
g.archived = n;
|
|
509
|
+
}), e.log("Local state updated", { archivedCount: i.length }), d;
|
|
510
|
+
}), e.groupEnd();
|
|
511
|
+
} catch (r) {
|
|
512
|
+
throw e.error("Failed to archive notifications", r, { ids: i }), e.groupEnd(), r;
|
|
513
|
+
}
|
|
514
|
+
}, ee = (t, n, i, r) => (e.log("Updating single delivery preference", {
|
|
515
|
+
notificationId: t,
|
|
516
|
+
channel: n,
|
|
517
|
+
delivery: i,
|
|
518
|
+
subNotificationId: r
|
|
519
|
+
}), H([
|
|
283
520
|
{
|
|
284
521
|
notificationId: t,
|
|
285
|
-
channel:
|
|
286
|
-
delivery:
|
|
522
|
+
channel: n,
|
|
523
|
+
delivery: i,
|
|
287
524
|
subNotificationId: r
|
|
288
525
|
}
|
|
289
|
-
]),
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
526
|
+
])), H = (t) => {
|
|
527
|
+
e.group("Updating delivery preferences"), e.log("Preference updates", { count: t.length, params: t });
|
|
528
|
+
try {
|
|
529
|
+
f.rest.postPreferences(t).then(() => {
|
|
530
|
+
e.log(
|
|
531
|
+
"Preferences updated successfully, fetching latest preferences"
|
|
532
|
+
), f.getPreferences().then((n) => {
|
|
533
|
+
var i, r, d;
|
|
534
|
+
e.log("Latest preferences fetched", {
|
|
535
|
+
preferencesCount: ((i = n.preferences) == null ? void 0 : i.length) || 0,
|
|
536
|
+
notificationsCount: ((r = n.notifications) == null ? void 0 : r.length) || 0,
|
|
537
|
+
subNotificationsCount: ((d = n.subNotifications) == null ? void 0 : d.length) || 0
|
|
538
|
+
}), l(n), e.groupEnd();
|
|
539
|
+
}).catch((n) => {
|
|
540
|
+
e.error("Failed to fetch updated preferences", n), e.groupEnd();
|
|
541
|
+
});
|
|
542
|
+
}).catch((n) => {
|
|
543
|
+
e.error("Failed to update preferences", n, { params: t }), e.groupEnd();
|
|
293
544
|
});
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
545
|
+
} catch (n) {
|
|
546
|
+
throw e.error("Error in updateDeliveries", n, { params: t }), e.groupEnd(), n;
|
|
547
|
+
}
|
|
548
|
+
}, R = A(() => {
|
|
549
|
+
e.group("Requesting web push permission"), e.log("Service worker support check", {
|
|
550
|
+
supported: "serviceWorker" in navigator,
|
|
551
|
+
customServiceWorkerPath: a.customServiceWorkerPath
|
|
552
|
+
}), "serviceWorker" in navigator ? (e.log("Registering service worker"), navigator.serviceWorker.register(a.customServiceWorkerPath).then(async (t) => {
|
|
553
|
+
e.log("Service worker registered successfully"), y(!1), de().then(async (n) => {
|
|
554
|
+
e.log("Notification permission result", { permission: n }), n === "granted" ? (e.log("Permission granted, subscribing to push manager"), await t.pushManager.subscribe({
|
|
299
555
|
userVisibleOnly: !0,
|
|
300
|
-
applicationServerKey:
|
|
301
|
-
}).then(async (
|
|
556
|
+
applicationServerKey: p == null ? void 0 : p.userAccountMetadata.environmentVapidPublicKey
|
|
557
|
+
}).then(async (i) => {
|
|
558
|
+
e.log("Push subscription successful");
|
|
302
559
|
const r = {
|
|
303
560
|
webPushTokens: [
|
|
304
561
|
{
|
|
305
562
|
sub: {
|
|
306
|
-
endpoint:
|
|
307
|
-
keys:
|
|
563
|
+
endpoint: i.toJSON().endpoint,
|
|
564
|
+
keys: i.toJSON().keys
|
|
308
565
|
}
|
|
309
566
|
}
|
|
310
567
|
]
|
|
311
568
|
};
|
|
312
|
-
await
|
|
313
|
-
}) :
|
|
569
|
+
e.log("Identifying user with web push tokens"), await f.identify(r), localStorage.setItem("hideWebPushOptInMessage", "true"), e.log("Web push setup completed successfully"), e.groupEnd();
|
|
570
|
+
})) : n === "denied" && (e.warn("Permission for notifications was denied"), console.log("Permission for notifications was denied"), e.groupEnd());
|
|
314
571
|
});
|
|
315
572
|
}).catch((t) => {
|
|
316
|
-
|
|
573
|
+
e.error(
|
|
574
|
+
"Service worker registration or push subscription failed",
|
|
575
|
+
t,
|
|
576
|
+
{
|
|
577
|
+
errorCode: t.code,
|
|
578
|
+
customServiceWorkerPath: a.customServiceWorkerPath
|
|
579
|
+
}
|
|
580
|
+
), t.code === 18 ? console.error(
|
|
317
581
|
"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
582
|
) : t.code === 19 ? console.error(
|
|
319
583
|
"The operation is aborted. This can happen if the user denies the permission request."
|
|
@@ -323,62 +587,95 @@ const Z = async (e, c, i, a, f, b, h) => {
|
|
|
323
587
|
"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
588
|
) : t.code === 22 ? console.error(
|
|
325
589
|
"The operation is not supported. This can occur if the browser does not support the required features."
|
|
326
|
-
) : console.error(t);
|
|
327
|
-
});
|
|
590
|
+
) : console.error(t), e.groupEnd();
|
|
591
|
+
})) : (e.warn("Service worker not supported in this browser"), e.groupEnd());
|
|
328
592
|
}, [
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
593
|
+
f,
|
|
594
|
+
a.customServiceWorkerPath,
|
|
595
|
+
p == null ? void 0 : p.userAccountMetadata.environmentVapidPublicKey,
|
|
596
|
+
e
|
|
332
597
|
]);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
598
|
+
E(() => {
|
|
599
|
+
e.group("Provider initialization effect"), e.log("Resetting state and loading initial data"), h([]), v(!1), l(void 0), P((/* @__PURE__ */ new Date()).toISOString()), x(!0), T(!0), e.log("Opening WebSocket connection"), f.openWebSocket(), e.log("Fetching user preferences"), f.getPreferences().then((t) => {
|
|
600
|
+
var n, i, r;
|
|
601
|
+
e.log("Initial preferences loaded", {
|
|
602
|
+
preferencesCount: ((n = t.preferences) == null ? void 0 : n.length) || 0,
|
|
603
|
+
notificationsCount: ((i = t.notifications) == null ? void 0 : i.length) || 0,
|
|
604
|
+
subNotificationsCount: ((r = t.subNotifications) == null ? void 0 : r.length) || 0
|
|
605
|
+
}), l(t), e.groupEnd();
|
|
606
|
+
}).catch((t) => {
|
|
607
|
+
e.error("Failed to fetch initial preferences", t), e.groupEnd();
|
|
336
608
|
});
|
|
337
|
-
}, [
|
|
338
|
-
|
|
339
|
-
|
|
609
|
+
}, [f, T, R, e]), E(() => {
|
|
610
|
+
e.group("Fetching user account metadata"), f.getUserAccountMetadata().then((t) => {
|
|
611
|
+
e.log("User account metadata loaded", {
|
|
612
|
+
hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled,
|
|
613
|
+
environmentVapidPublicKey: t.userAccountMetadata.environmentVapidPublicKey ? "present" : "missing"
|
|
614
|
+
}), b(t), G && "Notification" in window && typeof Notification.requestPermission == "function" ? (e.log("Browser notification support detected", {
|
|
615
|
+
permission: Notification.permission
|
|
616
|
+
}), Notification.permission !== "default" && (e.log(
|
|
617
|
+
"Setting webPushOptInMessage to false (permission already set)"
|
|
618
|
+
), y(!1))) : (e.log(
|
|
619
|
+
"Browser notification not supported, using server setting",
|
|
620
|
+
{
|
|
621
|
+
hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled
|
|
622
|
+
}
|
|
623
|
+
), y(t.userAccountMetadata.hasWebPushEnabled)), e.groupEnd();
|
|
624
|
+
}).catch((t) => {
|
|
625
|
+
e.error("Failed to fetch user account metadata", t), e.groupEnd();
|
|
340
626
|
});
|
|
341
|
-
}, [
|
|
342
|
-
|
|
343
|
-
localStorage.getItem("hideWebPushOptInMessage")
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
627
|
+
}, [f, e]), E(() => {
|
|
628
|
+
if (e.group("Handling webPushOptInMessage state"), e.log("webPushOptInMessage value", k), k === "AUTOMATIC") {
|
|
629
|
+
const t = localStorage.getItem("hideWebPushOptInMessage") === "true";
|
|
630
|
+
e.log("Automatic mode - checking localStorage", {
|
|
631
|
+
hideMessage: t,
|
|
632
|
+
shouldShow: !t
|
|
633
|
+
}), y(!t);
|
|
634
|
+
}
|
|
635
|
+
e.groupEnd();
|
|
636
|
+
}, [k, e]), E(() => {
|
|
637
|
+
e.group("Handling webPushOptIn state"), e.log("webPushOptIn state", M), M && (e.log("User opted in for web push, requesting permission"), R()), e.groupEnd();
|
|
638
|
+
}, [M, R, e]);
|
|
639
|
+
const te = {
|
|
640
|
+
notifications: c,
|
|
641
|
+
preferences: I,
|
|
642
|
+
userAccountMetaData: p,
|
|
643
|
+
webPushOptInMessage: k,
|
|
644
|
+
loadNotifications: T,
|
|
645
|
+
markAsOpened: Y,
|
|
646
|
+
markAsArchived: _,
|
|
647
|
+
markAsUnarchived: Z,
|
|
648
|
+
markAsClicked: X,
|
|
649
|
+
updateDelivery: ee,
|
|
650
|
+
updateDeliveries: H,
|
|
651
|
+
getClient: () => f,
|
|
652
|
+
setWebPushOptInMessage: y,
|
|
653
|
+
setWebPushOptIn: Q
|
|
363
654
|
};
|
|
364
|
-
return
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
655
|
+
return e.log("NotificationAPI Provider rendering", {
|
|
656
|
+
notificationsCount: (c == null ? void 0 : c.length) || 0,
|
|
657
|
+
hasPreferences: !!I,
|
|
658
|
+
hasUserAccountMetaData: !!p,
|
|
659
|
+
webPushOptInMessage: k,
|
|
660
|
+
webPushOptIn: M
|
|
661
|
+
}), /* @__PURE__ */ oe(V.Provider, { value: te, children: o.children });
|
|
662
|
+
}, ce = () => {
|
|
663
|
+
const o = ie(V);
|
|
664
|
+
if (!o)
|
|
368
665
|
throw new Error("useMyContext must be used within a MyProvider");
|
|
369
|
-
return
|
|
666
|
+
return o;
|
|
370
667
|
};
|
|
371
|
-
|
|
372
|
-
const
|
|
373
|
-
if (
|
|
668
|
+
ae.useNotificationAPIContext = ce;
|
|
669
|
+
const de = async () => {
|
|
670
|
+
if (G && "Notification" in window && typeof Notification.requestPermission == "function")
|
|
374
671
|
try {
|
|
375
672
|
return await Notification.requestPermission();
|
|
376
|
-
} catch (
|
|
377
|
-
return console.error("Error requesting notification permission:",
|
|
673
|
+
} catch (o) {
|
|
674
|
+
return console.error("Error requesting notification permission:", o), "default";
|
|
378
675
|
}
|
|
379
676
|
else
|
|
380
677
|
return console.warn("Web Push Notifications are not supported in this browser."), "default";
|
|
381
678
|
};
|
|
382
679
|
export {
|
|
383
|
-
|
|
680
|
+
ae as NotificationAPIProvider
|
|
384
681
|
};
|
package/dist/main.d.ts
CHANGED
|
@@ -2,3 +2,4 @@
|
|
|
2
2
|
export { NotificationFeed, NotificationPopup, NotificationLauncher, NotificationCounter } from './components/Notifications';
|
|
3
3
|
export { NotificationPreferencesInline, NotificationPreferencesPopup } from './components/Preferences';
|
|
4
4
|
export { NotificationAPIProvider } from './components/Provider';
|
|
5
|
+
export { createDebugLogger, type DebugLogger } from './utils/debug';
|
package/dist/main.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { NotificationFeed as r } from "./components/Notifications/NotificationFeed.js";
|
|
2
|
-
import { NotificationPopup as
|
|
2
|
+
import { NotificationPopup as i } from "./components/Notifications/NotificationPopup.js";
|
|
3
3
|
import { NotificationLauncher as n } from "./components/Notifications/NotificationLauncher.js";
|
|
4
4
|
import { NotificationCounter as c } from "./components/Notifications/NotificationCounter.js";
|
|
5
|
-
import { N } from "./assets/NotificationPreferencesPopup.js";
|
|
6
|
-
import { NotificationPreferencesInline as
|
|
5
|
+
import { N as m } from "./assets/NotificationPreferencesPopup.js";
|
|
6
|
+
import { NotificationPreferencesInline as N } from "./components/Preferences/NotificationPreferencesInline.js";
|
|
7
7
|
import { NotificationAPIProvider as u } from "./components/Provider/index.js";
|
|
8
|
+
import { createDebugLogger as s } from "./utils/debug.js";
|
|
8
9
|
export {
|
|
9
10
|
u as NotificationAPIProvider,
|
|
10
11
|
c as NotificationCounter,
|
|
11
12
|
r as NotificationFeed,
|
|
12
13
|
n as NotificationLauncher,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
i as NotificationPopup,
|
|
15
|
+
N as NotificationPreferencesInline,
|
|
16
|
+
m as NotificationPreferencesPopup,
|
|
17
|
+
s as createDebugLogger
|
|
16
18
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface DebugLogger {
|
|
2
|
+
log: (message: string, data?: unknown) => void;
|
|
3
|
+
warn: (message: string, data?: unknown) => void;
|
|
4
|
+
error: (message: string, error?: Error | unknown, context?: Record<string, unknown>) => void;
|
|
5
|
+
group: (label: string) => void;
|
|
6
|
+
groupEnd: () => void;
|
|
7
|
+
table: (data: Record<string, unknown> | unknown[]) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const createDebugLogger: (enabled: boolean) => DebugLogger;
|
|
10
|
+
export declare const formatApiCall: (method: string, endpoint: string, params?: Record<string, unknown>) => {
|
|
11
|
+
method: string;
|
|
12
|
+
endpoint: string;
|
|
13
|
+
params: Record<string, unknown> | undefined;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const formatWebSocketEvent: (event: string, data?: unknown) => {
|
|
17
|
+
event: string;
|
|
18
|
+
data: unknown;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const formatStateChange: (stateName: string, oldValue: unknown, newValue: unknown) => {
|
|
22
|
+
stateName: string;
|
|
23
|
+
oldValue: unknown;
|
|
24
|
+
newValue: unknown;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var s = Object.defineProperty;
|
|
2
|
+
var a = (t, o, e) => o in t ? s(t, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[o] = e;
|
|
3
|
+
var n = (t, o, e) => a(t, typeof o != "symbol" ? o + "" : o, e);
|
|
4
|
+
class c {
|
|
5
|
+
log() {
|
|
6
|
+
}
|
|
7
|
+
warn() {
|
|
8
|
+
}
|
|
9
|
+
error() {
|
|
10
|
+
}
|
|
11
|
+
group() {
|
|
12
|
+
}
|
|
13
|
+
groupEnd() {
|
|
14
|
+
}
|
|
15
|
+
table() {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
class g {
|
|
19
|
+
constructor() {
|
|
20
|
+
n(this, "prefix", "[NotificationAPI Debug]");
|
|
21
|
+
}
|
|
22
|
+
log(o, e) {
|
|
23
|
+
console.log(`${this.prefix} ${o}`, e || "");
|
|
24
|
+
}
|
|
25
|
+
warn(o, e) {
|
|
26
|
+
console.warn(`${this.prefix} ${o}`, e || "");
|
|
27
|
+
}
|
|
28
|
+
error(o, e, r) {
|
|
29
|
+
console.group(`${this.prefix} ERROR: ${o}`), e && console.error("Error:", e), r && console.error("Context:", r), e instanceof Error && e.stack && console.error("Stack trace:", e.stack), console.groupEnd();
|
|
30
|
+
}
|
|
31
|
+
group(o) {
|
|
32
|
+
console.group(`${this.prefix} ${o}`);
|
|
33
|
+
}
|
|
34
|
+
groupEnd() {
|
|
35
|
+
console.groupEnd();
|
|
36
|
+
}
|
|
37
|
+
table(o) {
|
|
38
|
+
console.table(o);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const l = (t) => t ? new g() : new c(), p = (t, o, e) => ({
|
|
42
|
+
method: t,
|
|
43
|
+
endpoint: o,
|
|
44
|
+
params: e,
|
|
45
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
46
|
+
}), u = (t, o) => ({
|
|
47
|
+
event: t,
|
|
48
|
+
data: o,
|
|
49
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
50
|
+
}), f = (t, o, e) => ({
|
|
51
|
+
stateName: t,
|
|
52
|
+
oldValue: o,
|
|
53
|
+
newValue: e,
|
|
54
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
55
|
+
});
|
|
56
|
+
export {
|
|
57
|
+
l as createDebugLogger,
|
|
58
|
+
p as formatApiCall,
|
|
59
|
+
f as formatStateChange,
|
|
60
|
+
u as formatWebSocketEvent
|
|
61
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notificationapi/react",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"overrides": {
|
|
7
7
|
"esbuild": "^0.25.0",
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
"format": "prettier --write \"{src,lib}/**/*.{ts,tsx,js,jsx,json,css,md,html}\"",
|
|
26
26
|
"prettier-check": "prettier --check \"{src,lib}/**/*.{ts,tsx,js,jsx,json,css,md,html}\"",
|
|
27
27
|
"preview": "vite preview",
|
|
28
|
-
"prepublishOnly": "npm run build"
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"test:e2e": "playwright test",
|
|
30
|
+
"test:e2e:ui": "playwright test --ui",
|
|
31
|
+
"test:e2e:headed": "playwright test --headed"
|
|
29
32
|
},
|
|
30
33
|
"peerDependencies": {
|
|
31
34
|
"react": "^17.0.2 || ^18.0.0 || ^19.0.0",
|
|
@@ -45,9 +48,10 @@
|
|
|
45
48
|
"eslint-plugin-react-refresh": "^0.4.6",
|
|
46
49
|
"faker-js": "^1.0.0",
|
|
47
50
|
"glob": "^10.4.1",
|
|
51
|
+
"@playwright/test": "^1.48.0",
|
|
48
52
|
"prettier": "^3.3.3",
|
|
49
53
|
"typescript": "^5.2.2",
|
|
50
|
-
"vite": "^5.4.
|
|
54
|
+
"vite": "^5.4.19",
|
|
51
55
|
"vite-plugin-dts": "^3.9.1",
|
|
52
56
|
"vite-plugin-lib-inject-css": "^2.1.1"
|
|
53
57
|
},
|
|
@@ -63,7 +67,7 @@
|
|
|
63
67
|
"@fontsource/roboto": "^5.1.1",
|
|
64
68
|
"@mui/icons-material": "^6.3.1",
|
|
65
69
|
"@mui/material": "^6.3.1",
|
|
66
|
-
"@notificationapi/core": "^0.0.
|
|
70
|
+
"@notificationapi/core": "^0.0.17",
|
|
67
71
|
"javascript-time-ago": "^2.5.10",
|
|
68
72
|
"liquidjs": "^10.14.0",
|
|
69
73
|
"rc-virtual-list": "^3.11.5",
|