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.
pull/21833/head
Damir Jelić 2019-10-11 16:40:10 +02:00
parent 4acec19d40
commit 3f53691834
1 changed files with 110 additions and 5 deletions

View File

@ -34,6 +34,7 @@ import { _t } from '../../languageHandler';
import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
import MatrixClientPeg from '../../MatrixClientPeg';
import PlatformPeg from "../../PlatformPeg";
import ContentMessages from '../../ContentMessages';
import Modal from '../../Modal';
import sdk from '../../index';
@ -1140,12 +1141,116 @@ module.exports = createReactClass({
}
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({
filter: filter,
term: term,
});
this._handleSearchResult(searchPromise).done();
}
},
_handleSearchResult: function(searchPromise) {