@trycourier/react-hooks 2.0.2-internal.9773702.0 → 3.0.1-internal.cbb755c.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 +99 -258
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,56 +2,127 @@
|
|
|
2
2
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
3
3
|
|
|
4
4
|
- [Overview](#overview)
|
|
5
|
+
- [3.X Breaking Changes](#3x-breaking-changes)
|
|
6
|
+
- [Message Interface](#message-interface)
|
|
7
|
+
- [Events](#events)
|
|
5
8
|
- [Types](#types)
|
|
6
|
-
- [Events](#events)
|
|
9
|
+
- [Events](#events-1)
|
|
10
|
+
- [Manually calling events (`useInbox` Example)](#manually-calling-events-useinbox-example)
|
|
7
11
|
|
|
8
12
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
9
13
|
|
|
10
14
|
<a name="0overviewmd"></a>
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
## [Overview](#overview)
|
|
13
17
|
|
|
14
18
|
`@trycourier/react-hooks` exist as a separate package so that you can build your own interface using our api and state management without having to install all the dependencies that `@trycourier/react-inbox` or other `react-dom` based packages include.
|
|
15
19
|
|
|
16
20
|
This also enables using this package with `react-native` in a much simpler way.
|
|
17
21
|
|
|
22
|
+
## [3.X Breaking Changes](#3x-breaking-changes)
|
|
23
|
+
|
|
24
|
+
As of 3.X we have started to use a new API for our inbox messages. The interface is slightly different which means interacting with the `useInbox` hook will need to be updated to match the new interface.
|
|
25
|
+
|
|
26
|
+
### Message Interface
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
interface ActionBlock {
|
|
30
|
+
type: "text";
|
|
31
|
+
text: string;
|
|
32
|
+
url: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface OldMessage {
|
|
36
|
+
title: string;
|
|
37
|
+
body: string;
|
|
38
|
+
read?: boolean;
|
|
39
|
+
blocks: Array<TextBlock | ActionBlock>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface ActionElement {
|
|
43
|
+
type: "text";
|
|
44
|
+
content: string;
|
|
45
|
+
href: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface NewMessage {
|
|
49
|
+
title: string;
|
|
50
|
+
preview: string;
|
|
51
|
+
read?: string;
|
|
52
|
+
actions: Array<ActionElement>;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This means if you were consuming `const { messages } = useInbox` that the array of messages will now be different and will need to be updated.
|
|
57
|
+
|
|
58
|
+
### Events
|
|
59
|
+
|
|
60
|
+
The old versions had events like `markRead(messageId, trackingId)`. The new version no longer requires passing a trackingId to track events.
|
|
61
|
+
|
|
62
|
+
- 1.X/2.X Old Interface:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
interface IInboxActions {
|
|
66
|
+
markMessageArchived: (
|
|
67
|
+
messageId: string,
|
|
68
|
+
trackingId?: string
|
|
69
|
+
) => Promise<void>;
|
|
70
|
+
markMessageRead: (messageId: string, trackingId?: string) => Promise<void>;
|
|
71
|
+
markMessageUnread: (messageId: string, trackingId?: string) => Promise<void>;
|
|
72
|
+
markMessageOpened: (messageId: string, trackingId: string) => Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- 3.X Interface:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
interface IInboxActions {
|
|
80
|
+
markMessageArchived: (messageId: string) => Promise<void>;
|
|
81
|
+
markMessageRead: (messageId: string) => Promise<void>;
|
|
82
|
+
markMessageUnread: (messageId: string) => Promise<void>;
|
|
83
|
+
markMessageOpened: (messageId: string) => Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
18
87
|
<a name="1typesmd"></a>
|
|
19
88
|
|
|
20
|
-
|
|
89
|
+
## [Types](#types)
|
|
21
90
|
|
|
22
91
|
Standard Inbox (`useInbox`):
|
|
23
92
|
|
|
24
93
|
```ts
|
|
25
94
|
const inbox: IInbox & IInboxActions = useInbox();
|
|
26
95
|
|
|
27
|
-
interface
|
|
28
|
-
|
|
29
|
-
|
|
96
|
+
interface ActionElement {
|
|
97
|
+
type: "text";
|
|
98
|
+
content: string;
|
|
99
|
+
href: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface IInboxMessagePreview {
|
|
103
|
+
actions?: IActionElemental[];
|
|
30
104
|
created: string;
|
|
31
|
-
data?:
|
|
32
|
-
clickAction: string;
|
|
33
|
-
};
|
|
34
|
-
icon?: string;
|
|
105
|
+
data?: Record<string, any>;
|
|
35
106
|
messageId: string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
deliveredTrackingId: string;
|
|
42
|
-
openTrackingId: string;
|
|
43
|
-
readTrackingId: string;
|
|
44
|
-
unreadTrackingId: string;
|
|
45
|
-
};
|
|
107
|
+
opened?: string;
|
|
108
|
+
preview?: string;
|
|
109
|
+
read?: string;
|
|
110
|
+
tags?: string[];
|
|
111
|
+
title?: string;
|
|
46
112
|
}
|
|
47
113
|
|
|
48
114
|
interface IInboxActions {
|
|
49
115
|
fetchMessages: (params?: IFetchMessagesParams) => void;
|
|
50
116
|
getUnreadMessageCount: (params?: IGetMessagesParams) => void;
|
|
51
117
|
init: (inbox: IInbox) => void;
|
|
52
|
-
markAllAsRead: () => void;
|
|
53
|
-
|
|
54
|
-
|
|
118
|
+
markAllAsRead: (fromWS?: boolean) => void;
|
|
119
|
+
markMessageArchived: (messageId: string, fromWS?: boolean) => Promise<void>;
|
|
120
|
+
markMessageOpened: (messageId: string, fromWS?: boolean) => Promise<void>;
|
|
121
|
+
markMessageRead: (messageId: string, fromWS?: boolean) => Promise<void>;
|
|
122
|
+
markMessageUnread: (messageId: string, fromWS?: boolean) => Promise<void>;
|
|
123
|
+
newMessage: (transportMessage: IInboxMessagePreview) => void;
|
|
124
|
+
rehydrateMessages: (payload: RehydrateMessages["payload"]) => void;
|
|
125
|
+
resetLastFetched: () => void;
|
|
55
126
|
setView: (view: "messages" | "preferences") => void;
|
|
56
127
|
toggleInbox: (isOpen?: boolean) => void;
|
|
57
128
|
}
|
|
@@ -59,7 +130,7 @@ interface IInboxActions {
|
|
|
59
130
|
interface IInbox {
|
|
60
131
|
isLoading?: boolean;
|
|
61
132
|
isOpen?: boolean;
|
|
62
|
-
messages?: Array<
|
|
133
|
+
messages?: Array<IInboxMessagePreview>;
|
|
63
134
|
startCursor?: string;
|
|
64
135
|
unreadMessageCount?: number;
|
|
65
136
|
view?: "messages" | "preferences";
|
|
@@ -68,9 +139,7 @@ interface IInbox {
|
|
|
68
139
|
|
|
69
140
|
<a name="2eventsmd"></a>
|
|
70
141
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
#### Inbox
|
|
142
|
+
## [Events](#events)
|
|
74
143
|
|
|
75
144
|
Inbox supports a few different events that can be triggered on the client side.
|
|
76
145
|
|
|
@@ -87,7 +156,7 @@ Some of these events are called automatically.
|
|
|
87
156
|
- Delivered events are called automatically inside the Courier Provider when a message has been delivered through the websocket
|
|
88
157
|
- Click events are triggered using our `click through tracking` links. Click events will also automatically trigger a `read` event.
|
|
89
158
|
|
|
90
|
-
|
|
159
|
+
### Manually calling events (`useInbox` Example)
|
|
91
160
|
|
|
92
161
|
You can call events manually by importing the corresponding function from the react hook.
|
|
93
162
|
|
|
@@ -106,149 +175,16 @@ const MyInbox = () => {
|
|
|
106
175
|
|
|
107
176
|
const handleReadMessage = (message) => (event) => {
|
|
108
177
|
event.preventDefault();
|
|
109
|
-
inbox.markMessageRead(
|
|
110
|
-
message.messageId,
|
|
111
|
-
message.trackingIds.readTrackingId
|
|
112
|
-
);
|
|
178
|
+
inbox.markMessageRead(message.messageId);
|
|
113
179
|
};
|
|
114
180
|
|
|
115
181
|
const handleUnreadMessage = (message) => (event) => {
|
|
116
182
|
event.preventDefault();
|
|
117
|
-
inbox.markMessageUnread(
|
|
118
|
-
message.messageId,
|
|
119
|
-
message.trackingIds.unreadTrackingId
|
|
120
|
-
);
|
|
183
|
+
inbox.markMessageUnread(message.messageId);
|
|
121
184
|
};
|
|
122
185
|
|
|
123
186
|
const handleArchiveMessage = (message) => (event) => {
|
|
124
187
|
event.preventDefault();
|
|
125
|
-
inbox.markMessageArchived(
|
|
126
|
-
message.messageId,
|
|
127
|
-
message.trackingIds.archiveTrackingId
|
|
128
|
-
);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<Container>
|
|
133
|
-
{inbox.messages.map((message) => {
|
|
134
|
-
return (
|
|
135
|
-
<Message>
|
|
136
|
-
{message.read ? (
|
|
137
|
-
<>
|
|
138
|
-
<button onClick={handleUnreadMessage(message)}>
|
|
139
|
-
Unread Me
|
|
140
|
-
</button>
|
|
141
|
-
<button onClick={handleArchiveMessage(message)}>
|
|
142
|
-
Archive Me
|
|
143
|
-
</button>
|
|
144
|
-
</>
|
|
145
|
-
) : (
|
|
146
|
-
<button onClick={handleReadMessage(message)}>Read Me</button>
|
|
147
|
-
)}
|
|
148
|
-
</Message>
|
|
149
|
-
);
|
|
150
|
-
})}
|
|
151
|
-
</Container>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const MyApp = () => {
|
|
156
|
-
return (
|
|
157
|
-
<CourierProvider userId="MY_USER_ID" clientKey="MY_CLIENT_KEY">
|
|
158
|
-
<MyInbox />
|
|
159
|
-
</CourierProvider>
|
|
160
|
-
);
|
|
161
|
-
};
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
<a name="3use-elemental-inboxmd"></a>
|
|
165
|
-
|
|
166
|
-
> useElementalInbox is in **BETA**
|
|
167
|
-
|
|
168
|
-
```ts
|
|
169
|
-
interface IInboxMessage {
|
|
170
|
-
created?: string;
|
|
171
|
-
messageId: string;
|
|
172
|
-
preview?: string;
|
|
173
|
-
/** ISO 8601 date the message was read */
|
|
174
|
-
read?: string;
|
|
175
|
-
title?: string;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export interface IFetchMessagesParams {
|
|
179
|
-
params?: IGetInboxMessagesParams;
|
|
180
|
-
after?: string;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export interface IGetInboxMessagesParams {
|
|
184
|
-
status?: "read" | "unread";
|
|
185
|
-
limit?: number;
|
|
186
|
-
tags?: string[];
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// This interface defines the return value of useElemental Inbox
|
|
190
|
-
interface IElementalInbox {
|
|
191
|
-
brand?: Brand;
|
|
192
|
-
from?: number;
|
|
193
|
-
isLoading?: boolean;
|
|
194
|
-
isOpen?: boolean;
|
|
195
|
-
lastMessagesFetched?: number;
|
|
196
|
-
messages?: Array<IElementalInboxMessage>;
|
|
197
|
-
startCursor?: string;
|
|
198
|
-
unreadMessageCount?: number;
|
|
199
|
-
view?: "messages" | "preferences";
|
|
200
|
-
/** Fetches messages from the server, sets inbox.messages to the received value */
|
|
201
|
-
fetchMessages: (params?: IFetchMessagesParams) => void;
|
|
202
|
-
/** Returns a count of messages that do not have a message.read date */
|
|
203
|
-
getUnreadMessageCount: (params?: IGetInboxMessagesParams) => void;
|
|
204
|
-
init: (inbox: IElementalInbox) => void;
|
|
205
|
-
/** Marks all messages as read by setting message.read to the current ISO 8601 date */
|
|
206
|
-
markAllAsRead: () => void;
|
|
207
|
-
/** Archives the supplied message, archived messages are not returned by fetchMessages */
|
|
208
|
-
markMessageArchived: (messageId: string) => Promise<void>;
|
|
209
|
-
/** Sets message.read to the current ISO 8601 date */
|
|
210
|
-
markMessageRead: (messageId: string) => Promise<void>;
|
|
211
|
-
/** Removes message.read, signalling that the message is no longer read */
|
|
212
|
-
markMessageUnread: (messageId: string) => Promise<void>;
|
|
213
|
-
setView: (view: "messages" | "preferences") => void;
|
|
214
|
-
toggleInbox: (isOpen?: boolean) => void;
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Allows for renewal of sessions authorized with short lived tokens.
|
|
218
|
-
* For example, if the supplied authorization token lasts 10 minutes,
|
|
219
|
-
* this function can be called with a new token every 5 minutes to ensure
|
|
220
|
-
* messages are received in real time with no interruptions.
|
|
221
|
-
*/
|
|
222
|
-
renewSession: (authorization: string) => void;
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
#### Manually calling events (`useElementalInbox` Example)
|
|
227
|
-
|
|
228
|
-
You can call events manually by importing the corresponding function from the react hook.
|
|
229
|
-
|
|
230
|
-
For Example:
|
|
231
|
-
|
|
232
|
-
```js
|
|
233
|
-
import { CourierProvider } from "@trycourier/react-provider";
|
|
234
|
-
import { useElementalInbox } from "@trycourier/react-hooks";
|
|
235
|
-
|
|
236
|
-
const MyInbox = () => {
|
|
237
|
-
const inbox = useElementalInbox();
|
|
238
|
-
|
|
239
|
-
useEffect(() => {
|
|
240
|
-
inbox.fetchMessages();
|
|
241
|
-
}, []);
|
|
242
|
-
|
|
243
|
-
const handleReadMessage = (message) => () => {
|
|
244
|
-
inbox.markMessageRead(message.messageId);
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const handleUnreadMessage = (message) => () => {
|
|
248
|
-
inbox.markMessageUnread(message.messageId);
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
const handleArchiveMessage = (message) => () => {
|
|
252
188
|
inbox.markMessageArchived(message.messageId);
|
|
253
189
|
};
|
|
254
190
|
|
|
@@ -284,98 +220,3 @@ const MyApp = () => {
|
|
|
284
220
|
);
|
|
285
221
|
};
|
|
286
222
|
```
|
|
287
|
-
|
|
288
|
-
#### Elemental Inbox
|
|
289
|
-
|
|
290
|
-
React Hooks exposes two inbox hooks, `useInbox` and `useElementalInbox`. Elemental inbox is a new inbox
|
|
291
|
-
that takes advantage of Courier's content specification, [Elemental](https://www.courier.com/docs/elemental/).
|
|
292
|
-
|
|
293
|
-
Elemental provides a more advanced format for delivered
|
|
294
|
-
notifications. This includes the ability to add customized buttons, images, and markdown formatted text
|
|
295
|
-
to your messages.
|
|
296
|
-
|
|
297
|
-
See [types](#1typesmd) for details on the interface.
|
|
298
|
-
|
|
299
|
-
#### Example Usage
|
|
300
|
-
|
|
301
|
-
```tsx
|
|
302
|
-
import { CourierProvider } from "@trycourier/react-provider";
|
|
303
|
-
import { useElementalInbox } from "@trycourier/react-hooks";
|
|
304
|
-
|
|
305
|
-
const MyApp = () => {
|
|
306
|
-
/**
|
|
307
|
-
* Auth token for courier provider, can be a token from Courier's auth/issue-token endpoint
|
|
308
|
-
* or a JWT signed with a valid courier api key. Must include scope: "user_id:<user_id_here> inbox:read:messages",
|
|
309
|
-
* you must also include the "inbox:write:events" scope if making a write request or mutation as well.
|
|
310
|
-
*
|
|
311
|
-
* For more information on the auth/issue-token endpoint, visit:
|
|
312
|
-
* https://courier.com/docs/reference/auth/intro/
|
|
313
|
-
*/
|
|
314
|
-
const authorization = await fetchAuthToken();
|
|
315
|
-
|
|
316
|
-
return (
|
|
317
|
-
<CourierProvider authorization="abc123" userId="MY_USER_ID">
|
|
318
|
-
<MyInbox />
|
|
319
|
-
</CourierProvider>
|
|
320
|
-
);
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const MyInbox = () => {
|
|
324
|
-
const inbox = useElementalInbox();
|
|
325
|
-
|
|
326
|
-
useEffect(() => {
|
|
327
|
-
inbox.fetchMessages();
|
|
328
|
-
}, []);
|
|
329
|
-
|
|
330
|
-
// Sets message.read to current date
|
|
331
|
-
const handleReadMessage = (message) => () => {
|
|
332
|
-
inbox.markMessageRead(message.messageId);
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
// Removes message.read
|
|
336
|
-
const handleUnreadMessage = (message) => () => {
|
|
337
|
-
inbox.markMessageUnread(message.messageId);
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
// Archived messages are not included in inbox.fetchMessages()
|
|
341
|
-
const handleArchiveMessage = (message) => () => {
|
|
342
|
-
inbox.markMessageArchived(message.messageId);
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
// If the supplied authorization token is short lived, renew the session with a fresh token
|
|
346
|
-
// proactively before the token is set to expire. Here we use 5 minutes assuming our token only
|
|
347
|
-
// lasts 10 minutes
|
|
348
|
-
useEffect(() => {
|
|
349
|
-
const interval = setInterval(async () => {
|
|
350
|
-
const authorization = await fetchAuthToken();
|
|
351
|
-
inbox.renewSession(authorization);
|
|
352
|
-
}, 300000);
|
|
353
|
-
|
|
354
|
-
// Return a cleanup function to tell react how to stop renewal when the component is unmounted.
|
|
355
|
-
return () => clearInterval(interval);
|
|
356
|
-
}, []);
|
|
357
|
-
|
|
358
|
-
return (
|
|
359
|
-
<>
|
|
360
|
-
{inbox.messages.map((message) => {
|
|
361
|
-
return (
|
|
362
|
-
<Message>
|
|
363
|
-
{message.read ? (
|
|
364
|
-
<>
|
|
365
|
-
<button onClick={handleUnreadMessage(message)}>
|
|
366
|
-
Unread Me
|
|
367
|
-
</button>
|
|
368
|
-
<button onClick={handleArchiveMessage(message)}>
|
|
369
|
-
Archive Me
|
|
370
|
-
</button>
|
|
371
|
-
</>
|
|
372
|
-
) : (
|
|
373
|
-
<button onClick={handleReadMessage(message)}>Read Me</button>
|
|
374
|
-
)}
|
|
375
|
-
</Message>
|
|
376
|
-
);
|
|
377
|
-
})}
|
|
378
|
-
</>
|
|
379
|
-
);
|
|
380
|
-
};
|
|
381
|
-
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trycourier/react-hooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1-internal.cbb755c.0+cbb755c",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "typings/index.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"concat-md": "^0.3.5"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@trycourier/client-graphql": "^
|
|
23
|
+
"@trycourier/client-graphql": "^3.0.1-internal.cbb755c.0+cbb755c",
|
|
24
24
|
"deep-extend": "^0.6.0",
|
|
25
25
|
"rimraf": "^3.0.2"
|
|
26
26
|
},
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
".": "./dist/index.js",
|
|
37
37
|
"./use-inbox": "./dist/inbox/use-inbox.js"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "cbb755c5412f69f2ff9f48f2cc0a7cde73c918e9"
|
|
40
40
|
}
|