Skip to content

Commit 903d37b

Browse files
committed
Merge branch 'master' into 6.x.x-rc
2 parents 3999ce7 + 1151578 commit 903d37b

15 files changed

+852
-567
lines changed

package-lock.json

Lines changed: 24 additions & 9 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
@@ -116,7 +116,7 @@
116116
"@ctrl/ngx-emoji-mart": "^8.2.0",
117117
"@floating-ui/dom": "^1.6.3",
118118
"@ngx-translate/core": "^14.0.0",
119-
"@stream-io/stream-chat-css": "5.6.1",
119+
"@stream-io/stream-chat-css": "5.8.0",
120120
"@stream-io/transliterate": "^1.5.2",
121121
"angular-mentions": "1.4.0",
122122
"dayjs": "^1.11.10",

projects/customizations-example/src/app/app.component.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,16 @@
275275
[isQuoted]="isQuoted"
276276
></app-message-text>
277277
</ng-template>
278+
279+
<ng-template
280+
#messageBlocked
281+
let-message="message"
282+
let-isMyMessage="isMyMessage"
283+
>
284+
<ng-container *ngIf="isMyMessage; else othersMessage">
285+
You message was blocked by moderation policies.
286+
</ng-container>
287+
<ng-template #othersMessage>
288+
Message from {{ message.user.name }} was blocked by moderation policies.
289+
</ng-template>
290+
</ng-template>

projects/customizations-example/src/app/app.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
ChannelPreviewInfoContext,
3838
MessageReactionsSelectorComponent,
3939
MessageTextContext,
40+
MessageBlockedContext,
4041
} from 'stream-chat-angular';
4142
import { environment } from '../environments/environment';
4243

@@ -98,6 +99,8 @@ export class AppComponent implements AfterViewInit {
9899
private emptyThreadMessageListTemplate!: TemplateRef<void>;
99100
@ViewChild('messageText')
100101
messageTextTemplate!: TemplateRef<MessageTextContext>;
102+
@ViewChild('messageBlocked')
103+
messageBlockedTemplate!: TemplateRef<MessageBlockedContext>;
101104

102105
constructor(
103106
private chatService: ChatClientService,
@@ -195,6 +198,9 @@ export class AppComponent implements AfterViewInit {
195198
this.customTemplatesService.messageTextTemplate$.next(
196199
this.messageTextTemplate
197200
);
201+
this.customTemplatesService.messageBlockedTemplate$.next(
202+
this.messageBlockedTemplate
203+
);
198204
}
199205

200206
inviteClicked(channel: Channel) {

projects/stream-chat-angular/src/assets/i18n/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,7 @@ export const en = {
131131
'You currently have {{count}} attachments, the maximum is {{max}}':
132132
'You currently have {{count}} attachments, the maximum is {{max}}',
133133
'and others': 'and others',
134+
'Message was blocked by moderation policies':
135+
'Message was blocked by moderation policies',
134136
},
135137
};

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
MentionTemplateContext,
2424
MessageActionBoxItemContext,
2525
MessageActionsBoxContext,
26+
MessageBlockedContext,
2627
MessageContext,
2728
MessageReactionsContext,
2829
MessageReactionsSelectorContext,
@@ -364,5 +365,14 @@ export class CustomTemplatesService {
364365
TemplateRef<MessageTextContext> | undefined
365366
>(undefined);
366367

368+
/**
369+
* The template used to display blocked messages that have been removed by moderation policies instead of the default [message blocked component](/chat/docs/sdk/angular/components/MessageBlockedComponent/)
370+
*
371+
* The template has no effect if you're using a custom `messageTemplate$`
372+
*/
373+
messageBlockedTemplate$ = new BehaviorSubject<
374+
TemplateRef<MessageBlockedContext> | undefined
375+
>(undefined);
376+
367377
constructor() {}
368378
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<div
2+
class="str-chat__message str-chat__message-simple str-chat__message--blocked"
3+
[class.str-chat__message--me]="isMyMessage"
4+
[class.str-chat__message-simple--me]="isMyMessage"
5+
[class.str-chat__message--other]="!isMyMessage"
6+
[attr.data-testid]="'message-blocked-component'"
7+
>
8+
<div class="str-chat__message--blocked-inner">
9+
{{ "streamChat.Message was blocked by moderation policies" | translate }}
10+
</div>
11+
</div>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { TranslateModule } from '@ngx-translate/core';
3+
import { MessageBlockedComponent } from './message-blocked.component';
4+
import { ChangeDetectionStrategy } from '@angular/core';
5+
6+
describe('MessageBlockedComponent', () => {
7+
let component: MessageBlockedComponent;
8+
let fixture: ComponentFixture<MessageBlockedComponent>;
9+
let nativeElement: HTMLElement;
10+
11+
beforeEach(async () => {
12+
await TestBed.configureTestingModule({
13+
imports: [TranslateModule.forRoot()],
14+
declarations: [MessageBlockedComponent],
15+
})
16+
.overrideComponent(MessageBlockedComponent, {
17+
set: { changeDetection: ChangeDetectionStrategy.Default },
18+
})
19+
.compileComponents();
20+
});
21+
22+
beforeEach(() => {
23+
fixture = TestBed.createComponent(MessageBlockedComponent);
24+
component = fixture.componentInstance;
25+
nativeElement = fixture.nativeElement as HTMLElement;
26+
fixture.detectChanges();
27+
});
28+
29+
it('should create', () => {
30+
expect(component).toBeTruthy();
31+
});
32+
33+
it('should display the blocked message text', () => {
34+
const blockedMessageElement = nativeElement.querySelector(
35+
'[data-testid="message-blocked-component"]'
36+
);
37+
expect(blockedMessageElement).not.toBeNull();
38+
expect(blockedMessageElement?.textContent?.trim()).toContain(
39+
'streamChat.Message was blocked by moderation policies'
40+
);
41+
});
42+
43+
it('should apply "me" classes when isMyMessage is true', () => {
44+
component.isMyMessage = true;
45+
fixture.detectChanges();
46+
47+
const messageElement = nativeElement.querySelector(
48+
'[data-testid="message-blocked-component"]'
49+
);
50+
expect(
51+
messageElement?.classList.contains('str-chat__message--me')
52+
).toBeTrue();
53+
expect(
54+
messageElement?.classList.contains('str-chat__message-simple--me')
55+
).toBeTrue();
56+
expect(
57+
messageElement?.classList.contains('str-chat__message--other')
58+
).toBeFalse();
59+
});
60+
61+
it('should apply "other" class when isMyMessage is false', () => {
62+
component.isMyMessage = false;
63+
fixture.detectChanges();
64+
65+
const messageElement = nativeElement.querySelector(
66+
'[data-testid="message-blocked-component"]'
67+
);
68+
expect(
69+
messageElement?.classList.contains('str-chat__message--me')
70+
).toBeFalse();
71+
expect(
72+
messageElement?.classList.contains('str-chat__message-simple--me')
73+
).toBeFalse();
74+
expect(
75+
messageElement?.classList.contains('str-chat__message--other')
76+
).toBeTrue();
77+
});
78+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
2+
import { StreamMessage } from '../types';
3+
4+
/**
5+
* The `MessageBlocked` component displays a message that has been blocked by moderation policies.
6+
*/
7+
@Component({
8+
selector: 'stream-message-blocked',
9+
templateUrl: './message-blocked.component.html',
10+
styles: [],
11+
changeDetection: ChangeDetectionStrategy.OnPush,
12+
})
13+
export class MessageBlockedComponent {
14+
/**
15+
* The message that has been blocked.
16+
*/
17+
@Input() message: StreamMessage | undefined;
18+
/**
19+
* Whether the message is the current user's own message.
20+
*/
21+
@Input() isMyMessage = false;
22+
}

0 commit comments

Comments
 (0)