1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 01:03:35 +00:00

[PM-9854] - Send Search Component (#10278)

* send list items container

* update send list items container

* finalize send list container

* remove unecessary file

* undo change to config

* prefer use of takeUntilDestroyed

* add send items service

* and send list filters and service

* undo changes to jest config

* add specs for send list filters

* Revert "Merge branch 'PM-9853' into PM-9852"

This reverts commit 9f65ded13f, reversing
changes made to 63f95600e8.

* add send items service

* Revert "Revert "Merge branch 'PM-9853' into PM-9852""

This reverts commit 81e9860c25.

* finish send search

* fix formControlName

* add specs

* finalize send search

* layout and copy fixes

* cleanup

* Remove unneeded empty file

* Remove the erroneous addition of send-list-filters to vault-export tsconfig

* update tests

* hide send list filters for non-premium users

* fix and add specss

* Fix small typo

* Re-add missing tests

* Remove unused NgZone

* Rename selector for send-search

---------

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
This commit is contained in:
Jordan Aasen
2024-08-07 05:34:03 -07:00
committed by GitHub
parent 5b47ca1011
commit af14c3fe6d
18 changed files with 514 additions and 53 deletions

View File

@@ -0,0 +1,102 @@
import { Injectable } from "@angular/core";
import {
BehaviorSubject,
combineLatest,
distinctUntilChanged,
from,
map,
Observable,
shareReplay,
startWith,
Subject,
switchMap,
tap,
} from "rxjs";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
import { SendListFiltersService } from "./send-list-filters.service";
/**
* Service for managing the various item lists on the new Vault tab in the browser popup.
*/
@Injectable({
providedIn: "root",
})
export class SendItemsService {
private _searchText$ = new BehaviorSubject<string>("");
/**
* Subject that emits whenever new sends are being processed/filtered.
* @private
*/
private _sendsLoading$ = new Subject<void>();
latestSearchText$: Observable<string> = this._searchText$.asObservable();
private _sendList$: Observable<SendView[]> = this.sendService.sendViews$;
/**
* Observable that emits the list of sends, filtered and sorted based on the current search text and filters.
* The list is sorted alphabetically by send name.
* @readonly
*/
filteredAndSortedSends$: Observable<SendView[]> = combineLatest([
this._sendList$,
this._searchText$,
this.sendListFiltersService.filterFunction$,
]).pipe(
tap(() => this._sendsLoading$.next()),
map(([sends, searchText, filterFunction]): [SendView[], string] => [
filterFunction(sends),
searchText,
]),
map(([sends, searchText]) => this.searchService.searchSends(sends, searchText)),
map((sends) => sends.sort((a, b) => a.name.localeCompare(b.name))),
shareReplay({ refCount: true, bufferSize: 1 }),
);
/**
* Observable that indicates whether the service is currently loading sends.
*/
loading$: Observable<boolean> = this._sendsLoading$
.pipe(map(() => true))
.pipe(startWith(true), distinctUntilChanged(), shareReplay({ refCount: false, bufferSize: 1 }));
/**
* Observable that indicates whether a filter is currently applied to the sends.
*/
hasFilterApplied$ = combineLatest([this._searchText$, this.sendListFiltersService.filters$]).pipe(
switchMap(([searchText, filters]) => {
return from(this.searchService.isSearchable(searchText)).pipe(
map(
(isSearchable) =>
isSearchable || Object.values(filters).some((filter) => filter !== null),
),
);
}),
);
/**
* Observable that indicates whether the user's vault is empty.
*/
emptyList$: Observable<boolean> = this._sendList$.pipe(map((sends) => !sends.length));
/**
* Observable that indicates whether there are no sends to show with the current filter.
*/
noFilteredResults$: Observable<boolean> = this.filteredAndSortedSends$.pipe(
map((sends) => !sends.length),
);
constructor(
private sendService: SendService,
private sendListFiltersService: SendListFiltersService,
private searchService: SearchService,
) {}
applyFilter(newSearchText: string) {
this._searchText$.next(newSearchText);
}
}