@linktr.ee/messaging-react 3.10.0 → 3.11.0-rc-1783756377
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-415OfRhw.cjs +2 -0
- package/dist/Card-415OfRhw.cjs.map +1 -0
- package/dist/Card-BnbNynLQ.js +694 -0
- package/dist/Card-BnbNynLQ.js.map +1 -0
- package/dist/Card-UnwKmYzt.cjs +2 -0
- package/dist/Card-UnwKmYzt.cjs.map +1 -0
- package/dist/Card-qS17qnN0.js +103 -0
- package/dist/Card-qS17qnN0.js.map +1 -0
- package/dist/LoadingDots-Ct3WmVlT.js +59 -0
- package/dist/LoadingDots-Ct3WmVlT.js.map +1 -0
- package/dist/LoadingDots-D9GGphgM.cjs +2 -0
- package/dist/LoadingDots-D9GGphgM.cjs.map +1 -0
- package/dist/assets/index.css +1 -1
- package/dist/index-CyHyftBi.cjs +2 -0
- package/dist/index-CyHyftBi.cjs.map +1 -0
- package/dist/{index-BxzzWK4K.js → index-DJXjS2H9.js} +1397 -1358
- package/dist/index-DJXjS2H9.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +196 -101
- package/dist/index.js +1 -1
- package/dist/testing.d.ts +1 -0
- package/package.json +2 -2
- package/src/components/ChannelList/CustomChannelPreview.test.tsx +95 -0
- package/src/components/ChannelList/CustomChannelPreview.tsx +21 -9
- package/src/components/ChannelList/index.test.tsx +46 -0
- package/src/components/ChannelList/index.tsx +12 -0
- package/src/components/CustomMessage/CustomMessage.stories.tsx +54 -1
- package/src/components/CustomMessage/LockedAttachment/LockedAttachment.stories.tsx +541 -0
- package/src/components/CustomMessage/LockedAttachment/LockedAttachment.test.tsx +117 -0
- package/src/components/CustomMessage/LockedAttachment/components/Media/Card.tsx +358 -0
- package/src/components/{LockedAttachment/components/Received → CustomMessage/LockedAttachment/components/Media}/CardActions.tsx +9 -2
- package/src/components/CustomMessage/LockedAttachment/components/Media/types.ts +79 -0
- package/src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx +153 -0
- package/src/components/CustomMessage/LockedAttachment/components/Text/types.ts +58 -0
- package/src/components/{LockedAttachment → CustomMessage/LockedAttachment}/components/_shared/CardBody.tsx +8 -7
- package/src/components/CustomMessage/LockedAttachment/components/_shared/CardThumbnail.tsx +92 -0
- package/src/components/{LockedAttachment → CustomMessage/LockedAttachment}/components/_shared/GalleryThumbnail.tsx +31 -39
- package/src/components/CustomMessage/LockedAttachment/components/_shared/LoadingDots.tsx +36 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/LockBadge.tsx +63 -0
- package/src/components/{LockedAttachment/components/_shared/LockedCardShell.tsx → CustomMessage/LockedAttachment/components/_shared/MediaShell.tsx} +8 -8
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PreviewToggle.tsx +58 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PriceLockRow.tsx +21 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PurchaseStatusBadge.tsx +74 -0
- package/src/components/{LockedAttachment/components/_shared/LockedThumbnail.tsx → CustomMessage/LockedAttachment/components/_shared/SingleThumbnail.tsx} +11 -7
- package/src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx +29 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/TextShell.tsx +28 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.test.ts +67 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.ts +89 -0
- package/src/components/CustomMessage/LockedAttachment/components/_shared/useReceivedSource.ts +83 -0
- package/src/components/CustomMessage/LockedAttachment/index.tsx +105 -0
- package/src/components/CustomMessage/LockedAttachment/types.ts +44 -0
- package/src/components/CustomMessage/MessageTag.tsx +8 -0
- package/src/components/CustomMessage/context.tsx +1 -1
- package/src/components/CustomMessage/index.tsx +76 -42
- package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +5 -3
- package/src/index.ts +3 -8
- package/src/stream-custom-data.ts +1 -0
- package/src/styles.css +12 -0
- package/src/types.ts +35 -2
- package/dist/Card-B-L2MST4.js +0 -107
- package/dist/Card-B-L2MST4.js.map +0 -1
- package/dist/Card-B56QxJW3.cjs +0 -2
- package/dist/Card-B56QxJW3.cjs.map +0 -1
- package/dist/Card-Bqh-BQaX.js +0 -132
- package/dist/Card-Bqh-BQaX.js.map +0 -1
- package/dist/Card-ZCE6Lhfc.cjs +0 -2
- package/dist/Card-ZCE6Lhfc.cjs.map +0 -1
- package/dist/Card-g4JD-2ES.js +0 -163
- package/dist/Card-g4JD-2ES.js.map +0 -1
- package/dist/Card-wac6AMNc.cjs +0 -2
- package/dist/Card-wac6AMNc.cjs.map +0 -1
- package/dist/LockedThumbnail-BAQmoIff.js +0 -220
- package/dist/LockedThumbnail-BAQmoIff.js.map +0 -1
- package/dist/LockedThumbnail-Cr0Gqs3Y.cjs +0 -2
- package/dist/LockedThumbnail-Cr0Gqs3Y.cjs.map +0 -1
- package/dist/index-BPhZyaxT.cjs +0 -2
- package/dist/index-BPhZyaxT.cjs.map +0 -1
- package/dist/index-BxzzWK4K.js.map +0 -1
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +0 -450
- package/src/components/LockedAttachment/components/Composer/Card.tsx +0 -221
- package/src/components/LockedAttachment/components/Composer/index.ts +0 -2
- package/src/components/LockedAttachment/components/Received/Card.tsx +0 -191
- package/src/components/LockedAttachment/components/Received/index.ts +0 -2
- package/src/components/LockedAttachment/components/Sent/Card.tsx +0 -177
- package/src/components/LockedAttachment/components/Sent/index.ts +0 -2
- package/src/components/LockedAttachment/components/_shared/LockBadge.tsx +0 -39
- package/src/components/LockedAttachment/index.tsx +0 -63
- package/src/components/LockedAttachment/types.ts +0 -51
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-CyHyftBi.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.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
|
@@ -6,7 +6,9 @@ import { ChannelPreviewUIComponentProps } from 'stream-chat-react';
|
|
|
6
6
|
import { ChannelSort } from 'stream-chat';
|
|
7
7
|
import { ComponentType } from 'react';
|
|
8
8
|
import { default as default_2 } from 'react';
|
|
9
|
+
import { Dispatch } from 'react';
|
|
9
10
|
import { EmptyStateIndicatorProps } from 'stream-chat-react';
|
|
11
|
+
import { Event as Event_2 } from 'stream-chat';
|
|
10
12
|
import { FC } from 'react';
|
|
11
13
|
import { InfiniteScrollProps } from 'stream-chat-react';
|
|
12
14
|
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
@@ -14,6 +16,7 @@ import { LocalMessage } from 'stream-chat';
|
|
|
14
16
|
import { MessagingUser } from '@linktr.ee/messaging-core';
|
|
15
17
|
import { Provider } from 'react';
|
|
16
18
|
import { SendMessageAPIResponse } from 'stream-chat';
|
|
19
|
+
import { SetStateAction } from 'react';
|
|
17
20
|
import { StreamChat } from 'stream-chat';
|
|
18
21
|
import { StreamChatService } from '@linktr.ee/messaging-core';
|
|
19
22
|
import { StreamChatServiceConfig } from '@linktr.ee/messaging-core';
|
|
@@ -153,8 +156,37 @@ export declare interface ChannelListProps {
|
|
|
153
156
|
* Falls back to message.text when no matching translation exists.
|
|
154
157
|
*/
|
|
155
158
|
viewerLanguage?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Lock the visible channel order so live events don't promote a channel to
|
|
161
|
+
* the top. Forwarded to Stream's `<ChannelList>`. Note `lockChannelOrder`
|
|
162
|
+
* alone doesn't cover `notification.message_new` or `channel.visible`; pair it
|
|
163
|
+
* with the event handlers below to fully neutralize promotion.
|
|
164
|
+
*/
|
|
165
|
+
lockChannelOrder?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Live channel-list event handlers forwarded verbatim to Stream's
|
|
168
|
+
* `<ChannelList>`. Left undefined, Stream applies its default "move the
|
|
169
|
+
* changed channel to the top" behaviour.
|
|
170
|
+
*
|
|
171
|
+
* Hosts that order by a custom channel field (`last_conversation_at` for the
|
|
172
|
+
* inbox, `priority_score` for Spotlight) use these to neutralize promotion on
|
|
173
|
+
* new-message / visibility events and re-sort on `channel.updated` instead.
|
|
174
|
+
* Each receives Stream's `setChannels` dispatcher and the triggering event.
|
|
175
|
+
* See MES-1214 / MES-1219.
|
|
176
|
+
*/
|
|
177
|
+
onMessageNewHandler?: ChannelListReorderHandler;
|
|
178
|
+
onMessageNew?: ChannelListReorderHandler;
|
|
179
|
+
onChannelVisible?: ChannelListReorderHandler;
|
|
180
|
+
onAddedToChannel?: ChannelListReorderHandler;
|
|
181
|
+
onChannelUpdated?: ChannelListReorderHandler;
|
|
156
182
|
}
|
|
157
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Signature of Stream's `<ChannelList>` live-event handlers: mutate the loaded
|
|
186
|
+
* channel array via `setChannels` in response to a websocket `event`.
|
|
187
|
+
*/
|
|
188
|
+
declare type ChannelListReorderHandler = (setChannels: Dispatch<SetStateAction<Channel[]>>, event: Event_2) => void;
|
|
189
|
+
|
|
158
190
|
declare type ChannelMember = ChannelMembers[string];
|
|
159
191
|
|
|
160
192
|
declare type ChannelMembers = NonNullable<Channel['state']>['members'];
|
|
@@ -404,44 +436,12 @@ export declare interface ChannelViewProps {
|
|
|
404
436
|
onParticipantNameClick?: () => void;
|
|
405
437
|
}
|
|
406
438
|
|
|
407
|
-
export declare interface ComposerCardProps extends LockedAttachmentBaseProps {
|
|
408
|
-
/** Placeholder shown in the title slot before the composer types one. */
|
|
409
|
-
placeholderTitle?: string;
|
|
410
|
-
/** Placeholder shown in the amount slot before one is configured. */
|
|
411
|
-
placeholderAmountText?: string;
|
|
412
|
-
/**
|
|
413
|
-
* When provided, renders a dismiss X in the thumbnail corner. Called when
|
|
414
|
-
* the composer clicks it to remove the attachment.
|
|
415
|
-
*/
|
|
416
|
-
onDismiss?: () => void;
|
|
417
|
-
/** Fired the first time the composer taps the thumbnail to preview. */
|
|
418
|
-
onPreviewClick?: () => void;
|
|
419
|
-
/**
|
|
420
|
-
* Lazily loads the underlying source so the composer can preview the
|
|
421
|
-
* attachment they're about to send. Called the first time the thumbnail is
|
|
422
|
-
* tapped; the returned source is cached and reused on subsequent toggles.
|
|
423
|
-
*/
|
|
424
|
-
onFetchSource?: () => Promise<LockedAttachmentSource | void>;
|
|
425
|
-
/**
|
|
426
|
-
* When provided, renders a pencil button in the body bottom-right that the
|
|
427
|
-
* composer can use to edit the attachment metadata (e.g. open the price /
|
|
428
|
-
* gallery editor). Matches the Composer "Button" instance in Figma.
|
|
429
|
-
*/
|
|
430
|
-
onEditClick?: () => void;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
439
|
/** Shared props for the `Composer` state of every attachment type. */
|
|
434
440
|
declare interface ComposerExtras {
|
|
435
441
|
/** Renders a dismiss `×` button overlaid on the attachment. */
|
|
436
442
|
onDismiss?: () => void;
|
|
437
443
|
}
|
|
438
444
|
|
|
439
|
-
/**
|
|
440
|
-
* @deprecated Renamed to `SentCardProps`. Drafting usages (with `onDismiss`)
|
|
441
|
-
* should migrate to `ComposerCardProps`.
|
|
442
|
-
*/
|
|
443
|
-
export declare type CreatorCardProps = SentCardProps;
|
|
444
|
-
|
|
445
445
|
export declare const CustomMessageProvider: Provider<Partial<CustomMessageRegistry>>;
|
|
446
446
|
|
|
447
447
|
export declare interface CustomMessageRegistry {
|
|
@@ -450,6 +450,19 @@ export declare interface CustomMessageRegistry {
|
|
|
450
450
|
|
|
451
451
|
declare type DmAgentSystemType = 'SYSTEM_DM_AGENT_PAUSED' | 'SYSTEM_DM_AGENT_RESUMED';
|
|
452
452
|
|
|
453
|
+
declare type DraftProps = MediaCardDraftProps & {
|
|
454
|
+
/** Drafting is always the sender — doesn't apply here. */
|
|
455
|
+
isMine?: never;
|
|
456
|
+
/**
|
|
457
|
+
* "text" renders as a chat bubble showing the real draft `text` instead of
|
|
458
|
+
* a media thumbnail card. Media-only fields below are ignored in text mode.
|
|
459
|
+
* Defaults to `"media"`.
|
|
460
|
+
*/
|
|
461
|
+
contentType?: 'text' | 'media';
|
|
462
|
+
/** The message's own text, shown as-is (not redacted yet). Only used when `contentType` is `"text"`. */
|
|
463
|
+
renderedText?: default_2.ReactNode;
|
|
464
|
+
};
|
|
465
|
+
|
|
453
466
|
export declare interface Faq {
|
|
454
467
|
id: string;
|
|
455
468
|
question: string;
|
|
@@ -479,6 +492,9 @@ export declare interface FaqListProps {
|
|
|
479
492
|
avatarName?: string;
|
|
480
493
|
}
|
|
481
494
|
|
|
495
|
+
/** Fetches the underlying source; `void` return means none available. */
|
|
496
|
+
declare type FetchSourceHandler = () => Promise<LockedAttachmentSource | void>;
|
|
497
|
+
|
|
482
498
|
declare interface FileAttachmentSharedProps extends MessageAttachmentBaseProps {
|
|
483
499
|
/** Source URL of the file (used as the download target). */
|
|
484
500
|
src?: string;
|
|
@@ -728,54 +744,111 @@ export declare interface LinkAttachmentSentCardProps extends LinkAttachmentBaseP
|
|
|
728
744
|
onClick?: () => void;
|
|
729
745
|
}
|
|
730
746
|
|
|
731
|
-
export declare const LockedAttachment:
|
|
732
|
-
Composer: (props: ComposerCardProps) => JSX_2.Element;
|
|
733
|
-
Sent: (props: SentCardProps) => JSX_2.Element;
|
|
734
|
-
Received: (props: ReceivedCardProps) => JSX_2.Element;
|
|
735
|
-
Creator: (props: SentCardProps) => JSX_2.Element;
|
|
736
|
-
Visitor: (props: ReceivedCardProps) => JSX_2.Element;
|
|
737
|
-
};
|
|
738
|
-
|
|
739
|
-
declare interface LockedAttachmentBaseProps {
|
|
740
|
-
title?: string;
|
|
741
|
-
mimeType?: string;
|
|
742
|
-
thumbnailUrl?: string;
|
|
743
|
-
detail?: string;
|
|
744
|
-
amountText?: string;
|
|
745
|
-
paymentStatus?: PaymentStatus;
|
|
746
|
-
/**
|
|
747
|
-
* When provided with 2+ items, the card renders as a mixed-media carousel
|
|
748
|
-
* (e.g. a couple of photos + a video) instead of a single thumbnail. Each
|
|
749
|
-
* item brings its own thumbnail and optional source so that
|
|
750
|
-
* `LockedAttachment.Composer` / `.Sent` / `.Received` can all share the
|
|
751
|
-
* same carousel chrome.
|
|
752
|
-
*/
|
|
753
|
-
gallery?: LockedAttachmentGalleryItem[];
|
|
754
|
-
}
|
|
747
|
+
export declare const LockedAttachment: default_2.FC<LockedAttachmentProps>;
|
|
755
748
|
|
|
756
749
|
export declare interface LockedAttachmentContextValue {
|
|
750
|
+
/** Whether the given message is mid-checkout. */
|
|
757
751
|
isUnlocking: (id: string) => boolean;
|
|
752
|
+
/** Opens the checkout flow for a message. */
|
|
758
753
|
onUnlockClick?: (message: LocalMessage, channel: Channel) => void;
|
|
754
|
+
/** Handles a Download click for a message. */
|
|
759
755
|
onDownloadClick?: (message: LocalMessage, channel: Channel) => void;
|
|
756
|
+
/** Reveals the locked media's source. Unused for text — payment writes `message.text` directly. */
|
|
760
757
|
onFetchSource?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource | void>;
|
|
761
758
|
}
|
|
762
759
|
|
|
763
760
|
export declare interface LockedAttachmentGalleryItem {
|
|
764
|
-
/**
|
|
761
|
+
/** Drives the per-item play/lock affordance. */
|
|
765
762
|
mimeType: string;
|
|
766
|
-
/** Poster image
|
|
763
|
+
/** Poster image, locked or unlocked. */
|
|
767
764
|
thumbnailUrl?: string;
|
|
768
|
-
/**
|
|
765
|
+
/** Media source, shown only when unlocked. */
|
|
769
766
|
sourceUrl?: string;
|
|
770
767
|
}
|
|
771
768
|
|
|
769
|
+
/**
|
|
770
|
+
* The card for a paid attachment — a still-drafting `isDraft` card, a static
|
|
771
|
+
* receiver-facing `isPreview` mockup, or a sent text/media card discriminated
|
|
772
|
+
* by `isMine` + `contentType`. Internally lazy-loads only the one underlying
|
|
773
|
+
* implementation the resolved branch needs.
|
|
774
|
+
*/
|
|
775
|
+
export declare type LockedAttachmentProps = DraftProps | PreviewProps | SentTextOwnProps | SentTextOtherProps | SentMediaOwnProps | SentMediaOtherProps;
|
|
776
|
+
|
|
772
777
|
export declare interface LockedAttachmentSource {
|
|
773
|
-
/** Proxied URL
|
|
778
|
+
/** Proxied URL for in-app playback. */
|
|
774
779
|
sourceUrl: string;
|
|
775
|
-
/**
|
|
780
|
+
/** Opened when the visitor clicks Download. */
|
|
776
781
|
redeemUrl?: string;
|
|
777
|
-
/**
|
|
782
|
+
/** Overrides the metadata thumbnail when present. */
|
|
783
|
+
thumbnailUrl?: string;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
declare interface MediaCardBaseProps {
|
|
787
|
+
/** Attachment title. */
|
|
788
|
+
title?: string;
|
|
789
|
+
/** Fallback shown when `title` is unset. */
|
|
790
|
+
placeholderTitle?: string;
|
|
791
|
+
/** Drives icon/thumbnail rendering. */
|
|
792
|
+
mimeType?: string;
|
|
793
|
+
/** Poster image, locked or unlocked. */
|
|
778
794
|
thumbnailUrl?: string;
|
|
795
|
+
/** Secondary description text. */
|
|
796
|
+
detail?: string;
|
|
797
|
+
/** Amount label. */
|
|
798
|
+
amountText?: string;
|
|
799
|
+
/** 2+ items renders as a carousel instead of a single thumbnail. */
|
|
800
|
+
gallery?: LockedAttachmentGalleryItem[];
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
declare interface MediaCardDraftProps extends MediaCardBaseProps {
|
|
804
|
+
/** True while composing — shows the real (unredacted) thumbnail. */
|
|
805
|
+
isDraft: true;
|
|
806
|
+
isPreview?: false;
|
|
807
|
+
/** Fallback amount before a price is set. */
|
|
808
|
+
placeholderAmountText?: string;
|
|
809
|
+
/** Lazily fetches the source on first tap; cached and reused after. */
|
|
810
|
+
onFetchSource?: FetchSourceHandler;
|
|
811
|
+
/** Fired on first tap to preview. */
|
|
812
|
+
onPreviewClick?: () => void;
|
|
813
|
+
/** Removes the draft attachment. */
|
|
814
|
+
onDismiss?: () => void;
|
|
815
|
+
/** Renders a pencil button to edit the attachment metadata. */
|
|
816
|
+
onEditClick?: () => void;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
declare type MediaCardOtherProps = MediaCardSentBaseProps & {
|
|
820
|
+
/** Recipient's view. */
|
|
821
|
+
isMine: false;
|
|
822
|
+
/** Opens checkout on click. Omit to hide the button. */
|
|
823
|
+
onUnlockClick?: () => void;
|
|
824
|
+
/** Omit to hide the Download button. */
|
|
825
|
+
onDownloadClick?: () => void;
|
|
826
|
+
/** Spinner on Unlock while checkout runs. */
|
|
827
|
+
isUnlocking?: boolean;
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
declare type MediaCardOwnProps = MediaCardSentBaseProps & {
|
|
831
|
+
/** Sender's own view. */
|
|
832
|
+
isMine: true;
|
|
833
|
+
/** Fired on first tap to preview own attachment. */
|
|
834
|
+
onPreviewClick?: () => void;
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
declare interface MediaCardPreviewProps extends MediaCardBaseProps {
|
|
838
|
+
/** True to render exactly as the recipient will see it before purchase — always locked/blurred. */
|
|
839
|
+
isDraft?: false;
|
|
840
|
+
isPreview: true;
|
|
841
|
+
/** Fallback amount before a price is set. */
|
|
842
|
+
placeholderAmountText?: string;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
declare interface MediaCardSentBaseProps extends MediaCardBaseProps {
|
|
846
|
+
/** False once sent. */
|
|
847
|
+
isDraft?: false;
|
|
848
|
+
isPreview?: false;
|
|
849
|
+
/** Drives the lock/skeleton/badge state. */
|
|
850
|
+
paymentStatus?: PaymentStatus;
|
|
851
|
+
onFetchSource?: FetchSourceHandler;
|
|
779
852
|
}
|
|
780
853
|
|
|
781
854
|
export declare const MediaMessage: default_2.FC<MediaMessageProps> & {
|
|
@@ -1233,6 +1306,7 @@ export declare interface MessageMetadata {
|
|
|
1233
1306
|
amount_text?: string;
|
|
1234
1307
|
payment_status?: PaymentStatus;
|
|
1235
1308
|
attachment_title?: string;
|
|
1309
|
+
attachment_content_type?: 'text' | 'media';
|
|
1236
1310
|
attachment_mime_type?: string;
|
|
1237
1311
|
attachment_thumbnail?: string;
|
|
1238
1312
|
attachment_detail?: string;
|
|
@@ -1445,6 +1519,16 @@ declare interface PdfAttachmentSharedProps extends MessageAttachmentBaseProps {
|
|
|
1445
1519
|
onClick?: (index: number) => boolean | void;
|
|
1446
1520
|
}
|
|
1447
1521
|
|
|
1522
|
+
declare type PreviewProps = MediaCardPreviewProps & {
|
|
1523
|
+
/** Drafting is always the sender — doesn't apply here. */
|
|
1524
|
+
isMine?: never;
|
|
1525
|
+
/**
|
|
1526
|
+
* "text" renders as a chat bubble instead of a media thumbnail card.
|
|
1527
|
+
* Media-only fields below are ignored in text mode. Defaults to `"media"`.
|
|
1528
|
+
*/
|
|
1529
|
+
contentType?: 'text' | 'media';
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1448
1532
|
export declare interface ReceivedBubbleProps extends MessageBubbleBaseProps {
|
|
1449
1533
|
/**
|
|
1450
1534
|
* Optional header rendered above the text inside the bubble — used by the
|
|
@@ -1453,31 +1537,6 @@ export declare interface ReceivedBubbleProps extends MessageBubbleBaseProps {
|
|
|
1453
1537
|
header?: default_2.ReactNode;
|
|
1454
1538
|
}
|
|
1455
1539
|
|
|
1456
|
-
export declare interface ReceivedCardProps extends LockedAttachmentBaseProps {
|
|
1457
|
-
/**
|
|
1458
|
-
* Called when the recipient clicks Unlock on an unpaid attachment.
|
|
1459
|
-
* Use this to open a checkout flow. Omit to hide the Unlock button.
|
|
1460
|
-
*/
|
|
1461
|
-
onUnlockClick?: () => void;
|
|
1462
|
-
/**
|
|
1463
|
-
* Called to fetch the attachment source — fired automatically when
|
|
1464
|
-
* `paymentStatus` transitions to `'paid'`, or immediately on click when
|
|
1465
|
-
* `paymentStatus` is already `'paid'`. Return a `LockedAttachmentSource`
|
|
1466
|
-
* to unlock the card.
|
|
1467
|
-
*/
|
|
1468
|
-
onFetchSource?: () => Promise<LockedAttachmentSource | void>;
|
|
1469
|
-
/**
|
|
1470
|
-
* Called when the recipient clicks Download on an unlocked card.
|
|
1471
|
-
* Omit to hide the Download button.
|
|
1472
|
-
*/
|
|
1473
|
-
onDownloadClick?: () => void;
|
|
1474
|
-
/**
|
|
1475
|
-
* When true, shows a loading spinner on the Unlock button.
|
|
1476
|
-
* Driven by the LockedAttachmentContext (e.g. checkout in progress).
|
|
1477
|
-
*/
|
|
1478
|
-
isUnlocking?: boolean;
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
1540
|
/**
|
|
1482
1541
|
* Resolves the member to display as the conversation's "other party".
|
|
1483
1542
|
*
|
|
@@ -1503,17 +1562,56 @@ export declare function resolveParticipantDisplayName(user?: ParticipantDisplayU
|
|
|
1503
1562
|
export declare interface SentBubbleProps extends MessageBubbleBaseProps {
|
|
1504
1563
|
}
|
|
1505
1564
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1565
|
+
declare type SentMediaOtherProps = MediaCardOtherProps & {
|
|
1566
|
+
contentType?: 'media';
|
|
1567
|
+
};
|
|
1568
|
+
|
|
1569
|
+
declare type SentMediaOwnProps = MediaCardOwnProps & {
|
|
1570
|
+
contentType?: 'media';
|
|
1571
|
+
/** Sender's view has no unlock/download flow — doesn't apply here. */
|
|
1572
|
+
onUnlockClick?: never;
|
|
1573
|
+
isUnlocking?: never;
|
|
1574
|
+
onDownloadClick?: never;
|
|
1575
|
+
};
|
|
1576
|
+
|
|
1577
|
+
declare type SentTextOtherProps = TextCardOtherProps & {
|
|
1578
|
+
contentType: 'text';
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
declare type SentTextOwnProps = TextCardOwnProps & {
|
|
1582
|
+
contentType: 'text';
|
|
1583
|
+
/** Sender's view has no unlock flow — doesn't apply here. */
|
|
1584
|
+
onUnlockClick?: never;
|
|
1585
|
+
isUnlocking?: never;
|
|
1586
|
+
};
|
|
1587
|
+
|
|
1588
|
+
declare interface TextCardBaseProps {
|
|
1589
|
+
/** Amount label. */
|
|
1590
|
+
amountText?: string;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
declare type TextCardOtherProps = TextCardSentBaseProps & {
|
|
1594
|
+
/** Recipient's view. */
|
|
1595
|
+
isMine: false;
|
|
1596
|
+
/** Spinner on Unlock while checkout runs. */
|
|
1597
|
+
isUnlocking?: boolean;
|
|
1598
|
+
/** Opens checkout on click. Omit to hide the button. */
|
|
1599
|
+
onUnlockClick?: () => void;
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
declare type TextCardOwnProps = TextCardSentBaseProps & {
|
|
1603
|
+
/** Sender's own view. */
|
|
1604
|
+
isMine: true;
|
|
1605
|
+
};
|
|
1606
|
+
|
|
1607
|
+
declare interface TextCardSentBaseProps extends TextCardBaseProps {
|
|
1608
|
+
/** False once sent. */
|
|
1609
|
+
isDraft?: false;
|
|
1610
|
+
isPreview?: false;
|
|
1611
|
+
/** Revealed content once paid. */
|
|
1612
|
+
renderedText?: default_2.ReactNode;
|
|
1613
|
+
/** Drives the lock/skeleton/badge state. */
|
|
1614
|
+
paymentStatus?: PaymentStatus;
|
|
1517
1615
|
}
|
|
1518
1616
|
|
|
1519
1617
|
/**
|
|
@@ -1584,9 +1682,6 @@ declare interface VideoAttachmentSharedProps extends MessageAttachmentBaseProps
|
|
|
1584
1682
|
onClick?: (index: number) => boolean | void;
|
|
1585
1683
|
}
|
|
1586
1684
|
|
|
1587
|
-
/** @deprecated Renamed to `ReceivedCardProps`. */
|
|
1588
|
-
export declare type VisitorCardProps = ReceivedCardProps;
|
|
1589
|
-
|
|
1590
1685
|
export declare type VoteSelection = 'up' | 'down' | null;
|
|
1591
1686
|
|
|
1592
1687
|
export { }
|
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 u, i as c, j as L, k as h, l as d, m as p, n as v, o as C, p as A, q as k, s as F, t as b, u as P, v as f, w as x, x as y, y as B, z as S, B as q, D as z, E as D, G as E, H as V } 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 u, i as c, j as L, k as h, l as d, m as p, n as v, o as C, p as A, q as k, s as F, t as b, u as P, v as f, w as x, x as y, y as B, z as S, B as q, D as z, E as D, G as E, H as V } from "./index-DJXjS2H9.js";
|
|
2
2
|
export {
|
|
3
3
|
e as ActionButton,
|
|
4
4
|
t as Avatar,
|
package/dist/testing.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export declare interface MessageMetadata {
|
|
|
47
47
|
amount_text?: string;
|
|
48
48
|
payment_status?: PaymentStatus;
|
|
49
49
|
attachment_title?: string;
|
|
50
|
+
attachment_content_type?: 'text' | 'media';
|
|
50
51
|
attachment_mime_type?: string;
|
|
51
52
|
attachment_thumbnail?: string;
|
|
52
53
|
attachment_detail?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0-rc-1783756377",
|
|
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": "
|
|
53
|
+
"@linktr.ee/messaging-core": "2.3.0-rc-1783756377",
|
|
54
54
|
"@phosphor-icons/react": "^2.1.10"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
@@ -260,6 +260,101 @@ describe('CustomChannelPreview', () => {
|
|
|
260
260
|
expect(screen.getByText('No messages yet')).toBeInTheDocument()
|
|
261
261
|
})
|
|
262
262
|
|
|
263
|
+
it('shows a locked indicator for a text-only attachment message, even when paid', () => {
|
|
264
|
+
// The channel-list preview always shows the locked wording for an
|
|
265
|
+
// attachment-type message and never echoes `message.text` — the
|
|
266
|
+
// revealed content is only ever shown inside the full conversation.
|
|
267
|
+
const channel = createMockChannel([
|
|
268
|
+
{
|
|
269
|
+
id: 'msg-1',
|
|
270
|
+
text: 'REDACTED',
|
|
271
|
+
type: 'regular',
|
|
272
|
+
created_at: new Date('2026-01-01T00:00:00.000Z'),
|
|
273
|
+
user: { id: 'participant-1', name: 'Alice' },
|
|
274
|
+
metadata: {
|
|
275
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
276
|
+
attachment_content_type: 'text',
|
|
277
|
+
payment_status: 'paid',
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
])
|
|
281
|
+
|
|
282
|
+
renderWithProviders(
|
|
283
|
+
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
expect(screen.getByText('🔒 Sent a locked message')).toBeInTheDocument()
|
|
287
|
+
expect(screen.queryByText(/REDACTED/)).not.toBeInTheDocument()
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('shows a locked indicator for an unpaid text-only attachment message', () => {
|
|
291
|
+
const channel = createMockChannel([
|
|
292
|
+
{
|
|
293
|
+
id: 'msg-1',
|
|
294
|
+
text: 'REDACTED',
|
|
295
|
+
type: 'regular',
|
|
296
|
+
created_at: new Date('2026-01-01T00:00:00.000Z'),
|
|
297
|
+
user: { id: 'participant-1', name: 'Alice' },
|
|
298
|
+
metadata: {
|
|
299
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
300
|
+
attachment_content_type: 'text',
|
|
301
|
+
payment_status: 'pending',
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
])
|
|
305
|
+
|
|
306
|
+
renderWithProviders(
|
|
307
|
+
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
expect(screen.getByText('🔒 Sent a locked message')).toBeInTheDocument()
|
|
311
|
+
expect(screen.queryByText(/REDACTED/)).not.toBeInTheDocument()
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
it('shows a locked indicator for a media attachment message, even when paid', () => {
|
|
315
|
+
const channel = createMockChannel([
|
|
316
|
+
{
|
|
317
|
+
id: 'msg-1',
|
|
318
|
+
type: 'regular',
|
|
319
|
+
created_at: new Date('2026-01-01T00:00:00.000Z'),
|
|
320
|
+
user: { id: 'participant-1', name: 'Alice' },
|
|
321
|
+
metadata: {
|
|
322
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
323
|
+
attachment_content_type: 'media',
|
|
324
|
+
payment_status: 'paid',
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
])
|
|
328
|
+
|
|
329
|
+
renderWithProviders(
|
|
330
|
+
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
expect(screen.getByText('🔒 Sent a locked attachment')).toBeInTheDocument()
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
it('shows a locked indicator for an unpaid media attachment message', () => {
|
|
337
|
+
const channel = createMockChannel([
|
|
338
|
+
{
|
|
339
|
+
id: 'msg-1',
|
|
340
|
+
type: 'regular',
|
|
341
|
+
created_at: new Date('2026-01-01T00:00:00.000Z'),
|
|
342
|
+
user: { id: 'participant-1', name: 'Alice' },
|
|
343
|
+
metadata: {
|
|
344
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
345
|
+
attachment_content_type: 'media',
|
|
346
|
+
payment_status: 'pending',
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
])
|
|
350
|
+
|
|
351
|
+
renderWithProviders(
|
|
352
|
+
<CustomChannelPreview {...defaultProps} channel={channel} />
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
expect(screen.getByText('🔒 Sent a locked attachment')).toBeInTheDocument()
|
|
356
|
+
})
|
|
357
|
+
|
|
263
358
|
it('updates starred state when the channel membership changes', () => {
|
|
264
359
|
const channel = createMockChannel([])
|
|
265
360
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ChannelPreviewUIComponentProps,
|
|
5
|
+
useChatContext,
|
|
6
|
+
} from 'stream-chat-react'
|
|
4
7
|
|
|
5
8
|
import { useChannelStar } from '../../hooks/useChannelStar'
|
|
6
9
|
import { formatRelativeTime } from '../../utils/formatRelativeTime'
|
|
@@ -85,14 +88,23 @@ const CustomChannelPreview = React.memo<ChannelPreviewUIComponentProps>(
|
|
|
85
88
|
viewerLanguage,
|
|
86
89
|
})
|
|
87
90
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
return displayText ?
|
|
91
|
+
const { custom_type, attachment_content_type } =
|
|
92
|
+
lastMessage?.metadata || {}
|
|
93
|
+
|
|
94
|
+
if (custom_type === 'MESSAGE_TIP') {
|
|
95
|
+
return displayText ? displayText : 'Sent a tip'
|
|
96
|
+
}
|
|
97
|
+
if (custom_type === 'MESSAGE_PAID') {
|
|
98
|
+
return displayText ? displayText : 'Sent a message'
|
|
99
|
+
}
|
|
100
|
+
if (custom_type === 'MESSAGE_ATTACHMENT') {
|
|
101
|
+
if (attachment_content_type === 'text') {
|
|
102
|
+
return '🔒 Sent a locked message'
|
|
103
|
+
}
|
|
104
|
+
if (attachment_content_type === 'media') {
|
|
105
|
+
return '🔒 Sent a locked attachment'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
96
108
|
|
|
97
109
|
if (displayText) return displayText
|
|
98
110
|
|
|
@@ -125,6 +125,52 @@ describe('ChannelList', () => {
|
|
|
125
125
|
})
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
+
it('leaves live-reorder controls undefined by default so Stream keeps its default ordering', () => {
|
|
129
|
+
renderWithProviders(<ChannelList {...defaultProps} />)
|
|
130
|
+
|
|
131
|
+
expect(streamChannelListMock).toHaveBeenCalledOnce()
|
|
132
|
+
const streamProps = streamChannelListMock.mock.calls[0][0] as Record<
|
|
133
|
+
string,
|
|
134
|
+
unknown
|
|
135
|
+
>
|
|
136
|
+
expect(streamProps.lockChannelOrder).toBeUndefined()
|
|
137
|
+
expect(streamProps.onMessageNewHandler).toBeUndefined()
|
|
138
|
+
expect(streamProps.onMessageNew).toBeUndefined()
|
|
139
|
+
expect(streamProps.onChannelVisible).toBeUndefined()
|
|
140
|
+
expect(streamProps.onAddedToChannel).toBeUndefined()
|
|
141
|
+
expect(streamProps.onChannelUpdated).toBeUndefined()
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('forwards live-reorder controls to Stream ChannelList when provided', () => {
|
|
145
|
+
const onMessageNewHandler = vi.fn()
|
|
146
|
+
const onMessageNew = vi.fn()
|
|
147
|
+
const onChannelVisible = vi.fn()
|
|
148
|
+
const onAddedToChannel = vi.fn()
|
|
149
|
+
const onChannelUpdated = vi.fn()
|
|
150
|
+
|
|
151
|
+
renderWithProviders(
|
|
152
|
+
<ChannelList
|
|
153
|
+
{...defaultProps}
|
|
154
|
+
lockChannelOrder
|
|
155
|
+
onMessageNewHandler={onMessageNewHandler}
|
|
156
|
+
onMessageNew={onMessageNew}
|
|
157
|
+
onChannelVisible={onChannelVisible}
|
|
158
|
+
onAddedToChannel={onAddedToChannel}
|
|
159
|
+
onChannelUpdated={onChannelUpdated}
|
|
160
|
+
/>
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
expect(streamChannelListMock).toHaveBeenCalledOnce()
|
|
164
|
+
expect(streamChannelListMock.mock.calls[0][0]).toMatchObject({
|
|
165
|
+
lockChannelOrder: true,
|
|
166
|
+
onMessageNewHandler,
|
|
167
|
+
onMessageNew,
|
|
168
|
+
onChannelVisible,
|
|
169
|
+
onAddedToChannel,
|
|
170
|
+
onChannelUpdated,
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
128
174
|
it('wraps channelRenderFilterFn to restore pending messages and delegates to consumer filter', () => {
|
|
129
175
|
const filterFn = vi.fn((channels: Channel[]) => channels)
|
|
130
176
|
|
|
@@ -32,6 +32,12 @@ export const ChannelList = React.memo<ChannelListProps>(
|
|
|
32
32
|
channelPreview,
|
|
33
33
|
renderMessagePreview,
|
|
34
34
|
viewerLanguage,
|
|
35
|
+
lockChannelOrder,
|
|
36
|
+
onMessageNewHandler,
|
|
37
|
+
onMessageNew,
|
|
38
|
+
onChannelVisible,
|
|
39
|
+
onAddedToChannel,
|
|
40
|
+
onChannelUpdated,
|
|
35
41
|
}) => {
|
|
36
42
|
// Track renders
|
|
37
43
|
const renderCountRef = React.useRef(0)
|
|
@@ -100,6 +106,12 @@ export const ChannelList = React.memo<ChannelListProps>(
|
|
|
100
106
|
allowNewMessagesFromUnfilteredChannels
|
|
101
107
|
}
|
|
102
108
|
channelRenderFilterFn={wrappedChannelRenderFilterFn}
|
|
109
|
+
lockChannelOrder={lockChannelOrder}
|
|
110
|
+
onMessageNewHandler={onMessageNewHandler}
|
|
111
|
+
onMessageNew={onMessageNew}
|
|
112
|
+
onChannelVisible={onChannelVisible}
|
|
113
|
+
onAddedToChannel={onAddedToChannel}
|
|
114
|
+
onChannelUpdated={onChannelUpdated}
|
|
103
115
|
Paginator={Paginator}
|
|
104
116
|
Preview={CustomChannelPreview}
|
|
105
117
|
EmptyStateIndicator={customEmptyStateIndicator}
|