/* Copyright 2024 New Vector Ltd. Copyright 2019-2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ /* * Object holding the global EventIndex object. Can only be initialized if the * platform supports event indexing. */ import { logger } from "matrix-js-sdk/src/logger"; import PlatformPeg from "../PlatformPeg"; import EventIndex from "../indexing/EventIndex"; import { MatrixClientPeg } from "../MatrixClientPeg"; import SettingsStore from "../settings/SettingsStore"; import { SettingLevel } from "../settings/SettingLevel"; const INDEX_VERSION = 1; /** * Holds the current instance of the `EventIndex` to use across the codebase. * Looking for an `EventIndex`? Just look for the `EventIndexPeg` on the peg * board. "Peg" is the literal meaning of something you hang something on. So * you'll find a `EventIndex` hanging on the `EventIndexPeg`. */ export class EventIndexPeg { public index: EventIndex | null = null; public error: unknown; private _supportIsInstalled = false; /** * Initialize the EventIndexPeg and if event indexing is enabled initialize * the event index. * * @return {Promise} A promise that will resolve to true if an * EventIndex was successfully initialized, false otherwise. */ public async init(): Promise { const indexManager = PlatformPeg.get()?.getEventIndexingManager(); if (!indexManager) { logger.log("EventIndex: Platform doesn't support event indexing, not initializing."); return false; } this._supportIsInstalled = await indexManager.supportsEventIndexing(); if (!this.supportIsInstalled()) { logger.log("EventIndex: Event indexing isn't installed for the platform, not initializing."); return false; } if (!SettingsStore.getValueAt(SettingLevel.DEVICE, "enableEventIndexing")) { logger.log("EventIndex: Event indexing is disabled, not initializing"); return false; } return this.initEventIndex(); } /** * Initialize the event index. * * @returns {boolean} True if the event index was successfully initialized, * false otherwise. */ public async initEventIndex(): Promise { const index = new EventIndex(); const indexManager = PlatformPeg.get()?.getEventIndexingManager(); const client = MatrixClientPeg.get(); if (!indexManager || !client) { throw new Error("Unable to init event index"); } const userId = client.getUserId()!; const deviceId = client.getDeviceId()!; try { await indexManager.initEventIndex(userId, deviceId); const userVersion = await indexManager.getUserVersion(); const eventIndexIsEmpty = await indexManager.isEventIndexEmpty(); if (eventIndexIsEmpty) { await indexManager.setUserVersion(INDEX_VERSION); } else if (userVersion === 0 && !eventIndexIsEmpty) { await indexManager.closeEventIndex(); await this.deleteEventIndex(); await indexManager.initEventIndex(userId, deviceId); await indexManager.setUserVersion(INDEX_VERSION); } logger.log("EventIndex: Successfully initialized the event index"); await index.init(); } catch (e) { logger.log("EventIndex: Error initializing the event index", e); this.error = e; return false; } this.index = index; return true; } /** * Check if the current platform has support for event indexing. * * @return {boolean} True if it has support, false otherwise. Note that this * does not mean that support is installed. */ public platformHasSupport(): boolean { return PlatformPeg.get()?.getEventIndexingManager() != null; } /** * Check if event indexing support is installed for the platform. * * Event indexing might require additional optional modules to be installed, * this tells us if those are installed. Note that this should only be * called after the init() method was called. * * @return {boolean} True if support is installed, false otherwise. */ public supportIsInstalled(): boolean { return this._supportIsInstalled; } /** * Get the current event index. * * @return {EventIndex} The current event index. */ public get(): EventIndex | null { return this.index; } public start(): void { if (this.index === null) return; this.index.startCrawler(); } public stop(): void { if (this.index === null) return; this.index.stopCrawler(); } /** * Unset our event store * * After a call to this the init() method will need to be called again. * * @return {Promise} A promise that will resolve once the event index is * closed. */ public async unset(): Promise { if (this.index === null) return; await this.index.close(); this.index = null; } /** * Delete our event indexer. * * After a call to this the init() method will need to be called again. * * @return {Promise} A promise that will resolve once the event index is * deleted. */ public async deleteEventIndex(): Promise { const indexManager = PlatformPeg.get()?.getEventIndexingManager(); if (indexManager) { await this.unset(); logger.log("EventIndex: Deleting event index."); await indexManager.deleteEventIndex(); } } } if (!window.mxEventIndexPeg) { window.mxEventIndexPeg = new EventIndexPeg(); } export default window.mxEventIndexPeg;