RoomView: Move the search logic into a separate module.

This commit is contained in:
Damir Jelić 2019-11-12 15:39:26 +01:00
parent cfdcf45ac6
commit e296fd05c0
3 changed files with 147 additions and 120 deletions

View file

@ -401,4 +401,9 @@ export default class EventIndexer {
this._crawlerRef.cancel(); this._crawlerRef.cancel();
this._crawlerRef = null; this._crawlerRef = null;
} }
async search(searchArgs) {
const platform = PlatformPeg.get();
return platform.searchEventIndex(searchArgs)
}
} }

137
src/Searching.js Normal file
View file

@ -0,0 +1,137 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import EventIndexPeg from "./EventIndexPeg";
import MatrixClientPeg from "./MatrixClientPeg";
function serverSideSearch(term, roomId = undefined) {
let filter;
if (roomId !== undefined) {
filter = {
// XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :(
rooms: [roomId],
};
}
let searchPromise = MatrixClientPeg.get().searchRoomEvents({
filter: filter,
term: term,
});
return searchPromise;
}
function eventIndexSearch(term, roomId = undefined) {
const combinedSearchFunc = async (searchTerm) => {
// Create two promises, one for the local search, one for the
// server-side search.
const client = MatrixClientPeg.get();
const serverSidePromise = serverSideSearch(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 eventIndex = EventIndexPeg.get();
const localResult = await eventIndex.search(searchArgs);
const response = {
search_categories: {
room_events: localResult,
},
};
const emptyResult = {
results: [],
highlights: [],
};
const result = MatrixClientPeg.get()._processRoomEventsSearch(
emptyResult, response);
return result;
};
let searchPromise;
if (roomId !== undefined) {
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 = serverSideSearch(term, roomId);
}
} else {
// Search across all rooms, combine a server side search and a
// local search.
searchPromise = combinedSearchFunc(term);
}
return searchPromise
}
export default function eventSearch(term, roomId = undefined) {
const eventIndex = EventIndexPeg.get();
if (eventIndex === null) return serverSideSearch(term, roomId);
else return eventIndexSearch(term, roomId);
}

View file

@ -34,7 +34,6 @@ 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';
@ -44,6 +43,7 @@ import Tinter from '../../Tinter';
import rate_limited_func from '../../ratelimitedfunc'; import rate_limited_func from '../../ratelimitedfunc';
import ObjectUtils from '../../ObjectUtils'; import ObjectUtils from '../../ObjectUtils';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import eventSearch from '../../Searching';
import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard'; import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
@ -1130,127 +1130,12 @@ module.exports = createReactClass({
// todo: should cancel any previous search requests. // todo: should cancel any previous search requests.
this.searchId = new Date().getTime(); this.searchId = new Date().getTime();
let filter; let roomId;
if (scope === "Room") { if (scope === "Room") roomId = this.state.room.roomId,
filter = {
// XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :(
rooms: [
this.state.room.roomId,
],
};
}
debuglog("sending search request"); debuglog("sending search request");
const platform = PlatformPeg.get(); const searchPromise = eventSearch(term, roomId);
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(); this._handleSearchResult(searchPromise).done();
} else {
const searchPromise = MatrixClientPeg.get().searchRoomEvents({
filter: filter,
term: term,
});
this._handleSearchResult(searchPromise).done();
}
}, },
_handleSearchResult: function(searchPromise) { _handleSearchResult: function(searchPromise) {