@linktr.ee/messaging-react 4.2.0-rc-1787325521 → 4.2.0-rc-1787599724
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-BYJyA83X.js → Card-D7UPq5-g.js} +2 -2
- package/dist/{Card-BYJyA83X.js.map → Card-D7UPq5-g.js.map} +1 -1
- package/dist/{Card-BplJtZao.cjs → Card-DcBZqMBt.cjs} +2 -2
- package/dist/{Card-BplJtZao.cjs.map → Card-DcBZqMBt.cjs.map} +1 -1
- package/dist/assets/index.css +1 -1
- package/dist/{index-BUC9vqhJ.js → index-CSkr_CO5.js} +2089 -1952
- package/dist/index-CSkr_CO5.js.map +1 -0
- package/dist/index-CwkY7QwT.cjs +3 -0
- package/dist/index-CwkY7QwT.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +59 -78
- package/dist/index.js +26 -30
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +2 -2
- package/dist/testing.js.map +1 -1
- package/package.json +13 -11
- package/src/components/AttachmentCard/utils/icons.ts +7 -6
- package/src/components/Avatar/Avatar.test.tsx +0 -126
- package/src/components/Avatar/getAvatarEmoji.test.ts +0 -39
- package/src/components/ChannelList/CustomChannelPreview.test.tsx +3 -410
- package/src/components/ChannelList/index.test.tsx +1 -132
- package/src/components/ChannelView.stories.tsx +0 -4
- package/src/components/ChannelView.test.tsx +3 -9
- package/src/components/CustomMessage/CustomMessage.stories.tsx +314 -6
- package/src/components/CustomMessage/CustomMessage.test.tsx +2 -56
- package/src/components/CustomMessage/MessageTag.stories.tsx +53 -17
- package/src/components/CustomMessage/MessageTag.test.tsx +40 -7
- package/src/components/CustomMessage/MessageTag.tsx +39 -7
- package/src/components/CustomMessage/SentMessageDeliveryStatus.test.tsx +7 -8
- package/src/components/CustomMessage/SentMessageDeliveryStatus.tsx +1 -2
- package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +33 -0
- package/src/components/CustomMessage/StreamAttachmentMessage.tsx +12 -5
- package/src/components/CustomMessage/index.tsx +19 -22
- package/src/components/CustomMessageInput/index.tsx +1 -1
- package/src/components/CustomSystemMessage/index.tsx +2 -3
- package/src/components/LinkAttachment/LinkAttachment.test.tsx +0 -327
- package/src/components/MessageAttachment/Audio/AudioAttachment.stories.tsx +165 -58
- package/src/components/MessageAttachment/Audio/WaveformAudioRow.test.tsx +153 -0
- package/src/components/MessageAttachment/Audio/WaveformAudioRow.tsx +450 -0
- package/src/components/MessageAttachment/Audio/audioRowRequester.test.ts +24 -0
- package/src/components/MessageAttachment/Audio/audioRowRequester.ts +16 -0
- package/src/components/MessageAttachment/Audio/index.tsx +83 -77
- package/src/components/MessageAttachment/MessageAttachment.test.tsx +176 -74
- package/src/components/MessageAttachment/_shared/fileMeta.test.ts +0 -44
- package/src/components/MessageAttachment/_shared/useIsClient.ts +23 -0
- package/src/components/MessageAttachment/index.tsx +25 -9
- package/src/components/MessageAttachment/types.ts +19 -9
- package/src/components/MessagingShell/MessagingShell.test.tsx +0 -20
- package/src/components/MessagingShell/index.tsx +0 -2
- package/src/components/RichCard/RichCard.test.tsx +1 -3
- package/src/index.ts +0 -4
- package/src/providers/MessagingProvider.test.tsx +2 -130
- package/src/providers/MessagingProvider.tsx +15 -26
- package/src/styles.css +210 -57
- package/src/testing/createMockMessagingClient.ts +2 -2
- package/src/types.ts +0 -9
- package/dist/index-BUC9vqhJ.js.map +0 -1
- package/dist/index-BkqyKPJP.cjs +0 -3
- package/dist/index-BkqyKPJP.cjs.map +0 -1
- package/src/components/AttachmentCard/MediaPlayer.test.tsx +0 -346
- package/src/components/AttachmentCard/Thumbnail.test.tsx +0 -215
- package/src/components/AttachmentCard/index.test.tsx +0 -160
- package/src/components/ChannelList/ChannelListContext.test.tsx +0 -87
- package/src/components/CustomMessage/Locked.stories.tsx +0 -108
- package/src/components/CustomMessage/PaidMessage.stories.tsx +0 -42
- package/src/components/CustomMessage/Tip.stories.tsx +0 -48
- package/src/components/CustomMessage/TipMessage/TipMessage.stories.tsx +0 -51
- package/src/components/CustomMessage/TipMessage/TipMessage.test.tsx +0 -65
- package/src/components/CustomMessage/TipMessage/index.tsx +0 -27
- package/src/components/FaqList/FaqList.test.tsx +0 -204
- package/src/components/LinkAttachment/components/_shared/BubbleTail.test.tsx +0 -76
- package/src/components/LinkAttachment/components/_shared/CardBody.test.tsx +0 -248
- package/src/components/LinkAttachment/components/_shared/CardCta.test.tsx +0 -123
- package/src/components/LinkAttachment/components/_shared/CardShell.test.tsx +0 -193
- package/src/components/LinkAttachment/components/_shared/CardThumbnail.test.tsx +0 -242
- package/src/components/LinkAttachment/components/_shared/hex.test.ts +0 -37
- package/src/components/LinkAttachment/components/_shared/normalizeExternalHref.test.ts +0 -72
- package/src/components/LinkAttachment/components/_shared/useChinPalette.test.ts +0 -162
- package/src/components/MessageAttachment/MessageAttachment.behavior.test.tsx +0 -182
- package/src/components/MessageAttachment/_shared/Bubble.test.tsx +0 -111
- package/src/components/MessageAttachment/_shared/CarouselNav.test.tsx +0 -36
- package/src/components/MessageAttachment/_shared/CompactDocumentRow.test.tsx +0 -114
- package/src/components/MessageAttachment/_shared/DismissButton.test.tsx +0 -42
- package/src/components/MessageAttachment/_shared/DownloadAction.test.tsx +0 -168
- package/src/components/MessageAttachment/_shared/ImageViewer.test.tsx +0 -52
- package/src/components/MessageAttachment/_shared/MediaStackGrid.test.tsx +0 -69
- package/src/components/MessageAttachment/_shared/PdfViewer.test.tsx +0 -45
- package/src/components/MessageAttachment/_shared/VideoViewer.test.tsx +0 -55
- package/src/components/MessageAttachment/_shared/ViewerShell.test.tsx +0 -246
- package/src/components/MessageAttachment/_shared/triggerDownload.test.ts +0 -113
- package/src/components/MessageAttachment/_shared/useCarousel.test.tsx +0 -68
- package/src/components/MessageAttachment/_shared/viewerChromeClasses.test.ts +0 -16
- package/src/logging/index.test.tsx +0 -136
- package/src/logging/index.tsx +0 -48
- package/src/stories/customMessageStoryTemplate.tsx +0 -202
|
@@ -56,7 +56,7 @@ import VideoAttachment, {
|
|
|
56
56
|
* - Pdf / Audio / File render their compact rows / players in a
|
|
57
57
|
* vertical stack with an 8px gap between rows. Each row keeps
|
|
58
58
|
* its own activation target — Pdf opens the carousel-aware
|
|
59
|
-
* `PdfViewer` at that index, Audio gets its own
|
|
59
|
+
* `PdfViewer` at that index, Audio gets its own waveform player,
|
|
60
60
|
* and File downloads the asset for that row.
|
|
61
61
|
*
|
|
62
62
|
* The Composer surface accepts only a single attachment at a time,
|
|
@@ -74,12 +74,29 @@ import VideoAttachment, {
|
|
|
74
74
|
* download button to the chrome; the Video viewer relies on the
|
|
75
75
|
* native `<video controls>` download menu, and the Pdf viewer
|
|
76
76
|
* inherits the browser's built-in PDF download. Sibling-row Download
|
|
77
|
-
* buttons on Pdf / File and the
|
|
77
|
+
* buttons on Pdf / File and the Audio card's trailing action expose
|
|
78
78
|
* downloads outside the viewer too. The lightbox chrome is styled
|
|
79
79
|
* with plain CSS (`.mes-media-viewer*`) so the package's shipped
|
|
80
80
|
* stylesheet is enough to render the viewer correctly without a
|
|
81
81
|
* Tailwind dependency in the consumer.
|
|
82
82
|
*
|
|
83
|
+
* # Audio requires a `<Channel>` ancestor
|
|
84
|
+
*
|
|
85
|
+
* `MessageAttachment.Audio.*` renders the waveform player card —
|
|
86
|
+
* a 32px play toggle, a 35-bar waveform with a progress fill and a
|
|
87
|
+
* native seek control, the duration, and a 32px trailing action
|
|
88
|
+
* (Remove in the composer, Download once sent). Playback is
|
|
89
|
+
* `stream-chat-react`'s pooled `AudioPlayer`, which is what supplies
|
|
90
|
+
* single-player-at-a-time across a thread, pause-on-navigation and
|
|
91
|
+
* saved-position restore across virtualized remounts.
|
|
92
|
+
*
|
|
93
|
+
* That pool is provided by `<Channel>`. Rendered outside one the card
|
|
94
|
+
* still draws in full, but its play and seek controls are disabled —
|
|
95
|
+
* so a story or a new consumer surface must mount `<Channel>` (or
|
|
96
|
+
* `stream-chat-react`'s `WithAudioPlayback`) for the card to be
|
|
97
|
+
* playable. The waveform bars themselves are styled with plain CSS
|
|
98
|
+
* (`.mes-audio-wave*`), so the shipped stylesheet is enough.
|
|
99
|
+
*
|
|
83
100
|
* # Lazy-loading defaults
|
|
84
101
|
*
|
|
85
102
|
* Media attachments bake in network-friendly defaults for long chat
|
|
@@ -100,13 +117,12 @@ import VideoAttachment, {
|
|
|
100
117
|
* `VideoItem.preload` per item). Once the viewer is open the
|
|
101
118
|
* active item bumps to `preload="metadata"` so duration / the
|
|
102
119
|
* first frame appear immediately.
|
|
103
|
-
* - **Audio** —
|
|
104
|
-
* `
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* (or `AudioItem.preload` per track).
|
|
120
|
+
* - **Audio** — no audio bytes are fetched until the user presses
|
|
121
|
+
* play: the pooled `AudioPlayer` acquires the shared `<audio>`
|
|
122
|
+
* element lazily. A card whose `durationSeconds` is unknown makes
|
|
123
|
+
* one `preload="metadata"` header request to fill the duration
|
|
124
|
+
* slot; supplying `durationSeconds` (which `StreamAttachmentMessage`
|
|
125
|
+
* maps from the attachment's persisted `duration`) avoids even that.
|
|
110
126
|
* - **Pdf** / **File** — no inline media element to throttle; the
|
|
111
127
|
* bubble renders compact rows that download / open lazily on
|
|
112
128
|
* activation. No `loading` / `preload` props on these surfaces.
|
|
@@ -119,21 +119,31 @@ export interface PdfItem {
|
|
|
119
119
|
/** A single audio file inside an Audio attachment (single or stacked). */
|
|
120
120
|
export interface AudioItem {
|
|
121
121
|
src: string
|
|
122
|
-
/** MIME type hint —
|
|
122
|
+
/** MIME type hint — gates playability via the player's `canPlayType` probe. */
|
|
123
123
|
mimeType?: string
|
|
124
124
|
/**
|
|
125
|
-
* Filename —
|
|
126
|
-
*
|
|
125
|
+
* Filename — the download default name for the card's trailing
|
|
126
|
+
* action, and part of the card's accessible name.
|
|
127
127
|
*/
|
|
128
128
|
filename?: string
|
|
129
129
|
/**
|
|
130
|
-
*
|
|
131
|
-
* the
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
130
|
+
* Track length in seconds. Rendered as `MM:SS` before playback
|
|
131
|
+
* starts, so the duration is correct on first paint with no network
|
|
132
|
+
* request. Sourced from the Stream attachment's `duration` field,
|
|
133
|
+
* which the composer writes at send time. When omitted the card
|
|
134
|
+
* shows `--:--` until a one-shot `loadedmetadata` probe resolves.
|
|
135
135
|
*/
|
|
136
|
-
|
|
136
|
+
durationSeconds?: number
|
|
137
|
+
/**
|
|
138
|
+
* Waveform amplitudes, each `0..1`, in track order. Resampled to the
|
|
139
|
+
* rendered bar count, so any length is accepted. Sourced from the
|
|
140
|
+
* Stream attachment's `waveform_data`, which the composer computes
|
|
141
|
+
* from the local file and writes at send time.
|
|
142
|
+
*
|
|
143
|
+
* When omitted, the card renders a flat placeholder row: every bar at
|
|
144
|
+
* the minimum height, with the progress fill still tracking playback.
|
|
145
|
+
*/
|
|
146
|
+
waveformData?: number[]
|
|
137
147
|
}
|
|
138
148
|
|
|
139
149
|
/** A single generic file inside a File attachment (single or stacked). */
|
|
@@ -125,26 +125,6 @@ describe('MessagingShell', () => {
|
|
|
125
125
|
})
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
-
it('forwards attachmentPreviewList to the selected channel view', async () => {
|
|
129
|
-
queryChannelsMock.mockResolvedValue([makeChannel('existing-1')])
|
|
130
|
-
const AttachmentPreviewList = () => <div>staged attachment</div>
|
|
131
|
-
|
|
132
|
-
renderWithProviders(
|
|
133
|
-
<MessagingShell
|
|
134
|
-
initialParticipantFilter="other-1"
|
|
135
|
-
attachmentPreviewList={AttachmentPreviewList}
|
|
136
|
-
/>
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
await waitFor(() => {
|
|
140
|
-
expect(screen.getByTestId('channel-view')).toBeInTheDocument()
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
expect(capturedChannelViewProps.attachmentPreviewList).toBe(
|
|
144
|
-
AttachmentPreviewList
|
|
145
|
-
)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
128
|
it('calls onExitConversation and renders "Conversation ended" when the user leaves the conversation', async () => {
|
|
149
129
|
queryChannelsMock.mockResolvedValue([makeChannel('existing-1')])
|
|
150
130
|
const onExit = vi.fn()
|
|
@@ -43,7 +43,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
43
43
|
onMessageLinkClick,
|
|
44
44
|
showChannelInfo,
|
|
45
45
|
composerInput,
|
|
46
|
-
attachmentPreviewList,
|
|
47
46
|
}) => {
|
|
48
47
|
const {
|
|
49
48
|
client,
|
|
@@ -270,7 +269,6 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
270
269
|
onMessageLinkClick={onMessageLinkClick}
|
|
271
270
|
showChannelInfo={showChannelInfo}
|
|
272
271
|
composerInput={composerInput}
|
|
273
|
-
attachmentPreviewList={attachmentPreviewList}
|
|
274
272
|
/>
|
|
275
273
|
</div>
|
|
276
274
|
</div>
|
|
@@ -29,9 +29,7 @@ describe('RichCard', () => {
|
|
|
29
29
|
renderWithProviders(
|
|
30
30
|
<RichCard.Received
|
|
31
31
|
title="Welcome"
|
|
32
|
-
subtitle={
|
|
33
|
-
'👋 Say hello as people arrive\n✨ Spark conversations\n💬 Add automated FAQs'
|
|
34
|
-
}
|
|
32
|
+
subtitle={'👋 Say hello as people arrive\n✨ Spark conversations\n💬 Add automated FAQs'}
|
|
35
33
|
subtitleLines={6}
|
|
36
34
|
images={[HERO]}
|
|
37
35
|
/>
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export { ChannelList } from './components/ChannelList'
|
|
|
7
7
|
export { ChannelView } from './components/ChannelView'
|
|
8
8
|
export { default as ActionButton } from './components/ActionButton'
|
|
9
9
|
export { default as LockedAttachment } from './components/CustomMessage/LockedAttachment'
|
|
10
|
-
export { TipMessage, isTipMessage } from './components/CustomMessage/TipMessage'
|
|
11
10
|
export { default as LinkAttachment } from './components/LinkAttachment'
|
|
12
11
|
export { default as RichCard } from './components/RichCard'
|
|
13
12
|
export { default as MessageAttachment } from './components/MessageAttachment'
|
|
@@ -29,13 +28,11 @@ export type {
|
|
|
29
28
|
|
|
30
29
|
// Providers
|
|
31
30
|
export { MessagingProvider } from './providers/MessagingProvider'
|
|
32
|
-
export { MessagingLoggerProvider } from './logging'
|
|
33
31
|
export { CustomMessageProvider } from './components/CustomMessage/context'
|
|
34
32
|
|
|
35
33
|
// Hooks
|
|
36
34
|
export { useComposerLocked } from './components/CustomMessageInput'
|
|
37
35
|
export { useMessaging } from './hooks/useMessaging'
|
|
38
|
-
export { useMessagingLogger } from './logging'
|
|
39
36
|
export { useCustomMessage } from './components/CustomMessage/context'
|
|
40
37
|
|
|
41
38
|
// Utils
|
|
@@ -138,4 +135,3 @@ export type { CustomMessageRegistry } from './components/CustomMessage/context'
|
|
|
138
135
|
export type { AttachmentSourceType } from './components/AttachmentCard/utils/mimeType'
|
|
139
136
|
export type { Faq, FaqListProps } from './components/FaqList'
|
|
140
137
|
export type { FaqListItemProps } from './components/FaqList/FaqListItem'
|
|
141
|
-
export type { Logger } from '@linktr.ee/messaging-core'
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { StreamChatService } from '@linktr.ee/messaging-core'
|
|
2
|
-
import type {
|
|
3
|
-
Logger,
|
|
4
|
-
MessagingUser,
|
|
5
|
-
StreamChatServiceConfig,
|
|
6
|
-
} from '@linktr.ee/messaging-core'
|
|
2
|
+
import type { MessagingUser } from '@linktr.ee/messaging-core'
|
|
7
3
|
import { render, waitFor, act } from '@testing-library/react'
|
|
8
4
|
import React from 'react'
|
|
9
5
|
import type { StreamChat } from 'stream-chat'
|
|
10
6
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
11
7
|
|
|
12
|
-
import { useMessagingLogger } from '../logging'
|
|
13
|
-
|
|
14
8
|
import { MessagingProvider, useMessagingContext } from './MessagingProvider'
|
|
15
9
|
|
|
16
10
|
// Stub stream-chat-react's <Chat /> so we don't need a real, fully-wired
|
|
@@ -22,9 +16,7 @@ vi.mock('stream-chat-react', () => ({
|
|
|
22
16
|
// The provider constructs the Chat client via `new StreamChat(apiKey)` and
|
|
23
17
|
// injects it into the service. Stub the constructor so <Chat> sees an instance.
|
|
24
18
|
vi.mock('stream-chat', () => ({
|
|
25
|
-
StreamChat: vi.fn().mockImplementation(
|
|
26
|
-
return { userID: 'mock' }
|
|
27
|
-
}),
|
|
19
|
+
StreamChat: vi.fn().mockImplementation(() => ({ userID: 'mock' })),
|
|
28
20
|
}))
|
|
29
21
|
|
|
30
22
|
const setupServiceMock = () => {
|
|
@@ -494,124 +486,4 @@ describe('MessagingProvider', () => {
|
|
|
494
486
|
expect(last.hasClient).toBe(false)
|
|
495
487
|
expect(last.error).toBeNull()
|
|
496
488
|
})
|
|
497
|
-
|
|
498
|
-
describe('logger seam', () => {
|
|
499
|
-
const ServiceProbe: React.FC<{
|
|
500
|
-
onService: (service: StreamChatService | null) => void
|
|
501
|
-
}> = ({ onService }) => {
|
|
502
|
-
const { service } = useMessagingContext()
|
|
503
|
-
React.useEffect(() => {
|
|
504
|
-
onService(service)
|
|
505
|
-
}, [service, onService])
|
|
506
|
-
return null
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
const LoggerProbe: React.FC<{ onLogger: (logger: Logger) => void }> = ({
|
|
510
|
-
onLogger,
|
|
511
|
-
}) => {
|
|
512
|
-
const logger = useMessagingLogger()
|
|
513
|
-
React.useEffect(() => {
|
|
514
|
-
onLogger(logger)
|
|
515
|
-
}, [logger, onLogger])
|
|
516
|
-
return null
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// The service stores its resolved sink privately; read it to prove which
|
|
520
|
-
// logger the provider handed to the constructor.
|
|
521
|
-
const serviceLogger = (service: StreamChatService) =>
|
|
522
|
-
(service as unknown as { logger: Logger }).logger
|
|
523
|
-
|
|
524
|
-
const renderWithLogger = async (
|
|
525
|
-
props: Partial<React.ComponentProps<typeof MessagingProvider>> & {
|
|
526
|
-
serviceConfig: Omit<StreamChatServiceConfig, 'apiKey'>
|
|
527
|
-
}
|
|
528
|
-
) => {
|
|
529
|
-
setupServiceMock()
|
|
530
|
-
const services: (StreamChatService | null)[] = []
|
|
531
|
-
const loggers: Logger[] = []
|
|
532
|
-
|
|
533
|
-
render(
|
|
534
|
-
<MessagingProvider
|
|
535
|
-
apiKey="mock-api-key"
|
|
536
|
-
user={
|
|
537
|
-
{ type: 'guest', id: 'guest-1', name: 'Guest' } as MessagingUser
|
|
538
|
-
}
|
|
539
|
-
{...props}
|
|
540
|
-
>
|
|
541
|
-
<ServiceProbe onService={(s) => services.push(s)} />
|
|
542
|
-
<LoggerProbe onLogger={(l) => loggers.push(l)} />
|
|
543
|
-
</MessagingProvider>
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
await waitFor(() => expect(services.filter(Boolean).length).toBe(1))
|
|
547
|
-
return {
|
|
548
|
-
service: services.filter(Boolean).pop() as StreamChatService,
|
|
549
|
-
logger: loggers[loggers.length - 1],
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
const baseServiceConfig: Omit<StreamChatServiceConfig, 'apiKey'> = {
|
|
554
|
-
fetchToken: async () => 'token',
|
|
555
|
-
createChannel: async () => ({ channelId: 'ch-1' }),
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
it('forwards the logger prop into the service and to the subtree', async () => {
|
|
559
|
-
const sink: Logger = { error: vi.fn() }
|
|
560
|
-
const { service, logger } = await renderWithLogger({
|
|
561
|
-
serviceConfig: baseServiceConfig,
|
|
562
|
-
logger: sink,
|
|
563
|
-
})
|
|
564
|
-
|
|
565
|
-
expect(serviceLogger(service).error).toBe(sink.error)
|
|
566
|
-
|
|
567
|
-
const error = new Error('boom')
|
|
568
|
-
logger.error?.('[MessagingShell] Failed:', error)
|
|
569
|
-
expect(sink.error).toHaveBeenCalledWith('[MessagingShell] Failed:', error)
|
|
570
|
-
})
|
|
571
|
-
|
|
572
|
-
it('resolves a partial prop sink before handing it to the service', async () => {
|
|
573
|
-
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
574
|
-
const sink: Logger = { error: vi.fn() }
|
|
575
|
-
const { service } = await renderWithLogger({
|
|
576
|
-
serviceConfig: baseServiceConfig,
|
|
577
|
-
logger: sink,
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
// The service swaps its own console defaults out wholesale, so an
|
|
581
|
-
// unresolved partial sink would silence the levels it omits.
|
|
582
|
-
serviceLogger(service).warn?.('[StreamChatService] Slow:', 1)
|
|
583
|
-
expect(consoleWarn).toHaveBeenCalledWith('[StreamChatService] Slow:', 1)
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
it('lets an explicit serviceConfig.logger win over the logger prop', async () => {
|
|
587
|
-
const configSink: Logger = { error: vi.fn() }
|
|
588
|
-
const propSink: Logger = { error: vi.fn() }
|
|
589
|
-
const { service } = await renderWithLogger({
|
|
590
|
-
serviceConfig: { ...baseServiceConfig, logger: configSink },
|
|
591
|
-
logger: propSink,
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
expect(serviceLogger(service)).toBe(configSink)
|
|
595
|
-
})
|
|
596
|
-
|
|
597
|
-
it('leaves the service on its console defaults when no logger is given', async () => {
|
|
598
|
-
const consoleError = vi
|
|
599
|
-
.spyOn(console, 'error')
|
|
600
|
-
.mockImplementation(() => {})
|
|
601
|
-
const { service, logger } = await renderWithLogger({
|
|
602
|
-
serviceConfig: baseServiceConfig,
|
|
603
|
-
})
|
|
604
|
-
|
|
605
|
-
// Not the react seam object: the service fell back to its own defaults.
|
|
606
|
-
expect(serviceLogger(service)).not.toBe(logger)
|
|
607
|
-
|
|
608
|
-
const error = new Error('boom')
|
|
609
|
-
logger.error?.('[MessagingShell] Failed:', error)
|
|
610
|
-
serviceLogger(service).error?.('[StreamChatService] Failed:', error)
|
|
611
|
-
expect(consoleError.mock.calls).toEqual([
|
|
612
|
-
['[MessagingShell] Failed:', error],
|
|
613
|
-
['[StreamChatService] Failed:', error],
|
|
614
|
-
])
|
|
615
|
-
})
|
|
616
|
-
})
|
|
617
489
|
})
|
|
@@ -13,7 +13,6 @@ import React, {
|
|
|
13
13
|
import { StreamChat } from 'stream-chat'
|
|
14
14
|
import { Chat } from 'stream-chat-react'
|
|
15
15
|
|
|
16
|
-
import { MessagingLoggerProvider, resolveLogger } from '../logging'
|
|
17
16
|
import type { MessagingProviderProps, MessagingCapabilities } from '../types'
|
|
18
17
|
|
|
19
18
|
/**
|
|
@@ -57,7 +56,6 @@ export const MessagingProvider: React.FC<MessagingProviderProps> = ({
|
|
|
57
56
|
capabilities = {},
|
|
58
57
|
debug = false,
|
|
59
58
|
client: injectedClient,
|
|
60
|
-
logger,
|
|
61
59
|
}) => {
|
|
62
60
|
// Create debug logger that respects the debug prop
|
|
63
61
|
const debugLog = useCallback(
|
|
@@ -96,8 +94,6 @@ export const MessagingProvider: React.FC<MessagingProviderProps> = ({
|
|
|
96
94
|
serviceConfigRef.current = serviceConfig
|
|
97
95
|
const debugRef = useRef(debug)
|
|
98
96
|
debugRef.current = debug
|
|
99
|
-
const loggerRef = useRef(logger)
|
|
100
|
-
loggerRef.current = logger
|
|
101
97
|
|
|
102
98
|
// Track renders and prop changes
|
|
103
99
|
const prevPropsRef = useRef({
|
|
@@ -203,11 +199,6 @@ export const MessagingProvider: React.FC<MessagingProviderProps> = ({
|
|
|
203
199
|
apiKey,
|
|
204
200
|
debug: debugRef.current,
|
|
205
201
|
client: chatClient,
|
|
206
|
-
// An explicit serviceConfig.logger wins — existing injectors keep working.
|
|
207
|
-
// Resolved, because the service swaps its console defaults out wholesale.
|
|
208
|
-
...(currentConfig.logger || !loggerRef.current
|
|
209
|
-
? {}
|
|
210
|
-
: { logger: resolveLogger(loggerRef.current) }),
|
|
211
202
|
})
|
|
212
203
|
|
|
213
204
|
serviceRef.current = newService
|
|
@@ -413,22 +404,20 @@ export const MessagingProvider: React.FC<MessagingProviderProps> = ({
|
|
|
413
404
|
})
|
|
414
405
|
|
|
415
406
|
return (
|
|
416
|
-
<
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
</MessagingContext.Provider>
|
|
432
|
-
</MessagingLoggerProvider>
|
|
407
|
+
<MessagingContext.Provider value={contextValue}>
|
|
408
|
+
{chatClient ? (
|
|
409
|
+
<Chat
|
|
410
|
+
client={chatClient}
|
|
411
|
+
customClasses={{
|
|
412
|
+
channelList:
|
|
413
|
+
'str-chat__channel-list str-chat__channel-list-react bg-transparent lg:border-r-2 border-r-0 border-[#0000000A]',
|
|
414
|
+
}}
|
|
415
|
+
>
|
|
416
|
+
{children}
|
|
417
|
+
</Chat>
|
|
418
|
+
) : (
|
|
419
|
+
children
|
|
420
|
+
)}
|
|
421
|
+
</MessagingContext.Provider>
|
|
433
422
|
)
|
|
434
423
|
}
|