Skip to content

Commit

Permalink
118220: Store messages with ID so clears can be targeted
Browse files Browse the repository at this point in the history
  • Loading branch information
AAwouters committed Sep 25, 2024
1 parent 35d29c8 commit c1fa52e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 16 deletions.
34 changes: 32 additions & 2 deletions src/app/shared/live-region/live-region.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { LiveRegionService } from './live-region.service';
import { fakeAsync, tick, flush } from '@angular/core/testing';
import { UUIDService } from '../../core/shared/uuid.service';

describe('liveRegionService', () => {
let service: LiveRegionService;


beforeEach(() => {
service = new LiveRegionService();
service = new LiveRegionService(
new UUIDService(),
);
});

describe('addMessage', () => {
Expand Down Expand Up @@ -85,6 +87,34 @@ describe('liveRegionService', () => {
expect(results[3]).toEqual([]);
}));

it('should not pop messages added after clearing within timeOut period', fakeAsync(() => {
const results: string[][] = [];

service.getMessages$().subscribe((messages) => {
results.push(messages);
});

expect(results.length).toEqual(1);
expect(results[0]).toEqual([]);

service.addMessage('Message One');
tick(10000);
service.clear();
tick(15000);
service.addMessage('Message Two');

// Message Two should not be cleared after 5 more seconds
tick(5000);

expect(results.length).toEqual(4);
expect(results[3]).toEqual(['Message Two']);

// But should be cleared 30 seconds after it was added
tick(25000);
expect(results.length).toEqual(5);
expect(results[4]).toEqual([]);
}));

it('should respect configured timeOut', fakeAsync(() => {
const results: string[][] = [];

Expand Down
39 changes: 25 additions & 14 deletions src/app/shared/live-region/live-region.service.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { environment } from '../../../environments/environment';
import { UUIDService } from '../../core/shared/uuid.service';

@Injectable({
providedIn: 'root',
})
export class LiveRegionService {

constructor(
protected uuidService: UUIDService,
) {
}

/**
* The duration after which the messages disappear in milliseconds
* @protected
*/
protected messageTimeOutDurationMs: number = environment.liveRegion.messageTimeOutDurationMs;

/**
* Array containing the messages that should be shown in the live region
* Array containing the messages that should be shown in the live region,
* together with a uuid, so they can be uniquely identified
* @protected
*/
protected messages: string[] = [];
protected messages: { message: string, uuid: string }[] = [];

/**
* BehaviorSubject emitting the array with messages every time the array updates
Expand All @@ -34,27 +41,28 @@ export class LiveRegionService {
/**
* Returns a copy of the array with the current live region messages
*/
getMessages() {
return [...this.messages];
getMessages(): string[] {
return this.messages.map(messageObj => messageObj.message);
}

/**
* Returns the BehaviorSubject emitting the array with messages every time the array updates
*/
getMessages$() {
getMessages$(): BehaviorSubject<string[]> {
return this.messages$;
}

/**
* Adds a message to the live-region messages array
* @param message
* @return The uuid of the message
*/
addMessage(message: string) {
this.messages.push(message);
addMessage(message: string): string {
const uuid = this.uuidService.generate();
this.messages.push({ message, uuid });
setTimeout(() => this.clearMessageByUUID(uuid), this.messageTimeOutDurationMs);
this.emitCurrentMessages();

// Clear the message once the timeOut has passed
setTimeout(() => this.pop(), this.messageTimeOutDurationMs);
return uuid;
}

/**
Expand All @@ -66,12 +74,15 @@ export class LiveRegionService {
}

/**
* Removes the longest living message from the array.
* Removes the message with the given UUID from the messages array
* @param uuid The uuid of the message to clear
* @protected
*/
protected pop() {
if (this.messages.length > 0) {
this.messages.shift();
clearMessageByUUID(uuid: string) {
const index = this.messages.findIndex(messageObj => messageObj.uuid === uuid);

if (index !== -1) {
this.messages.splice(index, 1);
this.emitCurrentMessages();
}
}
Expand Down

0 comments on commit c1fa52e

Please sign in to comment.