@linktr.ee/messaging-react 3.31.0-rc-1785485102 → 3.31.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/dist/{Card-2l_y20FM.js → Card-CmlaSw7i.js} +2 -2
- package/dist/{Card-2l_y20FM.js.map → Card-CmlaSw7i.js.map} +1 -1
- package/dist/{Card-Gr4HDVbn.cjs → Card-EWN07XIl.cjs} +2 -2
- package/dist/{Card-Gr4HDVbn.cjs.map → Card-EWN07XIl.cjs.map} +1 -1
- package/dist/assets/index.css +1 -1
- package/dist/{index-B96WLmx6.js → index-CN3errpB.js} +3055 -3109
- package/dist/index-CN3errpB.js.map +1 -0
- package/dist/index-CcitzVoW.cjs +5 -0
- package/dist/index-CcitzVoW.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +56 -60
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/components/ChannelView.broadcast-name.integration.test.tsx +116 -0
- package/src/components/ChannelView.tsx +17 -3
- package/src/components/CustomLinkPreviewList/CustomLinkPreviewList.test.tsx +15 -0
- package/src/components/CustomLinkPreviewList/index.tsx +24 -26
- package/src/components/CustomMessage/BroadcastNameContext.test.ts +43 -0
- package/src/components/CustomMessage/BroadcastNameContext.ts +95 -0
- package/src/components/CustomMessage/CustomMessage.stories.tsx +54 -22
- package/src/components/CustomMessage/CustomMessage.test.tsx +48 -0
- package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +62 -0
- package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +8 -2
- package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +0 -33
- package/src/components/CustomMessage/StreamAttachmentMessage.tsx +0 -8
- package/src/components/CustomMessage/index.tsx +23 -3
- package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +50 -2
- package/src/components/CustomMessageInput/CustomMessageInput.test.tsx +180 -2
- package/src/components/CustomMessageInput/index.tsx +143 -16
- package/src/components/MessageAttachment/Audio/AudioAttachment.stories.tsx +57 -166
- package/src/components/MessageAttachment/Audio/index.tsx +77 -71
- package/src/components/MessageAttachment/MessageAttachment.test.tsx +75 -175
- package/src/components/MessageAttachment/index.tsx +9 -25
- package/src/components/MessageAttachment/types.ts +9 -19
- package/src/components/MessagingShell/index.tsx +2 -0
- package/src/index.ts +1 -0
- package/src/styles.css +5 -120
- package/src/types.ts +11 -0
- package/src/utils/formatRelativeTime.test.ts +63 -57
- package/src/utils/formatRelativeTime.ts +21 -20
- package/dist/index-B96WLmx6.js.map +0 -1
- package/dist/index-CCtHMrmO.cjs +0 -5
- package/dist/index-CCtHMrmO.cjs.map +0 -1
- package/src/components/MessageAttachment/Audio/WaveformAudioRow.tsx +0 -335
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { formatRelativeTime } from './formatRelativeTime'
|
|
2
2
|
|
|
3
|
+
// Date strings deliberately omit the trailing 'Z' so they parse in the
|
|
4
|
+
// runner's local timezone — formatRelativeTime buckets by local calendar
|
|
5
|
+
// days, so this keeps assertions deterministic regardless of ambient TZ.
|
|
3
6
|
describe('formatRelativeTime', () => {
|
|
4
7
|
let originalDate: typeof Date
|
|
5
8
|
|
|
@@ -35,16 +38,16 @@ describe('formatRelativeTime', () => {
|
|
|
35
38
|
|
|
36
39
|
describe('Just now', () => {
|
|
37
40
|
it('should return "Just now" for messages less than 1 minute ago', () => {
|
|
38
|
-
mockDate('2024-01-15T12:00:
|
|
39
|
-
const date = new Date('2024-01-15T11:59:
|
|
41
|
+
mockDate('2024-01-15T12:00:00')
|
|
42
|
+
const date = new Date('2024-01-15T11:59:30') // 30 seconds ago
|
|
40
43
|
expect(formatRelativeTime(date)).toBe('Just now')
|
|
41
44
|
})
|
|
42
45
|
})
|
|
43
46
|
|
|
44
47
|
describe('Today', () => {
|
|
45
48
|
it('should return time in 12-hour format for messages from earlier today', () => {
|
|
46
|
-
mockDate('2024-01-15T14:08:
|
|
47
|
-
const date = new Date('2024-01-15T09:30:
|
|
49
|
+
mockDate('2024-01-15T14:08:00')
|
|
50
|
+
const date = new Date('2024-01-15T09:30:00')
|
|
48
51
|
const result = formatRelativeTime(date)
|
|
49
52
|
// Should be "9:30 AM" format
|
|
50
53
|
expect(result).toMatch(/^\d{1,2}:\d{2} (AM|PM)$/i)
|
|
@@ -53,93 +56,96 @@ describe('formatRelativeTime', () => {
|
|
|
53
56
|
|
|
54
57
|
describe('Yesterday', () => {
|
|
55
58
|
it('should return "Yesterday" for messages from the previous calendar day', () => {
|
|
56
|
-
mockDate('2024-01-15T12:00:
|
|
57
|
-
const date = new Date('2024-01-14T12:00:
|
|
59
|
+
mockDate('2024-01-15T12:00:00')
|
|
60
|
+
const date = new Date('2024-01-14T12:00:00')
|
|
58
61
|
expect(formatRelativeTime(date)).toBe('Yesterday')
|
|
59
62
|
})
|
|
60
63
|
|
|
61
64
|
it('should return "Yesterday" even if less than 24 hours ago but previous day', () => {
|
|
62
|
-
mockDate('2024-01-15T01:00:
|
|
63
|
-
const date = new Date('2024-01-14T23:00:
|
|
65
|
+
mockDate('2024-01-15T01:00:00')
|
|
66
|
+
const date = new Date('2024-01-14T23:00:00') // Only 2 hours ago
|
|
64
67
|
expect(formatRelativeTime(date)).toBe('Yesterday')
|
|
65
68
|
})
|
|
66
69
|
|
|
67
70
|
it('should NOT return "Yesterday" for messages from 2 days ago', () => {
|
|
68
|
-
mockDate('2024-01-15T12:00:
|
|
69
|
-
const date = new Date('2024-01-13T12:00:
|
|
71
|
+
mockDate('2024-01-15T12:00:00')
|
|
72
|
+
const date = new Date('2024-01-13T12:00:00')
|
|
70
73
|
expect(formatRelativeTime(date)).not.toBe('Yesterday')
|
|
71
|
-
expect(formatRelativeTime(date)).toBe('2d')
|
|
72
74
|
})
|
|
73
75
|
})
|
|
74
76
|
|
|
75
|
-
describe('
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
describe('2-6 days ago (short weekday)', () => {
|
|
78
|
+
// The weekday branch uses the runtime locale
|
|
79
|
+
// (toLocaleDateString(undefined, …)), so assertions compare against
|
|
80
|
+
// the same locale-aware formatter rather than fixed English strings.
|
|
81
|
+
it('should return a short weekday name for messages 2 days ago', () => {
|
|
82
|
+
mockDate('2024-01-15T12:00:00')
|
|
83
|
+
const date = new Date('2024-01-13T12:00:00') // Saturday
|
|
84
|
+
expect(formatRelativeTime(date)).toBe(
|
|
85
|
+
date.toLocaleDateString(undefined, { weekday: 'short' })
|
|
86
|
+
)
|
|
80
87
|
})
|
|
81
88
|
|
|
82
|
-
it('should return
|
|
83
|
-
mockDate('2024-01-15T12:00:
|
|
84
|
-
const date = new Date('2024-01-09T12:00:
|
|
85
|
-
expect(formatRelativeTime(date)).toBe(
|
|
89
|
+
it('should return a short weekday name for messages 6 days ago (boundary before dates)', () => {
|
|
90
|
+
mockDate('2024-01-15T12:00:00')
|
|
91
|
+
const date = new Date('2024-01-09T12:00:00') // Tuesday
|
|
92
|
+
expect(formatRelativeTime(date)).toBe(
|
|
93
|
+
date.toLocaleDateString(undefined, { weekday: 'short' })
|
|
94
|
+
)
|
|
86
95
|
})
|
|
87
96
|
})
|
|
88
97
|
|
|
89
|
-
describe('
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
describe('7+ days ago, same year (month and day)', () => {
|
|
99
|
+
// Compare against the same locale-aware formatter rather than
|
|
100
|
+
// hard-coded digits, which would fail under non-Latin numbering
|
|
101
|
+
// systems (e.g. ar_EG renders "٨ يناير").
|
|
102
|
+
it('should return month + day without year for messages 7 days ago', () => {
|
|
103
|
+
mockDate('2024-01-15T12:00:00')
|
|
104
|
+
const date = new Date('2024-01-08T12:00:00')
|
|
105
|
+
expect(formatRelativeTime(date)).toBe(
|
|
106
|
+
date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
|
|
107
|
+
)
|
|
94
108
|
})
|
|
95
|
-
})
|
|
96
109
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// day and 2-digit year in any order.
|
|
104
|
-
const numericDatePattern = /^\d{1,2}\/\d{1,2}\/\d{2}$/
|
|
105
|
-
|
|
106
|
-
it('should return a spelled-month date for messages more than 4 weeks ago', () => {
|
|
107
|
-
mockDate('2024-02-15T12:00:00Z')
|
|
108
|
-
const date = new Date('2024-01-01T12:00:00Z')
|
|
109
|
-
const result = formatRelativeTime(date)
|
|
110
|
-
expect(result).not.toMatch(numericDatePattern)
|
|
111
|
-
expect(result).toMatch(/\p{L}/u) // spelled-out month
|
|
112
|
-
expect(result).toMatch(/\b1\b/) // day
|
|
113
|
-
expect(result).toMatch(/24/) // 2-digit year
|
|
110
|
+
it('should return month + day without year for messages more than 4 weeks ago in the same year', () => {
|
|
111
|
+
mockDate('2024-02-15T12:00:00')
|
|
112
|
+
const date = new Date('2024-01-01T12:00:00')
|
|
113
|
+
expect(formatRelativeTime(date)).toBe(
|
|
114
|
+
date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
|
|
115
|
+
)
|
|
114
116
|
})
|
|
117
|
+
})
|
|
115
118
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
expect(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
describe('Previous years (month, day and year)', () => {
|
|
120
|
+
it('should include the year for messages from a previous year', () => {
|
|
121
|
+
mockDate('2024-01-15T12:00:00')
|
|
122
|
+
const date = new Date('2023-12-01T12:00:00')
|
|
123
|
+
expect(formatRelativeTime(date)).toBe(
|
|
124
|
+
date.toLocaleDateString(undefined, {
|
|
125
|
+
month: 'short',
|
|
126
|
+
day: 'numeric',
|
|
127
|
+
year: 'numeric',
|
|
128
|
+
})
|
|
129
|
+
)
|
|
124
130
|
})
|
|
125
131
|
})
|
|
126
132
|
|
|
127
133
|
describe('Edge cases', () => {
|
|
128
134
|
it('should handle month boundaries correctly', () => {
|
|
129
|
-
mockDate('2024-02-01T12:00:
|
|
130
|
-
const date = new Date('2024-01-31T12:00:
|
|
135
|
+
mockDate('2024-02-01T12:00:00')
|
|
136
|
+
const date = new Date('2024-01-31T12:00:00')
|
|
131
137
|
expect(formatRelativeTime(date)).toBe('Yesterday')
|
|
132
138
|
})
|
|
133
139
|
|
|
134
140
|
it('should handle year boundaries correctly', () => {
|
|
135
|
-
mockDate('2024-01-01T12:00:
|
|
136
|
-
const date = new Date('2023-12-31T12:00:
|
|
141
|
+
mockDate('2024-01-01T12:00:00')
|
|
142
|
+
const date = new Date('2023-12-31T12:00:00')
|
|
137
143
|
expect(formatRelativeTime(date)).toBe('Yesterday')
|
|
138
144
|
})
|
|
139
145
|
|
|
140
146
|
it('should handle leap year correctly', () => {
|
|
141
|
-
mockDate('2024-03-01T12:00:
|
|
142
|
-
const date = new Date('2024-02-29T12:00:
|
|
147
|
+
mockDate('2024-03-01T12:00:00')
|
|
148
|
+
const date = new Date('2024-02-29T12:00:00')
|
|
143
149
|
expect(formatRelativeTime(date)).toBe('Yesterday')
|
|
144
150
|
})
|
|
145
151
|
})
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Get the number of days between two dates (calendar days in
|
|
3
|
-
*
|
|
2
|
+
* Get the number of days between two dates (calendar days in the viewer's
|
|
3
|
+
* local timezone, not 24-hour periods). Uses local days so the bucket a
|
|
4
|
+
* message falls into always agrees with the locale-formatted output
|
|
5
|
+
* (time of day, weekday name, date), which is also rendered in local time.
|
|
4
6
|
*/
|
|
5
7
|
const getDaysDifference = (date1: Date, date2: Date): number => {
|
|
6
|
-
const d1 =
|
|
7
|
-
|
|
8
|
-
)
|
|
9
|
-
const d2 = new Date(
|
|
10
|
-
Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())
|
|
11
|
-
)
|
|
12
|
-
const diffTime = d2.getTime() - d1.getTime()
|
|
13
|
-
return Math.floor(diffTime / (1000 * 60 * 60 * 24))
|
|
8
|
+
const d1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate())
|
|
9
|
+
const d2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate())
|
|
10
|
+
return Math.floor((d2 - d1) / (1000 * 60 * 60 * 24))
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* Format a date - shows time for today, relative time for older messages
|
|
18
|
-
* (e.g., "Just now", "2:08 PM" for today, "Yesterday" for yesterday,
|
|
15
|
+
* (e.g., "Just now", "2:08 PM" for today, "Yesterday" for yesterday,
|
|
16
|
+
* "Mon" for 2-6 days ago, "Jul 14" for older dates this year,
|
|
17
|
+
* "Jul 14, 2025" for previous years)
|
|
19
18
|
*/
|
|
20
19
|
export const formatRelativeTime = (date: Date): string => {
|
|
21
20
|
const now = new Date()
|
|
@@ -43,21 +42,23 @@ export const formatRelativeTime = (date: Date): string => {
|
|
|
43
42
|
return 'Yesterday'
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
//
|
|
45
|
+
// 2-6 days ago - show short weekday name (e.g., "Mon")
|
|
47
46
|
if (daysDiff < 7) {
|
|
48
|
-
return
|
|
47
|
+
return date.toLocaleDateString(undefined, { weekday: 'short' })
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
//
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
// 7+ days ago, same local year - show month and day (e.g., "Jul 14")
|
|
51
|
+
if (date.getFullYear() === now.getFullYear()) {
|
|
52
|
+
return date.toLocaleDateString(undefined, {
|
|
53
|
+
month: 'short',
|
|
54
|
+
day: 'numeric',
|
|
55
|
+
})
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
//
|
|
58
|
+
// Previous years - include the year (e.g., "Jul 14, 2025")
|
|
58
59
|
return date.toLocaleDateString(undefined, {
|
|
59
|
-
day: 'numeric',
|
|
60
60
|
month: 'short',
|
|
61
|
-
|
|
61
|
+
day: 'numeric',
|
|
62
|
+
year: 'numeric',
|
|
62
63
|
})
|
|
63
64
|
}
|