Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / store / optimistic / selectors / select-optimistic-list.ts
blob747ae124678d4da7767b959050ef3538c0e9760f
1 import type { Unpack } from '@proton/pass/types';
2 import { not } from '@proton/pass/utils/fp/predicates';
4 import type { OptimisticReducersMapObject, OptimisticSelector, StateFromOptimisticReducersMapObject } from '../types';
5 import { asIfNotFailed } from './select-is-failed';
6 import { asIfNotOptimistic } from './select-is-optimistic';
8 export type OptimisticList<T extends any[]> = (Unpack<T> & { optimistic: boolean; failed: boolean })[];
10 /**
11  * When retrieving a list from a selector for an optimistic sub-state,
12  * it can be helpful to map each list item as being optimistic or failed
13  * in a single pass.
14  *
15  * The "lens" function is necessary in order to define how we should compare items
16  * (ie: checking on a specific key instead of relying on reference checks).
17  */
18 const selectOptimisticList =
19     <T extends {}, M extends OptimisticReducersMapObject>(reducerMap: M) =>
20     <R extends any[]>(selector: OptimisticSelector<M, R>, lens: (item: Unpack<R>) => any) =>
21     (state: T): OptimisticList<R> => {
22         const stateWithoutOptimistic = selector(asIfNotOptimistic(state, reducerMap));
23         const stateWithoutFailed = selector(asIfNotFailed(state, reducerMap));
24         const stateWithOptimistic = selector(state as any as StateFromOptimisticReducersMapObject<M>);
26         const compare = (value: Unpack<R>, stateToCompare: R): boolean => {
27             const match = lens(value);
28             return stateToCompare.some((val) => match === lens(val));
29         };
31         return stateWithOptimistic.map((value) => ({
32             ...value,
33             optimistic: not(compare)(value, stateWithoutOptimistic),
34             failed: not(compare)(value, stateWithoutFailed),
35         }));
36     };
38 export default selectOptimisticList;