1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

[PM-6194] Refactor injection of services in browser services module (#8380)

* refactored injector of services on the browser service module

* refactored the search and popup serach service to use state provider

* renamed back to default

* removed token service that was readded during merge conflict

* Updated search service construction on the cli

* updated to use user key definition

* Reafctored all components that refernce issearchable

* removed commented variable

* added uncommited code to remove dependencies not needed anymore

* added uncommited code to remove dependencies not needed anymore
This commit is contained in:
SmithThe4th
2024-04-10 14:02:46 +01:00
committed by GitHub
parent 560033cb88
commit 2bce6c538c
30 changed files with 393 additions and 182 deletions

View File

@@ -1,5 +1,5 @@
import { Directive, ViewChild, ViewContainerRef } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { Directive, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { BehaviorSubject, Subject, firstValueFrom, from, switchMap, takeUntil } from "rxjs";
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
@@ -32,8 +32,10 @@ const MaxCheckedCount = 500;
@Directive()
export abstract class BasePeopleComponent<
UserType extends ProviderUserUserDetailsResponse | OrganizationUserView,
> {
UserType extends ProviderUserUserDetailsResponse | OrganizationUserView,
>
implements OnInit, OnDestroy
{
@ViewChild("confirmTemplate", { read: ViewContainerRef, static: true })
confirmModalRef: ViewContainerRef;
@@ -88,7 +90,6 @@ export abstract class BasePeopleComponent<
status: StatusType;
users: UserType[] = [];
pagedUsers: UserType[] = [];
searchText: string;
actionPromise: Promise<void>;
protected allUsers: UserType[] = [];
@@ -97,7 +98,19 @@ export abstract class BasePeopleComponent<
protected didScroll = false;
protected pageSize = 100;
protected destroy$ = new Subject<void>();
private pagedUsersCount = 0;
private _searchText$ = new BehaviorSubject<string>("");
private isSearching: boolean = false;
get searchText() {
return this._searchText$.value;
}
set searchText(value: string) {
this._searchText$.next(value);
}
constructor(
protected apiService: ApiService,
@@ -122,6 +135,22 @@ export abstract class BasePeopleComponent<
abstract reinviteUser(id: string): Promise<void>;
abstract confirmUser(user: UserType, publicKey: Uint8Array): Promise<void>;
ngOnInit(): void {
this._searchText$
.pipe(
switchMap((searchText) => from(this.searchService.isSearchable(searchText))),
takeUntil(this.destroy$),
)
.subscribe((isSearchable) => {
this.isSearching = isSearchable;
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
async load() {
const response = await this.getUsers();
this.statusMap.clear();
@@ -390,12 +419,8 @@ export abstract class BasePeopleComponent<
}
}
isSearching() {
return this.searchService.isSearchable(this.searchText);
}
isPaging() {
const searching = this.isSearching();
const searching = this.isSearching;
if (searching && this.didScroll) {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises

View File

@@ -91,15 +91,16 @@ export class GroupsComponent implements OnInit, OnDestroy {
private pagedGroupsCount = 0;
private pagedGroups: GroupDetailsRow[];
private searchedGroups: GroupDetailsRow[];
private _searchText: string;
private _searchText$ = new BehaviorSubject<string>("");
private destroy$ = new Subject<void>();
private refreshGroups$ = new BehaviorSubject<void>(null);
private isSearching: boolean = false;
get searchText() {
return this._searchText;
return this._searchText$.value;
}
set searchText(value: string) {
this._searchText = value;
this._searchText$.next(value);
// Manually update as we are not using the search pipe in the template
this.updateSearchedGroups();
}
@@ -114,7 +115,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
if (this.isPaging()) {
return this.pagedGroups;
}
if (this.isSearching()) {
if (this.isSearching) {
return this.searchedGroups;
}
return this.groups;
@@ -180,6 +181,15 @@ export class GroupsComponent implements OnInit, OnDestroy {
takeUntil(this.destroy$),
)
.subscribe();
this._searchText$
.pipe(
switchMap((searchText) => this.searchService.isSearchable(searchText)),
takeUntil(this.destroy$),
)
.subscribe((isSearchable) => {
this.isSearching = isSearchable;
});
}
ngOnDestroy() {
@@ -297,10 +307,6 @@ export class GroupsComponent implements OnInit, OnDestroy {
this.loadMore();
}
isSearching() {
return this.searchService.isSearchable(this.searchText);
}
check(groupRow: GroupDetailsRow) {
groupRow.checked = !groupRow.checked;
}
@@ -310,7 +316,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
}
isPaging() {
const searching = this.isSearching();
const searching = this.isSearching;
if (searching && this.didScroll) {
this.resetPaging();
}
@@ -340,7 +346,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
}
private updateSearchedGroups() {
if (this.searchService.isSearchable(this.searchText)) {
if (this.isSearching) {
// Making use of the pipe in the component as we need know which groups where filtered
this.searchedGroups = this.searchPipe.transform(
this.groups,

View File

@@ -1,4 +1,4 @@
import { Component, OnDestroy, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import {
combineLatest,
@@ -9,7 +9,6 @@ import {
map,
Observable,
shareReplay,
Subject,
switchMap,
takeUntil,
} from "rxjs";
@@ -73,10 +72,7 @@ import { ResetPasswordComponent } from "./components/reset-password.component";
selector: "app-org-people",
templateUrl: "people.component.html",
})
export class PeopleComponent
extends BasePeopleComponent<OrganizationUserView>
implements OnInit, OnDestroy
{
export class PeopleComponent extends BasePeopleComponent<OrganizationUserView> {
@ViewChild("groupsTemplate", { read: ViewContainerRef, static: true })
groupsModalRef: ViewContainerRef;
@ViewChild("confirmTemplate", { read: ViewContainerRef, static: true })
@@ -99,7 +95,6 @@ export class PeopleComponent
orgResetPasswordPolicyEnabled = false;
protected canUseSecretsManager$: Observable<boolean>;
private destroy$ = new Subject<void>();
constructor(
apiService: ApiService,
@@ -210,8 +205,7 @@ export class PeopleComponent
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
super.ngOnDestroy();
}
async load() {

View File

@@ -281,7 +281,7 @@ export class AppComponent implements OnDestroy, OnInit {
await this.stateEventRunnerService.handleEvent("logout", userId as UserId);
this.searchService.clearIndex();
await this.searchService.clearIndex();
this.authService.logOut(async () => {
if (expired) {
this.platformUtilsService.showToast(

View File

@@ -272,7 +272,7 @@ export class VaultComponent implements OnInit, OnDestroy {
concatMap(async ([ciphers, filter, searchText]) => {
const filterFunction = createFilterFunction(filter);
if (this.searchService.isSearchable(searchText)) {
if (await this.searchService.isSearchable(searchText)) {
return await this.searchService.searchCiphers(searchText, [filterFunction], ciphers);
}
@@ -283,7 +283,7 @@ export class VaultComponent implements OnInit, OnDestroy {
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
filter(([collections, filter]) => collections != undefined && filter != undefined),
map(([collections, filter, searchText]) => {
concatMap(async ([collections, filter, searchText]) => {
if (filter.collectionId === undefined || filter.collectionId === Unassigned) {
return [];
}
@@ -303,7 +303,7 @@ export class VaultComponent implements OnInit, OnDestroy {
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
}
if (this.searchService.isSearchable(searchText)) {
if (await this.searchService.isSearchable(searchText)) {
collectionsToReturn = this.searchPipe.transform(
collectionsToReturn,
searchText,

View File

@@ -331,7 +331,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
}
this.searchService.indexCiphers(ciphers, organization.id);
await this.searchService.indexCiphers(ciphers, organization.id);
return ciphers;
}),
);
@@ -350,7 +350,7 @@ export class VaultComponent implements OnInit, OnDestroy {
const collections$ = combineLatest([nestedCollections$, filter$, this.currentSearchText$]).pipe(
filter(([collections, filter]) => collections != undefined && filter != undefined),
map(([collections, filter, searchText]) => {
concatMap(async ([collections, filter, searchText]) => {
if (
filter.collectionId === Unassigned ||
(filter.collectionId === undefined && filter.type !== undefined)
@@ -369,7 +369,7 @@ export class VaultComponent implements OnInit, OnDestroy {
collectionsToReturn = selectedCollection?.children.map((c) => c.node) ?? [];
}
if (this.searchService.isSearchable(searchText)) {
if (await this.searchService.isSearchable(searchText)) {
collectionsToReturn = this.searchPipe.transform(
collectionsToReturn,
searchText,
@@ -436,7 +436,7 @@ export class VaultComponent implements OnInit, OnDestroy {
const filterFunction = createFilterFunction(filter);
if (this.searchService.isSearchable(searchText)) {
if (await this.searchService.isSearchable(searchText)) {
return await this.searchService.searchCiphers(searchText, [filterFunction], ciphers);
}