1 import type { MutableRefObject } from 'react';
3 import type { DecryptedKey } from '@proton/shared/lib/interfaces';
5 import type { CachedItem, ESEvent, ESIndexingState, ESItem, ESItemInfo, ESStatus, ESTimepoint } from './interfaces';
8 * Show or update the search results in the UI
10 export type ESSetResultsList<ESItemMetadata, ESItemContent> = (
11 Elements: ESItem<ESItemMetadata, ESItemContent>[]
15 * Return the user keys
17 export type GetUserKeys = () => Promise<DecryptedKey[]>;
20 * Extract ID and timepoint from an item, encrypted or otherwise
22 export type GetItemInfo<ESItemMetadata> = (item: ESItemMetadata) => ESItemInfo;
25 * Types of ES functions
27 export type EncryptedSearch<ESItemMetadata, ESItemContent> = (
28 setResultsList: ESSetResultsList<ESItemMetadata, ESItemContent>,
30 ) => Promise<boolean>;
32 export type EncryptedSearchExecution<ESItemMetadata, ESItemContent, ESSearchParameters> = (
33 setResultsList: ESSetResultsList<ESItemMetadata, ESItemContent>,
34 esSearchParams: ESSearchParameters,
35 minimumItems: number | undefined,
36 sendMetricsOnSearch?: boolean
37 ) => Promise<boolean>;
38 export type HighlightString = (content: string, setAutoScroll: boolean) => string;
40 export type HighlightMetadata = (
44 ) => { numOccurrences: number; resultJSX: JSX.Element };
46 export type EnableContentSearch = (options?: {
47 isRefreshed?: boolean | undefined;
48 isBackgroundIndexing?: boolean;
49 notify?: boolean | undefined;
52 export type EnableEncryptedSearch = (options?: {
53 isRefreshed?: boolean | undefined;
54 isBackgroundIndexing?: boolean;
55 showErrorNotification?: boolean;
56 }) => Promise<boolean>;
59 * Core functionalities of ES to be used in the product
61 export interface EncryptedSearchFunctions<ESItemMetadata, ESSearchParameters, ESItemContent = void> {
63 * Run a new encrypted search or increment an existing one (the difference is handled internally).
64 * @param setResultsList a callback that will be given the items to show, i.e. those found as search
65 * results, and that should handle the UI part of displaying them to the users
66 * @param minimumItems is the optional smallest number of items that the search is expected to produce.
67 * If specified this parameter instructs the search to try finding at least this number of items from disk,
68 * both in case of a new search with limited cache and in case of an incremented search
69 * @returns a boolean indicating the success of the search
71 encryptedSearch: EncryptedSearch<ESItemMetadata, ESItemContent>;
74 * Insert the <mark></mark> highlighting markdown in a string and returns a string containing it,
75 * which then needs to be displayed in the UI. Note that the keywords to highlight are extracted
76 * directly with the getSearchParams callback
77 * @param content the string where to insert the markdown
78 * @param setAutoScroll whether to insert the data-auto-scroll attribute to the first istance of
79 * the inserted mark tags. The UI should automatically scroll, if possible, to said first tag
80 * @returns the string containing the markdown
82 highlightString: HighlightString;
85 * Inserts the <mark></mark> highlighting markdown in a string and returns directly the JSX node
87 * @param metadata the string where to insert the markdown
88 * @param isBold specifies whether the text should also be bolded (e.g. in some headers)
89 * @param trim specifies whether to substitute the initial portion of the string by an ellipsis
91 * @returns an object containing two properties: numOccurrences is the total number of times the
92 * markdown tag has been added to the given string, while resultJSX is the actual React node to be
95 highlightMetadata: HighlightMetadata;
98 * Start indexing metadata only
99 * @param isRefreshed is only used to be forward to the metrics route for statistical purposes.
100 * Whenever the user manually starts indexing, the latter shouldn't be specified (and defaults to false)
102 enableEncryptedSearch: EnableEncryptedSearch;
105 * Start indexing for the first time or resume it after the user paused it. It optionally accepts
106 * an object with two properties.
107 * @param notify specifies whether any pop-up banner will be displayed to the user indicating success
108 * or failure of the indexing process
109 * @param isRefreshed is only used to be forward to the metrics route for statistical purposes.
110 * Whenever the user manually starts indexing, the latter shouldn't be specified (and defaults to false).
111 * @param isResumed specifies whether to resume previously paused indexing processes. The difference is that
112 * if it's not specified only those processes that were halted and, therefore, have the INDEXING status
113 * saved will be resumed. If it's set to true, instead, also those that were paused, i.e. have the PAUSED
114 * status, are resumed as well
116 enableContentSearch: EnableContentSearch;
119 * Process events (according to the provided callbacks). It should be used in whatever event handling
120 * system the product uses to correctly sync the ES database.
121 * @param event a single event containing a change to the items stored in the ES database
123 handleEvent: (event: ESEvent<ESItemMetadata> | undefined) => Promise<void>;
126 * @param ID the item ID
127 * @returns whether a given item, specified by its ID, is part of the currently shown search results or not.
128 * It returns false if a search is not happening on going
130 isSearchResult: (ID: string) => boolean;
133 * Wipe all local data related to ES, both from IndexedDB and local storage
135 esDelete: () => Promise<void>;
138 * @returns whether some conditions to apply highlighting are met, i.e. whether a search is
139 * on and there are keywords. For example in cases where the user only specifies filters
140 * and not keywords, this function returns false
142 shouldHighlight: () => boolean;
145 * Run some initial checks on the status of ES. This must be the first function that
146 * the EncryptedSearchProvider runs, as it checks for new events, continues indexing in
147 * case a previous one was started, checks whether the index key is still accessible
149 initializeES: () => Promise<void>;
152 * Pause the currently ongoing content indexing process, if any
154 pauseContentIndexing: () => Promise<void>;
157 * Pause the currently ongoing metadata indexing process, if any
159 pauseMetadataIndexing: () => Promise<void>;
162 * Wrapper around `correctDecryptionErrors` es callback, used to correct previous decryption errors after a key recovery
164 correctDecryptionErrors: () => Promise<number>;
167 * Start the caching routine, i.e. fetching and decrypting as many items from the ES
168 * database as possible to be stored in memory for quick access
169 * @returns the reference to the current cache
171 cacheIndexedDB: () => Promise<void>;
174 * Deactivates ES. This does not remove anything, and the database keeps being synced.
175 * It is used to switch ES temporarily off in cases when server side search is available.
177 toggleEncryptedSearch: () => Promise<void>;
180 * Returns the ES cache, a map of indexed items. If the cache is not initialized, the return will be an empty map
182 getCache: () => Map<string, CachedItem<ESItemMetadata, ESItemContent>>;
185 * Reset the cache to its default empty state
187 resetCache: () => void;
190 * An object containing the different variables related to Encrypted Search status
192 esStatus: ESStatus<ESItemMetadata, ESItemContent, ESSearchParameters>;
195 * A reference object to two values related to an IndexedDB operation status.
196 * The first number in the returned list is the current number of items processed while
197 * the second is the total number of items to process. It is useful to show a progress bar.
199 progressRecorderRef: MutableRefObject<ESTimepoint>;
202 * An object containing variables describing the status of the indexing progress
204 esIndexingProgressState: ESIndexingState;