fix search ordering; add room labels; hide input areas if searching

This commit is contained in:
Matthew Hodgson 2015-11-29 04:41:17 +00:00
parent fc02331cd3
commit 01f0e61d6e
2 changed files with 63 additions and 32 deletions

View file

@ -288,6 +288,7 @@ module.exports = {
fillSpace: function() { fillSpace: function() {
if (!this.refs.messagePanel) return; if (!this.refs.messagePanel) return;
if (this.state.searchResults) return; // TODO: paginate search results
var messageWrapperScroll = this._getScrollNode(); var messageWrapperScroll = this._getScrollNode();
if (messageWrapperScroll.scrollTop < messageWrapperScroll.clientHeight && this.state.room.oldState.paginationToken) { if (messageWrapperScroll.scrollTop < messageWrapperScroll.clientHeight && this.state.room.oldState.paginationToken) {
this.setState({paginating: true}); this.setState({paginating: true});
@ -426,7 +427,7 @@ module.exports = {
onSearch: function(term, scope) { onSearch: function(term, scope) {
var filter; var filter;
if (scope === "Room") { // FIXME: should be enum if (scope === "Room") {
filter = { filter = {
// XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :( // XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :(
rooms: [ rooms: [
@ -443,6 +444,14 @@ module.exports = {
search_term: term, search_term: term,
filter: filter, filter: filter,
order_by: "recent", order_by: "recent",
include_state: true,
groupings: {
group_by: [
{
key: "room_id"
}
]
},
event_context: { event_context: {
before_limit: 1, before_limit: 1,
after_limit: 1, after_limit: 1,
@ -465,13 +474,14 @@ module.exports = {
.sort(function(a, b) { b.length - a.length }); .sort(function(a, b) { b.length - a.length });
} }
else { else {
// sqlite doesn't, so just highlight the literal search term // sqlite doesn't, so just try to highlight the literal search term
highlights = [ term ]; highlights = [ term ];
} }
self.setState({ self.setState({
highlights: highlights, highlights: highlights,
searchResults: data, searchResults: data,
searchScope: scope,
}); });
}, function(error) { }, function(error) {
var ErrorDialog = sdk.getComponent("organisms.ErrorDialog"); var ErrorDialog = sdk.getComponent("organisms.ErrorDialog");
@ -484,39 +494,51 @@ module.exports = {
getEventTiles: function() { getEventTiles: function() {
var DateSeparator = sdk.getComponent('molecules.DateSeparator'); var DateSeparator = sdk.getComponent('molecules.DateSeparator');
var cli = MatrixClientPeg.get();
var ret = []; var ret = [];
var count = 0; var count = 0;
var EventTile = sdk.getComponent('messages.Event'); var EventTile = sdk.getComponent('messages.Event');
var self = this;
if (this.state.searchResults) { if (this.state.searchResults) {
// XXX: this dance is foul, due to the results API not returning sorted results // XXX: this dance is foul, due to the results API not directly returning sorted results
var results = this.state.searchResults.search_categories.room_events.results; var results = this.state.searchResults.search_categories.room_events.results;
var eventIds = Object.keys(results); var roomIdGroups = this.state.searchResults.search_categories.room_events.groups.room_id;
// XXX: todo: merge overlapping results somehow?
// XXX: why doesn't searching on name work? Object.keys(roomIdGroups)
var resultList = eventIds.map(function(key) { return results[key]; }); // .sort(function(a, b) { b.rank - a.rank }); .sort(function(a, b) { roomIdGroups[a].order - roomIdGroups[b].order }) // WHY NOT RETURN AN ORDERED ARRAY?!?!?!
for (var i = 0; i < resultList.length; i++) { .forEach(function(roomId)
var ts1 = resultList[i].result.origin_server_ts; {
ret.push(<li key={ts1 + "-search"}><DateSeparator ts={ts1}/></li>); // Rank: {resultList[i].rank} // XXX: todo: merge overlapping results somehow?
var mxEv = new Matrix.MatrixEvent(resultList[i].result); // XXX: why doesn't searching on name work?
if (resultList[i].context.events_before[0]) { if (self.state.searchScope === 'All') {
var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_before[0]); ret.push(<li key={ roomId }><h1>Room: { cli.getRoom(roomId).name }</h1></li>);
if (EventTile.haveTileForEvent(mxEv2)) { }
ret.push(<li key={mxEv.getId() + "-1"}><EventTile mxEvent={mxEv2} contextual={true} /></li>);
var resultList = roomIdGroups[roomId].results.map(function(eventId) { return results[eventId]; });
for (var i = resultList.length - 1; i >= 0; i--) {
var ts1 = resultList[i].result.origin_server_ts;
ret.push(<li key={ts1 + "-search"}><DateSeparator ts={ts1}/></li>); // Rank: {resultList[i].rank}
var mxEv = new Matrix.MatrixEvent(resultList[i].result);
if (resultList[i].context.events_before[0]) {
var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_before[0]);
if (EventTile.haveTileForEvent(mxEv2)) {
ret.push(<li key={mxEv.getId() + "-1"}><EventTile mxEvent={mxEv2} contextual={true} /></li>);
}
}
if (EventTile.haveTileForEvent(mxEv)) {
ret.push(<li key={mxEv.getId() + "+0"}><EventTile mxEvent={mxEv} highlights={self.state.highlights}/></li>);
}
if (resultList[i].context.events_after[0]) {
var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]);
if (EventTile.haveTileForEvent(mxEv2)) {
ret.push(<li key={mxEv.getId() + "+1"}><EventTile mxEvent={mxEv2} contextual={true} /></li>);
}
} }
} }
if (EventTile.haveTileForEvent(mxEv)) { });
ret.push(<li key={mxEv.getId() + "+0"}><EventTile mxEvent={mxEv} highlights={this.state.highlights}/></li>);
}
if (resultList[i].context.events_after[0]) {
var mxEv2 = new Matrix.MatrixEvent(resultList[i].context.events_after[0]);
if (EventTile.haveTileForEvent(mxEv2)) {
ret.push(<li key={mxEv.getId() + "+1"}><EventTile mxEvent={mxEv2} contextual={true} /></li>);
}
}
}
return ret; return ret;
} }

View file

@ -291,6 +291,20 @@ module.exports = React.createClass({
</div>; </div>;
} }
var statusArea, messageComposer;
if (!this.state.searchResults) {
statusArea =
<div className="mx_RoomView_statusArea">
<div className="mx_RoomView_statusAreaBox">
<div className="mx_RoomView_statusAreaBox_line"></div>
{statusBar}
</div>
</div>
messageComposer =
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} />
}
return ( return (
<div className="mx_RoomView"> <div className="mx_RoomView">
<RoomHeader ref="header" room={this.state.room} editing={this.state.editingRoomSettings} onSearchClick={this.onSearchClick} <RoomHeader ref="header" room={this.state.room} editing={this.state.editingRoomSettings} onSearchClick={this.onSearchClick}
@ -310,13 +324,8 @@ module.exports = React.createClass({
</ol> </ol>
</div> </div>
</GeminiScrollbar> </GeminiScrollbar>
<div className="mx_RoomView_statusArea"> { statusArea }
<div className="mx_RoomView_statusAreaBox"> { messageComposer }
<div className="mx_RoomView_statusAreaBox_line"></div>
{statusBar}
</div>
</div>
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} />
</div> </div>
); );
} }