@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.
Files changed (2) hide show
  1. package/README.md +99 -258
  2. 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
- ### [Overview](#overview)
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
- ### [Types](#types)
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 IMessage {
28
- blocks?: Array<IActionBlock | ITextBlock>;
29
- body: string;
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
- read?: boolean;
37
- title: string;
38
- trackingIds?: {
39
- archiveTrackingId: string;
40
- clickTrackingId: string;
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
- markMessageRead: (messageId: string, trackingId: string) => Promise<void>;
54
- markMessageUnread: (messageId: string, trackingId: string) => Promise<void>;
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<IMessage>;
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
- ### [Events](#events)
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
- #### Manually calling events (`useInbox` Example)
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": "2.0.2-internal.9773702.0+9773702",
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": "^2.0.2-internal.9773702.0+9773702",
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": "97737026b3763f1e3686b12e74cb9c32795a07d6"
39
+ "gitHead": "cbb755c5412f69f2ff9f48f2cc0a7cde73c918e9"
40
40
  }