RoomView: Use platform specific search if our platform supports it.

This patch extends our search to include our platform specific event
index.

There are 3 search scenarios and are handled differently when platform
support for indexing is present:

    - Search a single non-encrypted room: Use the server-side search
        like before.
    - Search a single encrypted room: Search using our platform specific
        event index.
    - Search across all rooms: Search encrypted rooms using our local
        event index. Search non-encrypted rooms using the classic
        server-side search. Combine the results.

The combined search will result in having twice the amount of search
results since comparing the scores fairly wasn't deemed sensible.
This commit is contained in:
Damir Jelić 2019-10-11 16:40:10 +02:00
parent 4acec19d40
commit 3f53691834

View file

@ -34,6 +34,7 @@ import { _t } from '../../languageHandler';
import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks'; import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
import MatrixClientPeg from '../../MatrixClientPeg'; import MatrixClientPeg from '../../MatrixClientPeg';
import PlatformPeg from "../../PlatformPeg";
import ContentMessages from '../../ContentMessages'; import ContentMessages from '../../ContentMessages';
import Modal from '../../Modal'; import Modal from '../../Modal';
import sdk from '../../index'; import sdk from '../../index';
@ -1140,12 +1141,116 @@ module.exports = createReactClass({
} }
debuglog("sending search request"); debuglog("sending search request");
const platform = PlatformPeg.get();
if (platform.supportsEventIndexing()) {
const combinedSearchFunc = async (searchTerm) => {
// Create two promises, one for the local search, one for the
// server-side search.
const client = MatrixClientPeg.get();
const serverSidePromise = client.searchRoomEvents({
term: searchTerm,
});
const localPromise = localSearchFunc(searchTerm);
// Wait for both promises to resolve.
await Promise.all([serverSidePromise, localPromise]);
// Get both search results.
const localResult = await localPromise;
const serverSideResult = await serverSidePromise;
// Combine the search results into one result.
const result = {};
// Our localResult and serverSideResult are both ordered by
// recency separetly, when we combine them the order might not
// be the right one so we need to sort them.
const compare = (a, b) => {
const aEvent = a.context.getEvent().event;
const bEvent = b.context.getEvent().event;
if (aEvent.origin_server_ts >
bEvent.origin_server_ts) return -1;
if (aEvent.origin_server_ts <
bEvent.origin_server_ts) return 1;
return 0;
};
result.count = localResult.count + serverSideResult.count;
result.results = localResult.results.concat(
serverSideResult.results).sort(compare);
result.highlights = localResult.highlights.concat(
serverSideResult.highlights);
return result;
};
const localSearchFunc = async (searchTerm, roomId = undefined) => {
const searchArgs = {
search_term: searchTerm,
before_limit: 1,
after_limit: 1,
order_by_recency: true,
};
if (roomId !== undefined) {
searchArgs.room_id = roomId;
}
const localResult = await platform.searchEventIndex(
searchArgs);
const response = {
search_categories: {
room_events: localResult,
},
};
const emptyResult = {
results: [],
highlights: [],
};
// TODO is there a better way to convert our result into what
// is expected by the handler method.
const result = MatrixClientPeg.get()._processRoomEventsSearch(
emptyResult, response);
return result;
};
let searchPromise;
if (scope === "Room") {
const roomId = this.state.room.roomId;
if (MatrixClientPeg.get().isRoomEncrypted(roomId)) {
// The search is for a single encrypted room, use our local
// search method.
searchPromise = localSearchFunc(term, roomId);
} else {
// The search is for a single non-encrypted room, use the
// server-side search.
searchPromise = MatrixClientPeg.get().searchRoomEvents({
filter: filter,
term: term,
});
}
} else {
// Search across all rooms, combine a server side search and a
// local search.
searchPromise = combinedSearchFunc(term);
}
this._handleSearchResult(searchPromise).done();
} else {
const searchPromise = MatrixClientPeg.get().searchRoomEvents({ const searchPromise = MatrixClientPeg.get().searchRoomEvents({
filter: filter, filter: filter,
term: term, term: term,
}); });
this._handleSearchResult(searchPromise).done(); this._handleSearchResult(searchPromise).done();
}
}, },
_handleSearchResult: function(searchPromise) { _handleSearchResult: function(searchPromise) {