stream-chat-angular 6.3.1 → 6.3.2
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/esm2020/assets/version.mjs +2 -2
- package/esm2020/lib/channel.service.mjs +12 -1
- package/esm2020/lib/message-input/message-input.component.mjs +101 -4
- package/fesm2015/stream-chat-angular.mjs +116 -6
- package/fesm2015/stream-chat-angular.mjs.map +1 -1
- package/fesm2020/stream-chat-angular.mjs +114 -6
- package/fesm2020/stream-chat-angular.mjs.map +1 -1
- package/lib/channel.service.d.ts +8 -1
- package/lib/message-input/message-input.component.d.ts +29 -2
- package/package.json +1 -1
- package/src/assets/version.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { Injectable, Component, Input, EventEmitter, Output, ViewChild, HostBinding, TemplateRef, ContentChild, ChangeDetectionStrategy, InjectionToken, Directive, NgModule, Inject, Optional } from '@angular/core';
|
|
4
|
-
import { BehaviorSubject, ReplaySubject, combineLatest, map as map$1, shareReplay as shareReplay$1, take as take$1, pairwise, Subject, timer, merge, switchMap, distinctUntilChanged, filter as filter$1, of } from 'rxjs';
|
|
4
|
+
import { BehaviorSubject, ReplaySubject, combineLatest, map as map$1, shareReplay as shareReplay$1, take as take$1, pairwise, Subject, timer, merge, switchMap, distinctUntilChanged as distinctUntilChanged$1, filter as filter$1, of } from 'rxjs';
|
|
5
5
|
import { StreamChat, VotingVisibility, isVoteAnswer } from 'stream-chat';
|
|
6
|
-
import { take, shareReplay, map, first, filter, tap, debounceTime, throttleTime } from 'rxjs/operators';
|
|
6
|
+
import { take, shareReplay, map, first, filter, distinctUntilChanged, tap, debounceTime, throttleTime } from 'rxjs/operators';
|
|
7
7
|
import { v4 } from 'uuid';
|
|
8
8
|
import * as i6 from '@ngx-translate/core';
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core';
|
|
@@ -23,7 +23,7 @@ import { MentionModule } from 'angular-mentions';
|
|
|
23
23
|
import * as i1$1 from '@angular/forms';
|
|
24
24
|
import { FormGroup, FormControl, Validators, FormArray, ReactiveFormsModule } from '@angular/forms';
|
|
25
25
|
|
|
26
|
-
const version = '6.3.
|
|
26
|
+
const version = '6.3.2';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](/chat/docs/sdk/angular/components/NotificationListComponent/) component displays the currently active notifications.
|
|
@@ -468,6 +468,7 @@ class ChannelService {
|
|
|
468
468
|
this._shouldMarkActiveChannelAsRead = true;
|
|
469
469
|
this.isStateRecoveryInProgress = false;
|
|
470
470
|
this.channelQueryStateSubject = new BehaviorSubject(undefined);
|
|
471
|
+
this.channelSwitchStateSubject = new BehaviorSubject('end');
|
|
471
472
|
this.channelListSetter = (channels, shouldStopWatchingRemovedChannels = true) => {
|
|
472
473
|
var _a;
|
|
473
474
|
const currentChannels = this.channelsSubject.getValue() || [];
|
|
@@ -568,6 +569,9 @@ class ChannelService {
|
|
|
568
569
|
this.channelQueryState$ = this.channelQueryStateSubject
|
|
569
570
|
.asObservable()
|
|
570
571
|
.pipe(shareReplay(1));
|
|
572
|
+
this.channelSwitchState$ = this.channelSwitchStateSubject
|
|
573
|
+
.asObservable()
|
|
574
|
+
.pipe(shareReplay(1));
|
|
571
575
|
}
|
|
572
576
|
/**
|
|
573
577
|
* If set to false, read events won't be sent as new messages are received. If set to true active channel (if any) will immediately be marked as read.
|
|
@@ -607,6 +611,7 @@ class ChannelService {
|
|
|
607
611
|
*/
|
|
608
612
|
setAsActiveChannel(channel) {
|
|
609
613
|
var _a, _b;
|
|
614
|
+
this.channelSwitchStateSubject.next('start');
|
|
610
615
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
611
616
|
if ((prevActiveChannel === null || prevActiveChannel === void 0 ? void 0 : prevActiveChannel.cid) === channel.cid) {
|
|
612
617
|
return;
|
|
@@ -629,11 +634,13 @@ class ChannelService {
|
|
|
629
634
|
channel.state.latestMessages = channel.state.latestMessages.slice(channelStateLength - 2 * this.messagePageSize);
|
|
630
635
|
}
|
|
631
636
|
this.setChannelState(channel);
|
|
637
|
+
this.channelSwitchStateSubject.next('end');
|
|
632
638
|
}
|
|
633
639
|
/**
|
|
634
640
|
* Deselects the currently active (if any) channel
|
|
635
641
|
*/
|
|
636
642
|
deselectActiveChannel() {
|
|
643
|
+
this.channelSwitchStateSubject.next('start');
|
|
637
644
|
const activeChannel = this.activeChannelSubject.getValue();
|
|
638
645
|
if (!activeChannel) {
|
|
639
646
|
return;
|
|
@@ -654,6 +661,7 @@ class ChannelService {
|
|
|
654
661
|
this.activeChannelUnreadCount = undefined;
|
|
655
662
|
this.areReadEventsPaused = false;
|
|
656
663
|
this.isMessageLoadingInProgress = false;
|
|
664
|
+
this.channelSwitchStateSubject.next('end');
|
|
657
665
|
}
|
|
658
666
|
/**
|
|
659
667
|
* Sets the given `message` as an active parent message. If `undefined` is provided, it will deleselect the current parent message.
|
|
@@ -1090,6 +1098,9 @@ class ChannelService {
|
|
|
1090
1098
|
* @param message The message to select, if called with `undefined`, it deselects the message
|
|
1091
1099
|
*/
|
|
1092
1100
|
selectMessageToQuote(message) {
|
|
1101
|
+
if (message && !this.isStreamMessage(message)) {
|
|
1102
|
+
message = this.transformToStreamMessage(message);
|
|
1103
|
+
}
|
|
1093
1104
|
this.messageToQuoteSubject.next(message);
|
|
1094
1105
|
}
|
|
1095
1106
|
/**
|
|
@@ -6801,6 +6812,20 @@ class MessageInputComponent {
|
|
|
6801
6812
|
* Emits when a message was successfuly sent or updated
|
|
6802
6813
|
*/
|
|
6803
6814
|
this.messageUpdate = new EventEmitter();
|
|
6815
|
+
/**
|
|
6816
|
+
* Emits the messsage draft whenever the composed message changes.
|
|
6817
|
+
* - If the user clears the message input, or sends the message, undefined is emitted.
|
|
6818
|
+
* - If active channel changes, nothing is emitted.
|
|
6819
|
+
*
|
|
6820
|
+
* To save and fetch message drafts, you can use the [Stream message drafts API](https://getstream.io/chat/docs/javascript/drafts/).
|
|
6821
|
+
*
|
|
6822
|
+
* Message draft only works for new messages, nothing is emitted when input is in edit mode (if `message` input is set).
|
|
6823
|
+
*
|
|
6824
|
+
* To load a message draft into the input, use the `loadDraft` method.
|
|
6825
|
+
* - If channel id doesn't match the active channel id, the draft is ignored.
|
|
6826
|
+
* - If a thread message is loaded, and the input isn't in thread mode or parent ids don't match, the draft is ignored.
|
|
6827
|
+
*/
|
|
6828
|
+
this.messageDraftChange = new EventEmitter();
|
|
6804
6829
|
this.class = 'str-chat__message-input-angular-host';
|
|
6805
6830
|
this.isVoiceRecording = true;
|
|
6806
6831
|
this.textareaValue = '';
|
|
@@ -6813,12 +6838,16 @@ class MessageInputComponent {
|
|
|
6813
6838
|
this.isViewInited = false;
|
|
6814
6839
|
this.defaultTextareaPlaceholder = 'streamChat.Type your message';
|
|
6815
6840
|
this.slowModeTextareaPlaceholder = 'streamChat.Slow Mode ON';
|
|
6841
|
+
this.isChannelChangeResetInProgress = false;
|
|
6842
|
+
this.isSendingMessage = false;
|
|
6843
|
+
this.isLoadingDraft = false;
|
|
6816
6844
|
this.closePollComposer = () => {
|
|
6817
6845
|
this.isComposerOpen = false;
|
|
6818
6846
|
};
|
|
6819
6847
|
this.addPoll = (pollId) => {
|
|
6820
6848
|
this.isComposerOpen = false;
|
|
6821
6849
|
this.pollId = pollId;
|
|
6850
|
+
this.updateMessageDraft();
|
|
6822
6851
|
void this.messageSent();
|
|
6823
6852
|
};
|
|
6824
6853
|
this.textareaPlaceholder = this.defaultTextareaPlaceholder;
|
|
@@ -6828,6 +6857,15 @@ class MessageInputComponent {
|
|
|
6828
6857
|
this.hideNotification = undefined;
|
|
6829
6858
|
}
|
|
6830
6859
|
}));
|
|
6860
|
+
this.subscriptions.push(this.attachmentService.attachmentUploads$
|
|
6861
|
+
.pipe(distinctUntilChanged((prev, current) => prev.filter((v) => v.state === 'success').length ===
|
|
6862
|
+
current.filter((v) => v.state === 'success').length))
|
|
6863
|
+
.subscribe(() => {
|
|
6864
|
+
this.updateMessageDraft();
|
|
6865
|
+
}));
|
|
6866
|
+
this.subscriptions.push(this.attachmentService.customAttachments$.subscribe(() => {
|
|
6867
|
+
this.updateMessageDraft();
|
|
6868
|
+
}));
|
|
6831
6869
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
6832
6870
|
var _a;
|
|
6833
6871
|
if (channel && this.channel && channel.id !== this.channel.id) {
|
|
@@ -6835,6 +6873,8 @@ class MessageInputComponent {
|
|
|
6835
6873
|
this.attachmentService.resetAttachmentUploads();
|
|
6836
6874
|
this.pollId = undefined;
|
|
6837
6875
|
this.voiceRecorderService.isRecorderVisible$.next(false);
|
|
6876
|
+
// Preemptively deselect quoted message, to avoid unwanted draft emission
|
|
6877
|
+
this.channelService.selectMessageToQuote(undefined);
|
|
6838
6878
|
}
|
|
6839
6879
|
const capabilities = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
6840
6880
|
if (capabilities) {
|
|
@@ -6846,12 +6886,16 @@ class MessageInputComponent {
|
|
|
6846
6886
|
this.setCanSendMessages();
|
|
6847
6887
|
}
|
|
6848
6888
|
}));
|
|
6889
|
+
this.subscriptions.push(this.channelService.channelSwitchState$.subscribe((state) => {
|
|
6890
|
+
this.isChannelChangeResetInProgress = state === 'start';
|
|
6891
|
+
}));
|
|
6849
6892
|
this.subscriptions.push(this.channelService.messageToQuote$.subscribe((m) => {
|
|
6850
6893
|
const isThreadReply = m && m.parent_id;
|
|
6851
6894
|
if ((this.mode === 'thread' && isThreadReply) ||
|
|
6852
6895
|
(this.mode === 'thread' && this.quotedMessage && !m) ||
|
|
6853
6896
|
(this.mode === 'main' && !isThreadReply)) {
|
|
6854
6897
|
this.quotedMessage = m;
|
|
6898
|
+
this.updateMessageDraft();
|
|
6855
6899
|
}
|
|
6856
6900
|
}));
|
|
6857
6901
|
this.subscriptions.push(this.messageActionsService.messageToEdit$.subscribe((message) => {
|
|
@@ -6964,6 +7008,7 @@ class MessageInputComponent {
|
|
|
6964
7008
|
if (this.isCooldownInProgress) {
|
|
6965
7009
|
return;
|
|
6966
7010
|
}
|
|
7011
|
+
this.isSendingMessage = true;
|
|
6967
7012
|
let attachmentUploadInProgressCounter;
|
|
6968
7013
|
this.attachmentService.attachmentUploadInProgressCounter$
|
|
6969
7014
|
.pipe(first())
|
|
@@ -7010,10 +7055,15 @@ class MessageInputComponent {
|
|
|
7010
7055
|
}
|
|
7011
7056
|
}
|
|
7012
7057
|
catch (error) {
|
|
7058
|
+
this.isSendingMessage = false;
|
|
7013
7059
|
if (this.isUpdate) {
|
|
7014
7060
|
this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
|
|
7015
7061
|
}
|
|
7016
7062
|
}
|
|
7063
|
+
finally {
|
|
7064
|
+
this.isSendingMessage = false;
|
|
7065
|
+
this.updateMessageDraft();
|
|
7066
|
+
}
|
|
7017
7067
|
void this.channelService.typingStopped(this.parentMessageId);
|
|
7018
7068
|
if (this.quotedMessage) {
|
|
7019
7069
|
this.deselectMessageToQuote();
|
|
@@ -7100,6 +7150,40 @@ class MessageInputComponent {
|
|
|
7100
7150
|
openPollComposer() {
|
|
7101
7151
|
this.isComposerOpen = true;
|
|
7102
7152
|
}
|
|
7153
|
+
userMentionsChanged(userMentions) {
|
|
7154
|
+
if (userMentions.map((u) => u.id).join(',') !==
|
|
7155
|
+
this.mentionedUsers.map((u) => u.id).join(',')) {
|
|
7156
|
+
this.mentionedUsers = userMentions;
|
|
7157
|
+
this.updateMessageDraft();
|
|
7158
|
+
}
|
|
7159
|
+
}
|
|
7160
|
+
updateMessageDraft() {
|
|
7161
|
+
var _a, _b;
|
|
7162
|
+
if (this.isLoadingDraft ||
|
|
7163
|
+
this.isSendingMessage ||
|
|
7164
|
+
this.isChannelChangeResetInProgress ||
|
|
7165
|
+
this.isUpdate) {
|
|
7166
|
+
return;
|
|
7167
|
+
}
|
|
7168
|
+
const attachments = this.attachmentService.mapToAttachments();
|
|
7169
|
+
if (!this.textareaValue &&
|
|
7170
|
+
!this.mentionedUsers.length &&
|
|
7171
|
+
!(attachments === null || attachments === void 0 ? void 0 : attachments.length) &&
|
|
7172
|
+
!this.pollId &&
|
|
7173
|
+
!((_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
7174
|
+
this.messageDraftChange.emit(undefined);
|
|
7175
|
+
}
|
|
7176
|
+
else {
|
|
7177
|
+
this.messageDraftChange.emit({
|
|
7178
|
+
text: this.textareaValue,
|
|
7179
|
+
attachments: this.attachmentService.mapToAttachments(),
|
|
7180
|
+
mentioned_users: this.mentionedUsers.map((user) => user.id),
|
|
7181
|
+
poll_id: this.pollId,
|
|
7182
|
+
parent_id: this.parentMessageId,
|
|
7183
|
+
quoted_message_id: (_b = this.quotedMessage) === null || _b === void 0 ? void 0 : _b.id,
|
|
7184
|
+
});
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7103
7187
|
voiceRecordingReady(recording) {
|
|
7104
7188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7105
7189
|
try {
|
|
@@ -7116,6 +7200,30 @@ class MessageInputComponent {
|
|
|
7116
7200
|
get isUpdate() {
|
|
7117
7201
|
return !!this.message;
|
|
7118
7202
|
}
|
|
7203
|
+
/**
|
|
7204
|
+
*
|
|
7205
|
+
* @param draft DraftResponse to load into the message input.
|
|
7206
|
+
* - Draft messages are only supported for new messages, input is ignored in edit mode (if `message` input is set).
|
|
7207
|
+
* - If channel id doesn't match the active channel id, the draft is ignored.
|
|
7208
|
+
* - If a thread message is loaded, and the input isn't in thread mode or parent ids don't match, the draft is ignored.
|
|
7209
|
+
*/
|
|
7210
|
+
loadDraft(draft) {
|
|
7211
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
7212
|
+
if (((_a = this.channel) === null || _a === void 0 ? void 0 : _a.cid) !== draft.channel_cid ||
|
|
7213
|
+
((_b = draft === null || draft === void 0 ? void 0 : draft.message) === null || _b === void 0 ? void 0 : _b.parent_id) !== this.parentMessageId ||
|
|
7214
|
+
this.isUpdate) {
|
|
7215
|
+
return;
|
|
7216
|
+
}
|
|
7217
|
+
this.isLoadingDraft = true;
|
|
7218
|
+
this.textareaValue = ((_c = draft.message) === null || _c === void 0 ? void 0 : _c.text) || '';
|
|
7219
|
+
this.mentionedUsers =
|
|
7220
|
+
((_e = (_d = draft === null || draft === void 0 ? void 0 : draft.message) === null || _d === void 0 ? void 0 : _d.mentioned_users) === null || _e === void 0 ? void 0 : _e.map((id) => ({ id }))) || [];
|
|
7221
|
+
this.pollId = (_f = draft === null || draft === void 0 ? void 0 : draft.message) === null || _f === void 0 ? void 0 : _f.poll_id;
|
|
7222
|
+
this.attachmentService.resetAttachmentUploads();
|
|
7223
|
+
this.attachmentService.createFromAttachments(((_g = draft === null || draft === void 0 ? void 0 : draft.message) === null || _g === void 0 ? void 0 : _g.attachments) || []);
|
|
7224
|
+
this.channelService.selectMessageToQuote(draft.quoted_message);
|
|
7225
|
+
this.isLoadingDraft = false;
|
|
7226
|
+
}
|
|
7119
7227
|
deleteUpload(upload) {
|
|
7120
7228
|
if (this.isUpdate) {
|
|
7121
7229
|
// Delay delete to avoid modal detecting this click as outside click
|
|
@@ -7220,10 +7328,10 @@ class MessageInputComponent {
|
|
|
7220
7328
|
}
|
|
7221
7329
|
}
|
|
7222
7330
|
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: EmojiInputService }, { token: CustomTemplatesService }, { token: MessageActionsService }, { token: VoiceRecorderService }, { token: AudioRecorderService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
7223
|
-
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$", inputMode: "inputMode", autoFocus: "autoFocus", watchForMessageToEdit: "watchForMessageToEdit", displaySendButton: "displaySendButton", displayVoiceRecordingButton: "displayVoiceRecordingButton", displayPollCreateButton: "displayPollCreateButton" }, outputs: { messageUpdate: "messageUpdate" }, host: { properties: { "class": "this.class" } }, providers: [AttachmentService, EmojiInputService, VoiceRecorderService], queries: [{ propertyName: "voiceRecorderRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"canSendPolls && displayPollCreateButton && mode !== 'thread'\"\n >\n <button\n class=\"str-chat-angular__create-poll\"\n (click)=\"openPollComposer()\"\n >\n <stream-icon-placeholder icon=\"poll\"></stream-icon-placeholder>\n </button>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <ng-container\n *ngIf=\"\n quotedMessage?.poll_id &&\n (customTemplatesService.pollTemplate$ | async)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.pollTemplate$ | async)!;\n context: {\n pollId: quotedMessage?.poll_id,\n messageId: quotedMessage?.id,\n isQuote: true\n }\n \"\n ></ng-container>\n </ng-container>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n (pasteFromClipboard)=\"itemsPasted($event)\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (attachmentService.attachmentsCounter$ | async)! >\n attachmentService.maxNumberOfAttachments ||\n (!textareaValue &&\n (attachmentUploads$ | async)!.length === 0 &&\n (customAttachments$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <button\n *ngIf=\"displayVoiceRecordingButton\"\n class=\"str-chat__start-recording-audio-button\"\n data-testid=\"start-voice-recording\"\n [disabled]=\"\n voiceRecorderService.isRecorderVisible$.value ||\n audioRecorder?.isRecording ||\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (click)=\"startVoiceRecording()\"\n (keyup.enter)=\"startVoiceRecording()\"\n >\n <stream-icon-placeholder icon=\"mic\"></stream-icon-placeholder>\n </button>\n <ng-content select=\"[message-input-end]\"></ng-content>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n<ng-template\n *ngIf=\"voiceRecorderRef\"\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n></ng-template>\n<ng-template\n *ngIf=\"\n isComposerOpen && (customTemplatesService.pollComposerTemplate$ | async)\n \"\n [ngTemplateOutlet]=\"(customTemplatesService.pollComposerTemplate$ | async)!\"\n [ngTemplateOutletContext]=\"{\n pollCompose: addPoll,\n cancel: closePollComposer\n }\"\n></ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }, { kind: "directive", type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "inputMode", "value", "placeholder", "autoFocus"], outputs: ["valueChange", "send", "userMentions", "pasteFromClipboard"] }, { kind: "component", type: MessageTextComponent, selector: "stream-message-text", inputs: ["message", "isQuoted", "shouldTranslate"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }] });
|
|
7331
|
+
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$", inputMode: "inputMode", autoFocus: "autoFocus", watchForMessageToEdit: "watchForMessageToEdit", displaySendButton: "displaySendButton", displayVoiceRecordingButton: "displayVoiceRecordingButton", displayPollCreateButton: "displayPollCreateButton" }, outputs: { messageUpdate: "messageUpdate", messageDraftChange: "messageDraftChange" }, host: { properties: { "class": "this.class" } }, providers: [AttachmentService, EmojiInputService, VoiceRecorderService], queries: [{ propertyName: "voiceRecorderRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"canSendPolls && displayPollCreateButton && mode !== 'thread'\"\n >\n <button\n class=\"str-chat-angular__create-poll\"\n (click)=\"openPollComposer()\"\n >\n <stream-icon-placeholder icon=\"poll\"></stream-icon-placeholder>\n </button>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <ng-container\n *ngIf=\"\n quotedMessage?.poll_id &&\n (customTemplatesService.pollTemplate$ | async)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.pollTemplate$ | async)!;\n context: {\n pollId: quotedMessage?.poll_id,\n messageId: quotedMessage?.id,\n isQuote: true\n }\n \"\n ></ng-container>\n </ng-container>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next(); updateMessageDraft()\"\n (send)=\"messageSent()\"\n (userMentions)=\"userMentionsChanged($event)\"\n (pasteFromClipboard)=\"itemsPasted($event)\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (attachmentService.attachmentsCounter$ | async)! >\n attachmentService.maxNumberOfAttachments ||\n (!textareaValue &&\n (attachmentUploads$ | async)!.length === 0 &&\n (customAttachments$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <button\n *ngIf=\"displayVoiceRecordingButton\"\n class=\"str-chat__start-recording-audio-button\"\n data-testid=\"start-voice-recording\"\n [disabled]=\"\n voiceRecorderService.isRecorderVisible$.value ||\n audioRecorder?.isRecording ||\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (click)=\"startVoiceRecording()\"\n (keyup.enter)=\"startVoiceRecording()\"\n >\n <stream-icon-placeholder icon=\"mic\"></stream-icon-placeholder>\n </button>\n <ng-content select=\"[message-input-end]\"></ng-content>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n<ng-template\n *ngIf=\"voiceRecorderRef\"\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n></ng-template>\n<ng-template\n *ngIf=\"\n isComposerOpen && (customTemplatesService.pollComposerTemplate$ | async)\n \"\n [ngTemplateOutlet]=\"(customTemplatesService.pollComposerTemplate$ | async)!\"\n [ngTemplateOutletContext]=\"{\n pollCompose: addPoll,\n cancel: closePollComposer\n }\"\n></ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }, { kind: "directive", type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "inputMode", "value", "placeholder", "autoFocus"], outputs: ["valueChange", "send", "userMentions", "pasteFromClipboard"] }, { kind: "component", type: MessageTextComponent, selector: "stream-message-text", inputs: ["message", "isQuoted", "shouldTranslate"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }] });
|
|
7224
7332
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
7225
7333
|
type: Component,
|
|
7226
|
-
args: [{ selector: 'stream-message-input', providers: [AttachmentService, EmojiInputService, VoiceRecorderService], template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"canSendPolls && displayPollCreateButton && mode !== 'thread'\"\n >\n <button\n class=\"str-chat-angular__create-poll\"\n (click)=\"openPollComposer()\"\n >\n <stream-icon-placeholder icon=\"poll\"></stream-icon-placeholder>\n </button>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <ng-container\n *ngIf=\"\n quotedMessage?.poll_id &&\n (customTemplatesService.pollTemplate$ | async)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.pollTemplate$ | async)!;\n context: {\n pollId: quotedMessage?.poll_id,\n messageId: quotedMessage?.id,\n isQuote: true\n }\n \"\n ></ng-container>\n </ng-container>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"
|
|
7334
|
+
args: [{ selector: 'stream-message-input', providers: [AttachmentService, EmojiInputService, VoiceRecorderService], template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"canSendPolls && displayPollCreateButton && mode !== 'thread'\"\n >\n <button\n class=\"str-chat-angular__create-poll\"\n (click)=\"openPollComposer()\"\n >\n <stream-icon-placeholder icon=\"poll\"></stream-icon-placeholder>\n </button>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <ng-container\n *ngIf=\"\n quotedMessage?.poll_id &&\n (customTemplatesService.pollTemplate$ | async)\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.pollTemplate$ | async)!;\n context: {\n pollId: quotedMessage?.poll_id,\n messageId: quotedMessage?.id,\n isQuote: true\n }\n \"\n ></ng-container>\n </ng-container>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next(); updateMessageDraft()\"\n (send)=\"messageSent()\"\n (userMentions)=\"userMentionsChanged($event)\"\n (pasteFromClipboard)=\"itemsPasted($event)\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (attachmentService.attachmentsCounter$ | async)! >\n attachmentService.maxNumberOfAttachments ||\n (!textareaValue &&\n (attachmentUploads$ | async)!.length === 0 &&\n (customAttachments$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <button\n *ngIf=\"displayVoiceRecordingButton\"\n class=\"str-chat__start-recording-audio-button\"\n data-testid=\"start-voice-recording\"\n [disabled]=\"\n voiceRecorderService.isRecorderVisible$.value ||\n audioRecorder?.isRecording ||\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (click)=\"startVoiceRecording()\"\n (keyup.enter)=\"startVoiceRecording()\"\n >\n <stream-icon-placeholder icon=\"mic\"></stream-icon-placeholder>\n </button>\n <ng-content select=\"[message-input-end]\"></ng-content>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n<ng-template\n *ngIf=\"voiceRecorderRef\"\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n></ng-template>\n<ng-template\n *ngIf=\"\n isComposerOpen && (customTemplatesService.pollComposerTemplate$ | async)\n \"\n [ngTemplateOutlet]=\"(customTemplatesService.pollComposerTemplate$ | async)!\"\n [ngTemplateOutletContext]=\"{\n pollCompose: addPoll,\n cancel: closePollComposer\n }\"\n></ng-template>\n" }]
|
|
7227
7335
|
}], ctorParameters: function () {
|
|
7228
7336
|
return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
|
|
7229
7337
|
type: Inject,
|
|
@@ -7259,6 +7367,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
|
|
|
7259
7367
|
type: Input
|
|
7260
7368
|
}], messageUpdate: [{
|
|
7261
7369
|
type: Output
|
|
7370
|
+
}], messageDraftChange: [{
|
|
7371
|
+
type: Output
|
|
7262
7372
|
}], voiceRecorderRef: [{
|
|
7263
7373
|
type: ContentChild,
|
|
7264
7374
|
args: [TemplateRef]
|
|
@@ -7875,7 +7985,7 @@ class VirtualizedListService {
|
|
|
7875
7985
|
}
|
|
7876
7986
|
}));
|
|
7877
7987
|
this.subscriptions.push(this.scrollPosition$
|
|
7878
|
-
.pipe(distinctUntilChanged())
|
|
7988
|
+
.pipe(distinctUntilChanged$1())
|
|
7879
7989
|
.subscribe((position) => {
|
|
7880
7990
|
if (this.queryStateSubject.getValue().state === `loading-${position}`) {
|
|
7881
7991
|
return;
|