diff --git a/src/indexing/BaseEventIndexManager.ts b/src/indexing/BaseEventIndexManager.ts index c40d1300ea..32ab3b34fe 100644 --- a/src/indexing/BaseEventIndexManager.ts +++ b/src/indexing/BaseEventIndexManager.ts @@ -134,6 +134,19 @@ export default abstract class BaseEventIndexManager { throw new Error("Unimplemented"); } + /** + * Check if the room with the given id is already indexed. + * + * @param {string} roomId The ID of the room which we want to check if it + * has been already indexed. + * + * @return {Promise} Returns true if the index contains events for + * the given room, false otherwise. + */ + isRoomIndexed(roomId: string): Promise { + throw new Error("Unimplemented"); + } + /** * Get statistical information of the index. * diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index d4e8ab0117..5bacfd2e9c 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -62,6 +62,7 @@ export default class EventIndex extends EventEmitter { client.on('Event.decrypted', this.onEventDecrypted); client.on('Room.timelineReset', this.onTimelineReset); client.on('Room.redaction', this.onRedaction); + client.on('RoomState.events', this.onRoomStateEvent); } /** @@ -76,6 +77,7 @@ export default class EventIndex extends EventEmitter { client.removeListener('Event.decrypted', this.onEventDecrypted); client.removeListener('Room.timelineReset', this.onTimelineReset); client.removeListener('Room.redaction', this.onRedaction); + client.removeListener('RoomState.events', this.onRoomStateEvent); } /** @@ -194,6 +196,15 @@ export default class EventIndex extends EventEmitter { } } + onRoomStateEvent = async (ev, state) => { + if (!MatrixClientPeg.get().isRoomEncrypted(state.roomId)) return; + + if (ev.getType() === "m.room.encryption" && !await this.isRoomIndexed(state.roomId)) { + console.log("EventIndex: Adding a checkpoint for a newly encrypted room", state.roomId); + this.addRoomCheckpoint(state.roomId, true); + } + } + /* * The Event.decrypted listener. * @@ -234,26 +245,12 @@ export default class EventIndex extends EventEmitter { */ onTimelineReset = async (room, timelineSet, resetAllTimelines) => { if (room === null) return; - - const indexManager = PlatformPeg.get().getEventIndexingManager(); if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) return; - const timeline = room.getLiveTimeline(); - const token = timeline.getPaginationToken("b"); + console.log("EventIndex: Adding a checkpoint because of a limited timeline", + room.roomId); - const backwardsCheckpoint = { - roomId: room.roomId, - token: token, - fullCrawl: false, - direction: "b", - }; - - console.log("EventIndex: Added checkpoint because of a limited timeline", - backwardsCheckpoint); - - await indexManager.addCrawlerCheckpoint(backwardsCheckpoint); - - this.crawlerCheckpoints.push(backwardsCheckpoint); + this.addRoomCheckpoint(room.roomId, false); } /** @@ -334,7 +331,7 @@ export default class EventIndex extends EventEmitter { avatar_url: ev.sender.getMxcAvatarUrl(), }; - indexManager.addEventToIndex(e, profile); + await indexManager.addEventToIndex(e, profile); } /** @@ -345,6 +342,51 @@ export default class EventIndex extends EventEmitter { this.emit("changedCheckpoint", this.currentRoom()); } + async addEventsFromLiveTimeline(timeline) { + const events = timeline.getEvents(); + + for (let i = 0; i < events.length; i++) { + const ev = events[i]; + await this.addLiveEventToIndex(ev); + } + } + + async addRoomCheckpoint(roomId, fullCrawl = false) { + const indexManager = PlatformPeg.get().getEventIndexingManager(); + const client = MatrixClientPeg.get(); + const room = client.getRoom(roomId); + + if (!room) return; + + const timeline = room.getLiveTimeline(); + const token = timeline.getPaginationToken("b"); + + if (!token) { + // The room doesn't contain any tokens, meaning the live timeline + // contains all the events, add those to the index. + await this.addEventsFromLiveTimeline(timeline); + return; + } + + const checkpoint = { + roomId: room.roomId, + token: token, + fullCrawl: fullCrawl, + direction: "b", + }; + + console.log("EventIndex: Adding checkpoint", checkpoint); + + try { + await indexManager.addCrawlerCheckpoint(checkpoint); + } catch (e) { + console.log("EventIndex: Error adding new checkpoint for room", + room.roomId, checkpoint, e); + } + + this.crawlerCheckpoints.push(checkpoint); + } + /** * The main crawler loop. * @@ -833,6 +875,20 @@ export default class EventIndex extends EventEmitter { return indexManager.getStats(); } + /** + * Check if the room with the given id is already indexed. + * + * @param {string} roomId The ID of the room which we want to check if it + * has been already indexed. + * + * @return {Promise} Returns true if the index contains events for + * the given room, false otherwise. + */ + async isRoomIndexed(roomId) { + const indexManager = PlatformPeg.get().getEventIndexingManager(); + return indexManager.isRoomIndexed(roomId); + } + /** * Get the room that we are currently crawling. *