1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00
Files
browser/libs/tools/send/send-ui/src/services/send-items.service.ts
Jordan Aasen ab5a02f483 [PM-12774] - don't display filters when no sends are available (#11298)
* don't display filters when no sends are available

* move logic down. add conditional class

* fix logic for send filters
2024-10-01 20:46:10 +02:00

107 lines
3.2 KiB
TypeScript

import { Injectable } from "@angular/core";
import {
BehaviorSubject,
combineLatest,
distinctUntilChanged,
from,
map,
merge,
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> = merge(
this._sendsLoading$.pipe(map(() => true)),
this.filteredAndSortedSends$.pipe(map(() => false)),
).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 send list 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);
}
}