stream-chat-angular 4.32.2 → 4.34.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/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +67 -9
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/custom-templates.service.js +5 -1
- package/esm2015/lib/message/message.component.js +2 -2
- package/esm2015/lib/message-list/message-list.component.js +62 -8
- package/esm2015/lib/types.js +1 -1
- package/fesm2015/stream-chat-angular.js +67 -9
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/custom-templates.service.d.ts +4 -0
- package/lib/message-list/message-list.component.d.ts +11 -2
- package/lib/types.d.ts +1 -0
- package/package.json +2 -2
- package/src/assets/version.ts +1 -1
|
@@ -20,7 +20,7 @@ import transliterate from '@stream-io/transliterate';
|
|
|
20
20
|
import * as i8 from 'angular-mentions';
|
|
21
21
|
import { MentionModule } from 'angular-mentions';
|
|
22
22
|
|
|
23
|
-
const version = '4.
|
|
23
|
+
const version = '4.34.0';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
|
|
@@ -2388,6 +2388,10 @@ class CustomTemplatesService {
|
|
|
2388
2388
|
* The template used to display the date separator inside the [message list](../components/MessageListComponent.mdx)
|
|
2389
2389
|
*/
|
|
2390
2390
|
this.dateSeparatorTemplate$ = new BehaviorSubject(undefined);
|
|
2391
|
+
/**
|
|
2392
|
+
* The template used to display the new messages indicator inside the [message list](../components/MessageListComponent.mdx)
|
|
2393
|
+
*/
|
|
2394
|
+
this.newMessagesIndicatorTemplate$ = new BehaviorSubject(undefined);
|
|
2391
2395
|
}
|
|
2392
2396
|
}
|
|
2393
2397
|
CustomTemplatesService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: CustomTemplatesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -4635,7 +4639,7 @@ class MessageComponent {
|
|
|
4635
4639
|
}
|
|
4636
4640
|
}
|
|
4637
4641
|
MessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }, { token: CustomTemplatesService }, { token: i0.ChangeDetectorRef }, { token: ThemeService }, { token: DateParserService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4638
|
-
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", customActions: "customActions" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n \"\n data-testid=\"message-container\"\n (mouseleave)=\"isActionBoxOpen = false\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container *ngIf=\"themeVersion === '1'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n type=\"user\"\n location=\"message-sender\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-edit-in-progress]=\"isEditing\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n #messageActionsToggle\n class=\"\n str-chat__message-actions-container\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerClick\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"true\"\n [popperHideOnClickOutside]=\"true\"\n [popperHideOnMouseLeave]=\"false\"\n >\n <popper-content #popperContent>\n <ng-template\n #defaultMessageActionsBox\n let-isOpen=\"isOpen\"\n let-isMine=\"isMine\"\n let-enabledActions=\"enabledActions\"\n let-messageInput=\"message\"\n let-displayedActionsCountChangeHandler=\"displayedActionsCountChangeHandler\"\n let-isEditingChangeHandler=\"isEditingChangeHandler\"\n let-customActions=\"customActions\"\n >\n <stream-message-actions-box\n [isOpen]=\"isOpen\"\n [isMine]=\"isMine\"\n [enabledActions]=\"enabledActions\"\n [message]=\"messageInput\"\n [customActions]=\"customActions\"\n (displayedActionsCount)=\"\n displayedActionsCountChangeHandler($event)\n \"\n (isEditing)=\"isEditingChangeHandler($event)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageActionsBoxTemplate || defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </popper-content>\n <div\n class=\"str-chat__message-actions-box-button\"\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n >\n <stream-icon-placeholder\n icon=\"action-icon\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n str-chat__message-reply-in-thread-button\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reply-in-thread\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n str-chat__message-reactions-button\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reaction-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-isSelectorOpen=\"isSelectorOpen\"\n let-isSelectorOpenChangeHandler=\"isSelectorOpenChangeHandler\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [isSelectorOpen]=\"isSelectorOpen\"\n (isSelectorOpenChange)=\"isSelectorOpenChangeHandler($event)\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageReactionsTemplate || defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <!-- transform: translate3d(0, 0, 0) fixes scrolling issues on iOS, see: https://stackoverflow.com/questions/50105780/elements-disappear-when-scrolling-in-safari-webkit-transform-fix-only-works-t/50144295#50144295 -->\n <!-- transform: none is required when image carousel is open in order for the modal to be correctly positioned, see how the transform property changes the behavior of fixed positioned elements https://developer.mozilla.org/en-US/docs/Web/CSS/position -->\n <div\n class=\"str-chat__message-bubble\"\n style=\"transform: {{\n imageAttachmentModalState === 'opened'\n ? 'none'\n : 'translate3d(0, 0, 0)'\n }}\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n >\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div data-testid=\"text\">\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate || defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n *ngIf=\"themeVersion === '2'\"\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'outside-message-bubble', message: message }\n \"\n ></ng-container>\n\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'outside-message-bubble' }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <ng-container\n *ngTemplateOutlet=\"\n systemMessageTemplate || defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ messageInput?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [size]=\"20\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentListTemplate || defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<!-- We need these markups in slightly different positions in theme-v1 and theme-v2, this soultion makes that possible without duplicating the code -->\n<ng-template #messageDateAndSender let-position=\"position\">\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <ng-container\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n >\n <div\n class=\"str-chat__translation-notice\"\n *ngIf=\"shouldDisplayTranslationNotice\"\n data-testid=\"translation-notice\"\n >\n <button\n data-testid=\"see-original\"\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n translate\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n data-testid=\"see-translation\"\n *ngIf=\"displayedMessageTextContent === 'original'\"\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n translate\n >\n streamChat.See translation\n </button>\n </div>\n <div\n class=\"\n str-chat__message-data\n str-chat__message-simple-data\n str-chat__message-metadata\n \"\n >\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <ng-container *ngIf=\"themeVersion === '2'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customDeliveredStatusTemplate || defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </popper-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customSendingStatusTemplate || defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </popper-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customReadStatusTemplate || defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </popper-content>\n <stream-avatar-placeholder\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n type=\"user\"\n location=\"message-reader\"\n [user]=\"lastReadUser\"\n ></stream-avatar-placeholder>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton let-position=\"position\">\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n class=\"\n str-chat__message-simple-reply-button\n str-chat__message-replies-count-button-wrapper\n \"\n >\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n *ngIf=\"themeVersion === '1'\"\n stream-icon-placeholder\n icon=\"reply\"\n ></stream-icon-placeholder>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentListTemplate || defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size", "location", "channel", "user", "type", "initialsType"] }, { type: i3.NgxPopperjsContentComponent, selector: "popper-content" }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions", "customActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgxPopperjsDirective, selector: "[popper]", inputs: ["popperTimeout", "popperTimeoutAfterShow", "popperApplyClass", "popper", "popperDisabled", "popperPlacement", "popperApplyArrowClass", "popperPreventOverflow", "popperHideOnClickOutside", "popperTrigger", "popperStyles", "popperAriaDescribeBy", "popperAriaRole", "popperBoundaries", "popperCloseOnClickOutside", "popperDisableAnimation", "popperDisableStyle", "popperHideOnMouseLeave", "popperHideOnScroll", "popperAppendTo", "popperModifiers", "popperPositionFixed", "popperDelay", "popperShowOnStart", "popperTarget"], outputs: ["popperOnHidden", "popperOnShown", "popperOnUpdate"], exportAs: ["popper"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i9.TranslatePipe } });
|
|
4642
|
+
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", customActions: "customActions" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n \"\n data-testid=\"message-container\"\n (mouseleave)=\"isActionBoxOpen = false\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container *ngIf=\"themeVersion === '1'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n type=\"user\"\n location=\"message-sender\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-edit-in-progress]=\"isEditing\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n #messageActionsToggle\n class=\"\n str-chat__message-actions-container\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerClick\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"true\"\n [popperHideOnClickOutside]=\"true\"\n [popperHideOnMouseLeave]=\"false\"\n >\n <popper-content #popperContent>\n <ng-template\n #defaultMessageActionsBox\n let-isOpen=\"isOpen\"\n let-isMine=\"isMine\"\n let-enabledActions=\"enabledActions\"\n let-messageInput=\"message\"\n let-displayedActionsCountChangeHandler=\"displayedActionsCountChangeHandler\"\n let-isEditingChangeHandler=\"isEditingChangeHandler\"\n let-customActions=\"customActions\"\n >\n <stream-message-actions-box\n [isOpen]=\"isOpen\"\n [isMine]=\"isMine\"\n [enabledActions]=\"enabledActions\"\n [message]=\"messageInput\"\n [customActions]=\"customActions\"\n (displayedActionsCount)=\"\n displayedActionsCountChangeHandler($event)\n \"\n (isEditing)=\"isEditingChangeHandler($event)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageActionsBoxTemplate || defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </popper-content>\n <div\n class=\"str-chat__message-actions-box-button\"\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n >\n <stream-icon-placeholder\n icon=\"action-icon\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n str-chat__message-reply-in-thread-button\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reply-in-thread\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n str-chat__message-reactions-button\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reaction-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-isSelectorOpen=\"isSelectorOpen\"\n let-isSelectorOpenChangeHandler=\"isSelectorOpenChangeHandler\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [isSelectorOpen]=\"isSelectorOpen\"\n (isSelectorOpenChange)=\"isSelectorOpenChangeHandler($event)\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageReactionsTemplate || defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <!-- transform: translate3d(0, 0, 0) fixes scrolling issues on iOS, see: https://stackoverflow.com/questions/50105780/elements-disappear-when-scrolling-in-safari-webkit-transform-fix-only-works-t/50144295#50144295 -->\n <!-- transform: none is required when image carousel is open in order for the modal to be correctly positioned, see how the transform property changes the behavior of fixed positioned elements https://developer.mozilla.org/en-US/docs/Web/CSS/position -->\n <div\n class=\"str-chat__message-bubble\"\n style=\"transform: {{\n imageAttachmentModalState === 'opened'\n ? 'none'\n : 'translate3d(0, 0, 0)'\n }}\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n >\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div data-testid=\"text\">\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate || defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n *ngIf=\"themeVersion === '2'\"\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'outside-message-bubble', message: message }\n \"\n ></ng-container>\n\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'outside-message-bubble' }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <ng-container\n *ngTemplateOutlet=\"\n systemMessageTemplate || defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ messageInput?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [size]=\"20\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentListTemplate || defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<!-- We need these markups in slightly different positions in theme-v1 and theme-v2, this soultion makes that possible without duplicating the code -->\n<ng-template #messageDateAndSender let-position=\"position\">\n <ng-container\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n >\n <div\n class=\"str-chat__translation-notice\"\n *ngIf=\"shouldDisplayTranslationNotice\"\n data-testid=\"translation-notice\"\n >\n <button\n data-testid=\"see-original\"\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n translate\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n data-testid=\"see-translation\"\n *ngIf=\"displayedMessageTextContent === 'original'\"\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n translate\n >\n streamChat.See translation\n </button>\n </div>\n <div\n class=\"\n str-chat__message-data\n str-chat__message-simple-data\n str-chat__message-metadata\n \"\n >\n <ng-container *ngIf=\"themeVersion === '2'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customDeliveredStatusTemplate || defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </popper-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customSendingStatusTemplate || defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </popper-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n customReadStatusTemplate || defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </popper-content>\n <stream-avatar-placeholder\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n type=\"user\"\n location=\"message-reader\"\n [user]=\"lastReadUser\"\n ></stream-avatar-placeholder>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton let-position=\"position\">\n <div\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n class=\"\n str-chat__message-simple-reply-button\n str-chat__message-replies-count-button-wrapper\n \"\n >\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n *ngIf=\"themeVersion === '1'\"\n stream-icon-placeholder\n icon=\"reply\"\n ></stream-icon-placeholder>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentListTemplate || defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size", "location", "channel", "user", "type", "initialsType"] }, { type: i3.NgxPopperjsContentComponent, selector: "popper-content" }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions", "customActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgxPopperjsDirective, selector: "[popper]", inputs: ["popperTimeout", "popperTimeoutAfterShow", "popperApplyClass", "popper", "popperDisabled", "popperPlacement", "popperApplyArrowClass", "popperPreventOverflow", "popperHideOnClickOutside", "popperTrigger", "popperStyles", "popperAriaDescribeBy", "popperAriaRole", "popperBoundaries", "popperCloseOnClickOutside", "popperDisableAnimation", "popperDisableStyle", "popperHideOnMouseLeave", "popperHideOnScroll", "popperAppendTo", "popperModifiers", "popperPositionFixed", "popperDelay", "popperShowOnStart", "popperTarget"], outputs: ["popperOnHidden", "popperOnShown", "popperOnUpdate"], exportAs: ["popper"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i9.TranslatePipe } });
|
|
4639
4643
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
4640
4644
|
type: Component,
|
|
4641
4645
|
args: [{
|
|
@@ -5093,27 +5097,47 @@ class MessageListComponent {
|
|
|
5093
5097
|
this.displayDateSeparator = true;
|
|
5094
5098
|
/**
|
|
5095
5099
|
* If date separators are displayed, you can set the horizontal position of the date text.
|
|
5100
|
+
* If `openMessageListAt` is `last-unread-message` it will also set the text position of the new messages indicator.
|
|
5096
5101
|
*/
|
|
5097
5102
|
this.dateSeparatorTextPos = 'center';
|
|
5103
|
+
/**
|
|
5104
|
+
* `last-message` option will open the message list at the last message, `last-unread-message` will open the list at the last unread message. This option only works if mode is `main`.
|
|
5105
|
+
*/
|
|
5106
|
+
this.openMessageListAt = 'last-message';
|
|
5098
5107
|
this.enabledMessageActions = [];
|
|
5099
5108
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host str-chat__main-panel-inner';
|
|
5100
5109
|
this.unreadMessageCount = 0;
|
|
5101
5110
|
this.groupStyles = [];
|
|
5102
5111
|
this.isLoading = false;
|
|
5103
5112
|
this.isScrollInProgress = false;
|
|
5113
|
+
this.isJumpingToLatestUnreadMessage = false;
|
|
5104
5114
|
this.subscriptions = [];
|
|
5105
5115
|
this.isLatestMessageInList = true;
|
|
5106
5116
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
5107
|
-
var _a, _b;
|
|
5117
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
5118
|
+
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `${(channel === null || channel === void 0 ? void 0 : channel.cid) || 'undefined'} selected`, { tags: `message list ${this.mode}` });
|
|
5108
5119
|
if (this.channelId !== (channel === null || channel === void 0 ? void 0 : channel.id)) {
|
|
5120
|
+
(_e = (_d = (_c = this.chatClientService) === null || _c === void 0 ? void 0 : _c.chatClient) === null || _d === void 0 ? void 0 : _d.logger) === null || _e === void 0 ? void 0 : _e.call(_d, 'info', `new channel is different from prev channel, reseting scroll state`, { tags: `message list ${this.mode}` });
|
|
5109
5121
|
this.resetScrollState();
|
|
5110
5122
|
this.channelId = channel === null || channel === void 0 ? void 0 : channel.id;
|
|
5123
|
+
if (this.openMessageListAt === 'last-unread-message' &&
|
|
5124
|
+
this.mode === 'main') {
|
|
5125
|
+
this.lastReadMessageId =
|
|
5126
|
+
(_g = channel === null || channel === void 0 ? void 0 : channel.state.read[((_f = this.chatClientService.chatClient.user) === null || _f === void 0 ? void 0 : _f.id) || '']) === null || _g === void 0 ? void 0 : _g.last_read_message_id;
|
|
5127
|
+
if (this.lastReadMessageId) {
|
|
5128
|
+
this.isJumpingToLatestUnreadMessage = true;
|
|
5129
|
+
void this.channelService.jumpToMessage(this.lastReadMessageId);
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
5132
|
+
else {
|
|
5133
|
+
this.lastReadMessageId = undefined;
|
|
5134
|
+
}
|
|
5111
5135
|
}
|
|
5112
|
-
const capabilites = (
|
|
5136
|
+
const capabilites = (_h = channel === null || channel === void 0 ? void 0 : channel.data) === null || _h === void 0 ? void 0 : _h.own_capabilities;
|
|
5113
5137
|
if (capabilites) {
|
|
5114
5138
|
this.enabledMessageActions = capabilites;
|
|
5115
5139
|
}
|
|
5116
|
-
(
|
|
5140
|
+
(_j = this.newMessageSubscription) === null || _j === void 0 ? void 0 : _j.unsubscribe();
|
|
5117
5141
|
if (channel) {
|
|
5118
5142
|
this.newMessageSubscription = channel.on('message.new', (event) => {
|
|
5119
5143
|
// If we display main channel messages and we're switched to an older message set -> use message.new event to update unread count and detect new messages sent by current user
|
|
@@ -5141,6 +5165,7 @@ class MessageListComponent {
|
|
|
5141
5165
|
}));
|
|
5142
5166
|
this.subscriptions.push(this.customTemplatesService.messageTemplate$.subscribe((template) => (this.messageTemplate = template)));
|
|
5143
5167
|
this.subscriptions.push(this.customTemplatesService.dateSeparatorTemplate$.subscribe((template) => (this.customDateSeparatorTemplate = template)));
|
|
5168
|
+
this.subscriptions.push(this.customTemplatesService.newMessagesIndicatorTemplate$.subscribe((template) => (this.customnewMessagesIndicatorTemplate = template)));
|
|
5144
5169
|
this.subscriptions.push(this.customTemplatesService.typingIndicatorTemplate$.subscribe((template) => (this.typingIndicatorTemplate = template)));
|
|
5145
5170
|
this.usersTypingInChannel$ = this.channelService.usersTypingInChannel$;
|
|
5146
5171
|
this.usersTypingInThread$ = this.channelService.usersTypingInThread$;
|
|
@@ -5163,6 +5188,7 @@ class MessageListComponent {
|
|
|
5163
5188
|
this.subscriptions.push(this.channelService.jumpToMessage$
|
|
5164
5189
|
.pipe(filter((config) => !!config.id))
|
|
5165
5190
|
.subscribe((config) => {
|
|
5191
|
+
var _a, _b;
|
|
5166
5192
|
let messageId = undefined;
|
|
5167
5193
|
if (this.mode === 'main') {
|
|
5168
5194
|
messageId = config.parentId || config.id;
|
|
@@ -5170,6 +5196,7 @@ class MessageListComponent {
|
|
|
5170
5196
|
else if (config.parentId) {
|
|
5171
5197
|
messageId = config.id;
|
|
5172
5198
|
}
|
|
5199
|
+
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Jumping to ${messageId || ''}`, { tags: `message list ${this.mode}` });
|
|
5173
5200
|
if (messageId) {
|
|
5174
5201
|
if (messageId === 'latest') {
|
|
5175
5202
|
this.scrollToLatestMessage();
|
|
@@ -5182,6 +5209,7 @@ class MessageListComponent {
|
|
|
5182
5209
|
}));
|
|
5183
5210
|
}
|
|
5184
5211
|
ngAfterViewChecked() {
|
|
5212
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5185
5213
|
if (this.highlightedMessageId) {
|
|
5186
5214
|
// Turn off programatic scroll adjustments while jump to message is in progress
|
|
5187
5215
|
this.hasNewMessages = false;
|
|
@@ -5200,6 +5228,7 @@ class MessageListComponent {
|
|
|
5200
5228
|
else {
|
|
5201
5229
|
if (this.hasNewMessages) {
|
|
5202
5230
|
if (!this.isUserScrolled || this.isNewMessageSentByUser) {
|
|
5231
|
+
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `User has new messages, and not scrolled or sent new messages, therefore we ${this.isLatestMessageInList ? 'scroll' : 'jump'} to latest message`, { tags: `message list ${this.mode}` });
|
|
5203
5232
|
this.isLatestMessageInList
|
|
5204
5233
|
? this.scrollToBottom()
|
|
5205
5234
|
: this.jumpToLatestMessage();
|
|
@@ -5208,6 +5237,7 @@ class MessageListComponent {
|
|
|
5208
5237
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
5209
5238
|
}
|
|
5210
5239
|
else if (this.olderMassagesLoaded) {
|
|
5240
|
+
(_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.logger) === null || _d === void 0 ? void 0 : _d.call(_c, 'info', `Older messages are loaded, we preserve the scroll position`, { tags: `message list ${this.mode}` });
|
|
5211
5241
|
this.preserveScrollbarPosition();
|
|
5212
5242
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
5213
5243
|
this.olderMassagesLoaded = false;
|
|
@@ -5215,6 +5245,7 @@ class MessageListComponent {
|
|
|
5215
5245
|
else if (this.getScrollPosition() !== 'bottom' &&
|
|
5216
5246
|
!this.isUserScrolled &&
|
|
5217
5247
|
!this.highlightedMessageId) {
|
|
5248
|
+
(_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.logger) === null || _f === void 0 ? void 0 : _f.call(_e, 'info', `Container grew and user didn't scroll therefore we ${this.isLatestMessageInList ? 'scroll' : 'jump'} to latest message`, { tags: `message list ${this.mode}` });
|
|
5218
5249
|
this.isLatestMessageInList
|
|
5219
5250
|
? this.scrollToBottom()
|
|
5220
5251
|
: this.jumpToLatestMessage();
|
|
@@ -5248,6 +5279,7 @@ class MessageListComponent {
|
|
|
5248
5279
|
this.scrollContainer.nativeElement.scrollTop = 0;
|
|
5249
5280
|
}
|
|
5250
5281
|
scrolled() {
|
|
5282
|
+
var _a, _b;
|
|
5251
5283
|
this.isScrollInProgress = true;
|
|
5252
5284
|
if (this.scrollEndTimeout) {
|
|
5253
5285
|
clearTimeout(this.scrollEndTimeout);
|
|
@@ -5260,6 +5292,7 @@ class MessageListComponent {
|
|
|
5260
5292
|
return;
|
|
5261
5293
|
}
|
|
5262
5294
|
const scrollPosition = this.getScrollPosition();
|
|
5295
|
+
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Scrolled - scroll position: ${scrollPosition}`, { tags: `message list ${this.mode}` });
|
|
5263
5296
|
this.isUserScrolled =
|
|
5264
5297
|
(this.direction === 'bottom-to-top'
|
|
5265
5298
|
? scrollPosition !== 'bottom'
|
|
@@ -5293,7 +5326,7 @@ class MessageListComponent {
|
|
|
5293
5326
|
return text;
|
|
5294
5327
|
}
|
|
5295
5328
|
areOnSeparateDates(message, nextMessage) {
|
|
5296
|
-
if (!nextMessage) {
|
|
5329
|
+
if (!message || !nextMessage) {
|
|
5297
5330
|
return false;
|
|
5298
5331
|
}
|
|
5299
5332
|
if (message.created_at.getDate() !== nextMessage.created_at.getDate()) {
|
|
@@ -5306,6 +5339,13 @@ class MessageListComponent {
|
|
|
5306
5339
|
}
|
|
5307
5340
|
return false;
|
|
5308
5341
|
}
|
|
5342
|
+
isSentByCurrentUser(message) {
|
|
5343
|
+
var _a, _b;
|
|
5344
|
+
if (!message) {
|
|
5345
|
+
return false;
|
|
5346
|
+
}
|
|
5347
|
+
return ((_a = message.user) === null || _a === void 0 ? void 0 : _a.id) === ((_b = this.chatClientService.chatClient.user) === null || _b === void 0 ? void 0 : _b.id);
|
|
5348
|
+
}
|
|
5309
5349
|
parseDate(date) {
|
|
5310
5350
|
return this.dateParser.parseDate(date);
|
|
5311
5351
|
}
|
|
@@ -5342,11 +5382,18 @@ class MessageListComponent {
|
|
|
5342
5382
|
this.messages$ = (this.mode === 'main'
|
|
5343
5383
|
? this.channelService.activeChannelMessages$
|
|
5344
5384
|
: this.channelService.activeThreadMessages$).pipe(tap((messages) => {
|
|
5385
|
+
var _a, _b, _c, _d;
|
|
5345
5386
|
this.isLoading = false;
|
|
5346
5387
|
if (messages.length === 0) {
|
|
5388
|
+
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Empty messages array, reseting scroll state`, {
|
|
5389
|
+
tags: `message list ${this.mode}`,
|
|
5390
|
+
});
|
|
5347
5391
|
this.resetScrollState();
|
|
5348
5392
|
return;
|
|
5349
5393
|
}
|
|
5394
|
+
(_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.logger) === null || _d === void 0 ? void 0 : _d.call(_c, 'info', `Received one or more messages`, {
|
|
5395
|
+
tags: `message list ${this.mode}`,
|
|
5396
|
+
});
|
|
5350
5397
|
const currentLatestMessage = messages[messages.length - 1];
|
|
5351
5398
|
this.newMessageReceived(currentLatestMessage);
|
|
5352
5399
|
const currentOldestMessage = messages[0];
|
|
@@ -5376,6 +5423,13 @@ class MessageListComponent {
|
|
|
5376
5423
|
if (!this.isLatestMessageInList) {
|
|
5377
5424
|
this.isUserScrolled = true;
|
|
5378
5425
|
}
|
|
5426
|
+
}), tap(() => {
|
|
5427
|
+
var _a;
|
|
5428
|
+
if (this.isJumpingToLatestUnreadMessage &&
|
|
5429
|
+
this.lastReadMessageId &&
|
|
5430
|
+
this.lastReadMessageId === ((_a = this.latestMessage) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
5431
|
+
this.lastReadMessageId = undefined;
|
|
5432
|
+
}
|
|
5379
5433
|
}), map((messages) => this.direction === 'bottom-to-top' ? messages : [...messages].reverse()), tap((messages) => {
|
|
5380
5434
|
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
5381
5435
|
}));
|
|
@@ -5407,6 +5461,7 @@ class MessageListComponent {
|
|
|
5407
5461
|
element.scrollIntoView({ block: 'center' });
|
|
5408
5462
|
setTimeout(() => {
|
|
5409
5463
|
this.highlightedMessageId = undefined;
|
|
5464
|
+
this.isJumpingToLatestUnreadMessage = false;
|
|
5410
5465
|
}, 1000);
|
|
5411
5466
|
}
|
|
5412
5467
|
}
|
|
@@ -5422,13 +5477,14 @@ class MessageListComponent {
|
|
|
5422
5477
|
}
|
|
5423
5478
|
}
|
|
5424
5479
|
newMessageReceived(message) {
|
|
5425
|
-
var _a, _b, _c, _d;
|
|
5480
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5426
5481
|
if (!this.latestMessage ||
|
|
5427
5482
|
((_a = this.latestMessage.created_at) === null || _a === void 0 ? void 0 : _a.getTime()) < message.created_at.getTime()) {
|
|
5483
|
+
(_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.logger) === null || _c === void 0 ? void 0 : _c.call(_b, 'info', `Received new message`, { tags: `message list ${this.mode}` });
|
|
5428
5484
|
this.latestMessage = message;
|
|
5429
5485
|
this.hasNewMessages = true;
|
|
5430
5486
|
this.isNewMessageSentByUser =
|
|
5431
|
-
((
|
|
5487
|
+
((_d = message.user) === null || _d === void 0 ? void 0 : _d.id) === ((_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.user) === null || _f === void 0 ? void 0 : _f.id);
|
|
5432
5488
|
if (this.isUserScrolled) {
|
|
5433
5489
|
this.unreadMessageCount++;
|
|
5434
5490
|
}
|
|
@@ -5436,7 +5492,7 @@ class MessageListComponent {
|
|
|
5436
5492
|
}
|
|
5437
5493
|
}
|
|
5438
5494
|
MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: CustomTemplatesService }, { token: DateParserService }], target: i0.ɵɵFactoryTarget.Component });
|
|
5439
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", messageOptionsTrigger: "messageOptionsTrigger", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", customMessageActions: "customMessageActions", displayDateSeparator: "displayDateSeparator", dateSeparatorTextPos: "dateSeparatorTextPos" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul\n class=\"str-chat__ul\"\n [class.str-chat__message-options-in-bubble]=\"\n messageOptionsTrigger === 'message-bubble'\n \"\n >\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread' && parentMessage\"\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <stream-loading-indicator\n data-testid=\"top-loading-indicator\"\n *ngIf=\"isLoading && direction === 'bottom-to-top'\"\n ></stream-loading-indicator>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container *ngIf=\"areOnSeparateDates(message, messages[i + 1])\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator\n data-testid=\"bottom-loading-indicator\"\n *ngIf=\"isLoading && direction === 'top-to-bottom'\"\n ></stream-loading-indicator>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n data-testid=\"scroll-to-latest\"\n *ngIf=\"\n isUserScrolled &&\n (!isScrollInProgress || !hideJumpToLatestButtonDuringScroll)\n \"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-customActions=\"customActions\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [customActions]=\"customActions\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n customActions: customMessageActions\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: { date: date, parsedDate: parsedDate }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n", components: [{ type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "customActions"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "translate": i9.TranslatePipe, "async": i5.AsyncPipe } });
|
|
5495
|
+
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", messageOptionsTrigger: "messageOptionsTrigger", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", customMessageActions: "customMessageActions", displayDateSeparator: "displayDateSeparator", dateSeparatorTextPos: "dateSeparatorTextPos", openMessageListAt: "openMessageListAt" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul\n class=\"str-chat__ul\"\n [class.str-chat__message-options-in-bubble]=\"\n messageOptionsTrigger === 'message-bubble'\n \"\n >\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread' && parentMessage\"\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <stream-loading-indicator\n data-testid=\"top-loading-indicator\"\n *ngIf=\"isLoading && direction === 'bottom-to-top'\"\n ></stream-loading-indicator>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at),\n isNewMessage: false\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message.id &&\n !isLast &&\n direction === 'bottom-to-top' &&\n !isSentByCurrentUser(messages[i + 1]) &&\n (!displayDateSeparator ||\n !areOnSeparateDates(message, messages[i + 1]))) ||\n (direction === 'top-to-bottom' &&\n !isLast &&\n !isSentByCurrentUser(message) &&\n lastReadMessageId === messages[i + 1].id)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"areOnSeparateDates(message, messages[i + 1])\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at),\n isNewMessage:\n (direction === 'bottom-to-top' &&\n message.id === lastReadMessageId &&\n !isSentByCurrentUser(messages[i + 1])) ||\n (direction === 'top-to-bottom' && false)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator\n data-testid=\"bottom-loading-indicator\"\n *ngIf=\"isLoading && direction === 'top-to-bottom'\"\n ></stream-loading-indicator>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n data-testid=\"scroll-to-latest\"\n *ngIf=\"\n isUserScrolled &&\n (!isScrollInProgress || !hideJumpToLatestButtonDuringScroll)\n \"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-customActions=\"customActions\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [customActions]=\"customActions\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted:\n message?.id === highlightedMessageId &&\n !isJumpingToLatestUnreadMessage,\n customActions: customMessageActions\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template\n #dateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n let-isNewMessage=\"isNewMessage\"\n>\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate,\n isNewMessage: isNewMessage\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n let-isNewMessage=\"isNewMessage\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n <span\n *ngIf=\"isNewMessage\"\n data-testid=\"new-messages-indicator-date-separator\"\n >\u2022 {{ \"streamChat.New\" | translate }}</span\n >\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator>\n <div data-testid=\"new-messages-indicator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\" translate>streamChat.New</div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n</ng-template>\n", components: [{ type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "customActions"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i9.TranslatePipe, "async": i5.AsyncPipe } });
|
|
5440
5496
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
5441
5497
|
type: Component,
|
|
5442
5498
|
args: [{
|
|
@@ -5458,6 +5514,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
5458
5514
|
type: Input
|
|
5459
5515
|
}], dateSeparatorTextPos: [{
|
|
5460
5516
|
type: Input
|
|
5517
|
+
}], openMessageListAt: [{
|
|
5518
|
+
type: Input
|
|
5461
5519
|
}], class: [{
|
|
5462
5520
|
type: HostBinding,
|
|
5463
5521
|
args: ['class']
|