Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / store / reducers / monitor.ts
blobf279d6b9706bdc86b20268ee51126cab2d809740
1 import type { Reducer } from 'redux';
3 import { PassErrorCode } from '@proton/pass/lib/api/errors';
4 import {
5     intoCustomMonitorAddress,
6     intoMonitorDomain,
7     intoProtonMonitorAddress,
8 } from '@proton/pass/lib/monitor/monitor.utils';
9 import { AddressType, type MonitorAddress, type MonitorDomain } from '@proton/pass/lib/monitor/types';
10 import {
11     addCustomAddress,
12     deleteCustomAddress,
13     getBreaches,
14     resolveAddressMonitor,
15     toggleAddressMonitor,
16     verifyCustomAddress,
17 } from '@proton/pass/store/actions';
18 import type { MaybeNull } from '@proton/pass/types';
19 import { partialMerge } from '@proton/pass/utils/object/merge';
20 import lastItem from '@proton/utils/lastItem';
22 export type MonitorState = MaybeNull<{
23     custom: MonitorAddress<AddressType.CUSTOM>[];
24     preview: MonitorDomain[];
25     proton: MonitorAddress<AddressType.PROTON>[];
26     customDomains: boolean;
27     total: number;
28 }>;
30 const monitorReducer: Reducer<MonitorState> = (state = null, action) => {
31     if (getBreaches.success.match(action)) {
32         return {
33             custom: action.payload.CustomEmails?.map(intoCustomMonitorAddress) ?? [],
34             preview: action.payload.DomainsPeek?.map(intoMonitorDomain) ?? [],
35             proton: action.payload.Addresses?.map(intoProtonMonitorAddress) ?? [],
36             customDomains: action.payload.HasCustomDomains,
37             total: action.payload.EmailsCount,
38         };
39     }
41     if (state) {
42         if (addCustomAddress.success.match(action)) {
43             return partialMerge(state, {
44                 custom: state.custom.concat(intoCustomMonitorAddress(action.payload)),
45             });
46         }
48         if (verifyCustomAddress.success.match(action)) {
49             const breached = (action.payload.breachCount ?? 0) > 0;
51             return partialMerge(state, {
52                 total: state.total + Number(breached),
53                 custom: state.custom.map((breach) => {
54                     if (breach.addressId !== action.payload.addressId) return breach;
55                     return action.payload;
56                 }),
57             });
58         }
60         if (verifyCustomAddress.failure.match(action)) {
61             const addressId = lastItem(action.meta.request.id.split('::'));
62             if (action.payload.code === PassErrorCode.NOT_ALLOWED && addressId) {
63                 return partialMerge(state, { custom: state.custom.filter((breach) => breach.addressId !== addressId) });
64             }
65         }
67         if (deleteCustomAddress.success.match(action)) {
68             const breach = state.custom.find((breach) => breach.addressId === action.payload);
69             const breached = (breach?.breachCount ?? 0) > 0;
71             return partialMerge(state, {
72                 total: Math.max(0, state.total - Number(breached)),
73                 custom: state.custom.filter((breach) => breach.addressId !== action.payload),
74             });
75         }
77         if (resolveAddressMonitor.success.match(action)) {
78             const dto = action.payload;
80             switch (dto.type) {
81                 case AddressType.ALIAS: {
82                     return partialMerge(state, { total: Math.max(0, state.total - 1) });
83                 }
85                 case AddressType.CUSTOM: {
86                     const address = state.custom.find(({ addressId }) => addressId === dto.addressId);
87                     const breached = (address?.breachCount ?? 0) > 0;
89                     return address
90                         ? partialMerge(state, {
91                               total: Math.max(0, state.total - Number(breached)),
92                               custom: state.custom.map((breach) => {
93                                   if (breach.addressId !== dto.addressId) return breach;
94                                   return { ...breach, breachCount: 0, breached: false };
95                               }),
96                           })
97                         : state;
98                 }
100                 case AddressType.PROTON: {
101                     const address = state.proton.find(({ addressId }) => addressId === dto.addressId);
102                     const breached = (address?.breachCount ?? 0) > 0;
104                     return address
105                         ? partialMerge(state, {
106                               total: Math.max(0, state.total - Number(breached)),
107                               proton: state.proton.map((breach) => {
108                                   if (breach.addressId !== dto.addressId) return breach;
109                                   return { ...breach, breachCount: 0, breached: false };
110                               }),
111                           })
112                         : state;
113                 }
114             }
115         }
117         if (toggleAddressMonitor.success.match(action)) {
118             const type = action.payload.type;
119             if (type === AddressType.ALIAS) return state;
121             return partialMerge(state, {
122                 [type]: state[type].map((breach) =>
123                     action.payload.type === AddressType.ALIAS || breach.addressId !== action.payload.addressId
124                         ? breach
125                         : action.payload
126                 ),
127             });
128         }
129     }
131     return state;
134 export default monitorReducer;