1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-10610] push notification to end user notification service (#13876)

* use NotificationsService.notifictions$ for tracking inside default end user notification
This commit is contained in:
Jason Ng
2025-03-26 13:16:40 -04:00
committed by GitHub
parent be8c5f28b5
commit a3e01ad672
7 changed files with 45 additions and 16 deletions

View File

@@ -1480,7 +1480,7 @@ const safeProviders: SafeProvider[] = [
safeProvider({
provide: EndUserNotificationService,
useClass: DefaultEndUserNotificationService,
deps: [StateProvider, ApiServiceAbstraction],
deps: [StateProvider, ApiServiceAbstraction, NotificationsService],
}),
safeProvider({
provide: DeviceTrustToastServiceAbstraction,

View File

@@ -24,4 +24,6 @@ export enum NotificationType {
SyncOrganizations = 17,
SyncOrganizationStatusChanged = 18,
SyncOrganizationCollectionSettingChanged = 19,
Notification = 20,
NotificationStatus = 21,
}

View File

@@ -1,9 +1,14 @@
import { Subscription } from "rxjs";
import { Observable, Subject, Subscription } from "rxjs";
import { NotificationResponse } from "@bitwarden/common/models/response/notification.response";
import { UserId } from "@bitwarden/common/types/guid";
import { LogService } from "../../abstractions/log.service";
import { NotificationsService } from "../notifications.service";
export class NoopNotificationsService implements NotificationsService {
notifications$: Observable<readonly [NotificationResponse, UserId]> = new Subject();
constructor(private logService: LogService) {}
startListening(): Subscription {

View File

@@ -1,9 +1,13 @@
import { Subscription } from "rxjs";
import { Observable, Subscription } from "rxjs";
import { NotificationResponse } from "@bitwarden/common/models/response/notification.response";
import { UserId } from "@bitwarden/common/types/guid";
/**
* A service offering abilities to interact with push notifications from the server.
*/
export abstract class NotificationsService {
abstract notifications$: Observable<readonly [NotificationResponse, UserId]>;
/**
* Starts automatic listening and processing of notifications, should only be called once per application,
* or you will risk notifications being processed multiple times.

View File

@@ -34,13 +34,6 @@ export abstract class EndUserNotificationService {
*/
abstract markAsDeleted(notificationId: any, userId: UserId): Promise<void>;
/**
* Create/update a notification in the state for the user specified within the notification.
* @remarks This method should only be called when a notification payload is received from the web socket.
* @param notification
*/
abstract upsert(notification: Notification): Promise<void>;
/**
* Clear all notifications from state for the given user.
* @param userId

View File

@@ -1,7 +1,8 @@
import { TestBed } from "@angular/core/testing";
import { firstValueFrom } from "rxjs";
import { firstValueFrom, of } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { NotificationsService } from "@bitwarden/common/platform/notifications";
import { StateProvider } from "@bitwarden/common/platform/state";
import { NotificationId, UserId } from "@bitwarden/common/types/guid";
import { DefaultEndUserNotificationService } from "@bitwarden/vault";
@@ -36,6 +37,12 @@ describe("End User Notification Center Service", () => {
send: mockApiSend,
},
},
{
provide: NotificationsService,
useValue: {
notifications$: of(null),
},
},
],
});
});

View File

@@ -1,8 +1,10 @@
import { Injectable } from "@angular/core";
import { map, Observable, switchMap } from "rxjs";
import { concatMap, filter, map, Observable, switchMap } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { NotificationType } from "@bitwarden/common/enums";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { NotificationsService } from "@bitwarden/common/platform/notifications";
import { StateProvider } from "@bitwarden/common/platform/state";
import { UserId } from "@bitwarden/common/types/guid";
@@ -14,12 +16,30 @@ import { NOTIFICATIONS } from "../state/end-user-notification.state";
/**
* A service for retrieving and managing notifications for end users.
*/
@Injectable()
@Injectable({
providedIn: "root",
})
export class DefaultEndUserNotificationService implements EndUserNotificationService {
constructor(
private stateProvider: StateProvider,
private apiService: ApiService,
) {}
private defaultNotifications: NotificationsService,
) {
this.defaultNotifications.notifications$
.pipe(
filter(
([notification]) =>
notification.type === NotificationType.Notification ||
notification.type === NotificationType.NotificationStatus,
),
concatMap(([notification, userId]) =>
this.updateNotificationState(userId, [
new NotificationViewData(notification.payload as NotificationViewResponse),
]),
),
)
.subscribe();
}
notifications$ = perUserCache$((userId: UserId): Observable<NotificationView[]> => {
return this.notificationState(userId).state$.pipe(
@@ -58,8 +78,6 @@ export class DefaultEndUserNotificationService implements EndUserNotificationSer
await this.getNotifications(userId);
}
upsert(notification: Notification): any {}
async clearState(userId: UserId): Promise<void> {
await this.updateNotificationState(userId, []);
}