@linktr.ee/messaging-react 1.8.4 → 1.8.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.8.4",
3
+ "version": "1.8.5",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,6 +13,9 @@ const meta: Meta<ComponentProps> = {
13
13
  layout: 'centered',
14
14
  },
15
15
  decorators: [(Story) => <Story />],
16
+ args: {
17
+ onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
18
+ },
16
19
  }
17
20
  export default meta
18
21
 
@@ -32,6 +35,12 @@ const createMockChannel = (options: {
32
35
  lastMessageText?: string
33
36
  lastMessageTime?: Date
34
37
  unreadCount?: number
38
+ lastMessageAttachments?: Array<{
39
+ asset_url?: string
40
+ image_url?: string
41
+ og_scrape_url?: string
42
+ thumb_url?: string
43
+ }>
35
44
  }): Channel => {
36
45
  const {
37
46
  id,
@@ -41,6 +50,7 @@ const createMockChannel = (options: {
41
50
  lastMessageText = 'Hey! How are you doing?',
42
51
  lastMessageTime = new Date(),
43
52
  unreadCount = 0,
53
+ lastMessageAttachments,
44
54
  } = options
45
55
 
46
56
  return {
@@ -64,19 +74,21 @@ const createMockChannel = (options: {
64
74
  user_id: participantId,
65
75
  },
66
76
  },
67
- messages: lastMessageText
68
- ? ([
69
- {
70
- id: `msg-${id}-1`,
71
- text: lastMessageText,
72
- created_at: lastMessageTime.toISOString(),
73
- user: {
74
- id: participantId,
75
- name: participantName,
77
+ messages:
78
+ lastMessageText || lastMessageAttachments
79
+ ? ([
80
+ {
81
+ id: `msg-${id}-1`,
82
+ text: lastMessageText,
83
+ created_at: lastMessageTime.toISOString(),
84
+ user: {
85
+ id: participantId,
86
+ name: participantName,
87
+ },
88
+ attachments: lastMessageAttachments,
76
89
  },
77
- },
78
- ] as unknown as LocalMessage[])
79
- : ([] as LocalMessage[]),
90
+ ] as unknown as LocalMessage[])
91
+ : ([] as LocalMessage[]),
80
92
  unreadCount,
81
93
  },
82
94
  } as unknown as Channel
@@ -100,7 +112,6 @@ Default.args = {
100
112
  lastMessageText: 'Hey! How are you doing?',
101
113
  lastMessageTime: new Date(),
102
114
  }),
103
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
104
115
  }
105
116
 
106
117
  export const Selected: StoryFn<ComponentProps> = Template.bind({})
@@ -119,7 +130,6 @@ Selected.args = {
119
130
  participantId: 'participant-2',
120
131
  participantImage: 'https://i.pravatar.cc/150?img=3',
121
132
  }),
122
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
123
133
  }
124
134
 
125
135
  export const WithUnreadMessages: StoryFn<ComponentProps> = Template.bind({})
@@ -133,7 +143,6 @@ WithUnreadMessages.args = {
133
143
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 15), // 15 minutes ago
134
144
  unreadCount: 3,
135
145
  }),
136
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
137
146
  }
138
147
 
139
148
  export const ManyUnreadMessages: StoryFn<ComponentProps> = Template.bind({})
@@ -147,7 +156,6 @@ ManyUnreadMessages.args = {
147
156
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60), // 1 hour ago
148
157
  unreadCount: 127,
149
158
  }),
150
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
151
159
  }
152
160
 
153
161
  export const NoAvatar: StoryFn<ComponentProps> = Template.bind({})
@@ -159,7 +167,6 @@ NoAvatar.args = {
159
167
  lastMessageText: 'Thanks for your help!',
160
168
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 30), // 30 minutes ago
161
169
  }),
162
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
163
170
  }
164
171
 
165
172
  export const NoMessages: StoryFn<ComponentProps> = Template.bind({})
@@ -171,7 +178,6 @@ NoMessages.args = {
171
178
  participantImage: 'https://i.pravatar.cc/150?img=6',
172
179
  lastMessageText: '',
173
180
  }),
174
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
175
181
  }
176
182
 
177
183
  export const LongMessage: StoryFn<ComponentProps> = Template.bind({})
@@ -185,7 +191,6 @@ LongMessage.args = {
185
191
  'This is a very long message that should be truncated because it contains way too much text to display in the preview. We want to make sure the component handles this gracefully.',
186
192
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 2), // 2 hours ago
187
193
  }),
188
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
189
194
  }
190
195
 
191
196
  export const LongName: StoryFn<ComponentProps> = Template.bind({})
@@ -197,7 +202,6 @@ LongName.args = {
197
202
  lastMessageText: 'Nice to meet you!',
198
203
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 45), // 45 minutes ago
199
204
  }),
200
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
201
205
  }
202
206
 
203
207
  export const SelectedWithUnread: StoryFn<ComponentProps> = Template.bind({})
@@ -216,7 +220,6 @@ SelectedWithUnread.args = {
216
220
  participantName: 'Helen Park',
217
221
  participantId: 'participant-9',
218
222
  }),
219
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
220
223
  }
221
224
 
222
225
  export const MultipleChannels: StoryFn = () => {
@@ -289,7 +292,6 @@ WithUrl.args = {
289
292
  lastMessageText: 'https://example.com/page',
290
293
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 8), // 8 minutes ago
291
294
  }),
292
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
293
295
  }
294
296
 
295
297
  export const WithVeryLongUrl: StoryFn<ComponentProps> = Template.bind({})
@@ -303,7 +305,6 @@ WithVeryLongUrl.args = {
303
305
  'https://example.com/very/long/path/with/many/segments/and/query/parameters?param1=value1&param2=value2&param3=value3&param4=value4&param5=very-long-value-that-makes-the-url-extremely-long',
304
306
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 20), // 20 minutes ago
305
307
  }),
306
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
307
308
  }
308
309
 
309
310
  // Time-based stories
@@ -317,7 +318,6 @@ JustNow.args = {
317
318
  lastMessageText: 'I just sent this!',
318
319
  lastMessageTime: new Date(Date.now() - 1000 * 30), // 30 seconds ago
319
320
  }),
320
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
321
321
  }
322
322
 
323
323
  export const FiveMinutesAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -330,7 +330,6 @@ FiveMinutesAgo.args = {
330
330
  lastMessageText: 'Be right back',
331
331
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 5), // 5 minutes ago
332
332
  }),
333
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
334
333
  }
335
334
 
336
335
  export const ThreeHoursAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -343,7 +342,6 @@ ThreeHoursAgo.args = {
343
342
  lastMessageText: 'Got it, thanks!',
344
343
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 3), // 3 hours ago
345
344
  }),
346
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
347
345
  }
348
346
 
349
347
  export const Yesterday: StoryFn<ComponentProps> = Template.bind({})
@@ -356,7 +354,6 @@ Yesterday.args = {
356
354
  lastMessageText: 'See you tomorrow',
357
355
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 30), // 30 hours ago
358
356
  }),
359
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
360
357
  }
361
358
 
362
359
  export const ThreeDaysAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -369,7 +366,6 @@ ThreeDaysAgo.args = {
369
366
  lastMessageText: 'Have a great weekend!',
370
367
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3), // 3 days ago
371
368
  }),
372
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
373
369
  }
374
370
 
375
371
  export const LastWeek: StoryFn<ComponentProps> = Template.bind({})
@@ -382,7 +378,6 @@ LastWeek.args = {
382
378
  lastMessageText: 'Talk to you next week',
383
379
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7), // 1 week ago
384
380
  }),
385
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
386
381
  }
387
382
 
388
383
  export const TwoWeeksAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -395,7 +390,6 @@ TwoWeeksAgo.args = {
395
390
  lastMessageText: 'Sounds good',
396
391
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 24 * 14), // 2 weeks ago
397
392
  }),
398
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
399
393
  }
400
394
 
401
395
  export const OneMonthAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -408,7 +402,6 @@ OneMonthAgo.args = {
408
402
  lastMessageText: 'Happy New Year!',
409
403
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 24 * 30), // 1 month ago
410
404
  }),
411
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
412
405
  }
413
406
 
414
407
  export const SixMonthsAgo: StoryFn<ComponentProps> = Template.bind({})
@@ -421,7 +414,6 @@ SixMonthsAgo.args = {
421
414
  lastMessageText: 'Long time no talk!',
422
415
  lastMessageTime: new Date(Date.now() - 1000 * 60 * 60 * 24 * 180), // 6 months ago
423
416
  }),
424
- onChannelSelect: (channel) => console.log('Channel selected:', channel.id),
425
417
  }
426
418
 
427
419
  export const TimeVariations: StoryFn = () => {
@@ -521,3 +513,92 @@ export const TimeVariations: StoryFn = () => {
521
513
  </div>
522
514
  )
523
515
  }
516
+
517
+ // Message text fallback stories
518
+ export const WithAttachmentAssetUrl: StoryFn<ComponentProps> = Template.bind({})
519
+ WithAttachmentAssetUrl.args = {
520
+ channel: createMockChannel({
521
+ id: 'channel-attachment-asset',
522
+ participantName: 'Tom Wilson',
523
+ participantId: 'participant-attachment-asset',
524
+ participantImage: 'https://i.pravatar.cc/150?img=30',
525
+ lastMessageText: '', // No text, only attachment
526
+ lastMessageTime: new Date(Date.now() - 1000 * 60 * 10), // 10 minutes ago
527
+ lastMessageAttachments: [
528
+ {
529
+ asset_url: 'https://example.com/document.pdf',
530
+ },
531
+ ],
532
+ }),
533
+ }
534
+
535
+ export const WithAttachmentImageUrl: StoryFn<ComponentProps> = Template.bind({})
536
+ WithAttachmentImageUrl.args = {
537
+ channel: createMockChannel({
538
+ id: 'channel-attachment-image',
539
+ participantName: 'Uma Patel',
540
+ participantId: 'participant-attachment-image',
541
+ participantImage: 'https://i.pravatar.cc/150?img=31',
542
+ lastMessageText: '', // No text, only attachment
543
+ lastMessageTime: new Date(Date.now() - 1000 * 60 * 15), // 15 minutes ago
544
+ lastMessageAttachments: [
545
+ {
546
+ image_url: 'https://example.com/image.jpg',
547
+ },
548
+ ],
549
+ }),
550
+ }
551
+
552
+ export const WithAttachmentOgScrapeUrl: StoryFn<ComponentProps> = Template.bind(
553
+ {}
554
+ )
555
+ WithAttachmentOgScrapeUrl.args = {
556
+ channel: createMockChannel({
557
+ id: 'channel-attachment-og',
558
+ participantName: 'Victor Zhang',
559
+ participantId: 'participant-attachment-og',
560
+ participantImage: 'https://i.pravatar.cc/150?img=32',
561
+ lastMessageText: '', // No text, only attachment
562
+ lastMessageTime: new Date(Date.now() - 1000 * 60 * 7), // 7 minutes ago
563
+ lastMessageAttachments: [
564
+ {
565
+ og_scrape_url: 'https://example.com/article',
566
+ },
567
+ ],
568
+ }),
569
+ }
570
+
571
+ export const WithAttachmentThumbUrl: StoryFn<ComponentProps> = Template.bind({})
572
+ WithAttachmentThumbUrl.args = {
573
+ channel: createMockChannel({
574
+ id: 'channel-attachment-thumb',
575
+ participantName: 'Wendy Kim',
576
+ participantId: 'participant-attachment-thumb',
577
+ participantImage: 'https://i.pravatar.cc/150?img=33',
578
+ lastMessageText: '', // No text, only attachment
579
+ lastMessageTime: new Date(Date.now() - 1000 * 60 * 12), // 12 minutes ago
580
+ lastMessageAttachments: [
581
+ {
582
+ thumb_url: 'https://example.com/thumb.jpg',
583
+ },
584
+ ],
585
+ }),
586
+ }
587
+
588
+ export const WithLongAttachmentUrl: StoryFn<ComponentProps> = Template.bind({})
589
+ WithLongAttachmentUrl.args = {
590
+ channel: createMockChannel({
591
+ id: 'channel-attachment-long',
592
+ participantName: 'Xavier Cruz',
593
+ participantId: 'participant-attachment-long',
594
+ participantImage: 'https://i.pravatar.cc/150?img=34',
595
+ lastMessageText: '', // No text, only attachment
596
+ lastMessageTime: new Date(Date.now() - 1000 * 60 * 20), // 20 minutes ago
597
+ lastMessageAttachments: [
598
+ {
599
+ asset_url:
600
+ 'https://example.com/very/long/path/to/file/with/many/segments/document-with-very-long-name-that-should-be-truncated.pdf',
601
+ },
602
+ ],
603
+ }),
604
+ }
@@ -35,7 +35,21 @@ const CustomChannelPreview: React.FC<
35
35
  // Get last message and format timestamp
36
36
  const lastMessage =
37
37
  channel?.state?.messages?.[channel.state.messages.length - 1]
38
- const lastMessageText = lastMessage?.text || 'No messages yet'
38
+
39
+ // Fallback order: text -> attachment URL -> "No messages yet"
40
+ const getLastMessageText = () => {
41
+ if (lastMessage?.text) return lastMessage.text
42
+
43
+ const attachment = lastMessage?.attachments?.[0]
44
+ if (attachment?.asset_url) return attachment.asset_url
45
+ if (attachment?.image_url) return attachment.image_url
46
+ if (attachment?.og_scrape_url) return attachment.og_scrape_url
47
+ if (attachment?.thumb_url) return attachment.thumb_url
48
+
49
+ return 'No messages yet'
50
+ }
51
+
52
+ const lastMessageText = getLastMessageText()
39
53
  const lastMessageTime = lastMessage?.created_at
40
54
  ? formatRelativeTime(new Date(lastMessage.created_at))
41
55
  : ''