99} from '@angular/core' ;
1010
1111import { select , Store } from '@ngrx/store' ;
12- import { BehaviorSubject , Subscription } from 'rxjs' ;
12+ import { BehaviorSubject , Subscription , of as observableOf } from 'rxjs' ;
1313import difference from 'lodash/difference' ;
1414
1515import { NotificationsService } from '../notifications.service' ;
@@ -18,6 +18,9 @@ import { notificationsStateSelector } from '../selectors';
1818import { INotification } from '../models/notification.model' ;
1919import { NotificationsState } from '../notifications.reducers' ;
2020import { INotificationBoardOptions } from '../../../../config/notifications-config.interfaces' ;
21+ import { LiveRegionService } from '../../live-region/live-region.service' ;
22+ import { hasNoValue , isNotEmptyOperator } from '../../empty.util' ;
23+ import { take } from 'rxjs/operators' ;
2124
2225@Component ( {
2326 selector : 'ds-notifications-board' ,
@@ -49,9 +52,12 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy {
4952 */
5053 public isPaused$ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( false ) ;
5154
52- constructor ( private service : NotificationsService ,
53- private store : Store < AppState > ,
54- private cdr : ChangeDetectorRef ) {
55+ constructor (
56+ private service : NotificationsService ,
57+ private store : Store < AppState > ,
58+ private cdr : ChangeDetectorRef ,
59+ protected liveRegionService : LiveRegionService ,
60+ ) {
5561 }
5662
5763 ngOnInit ( ) : void {
@@ -85,6 +91,7 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy {
8591 this . notifications . splice ( this . notifications . length - 1 , 1 ) ;
8692 }
8793 this . notifications . splice ( 0 , 0 , item ) ;
94+ this . addContentToLiveRegion ( item ) ;
8895 } else {
8996 // Remove the notification from the store
9097 // This notification was in the store, but not in this.notifications
@@ -93,29 +100,44 @@ export class NotificationsBoardComponent implements OnInit, OnDestroy {
93100 }
94101 }
95102
103+ /**
104+ * Adds the content of the notification (if any) to the live region, so it can be announced by screen readers.
105+ */
106+ private addContentToLiveRegion ( item : INotification ) {
107+ let content = item . content ;
108+
109+ if ( ! item . options . announceContentInLiveRegion || hasNoValue ( content ) ) {
110+ return ;
111+ }
112+
113+ if ( typeof content === 'string' ) {
114+ content = observableOf ( content ) ;
115+ }
116+
117+ content . pipe (
118+ isNotEmptyOperator ( ) ,
119+ take ( 1 ) ,
120+ ) . subscribe ( contentStr => this . liveRegionService . addMessage ( contentStr ) ) ;
121+ }
122+
123+ /**
124+ * Whether to block the provided item because a duplicate notification with the exact same information already
125+ * exists within the notifications array.
126+ * @param item The item to check
127+ * @return true if the notifications array already contains a notification with the exact same information as the
128+ * provided item. false otherwise.
129+ * @private
130+ */
96131 private block ( item : INotification ) : boolean {
97132 const toCheck = item . html ? this . checkHtml : this . checkStandard ;
133+
98134 this . notifications . forEach ( ( notification ) => {
99135 if ( toCheck ( notification , item ) ) {
100136 return true ;
101137 }
102138 } ) ;
103139
104- if ( this . notifications . length > 0 ) {
105- this . notifications . forEach ( ( notification ) => {
106- if ( toCheck ( notification , item ) ) {
107- return true ;
108- }
109- } ) ;
110- }
111-
112- let comp : INotification ;
113- if ( this . notifications . length > 0 ) {
114- comp = this . notifications [ 0 ] ;
115- } else {
116- return false ;
117- }
118- return toCheck ( comp , item ) ;
140+ return false ;
119141 }
120142
121143 private checkStandard ( checker : INotification , item : INotification ) : boolean {
0 commit comments