Skip to content

Commit 3b1dbe1

Browse files
committed
feat: create message-text component
1 parent 141e8ab commit 3b1dbe1

15 files changed

+708
-475
lines changed

package-lock.json

Lines changed: 8 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
"@ctrl/ngx-emoji-mart": "^8.2.0",
113113
"@floating-ui/dom": "^1.6.3",
114114
"@ngx-translate/core": "^14.0.0",
115-
"@stream-io/stream-chat-css": "5.3.0",
115+
"@stream-io/stream-chat-css": "5.6.1",
116116
"@stream-io/transliterate": "^1.5.2",
117117
"angular-mentions": "1.4.0",
118118
"dayjs": "^1.11.10",

projects/stream-chat-angular/src/lib/custom-templates.service.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
MessageContext,
2727
MessageReactionsContext,
2828
MessageReactionsSelectorContext,
29+
MessageTextContext,
2930
ModalContext,
3031
NotificationContext,
3132
ReadStatusContext,
@@ -358,6 +359,12 @@ export class CustomTemplatesService<
358359
customMessageMetadataInsideBubbleTemplate$ = new BehaviorSubject<
359360
TemplateRef<CustomMetadataContext> | undefined
360361
>(undefined);
362+
/**
363+
* Template to display the text content inside the [message component](/chat/docs/sdk/angular/components/MessageComponent/). The default component is [stream-message-text](/chat/docs/sdk/angular/components/MessageTextComponent/)
364+
*/
365+
messageTextTemplate$ = new BehaviorSubject<
366+
TemplateRef<MessageTextContext> | undefined
367+
>(undefined);
361368

362369
constructor() {}
363370
}

projects/stream-chat-angular/src/lib/message-input/message-input.component.html

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,28 @@
9191
[attachments]="quotedMessageAttachments"
9292
[messageId]="quotedMessage.id"
9393
></stream-attachment-list>
94-
<div
95-
class="str-chat__quoted-message-text"
96-
data-testid="quoted-message-text"
97-
[innerHTML]="
98-
quotedMessage.translation ||
99-
quotedMessage.html ||
100-
quotedMessage.text
101-
"
102-
></div>
94+
<div class="str-chat__quoted-message-text">
95+
<ng-container
96+
*ngTemplateOutlet="
97+
(customTemplatesService.messageTextTemplate$ | async) ||
98+
defaultText;
99+
context: getQuotedMessageTextContext()
100+
"
101+
></ng-container>
102+
<ng-template
103+
#defaultText
104+
let-message="message"
105+
let-isQuoted="isQuoted"
106+
let-shouldTranslate="shouldTranslate"
107+
>
108+
<stream-message-text
109+
[message]="message"
110+
[isQuoted]="isQuoted"
111+
[shouldTranslate]="shouldTranslate"
112+
data-testid="quoted-message-text"
113+
></stream-message-text>
114+
</ng-template>
115+
</div>
103116
</div>
104117
</div>
105118
<ng-template

projects/stream-chat-angular/src/lib/message-input/message-input.component.spec.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { StreamAvatarModule } from '../stream-avatar.module';
3838
import { VoiceRecorderService } from './voice-recorder.service';
3939
import { CustomTemplatesService } from '../custom-templates.service';
4040
import { MessageInputConfigService } from './message-input-config.service';
41+
import { MessageTextComponent } from '../message-text/message-text.component';
4142

4243
describe('MessageInputComponent', () => {
4344
let nativeElement: HTMLElement;
@@ -131,6 +132,7 @@ describe('MessageInputComponent', () => {
131132
AutocompleteTextareaComponent,
132133
AttachmentListComponent,
133134
AttachmentPreviewListComponent,
135+
MessageTextComponent,
134136
],
135137
providers: [
136138
{
@@ -783,10 +785,15 @@ describe('MessageInputComponent', () => {
783785
expect(avatar.location).toBe('quoted-message-sender');
784786
expect(avatar.user).toBe(message.user!);
785787
expect(attachments.attachments).toEqual([{ id: '1' }]);
786-
expect(
787-
nativeElement.querySelector('[data-testid="quoted-message-text"]')
788-
?.innerHTML
789-
).toContain(message.text);
788+
789+
const textComponent = fixture.debugElement
790+
.query(By.css(quotedMessageContainerSelector))
791+
.query(By.directive(MessageTextComponent))
792+
.componentInstance as MessageTextComponent;
793+
794+
expect(textComponent.message).toBe(message);
795+
expect(textComponent.isQuoted).toBe(true);
796+
expect(textComponent.shouldTranslate).toBe(true);
790797

791798
mockMessageToQuote$.next(undefined);
792799
fixture.detectChanges();

projects/stream-chat-angular/src/lib/message-input/message-input.component.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
CustomAttachmentUploadContext,
3535
DefaultStreamChatGenerics,
3636
EmojiPickerContext,
37+
MessageTextContext,
3738
StreamMessage,
3839
} from '../types';
3940
import { MessageInputConfigService } from './message-input-config.service';
@@ -163,7 +164,7 @@ export class MessageInputComponent
163164
private componentFactoryResolver: ComponentFactoryResolver,
164165
private cdRef: ChangeDetectorRef,
165166
private emojiInputService: EmojiInputService,
166-
private customTemplatesService: CustomTemplatesService,
167+
readonly customTemplatesService: CustomTemplatesService,
167168
private messageActionsService: MessageActionsService,
168169
public readonly voiceRecorderService: VoiceRecorderService,
169170
@Optional() public audioRecorder?: AudioRecorderService
@@ -494,6 +495,14 @@ export class MessageInputComponent
494495
};
495496
}
496497

498+
getQuotedMessageTextContext(): MessageTextContext {
499+
return {
500+
message: this.quotedMessage,
501+
isQuoted: true,
502+
shouldTranslate: true,
503+
};
504+
}
505+
497506
async startVoiceRecording() {
498507
await this.audioRecorder?.start();
499508
if (this.audioRecorder?.isRecording) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<p
2+
[class.str-chat__quoted-message-text-value]="isQuoted"
3+
[class.str-chat__message-text-value]="!isQuoted"
4+
*ngIf="message?.text"
5+
data-testid="text"
6+
>
7+
<ng-container *ngIf="messageTextParts; else defaultContent">
8+
<!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->
9+
<ng-container *ngFor="let part of messageTextParts">
10+
<span
11+
*ngIf="part.type === 'text'; else mention"
12+
[innerHTML]="part.content"
13+
></span>
14+
<ng-template #mention>
15+
<ng-template #defaultMention let-content="content">
16+
<span class="str-chat__message-mention">{{ content }}</span>
17+
</ng-template>
18+
<ng-container
19+
*ngTemplateOutlet="
20+
(customTemplatesService.mentionTemplate$ | async) || defaultMention;
21+
context: getMentionContext(part)
22+
"
23+
></ng-container>
24+
</ng-template>
25+
</ng-container>
26+
</ng-container>
27+
<ng-template #defaultContent>
28+
<ng-container *ngIf="displayAs === 'text'; else asHTML">
29+
{{ messageText || "" }}
30+
</ng-container>
31+
<ng-template #asHTML
32+
><span data-testid="html-content" [innerHTML]="messageText"></span
33+
></ng-template>
34+
</ng-template>
35+
</p>

0 commit comments

Comments
 (0)