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 })[];
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
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).
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));
31 return stateWithOptimistic.map((value) => ({
33 optimistic: not(compare)(value, stateWithoutOptimistic),
34 failed: not(compare)(value, stateWithoutFailed),
38 export default selectOptimisticList;