@linktr.ee/messaging-react 3.17.0-rc-1785345258 → 3.17.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-Cyp6T66U.cjs → Card-D7OY-zlB.cjs} +2 -2
- package/dist/{Card-Cyp6T66U.cjs.map → Card-D7OY-zlB.cjs.map} +1 -1
- package/dist/{Card-DDZI9ZIj.js → Card-DkW8wedR.js} +2 -2
- package/dist/{Card-DDZI9ZIj.js.map → Card-DkW8wedR.js.map} +1 -1
- package/dist/assets/index.css +1 -1
- package/dist/index-BFZ-G_jg.cjs +2 -0
- package/dist/index-BFZ-G_jg.cjs.map +1 -0
- package/dist/{index-DskHxSVN.js → index-CxGxAIhL.js} +1568 -1527
- package/dist/index-CxGxAIhL.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -14
- package/dist/index.js +1 -1
- package/dist/testing.d.ts +1 -3
- package/package.json +2 -2
- package/src/components/ChannelView.tsx +1 -6
- package/src/components/CustomMessage/CustomMessage.stories.tsx +0 -40
- package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +4 -76
- package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +7 -75
- package/src/components/CustomMessage/index.tsx +1 -4
- package/src/components/MessageAttachment/Image/ImageAttachment.stories.tsx +77 -0
- package/src/components/MessageAttachment/Image/index.tsx +117 -8
- package/src/components/MessageAttachment/MessageAttachment.test.tsx +177 -0
- package/src/components/MessageAttachment/Video/index.tsx +1 -5
- package/src/components/MessageAttachment/_shared/Bubble.tsx +40 -7
- package/src/components/MessageAttachment/_shared/ImageViewer.tsx +25 -16
- package/src/components/MessageAttachment/_shared/MediaStackGrid.tsx +105 -7
- package/src/components/MessagingShell/index.tsx +0 -2
- package/src/index.ts +0 -1
- package/src/stream-custom-data.ts +0 -3
- package/src/styles.css +5 -48
- package/src/types.ts +0 -12
- package/dist/index-DBjALsli.cjs +0 -2
- package/dist/index-DBjALsli.cjs.map +0 -1
- package/dist/index-DskHxSVN.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BFZ-G_jg.cjs");exports.ActionButton=e.ActionButton;exports.Avatar=e.Avatar;exports.ChannelEmptyState=e.ChannelEmptyState;exports.ChannelList=e.ChannelList;exports.ChannelView=e.ChannelView;exports.CustomMessageProvider=e.CustomMessageProvider;exports.FaqList=e.FaqList;exports.FaqListItem=e.FaqListItem;exports.LinkAttachment=e.LinkAttachment;exports.LockedAttachment=e.LockedAttachment;exports.MediaMessage=e.MediaMessage;exports.MessageAttachment=e.MessageAttachment;exports.MessageBubble=e.MessageBubble;exports.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.optimizeMessagingAttachmentUrl=e.optimizeMessagingAttachmentUrl;exports.resolveConversationParticipant=e.resolveConversationParticipant;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useComposerLocked=e.useComposerLocked;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -83,11 +83,6 @@ export declare interface AvatarProps {
|
|
|
83
83
|
dmAgentEnabled?: boolean;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export declare type BroadcastClickHandler = (broadcast: {
|
|
87
|
-
id: string;
|
|
88
|
-
name?: string;
|
|
89
|
-
}) => void;
|
|
90
|
-
|
|
91
86
|
/**
|
|
92
87
|
* Build the meta line shown under the title in compact document / file
|
|
93
88
|
* attachments — `EXT · SIZE` (`PDF · 379.5 KB`). Either part is dropped
|
|
@@ -211,7 +206,7 @@ export declare const ChannelView: default_2.NamedExoticComponent<ChannelViewProp
|
|
|
211
206
|
* Props that MessagingShell passes through to ChannelView.
|
|
212
207
|
* ChannelViewProps is the source of truth for these props.
|
|
213
208
|
*/
|
|
214
|
-
declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | '
|
|
209
|
+
declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'showChannelInfo' | 'composerInput'>;
|
|
215
210
|
|
|
216
211
|
/**
|
|
217
212
|
* ChannelView component props
|
|
@@ -397,11 +392,6 @@ export declare interface ChannelViewProps {
|
|
|
397
392
|
* onMessageLinkClick={(url) => trackChannelLinkClicked(url)}
|
|
398
393
|
*/
|
|
399
394
|
onMessageLinkClick?: MessageLinkClickHandler;
|
|
400
|
-
/**
|
|
401
|
-
* Fired when a broadcast label is clicked on an outgoing broadcast message.
|
|
402
|
-
* Hosts own navigation so this shared package never assumes an admin URL.
|
|
403
|
-
*/
|
|
404
|
-
onBroadcastClick?: BroadcastClickHandler;
|
|
405
395
|
/**
|
|
406
396
|
* Passed to Stream `Channel` as `SendButton`. Required for hosts that replace
|
|
407
397
|
* the send control: `Channel` merges this into `ComponentContext` and an
|
|
@@ -1299,7 +1289,7 @@ export declare interface MessageBubbleBaseProps {
|
|
|
1299
1289
|
*/
|
|
1300
1290
|
export declare type MessageBubbleVariant = 'sent' | 'received';
|
|
1301
1291
|
|
|
1302
|
-
declare type MessageCustomType = 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT' | '
|
|
1292
|
+
declare type MessageCustomType = 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT' | 'MESSAGE_ATTACHMENT' | AgeSafetySystemType | EscalationSystemType | DmAgentSystemType;
|
|
1303
1293
|
|
|
1304
1294
|
/**
|
|
1305
1295
|
* Callback invoked when a user clicks a link inside the channel view.
|
|
@@ -1330,8 +1320,6 @@ export declare interface MessageMetadata {
|
|
|
1330
1320
|
* `custom_type` — it identifies the send context, not the message kind. (MES-1266)
|
|
1331
1321
|
*/
|
|
1332
1322
|
sent_from?: 'stack_detail';
|
|
1333
|
-
broadcast_id?: string;
|
|
1334
|
-
broadcast_name?: string;
|
|
1335
1323
|
}
|
|
1336
1324
|
|
|
1337
1325
|
export declare const MessageVoteButtons: default_2.FC<MessageVoteButtonsProps>;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as c, i as u, j as L, k as h, l as p, m as d, n as v, p as C, q as A, s as k, t as F, u as b, v as P, w as f, x, o as y, y as z, z as B, B as S, D as q, E as D, G as E, H as V, I as w } from "./index-
|
|
1
|
+
import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as c, i as u, j as L, k as h, l as p, m as d, n as v, p as C, q as A, s as k, t as F, u as b, v as P, w as f, x, o as y, y as z, z as B, B as S, D as q, E as D, G as E, H as V, I as w } from "./index-CxGxAIhL.js";
|
|
2
2
|
export {
|
|
3
3
|
e as ActionButton,
|
|
4
4
|
t as Avatar,
|
package/dist/testing.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ declare type DmAgentSystemType = 'SYSTEM_DM_AGENT_PAUSED' | 'SYSTEM_DM_AGENT_RES
|
|
|
41
41
|
|
|
42
42
|
declare type EscalationSystemType = 'SYSTEM_ESCALATION';
|
|
43
43
|
|
|
44
|
-
declare type MessageCustomType = 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT' | '
|
|
44
|
+
declare type MessageCustomType = 'MESSAGE_TIP' | 'MESSAGE_PAID' | 'MESSAGE_CHATBOT' | 'MESSAGE_ATTACHMENT' | AgeSafetySystemType | EscalationSystemType | DmAgentSystemType;
|
|
45
45
|
|
|
46
46
|
export declare interface MessageMetadata {
|
|
47
47
|
custom_type?: MessageCustomType;
|
|
@@ -62,8 +62,6 @@ export declare interface MessageMetadata {
|
|
|
62
62
|
* `custom_type` — it identifies the send context, not the message kind. (MES-1266)
|
|
63
63
|
*/
|
|
64
64
|
sent_from?: 'stack_detail';
|
|
65
|
-
broadcast_id?: string;
|
|
66
|
-
broadcast_name?: string;
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "3.17.0
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "React messaging components built on messaging-core for web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@linktr.ee/component-library": "11.8.6",
|
|
53
|
-
"@linktr.ee/messaging-core": "2.
|
|
53
|
+
"@linktr.ee/messaging-core": "^2.2.0",
|
|
54
54
|
"@phosphor-icons/react": "^2.1.10"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
@@ -56,7 +56,6 @@ const ChannelViewInner: React.FC<{
|
|
|
56
56
|
viewerLanguage?: string
|
|
57
57
|
showChannelInfo?: boolean
|
|
58
58
|
onParticipantNameClick?: () => void
|
|
59
|
-
onBroadcastClick?: ChannelViewProps['onBroadcastClick']
|
|
60
59
|
composerInput?: ChannelViewProps['composerInput']
|
|
61
60
|
}> = ({
|
|
62
61
|
onBack,
|
|
@@ -83,7 +82,6 @@ const ChannelViewInner: React.FC<{
|
|
|
83
82
|
viewerLanguage,
|
|
84
83
|
showChannelInfo = true,
|
|
85
84
|
onParticipantNameClick,
|
|
86
|
-
onBroadcastClick,
|
|
87
85
|
composerInput,
|
|
88
86
|
}) => {
|
|
89
87
|
const { channel } = useChannelStateContext()
|
|
@@ -127,7 +125,6 @@ const ChannelViewInner: React.FC<{
|
|
|
127
125
|
{...props}
|
|
128
126
|
chatbotVotingEnabled={chatbotVotingEnabled}
|
|
129
127
|
viewerLanguage={viewerLanguage}
|
|
130
|
-
onBroadcastClick={onBroadcastClick}
|
|
131
128
|
/>
|
|
132
129
|
)
|
|
133
130
|
|
|
@@ -137,7 +134,7 @@ const ChannelViewInner: React.FC<{
|
|
|
137
134
|
|
|
138
135
|
return renderMessage(messageNode, message)
|
|
139
136
|
},
|
|
140
|
-
[chatbotVotingEnabled,
|
|
137
|
+
[chatbotVotingEnabled, renderMessage, viewerLanguage]
|
|
141
138
|
)
|
|
142
139
|
|
|
143
140
|
return (
|
|
@@ -295,7 +292,6 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
295
292
|
viewerLanguage,
|
|
296
293
|
showChannelInfo = true,
|
|
297
294
|
onParticipantNameClick,
|
|
298
|
-
onBroadcastClick,
|
|
299
295
|
composerInput,
|
|
300
296
|
}) => {
|
|
301
297
|
// Custom send message handler that:
|
|
@@ -409,7 +405,6 @@ export const ChannelView = React.memo<ChannelViewProps>(
|
|
|
409
405
|
viewerLanguage={viewerLanguage}
|
|
410
406
|
showChannelInfo={showChannelInfo}
|
|
411
407
|
onParticipantNameClick={onParticipantNameClick}
|
|
412
|
-
onBroadcastClick={onBroadcastClick}
|
|
413
408
|
composerInput={composerInput}
|
|
414
409
|
/>
|
|
415
410
|
</Channel>
|
|
@@ -120,7 +120,6 @@ interface TemplateProps {
|
|
|
120
120
|
| 'MESSAGE_PAID'
|
|
121
121
|
| 'MESSAGE_CHATBOT'
|
|
122
122
|
| 'MESSAGE_ATTACHMENT'
|
|
123
|
-
| 'MESSAGE_OUTBOUND'
|
|
124
123
|
payment_status?: 'pending' | 'paid' | 'failed' | 'refunded'
|
|
125
124
|
amount_text?: string
|
|
126
125
|
attachment_title?: string
|
|
@@ -128,8 +127,6 @@ interface TemplateProps {
|
|
|
128
127
|
attachment_thumbnail?: string
|
|
129
128
|
attachment_detail?: string
|
|
130
129
|
attachment_content_type?: 'text' | 'media'
|
|
131
|
-
broadcast_id?: string
|
|
132
|
-
broadcast_name?: string
|
|
133
130
|
}
|
|
134
131
|
}>
|
|
135
132
|
}
|
|
@@ -260,43 +257,6 @@ DeliveredStatus.args = {
|
|
|
260
257
|
],
|
|
261
258
|
}
|
|
262
259
|
|
|
263
|
-
export const BroadcastStatus: StoryFn<TemplateProps> = Template.bind({})
|
|
264
|
-
BroadcastStatus.args = {
|
|
265
|
-
messages: [
|
|
266
|
-
{
|
|
267
|
-
id: 'msg-1',
|
|
268
|
-
text: 'July class details',
|
|
269
|
-
user: storyUsers.creator,
|
|
270
|
-
metadata: {
|
|
271
|
-
custom_type: 'MESSAGE_OUTBOUND',
|
|
272
|
-
broadcast_id: 'broadcast-1',
|
|
273
|
-
broadcast_name: 'July 9th Class attendees',
|
|
274
|
-
},
|
|
275
|
-
},
|
|
276
|
-
],
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export const BroadcastStatusNonLatest: StoryFn<TemplateProps> = Template.bind({})
|
|
280
|
-
BroadcastStatusNonLatest.args = {
|
|
281
|
-
messages: [
|
|
282
|
-
{
|
|
283
|
-
id: 'msg-1',
|
|
284
|
-
text: 'July class details',
|
|
285
|
-
user: storyUsers.creator,
|
|
286
|
-
metadata: {
|
|
287
|
-
custom_type: 'MESSAGE_OUTBOUND',
|
|
288
|
-
broadcast_id: 'broadcast-1',
|
|
289
|
-
broadcast_name: 'July 9th Class attendees',
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
id: 'msg-2',
|
|
294
|
-
text: 'Let me know if you have any questions.',
|
|
295
|
-
user: storyUsers.creator,
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
}
|
|
299
|
-
|
|
300
260
|
export const WithTipTag: StoryFn<TemplateProps> = Template.bind({})
|
|
301
261
|
WithTipTag.args = {
|
|
302
262
|
messages: [
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useChannelStateContext,
|
|
4
|
+
useMessageContext,
|
|
5
|
+
} from 'stream-chat-react'
|
|
3
6
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
7
|
|
|
5
8
|
import { renderWithProviders, screen, within } from '../../test/utils'
|
|
@@ -66,7 +69,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
66
69
|
// avatars.
|
|
67
70
|
mockedUseMessageContext.mockReturnValue({
|
|
68
71
|
message: { id: 'own-2' },
|
|
69
|
-
isMyMessage: () => true,
|
|
70
72
|
} as never)
|
|
71
73
|
|
|
72
74
|
renderWithProviders(<SentMessageDeliveryStatus />)
|
|
@@ -81,7 +83,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
81
83
|
it('renders nothing for an earlier own message once a later message exists', () => {
|
|
82
84
|
mockedUseMessageContext.mockReturnValue({
|
|
83
85
|
message: { id: 'own-1' },
|
|
84
|
-
isMyMessage: () => true,
|
|
85
86
|
} as never)
|
|
86
87
|
|
|
87
88
|
renderWithProviders(<SentMessageDeliveryStatus />)
|
|
@@ -103,7 +104,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
103
104
|
} as never)
|
|
104
105
|
mockedUseMessageContext.mockReturnValue({
|
|
105
106
|
message: { id: 'own-2' },
|
|
106
|
-
isMyMessage: () => true,
|
|
107
107
|
} as never)
|
|
108
108
|
|
|
109
109
|
renderWithProviders(<SentMessageDeliveryStatus />)
|
|
@@ -124,7 +124,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
124
124
|
} as never)
|
|
125
125
|
mockedUseMessageContext.mockReturnValue({
|
|
126
126
|
message: { id: 'own-2' },
|
|
127
|
-
isMyMessage: () => true,
|
|
128
127
|
} as never)
|
|
129
128
|
|
|
130
129
|
renderWithProviders(<SentMessageDeliveryStatus />)
|
|
@@ -139,7 +138,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
139
138
|
it('renders "Sending" in the sending slot for the latest message', () => {
|
|
140
139
|
mockedUseMessageContext.mockReturnValue({
|
|
141
140
|
message: { id: 'own-2', status: 'sending' },
|
|
142
|
-
isMyMessage: () => true,
|
|
143
141
|
threadList: false,
|
|
144
142
|
} as never)
|
|
145
143
|
|
|
@@ -151,7 +149,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
151
149
|
it('does not render "Sending" for an earlier message', () => {
|
|
152
150
|
mockedUseMessageContext.mockReturnValue({
|
|
153
151
|
message: { id: 'own-1', status: 'sending' },
|
|
154
|
-
isMyMessage: () => true,
|
|
155
152
|
threadList: false,
|
|
156
153
|
} as never)
|
|
157
154
|
|
|
@@ -165,7 +162,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
165
162
|
// threadList is true; we suppress the stamp ourselves.
|
|
166
163
|
mockedUseMessageContext.mockReturnValue({
|
|
167
164
|
message: { id: 'own-2', status: 'sending' },
|
|
168
|
-
isMyMessage: () => true,
|
|
169
165
|
threadList: true,
|
|
170
166
|
} as never)
|
|
171
167
|
|
|
@@ -177,74 +173,6 @@ describe('SentMessageDeliveryStatus', () => {
|
|
|
177
173
|
).not.toBeInTheDocument()
|
|
178
174
|
})
|
|
179
175
|
|
|
180
|
-
it('renders a broadcast label for every own broadcast message, including non-latest messages', () => {
|
|
181
|
-
mockedUseMessageContext.mockReturnValue({
|
|
182
|
-
message: {
|
|
183
|
-
id: 'own-1',
|
|
184
|
-
metadata: {
|
|
185
|
-
broadcast_id: 'broadcast-1',
|
|
186
|
-
broadcast_name: 'July 9th Class attendees',
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
isMyMessage: () => true,
|
|
190
|
-
threadList: false,
|
|
191
|
-
} as never)
|
|
192
|
-
|
|
193
|
-
renderWithProviders(<SentMessageDeliveryStatus />)
|
|
194
|
-
|
|
195
|
-
expect(
|
|
196
|
-
screen.getByTestId('sent-message-broadcast-status')
|
|
197
|
-
).toHaveTextContent('July 9th Class attendees')
|
|
198
|
-
expect(
|
|
199
|
-
screen.queryByTestId('sent-message-delivery-status')
|
|
200
|
-
).not.toBeInTheDocument()
|
|
201
|
-
expect(screen.queryByText('•')).not.toBeInTheDocument()
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it('uses a generic label and invokes the broadcast callback when the name is missing', () => {
|
|
205
|
-
const onBroadcastClick = vi.fn()
|
|
206
|
-
mockedUseMessageContext.mockReturnValue({
|
|
207
|
-
message: { id: 'own-2', metadata: { broadcast_id: 'broadcast-1' } },
|
|
208
|
-
isMyMessage: () => true,
|
|
209
|
-
threadList: false,
|
|
210
|
-
} as never)
|
|
211
|
-
|
|
212
|
-
renderWithProviders(
|
|
213
|
-
<SentMessageDeliveryStatus onBroadcastClick={onBroadcastClick} />
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
expect(
|
|
217
|
-
screen.getByTestId('sent-message-broadcast-status')
|
|
218
|
-
).toHaveTextContent('Broadcast')
|
|
219
|
-
expect(
|
|
220
|
-
screen.getByRole('button', { name: 'View broadcast Broadcast' })
|
|
221
|
-
).toBeInTheDocument()
|
|
222
|
-
screen.getByRole('button', { name: 'View broadcast Broadcast' }).click()
|
|
223
|
-
expect(onBroadcastClick).toHaveBeenCalledWith({ id: 'broadcast-1' })
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('does not render a broadcast label for a visitor viewing a broadcast message', () => {
|
|
227
|
-
mockedUseMessageContext.mockReturnValue({
|
|
228
|
-
message: {
|
|
229
|
-
id: 'broadcast-1',
|
|
230
|
-
metadata: {
|
|
231
|
-
broadcast_id: 'broadcast-1',
|
|
232
|
-
broadcast_name: 'July 9th Class attendees',
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
isMyMessage: () => false,
|
|
236
|
-
threadList: false,
|
|
237
|
-
} as never)
|
|
238
|
-
|
|
239
|
-
renderWithProviders(
|
|
240
|
-
<SentMessageDeliveryStatus onBroadcastClick={vi.fn()} />
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
expect(
|
|
244
|
-
screen.queryByTestId('sent-message-broadcast-status')
|
|
245
|
-
).not.toBeInTheDocument()
|
|
246
|
-
})
|
|
247
|
-
|
|
248
176
|
it('renders "Failed to send" for every own failed message', () => {
|
|
249
177
|
mockedUseMessageContext.mockReturnValue({
|
|
250
178
|
message: { id: 'own-1', status: 'failed', type: 'regular' },
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChecksIcon,
|
|
3
3
|
CircleNotchIcon,
|
|
4
|
-
MegaphoneIcon,
|
|
5
4
|
WarningCircleIcon,
|
|
6
5
|
} from '@phosphor-icons/react'
|
|
7
6
|
import {
|
|
@@ -94,44 +93,6 @@ const SendingStatus = () => {
|
|
|
94
93
|
)
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
const BroadcastStatus = ({
|
|
98
|
-
broadcastId,
|
|
99
|
-
broadcastName,
|
|
100
|
-
onBroadcastClick,
|
|
101
|
-
}: {
|
|
102
|
-
broadcastId: string
|
|
103
|
-
broadcastName?: string
|
|
104
|
-
onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
|
|
105
|
-
}) => {
|
|
106
|
-
const name = broadcastName || 'Broadcast'
|
|
107
|
-
const isLatestRealMessage = useIsLatestRealMessage()
|
|
108
|
-
const content = (
|
|
109
|
-
<>
|
|
110
|
-
{isLatestRealMessage && <span aria-hidden="true">•</span>}
|
|
111
|
-
<MegaphoneIcon weight="bold" aria-hidden="true" />
|
|
112
|
-
<span data-testid="sent-message-broadcast-status">{name}</span>
|
|
113
|
-
</>
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
return onBroadcastClick ? (
|
|
117
|
-
<button
|
|
118
|
-
type="button"
|
|
119
|
-
className="sent-message-broadcast-link"
|
|
120
|
-
aria-label={`View broadcast ${name}`}
|
|
121
|
-
onClick={() =>
|
|
122
|
-
onBroadcastClick({
|
|
123
|
-
id: broadcastId,
|
|
124
|
-
...(broadcastName ? { name: broadcastName } : {}),
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
>
|
|
128
|
-
{content}
|
|
129
|
-
</button>
|
|
130
|
-
) : (
|
|
131
|
-
content
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
96
|
const FailedStatus = () => (
|
|
136
97
|
<span className="str-chat__message-status sent-message-status--failed">
|
|
137
98
|
<WarningCircleIcon weight="bold" aria-hidden="true" />
|
|
@@ -153,15 +114,10 @@ const FailedStatus = () => (
|
|
|
153
114
|
* because it has no failed slot and are shown on every own, non-thread
|
|
154
115
|
* failed message.
|
|
155
116
|
*/
|
|
156
|
-
export const SentMessageDeliveryStatus = ({
|
|
157
|
-
onBroadcastClick,
|
|
158
|
-
}: {
|
|
159
|
-
onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
|
|
160
|
-
}) => {
|
|
117
|
+
export const SentMessageDeliveryStatus = () => {
|
|
161
118
|
const { isMyMessage, message, threadList } = useMessageContext(
|
|
162
119
|
'SentMessageDeliveryStatus'
|
|
163
120
|
)
|
|
164
|
-
const isOwnMessage = isMyMessage()
|
|
165
121
|
|
|
166
122
|
// Stream's MessageStatus still mounts MessageSendingStatus when
|
|
167
123
|
// threadList is true; keep all of our stamps out of thread replies.
|
|
@@ -169,28 +125,15 @@ export const SentMessageDeliveryStatus = ({
|
|
|
169
125
|
return null
|
|
170
126
|
}
|
|
171
127
|
|
|
172
|
-
if (
|
|
128
|
+
if (
|
|
129
|
+
message.status === 'failed' &&
|
|
130
|
+
isMyMessage() &&
|
|
131
|
+
message.type !== 'error'
|
|
132
|
+
) {
|
|
173
133
|
return <FailedStatus />
|
|
174
134
|
}
|
|
175
135
|
|
|
176
|
-
|
|
177
|
-
return null
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const broadcastId = message.metadata?.broadcast_id
|
|
181
|
-
const broadcastName = message.metadata?.broadcast_name
|
|
182
|
-
const broadcastStatus =
|
|
183
|
-
message.status !== 'sending' &&
|
|
184
|
-
message.status !== 'failed' &&
|
|
185
|
-
broadcastId ? (
|
|
186
|
-
<BroadcastStatus
|
|
187
|
-
broadcastId={broadcastId}
|
|
188
|
-
broadcastName={broadcastName}
|
|
189
|
-
onBroadcastClick={onBroadcastClick}
|
|
190
|
-
/>
|
|
191
|
-
) : null
|
|
192
|
-
|
|
193
|
-
const messageStatus = (
|
|
136
|
+
return (
|
|
194
137
|
<MessageStatus
|
|
195
138
|
MessageSentStatus={DeliveredStatus}
|
|
196
139
|
MessageDeliveredStatus={DeliveredStatus}
|
|
@@ -198,15 +141,4 @@ export const SentMessageDeliveryStatus = ({
|
|
|
198
141
|
MessageSendingStatus={SendingStatus}
|
|
199
142
|
/>
|
|
200
143
|
)
|
|
201
|
-
|
|
202
|
-
if (!broadcastStatus) {
|
|
203
|
-
return messageStatus
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return (
|
|
207
|
-
<span className="sent-message-status-row">
|
|
208
|
-
{messageStatus}
|
|
209
|
-
{broadcastStatus}
|
|
210
|
-
</span>
|
|
211
|
-
)
|
|
212
144
|
}
|
|
@@ -54,13 +54,11 @@ import StreamAttachmentMessage, {
|
|
|
54
54
|
type CustomMessageUIComponentProps = MessageUIComponentProps & {
|
|
55
55
|
chatbotVotingEnabled?: boolean
|
|
56
56
|
viewerLanguage?: string
|
|
57
|
-
onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
type CustomMessageWithContextProps = MessageContextValue & {
|
|
61
60
|
chatbotVotingEnabled?: boolean
|
|
62
61
|
viewerLanguage?: string
|
|
63
|
-
onBroadcastClick?: (broadcast: { id: string; name?: string }) => void
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
@@ -81,7 +79,6 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
81
79
|
renderText,
|
|
82
80
|
threadList,
|
|
83
81
|
viewerLanguage,
|
|
84
|
-
onBroadcastClick,
|
|
85
82
|
} = props
|
|
86
83
|
|
|
87
84
|
const { client } = useChatContext('CustomMessage')
|
|
@@ -427,7 +424,7 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
427
424
|
)}
|
|
428
425
|
</div>
|
|
429
426
|
)}
|
|
430
|
-
<SentMessageDeliveryStatus
|
|
427
|
+
<SentMessageDeliveryStatus />
|
|
431
428
|
{showReplyCountButton && (
|
|
432
429
|
<MessageRepliesCountButton
|
|
433
430
|
onClick={handleOpenThread}
|
|
@@ -21,6 +21,52 @@ const STACK_IMAGES: ImageItem[] = [
|
|
|
21
21
|
{ src: 'https://picsum.photos/seed/img-6/720/720', alt: 'Photo 6' },
|
|
22
22
|
]
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* One source per aspect bucket, with intrinsic dimensions supplied so
|
|
26
|
+
* the card resolves at first paint instead of waiting on a network
|
|
27
|
+
* decode. Expected web cards (326×436 content box inside a 2px
|
|
28
|
+
* frame): portrait 249×440, landscape 330×187, square 330×330,
|
|
29
|
+
* panorama 330×69.
|
|
30
|
+
*/
|
|
31
|
+
const ASPECT_BUCKETS: { label: string; item: ImageItem }[] = [
|
|
32
|
+
{
|
|
33
|
+
label: 'Portrait 9:16',
|
|
34
|
+
item: {
|
|
35
|
+
src: 'https://picsum.photos/seed/ratio-portrait/1080/1920',
|
|
36
|
+
alt: 'Portrait photo',
|
|
37
|
+
width: 1080,
|
|
38
|
+
height: 1920,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: 'Landscape 16:9',
|
|
43
|
+
item: {
|
|
44
|
+
src: 'https://picsum.photos/seed/ratio-landscape/1920/1080',
|
|
45
|
+
alt: 'Landscape photo',
|
|
46
|
+
width: 1920,
|
|
47
|
+
height: 1080,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: 'Square 1:1',
|
|
52
|
+
item: {
|
|
53
|
+
src: 'https://picsum.photos/seed/ratio-square/1200/1200',
|
|
54
|
+
alt: 'Square photo',
|
|
55
|
+
width: 1200,
|
|
56
|
+
height: 1200,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: 'Panorama 5:1',
|
|
61
|
+
item: {
|
|
62
|
+
src: 'https://picsum.photos/seed/ratio-panorama/3000/600',
|
|
63
|
+
alt: 'Panoramic photo',
|
|
64
|
+
width: 3000,
|
|
65
|
+
height: 600,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
]
|
|
69
|
+
|
|
24
70
|
const meta: Meta = {
|
|
25
71
|
title: 'MessageAttachment/Image',
|
|
26
72
|
parameters: { layout: 'fullscreen' },
|
|
@@ -75,6 +121,37 @@ export const Single: StoryFn = () => (
|
|
|
75
121
|
</StoryPage>
|
|
76
122
|
)
|
|
77
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Single image, one row per aspect bucket. The image keeps its own
|
|
126
|
+
* ratio, fitted inside a max 326×436 content box on web (309×436
|
|
127
|
+
* below the `sm` breakpoint) — so `object-cover` never crops. Portrait
|
|
128
|
+
* resolves against the 440px height cap; landscape, square and
|
|
129
|
+
* panorama against the 330px width cap.
|
|
130
|
+
*
|
|
131
|
+
* Sent + Received only: the composer thumbnail is a fixed square and
|
|
132
|
+
* is unaffected by this treatment, so the Composer column is blank.
|
|
133
|
+
*/
|
|
134
|
+
export const SingleAspectRatios: StoryFn = () => (
|
|
135
|
+
<StoryPage>
|
|
136
|
+
<StoryHeading
|
|
137
|
+
title="Single image — aspect ratios"
|
|
138
|
+
description="Pascal's original defect was every single image being forced to 1:1. Each row here is one source ratio; the card adopts the fitted box rather than cropping to a square. Composer column is intentionally blank — the composer thumbnail is unchanged."
|
|
139
|
+
/>
|
|
140
|
+
<StoryGrid>
|
|
141
|
+
{ASPECT_BUCKETS.map(({ label, item }) => (
|
|
142
|
+
<StoryRow
|
|
143
|
+
key={label}
|
|
144
|
+
label={label}
|
|
145
|
+
sent={<ImageAttachment.Sent items={[item]} filename="photo.jpg" />}
|
|
146
|
+
received={
|
|
147
|
+
<ImageAttachment.Received items={[item]} filename="photo.jpg" />
|
|
148
|
+
}
|
|
149
|
+
/>
|
|
150
|
+
))}
|
|
151
|
+
</StoryGrid>
|
|
152
|
+
</StoryPage>
|
|
153
|
+
)
|
|
154
|
+
|
|
78
155
|
/** Single image with an accompanying caption rendered inside the bubble.
|
|
79
156
|
* Sent + Received only — captions are not rendered on the composer
|
|
80
157
|
* surface (the user types them in the message input, not on the
|