1 import noop from '@proton/utils/noop';
3 import type { ESIndexingState, ESProgress, EncryptedSearchFunctions, OptionalESCallbacks } from './models';
6 * Number of items to add to the search results list during
7 * a partial search. It corresponds to one page of results in mail
9 export const ES_EXTRA_RESULTS_LIMIT = 50;
12 * Size of a batch of items during indexing and syncing.
13 * It corresponds to the maximum number of items' metadata returned
16 export const ES_MAX_PARALLEL_ITEMS = 150;
19 * Number of items to fetch and process concurrently during indexing. Some
20 * browsers internally set the maximum concurrent requests to handle to 100,
21 * therefore we impose a slightly more stringent limit to allow some room for
22 * other requests the app might send. Note that this should not be used for backgound
23 * indexing, in which case ES_BACKGROUND_CONCURRENT should be used instead
25 export const ES_MAX_CONCURRENT = 20;
28 * Number of items to fetch and process concurrently when the indexing is started in background mode
30 export const ES_BACKGROUND_CONCURRENT = 1;
33 * Number of characters to retain from an item's metadata when highlighting it
35 export const ES_MAX_INITIAL_CHARS = 20;
38 * Maximum size of cached items expressed in MB. It is heuristically determined
39 * so to cover most users (it should be enough for ~50k emails, and more than 95% of
40 * paid users have less than that, based on an extrapolation made in 2021) yet not
41 * to be too heavy on their devices' memory. The target size is 500 MB, however the
42 * number is larger due to our size estimation function being more conservative
43 * than the actual memory occupation
45 export const ES_MAX_CACHE = 600000000; // 600 MB
48 * Maximum number of metadata "pages" per batch during metadata indexing
50 export const ES_MAX_METADATA_BATCH = 20;
51 export const ES_BACKGROUND_METADATA_BATCH = 1;
54 * Upper bound of number of items queried from IndexedDB at once
56 export const ES_MAX_ITEMS_PER_BATCH = 1000;
59 * Current version of the most up-to-date ES IndexedDB
61 export const INDEXEDDB_VERSION = 2;
64 * Maximum number of times an API call to fetch an item
65 * content will be retried before being stored locally
68 export const ES_MAX_RETRIES = 10;
71 * Error codes that are deemed temporary and therefore will trigger a retry
72 * during API calls that the ES library does
74 export const ES_TEMPORARY_ERRORS = [408, 429, 502, 503];
77 * Regular expression used to find and/or remove diacritics for the purpose of
78 * searching and highlighting text. It matches all combining characters
80 export const DIACRITICS_REGEXP = /\p{Mark}/gu;
83 * Regular expression used to turn all fancy quotes into normal ones
85 export const QUOTES_REGEXP =
86 /\u00ab|\u00bb|\u201e|\u201c|\u201f|\u201d|\u275d|\u275e|\u276e|\u276f|\u2e42|\u301d|\u301e|\u301f|\uff02/gu;
89 * Regular expression used to turn all fancy apostrophes into normal ones
91 export const APOSTROPHES_REGEXP = /\u2018|\u2019|\u02bc/gu;
94 * Configuration of the Web Crypto API to symmetrically encrypt items in IndexedDB
96 export const AesKeyGenParams: AesKeyGenParams = { name: 'AES-GCM', length: 128 };
97 export const KeyUsages: KeyUsage[] = ['encrypt', `decrypt`];
102 export enum INDEXING_STATUS {
109 export enum TIMESTAMP_TYPE {
115 export enum ES_SYNC_ACTIONS {
122 export enum STORING_OUTCOME {
131 export const defaultESStatus = {
132 permanentResults: [],
133 setResultsList: () => {},
134 lastTimePoint: undefined,
135 previousESSearchParams: undefined,
136 cachedIndexKey: undefined,
138 isEnablingContentSearch: false,
143 isSearchPartial: false,
146 isEnablingEncryptedSearch: false,
147 isContentIndexingPaused: false,
148 isMetadataIndexingPaused: false,
149 contentIndexingDone: false,
150 isConfigFromESDBLoaded: false,
151 getCacheStatus: () => ({ isCacheReady: false, isCacheLimited: false }),
154 export const defaultESCache = {
157 isCacheLimited: false,
161 export const defaultESIndexingState: ESIndexingState = {
164 totalIndexingItems: 0,
165 currentProgressValue: 0,
168 export const defaultESContext: EncryptedSearchFunctions<any, any, any> = {
169 encryptedSearch: async () => false,
170 highlightString: () => '',
171 highlightMetadata: () => ({ numOccurrences: 0, resultJSX: null as any }),
172 enableEncryptedSearch: async () => false,
173 enableContentSearch: async () => {},
174 handleEvent: async () => {},
175 isSearchResult: () => false,
176 esDelete: async () => {},
177 shouldHighlight: () => false,
178 initializeES: async () => {},
179 pauseContentIndexing: async () => {},
180 pauseMetadataIndexing: async () => {},
181 cacheIndexedDB: async () => {},
182 toggleEncryptedSearch: async () => {},
183 getCache: () => new Map(),
184 resetCache: () => {},
185 correctDecryptionErrors: async () => 0,
186 esStatus: defaultESStatus,
187 progressRecorderRef: { current: [0, 0] },
188 esIndexingProgressState: defaultESIndexingState,
191 export const defaultESCallbacks: OptionalESCallbacks<any, any, any> = {
192 checkIsReverse: () => true,
193 shouldOnlySortResults: () => false,
195 getSearchInterval: () => ({ begin: undefined, end: undefined }),
196 applyFilters: () => true,
197 onContentDeletion: async () => {},
198 correctDecryptionErrors: async () => 0,
201 export const defaultESProgress: ESProgress = {
207 recoveryPoint: undefined,
208 status: INDEXING_STATUS.INACTIVE,