1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 05:30:01 +00:00

Improve filter service results

This commit is contained in:
Matt Gibson
2025-03-13 14:23:58 -07:00
parent ecb95bb471
commit 9353cfb6fb

View File

@@ -2,17 +2,31 @@
// @ts-strict-ignore
import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { BehaviorSubject, Observable, Subject, firstValueFrom, map } from "rxjs";
import {
BehaviorSubject,
Observable,
Subject,
combineLatest,
firstValueFrom,
map,
of,
switchMap,
} from "rxjs";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { FilterService } from "@bitwarden/common/vault/search/filter.service";
import { ProcessInstructions } from "@bitwarden/common/vault/search/query.types";
import { ParseResult } from "@bitwarden/common/vault/search/query.types";
// eslint-disable-next-line no-restricted-imports -- TODO: this needs to go
import { CollectionService } from "../../../../admin-console/src/common/collections";
@Directive()
export class VaultItemsComponent implements OnInit, OnDestroy {
@@ -34,7 +48,7 @@ export class VaultItemsComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();
private searchTimeout: any = null;
private isSearchable: boolean = false;
private processInstructions$: Observable<ProcessInstructions>;
private parsedFilter$: Observable<ParseResult>;
private _searchText$ = new BehaviorSubject<string>("");
get searchText() {
return this._searchText$.value;
@@ -47,16 +61,18 @@ export class VaultItemsComponent implements OnInit, OnDestroy {
protected filterService: FilterService,
protected searchService: SearchService,
protected cipherService: CipherService,
protected folderService: FolderService,
protected organizationService: OrganizationService,
protected collectionService: CollectionService,
protected accountService: AccountService,
) {}
async ngOnInit() {
this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
const parsed$ = this.filterService.parse(this._searchText$).pipe(takeUntilDestroyed());
const parsedFilter$ = this.filterService.parse(this._searchText$).pipe(takeUntilDestroyed());
this.processInstructions$ = parsed$.pipe(map((p) => p.processInstructions));
parsed$.subscribe(({ isError }) => {
parsedFilter$.subscribe(({ isError }) => {
this.isSearchable = !isError;
});
}
@@ -138,6 +154,33 @@ export class VaultItemsComponent implements OnInit, OnDestroy {
indexedCiphers = [...failedCiphers, ...indexedCiphers];
}
this.ciphers = await firstValueFrom(this.filterService.filter(this.processInstructions$));
const context$ = this.accountService.activeAccount$.pipe(
switchMap((account) => {
return this.filterService.context$({
ciphers: this.cipherService.cipherViews$(account.id),
folders: this.folderService.folderViews$(account.id),
collections: this.collectionService.decryptedCollections$,
organizations: this.organizationService.organizations$(account.id),
});
}),
);
const ciphers$ = combineLatest([this.parsedFilter$, context$]).pipe(
switchMap(([parsedFilter, context]) => {
return this.filterService.filter(of([parsedFilter, context]));
}),
// this.filterService.filter,
switchMap((result) => {
if (result.isError) {
// return all ciphers
return context$.pipe(map((c) => c.ciphers));
} else {
// return filtered ciphers
return of(result.ciphers);
}
}),
);
this.ciphers = await firstValueFrom(ciphers$);
}
}