Make publicrooms use the new paginating API

Also do filtering on the server

WIP: This breaks the network dropdown
pull/2241/head
David Baker 2016-09-16 17:33:28 +01:00
parent 135c22c99d
commit a11516a984
2 changed files with 72 additions and 43 deletions

View File

@ -29,6 +29,7 @@ var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');
var q = require('q');
linkifyMatrix(linkify);
@ -50,7 +51,6 @@ module.exports = React.createClass({
getInitialState: function() {
return {
publicRooms: [],
roomAlias: '',
loading: true,
filterByNetwork: null,
}
@ -64,6 +64,8 @@ module.exports = React.createClass({
this.networkPatterns[network] = new RegExp(this.props.config.networkPatterns[network]);
}
}
this.nextBatch = null;
this.filterString = null;
// dis.dispatch({
// action: 'ui_opacity',
@ -73,7 +75,7 @@ module.exports = React.createClass({
},
componentDidMount: function() {
this.getPublicRooms();
this.refreshRoomList();
},
componentWillUnmount: function() {
@ -84,24 +86,34 @@ module.exports = React.createClass({
// });
},
getPublicRooms: function() {
var self = this;
MatrixClientPeg.get().publicRooms(function (err, data) {
if (err) {
self.setState({ loading: false });
refreshRoomList: function() {
this.nextBatch = null;
this.setState({
publicRooms: [],
});
this.getMoreRooms().done();
},
getMoreRooms: function() {
const opts = {limit: 20};
if (this.nextBatch) opts.since = this.nextBatch;
if (this.filterString) opts.filter = { generic_search_term: this.filterString } ;
return MatrixClientPeg.get().publicRooms(opts).then((data) => {
this.nextBatch = data.next_batch;
this.setState((s) => {
s.publicRooms.push(...data.chunk);
s.loading = false;
return s;
});
return Boolean(data.next_batch);
}, (err) => {
this.setState({ loading: false });
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to get public room list",
description: err.message
});
}
else {
self.setState({
publicRooms: data.chunk,
loading: false,
});
}
});
},
@ -142,10 +154,10 @@ module.exports = React.createClass({
return MatrixClientPeg.get().deleteAlias(alias);
}).done(() => {
modal.close();
this.getPublicRooms();
this.refreshRoomList();
}, function(err) {
modal.close();
this.getPublicRooms();
this.refreshRoomList();
Modal.createDialog(ErrorDialog, {
title: "Failed to "+step,
description: err.toString()
@ -170,6 +182,23 @@ module.exports = React.createClass({
});
},
onFillRequest: function(backwards) {
if (backwards || !this.nextBatch) return q(false);
return this.getMoreRooms();
},
onFilterChange: function(ev) {
const alias = ev.target.value;
if (ev.key == "Enter") {
this.showRoomAlias(alias);
} else {
this.filterString = alias || null;
this.refreshRoomList();
}
},
showRoomAlias: function(alias) {
this.showRoom(null, alias);
},
@ -214,23 +243,17 @@ module.exports = React.createClass({
dis.dispatch(payload);
},
getRows: function(filter) {
getRows: function() {
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
if (!this.state.publicRooms) return [];
var rooms = this.state.publicRooms.filter((a) => {
// FIXME: if incrementally typing, keep narrowing down the search set
// incrementally rather than starting over each time.
if (this.state.filterByNetwork) {
if (!this._isRoomInNetwork(a, this.state.filterByNetwork)) return false;
}
return (((a.name && a.name.toLowerCase().search(filter.toLowerCase()) >= 0) ||
(a.aliases && a.aliases[0].toLowerCase().search(filter.toLowerCase()) >= 0)) &&
a.num_joined_members > 0);
}).sort(function(a,b) {
return a.num_joined_members - b.num_joined_members;
return true;
});
var rows = [];
var self = this;
@ -259,7 +282,7 @@ module.exports = React.createClass({
var topic = rooms[i].topic || '';
topic = linkifyString(sanitizeHtml(topic));
rows.unshift(
rows.push(
<tr key={ rooms[i].room_id }
onClick={self.onRoomClicked.bind(self, rooms[i])}
// cancel onMouseDown otherwise shift-clicking highlights text
@ -289,14 +312,6 @@ module.exports = React.createClass({
return rows;
},
onKeyUp: function(ev) {
this.forceUpdate();
this.setState({ roomAlias : this.refs.roomAlias.value })
if (ev.key == "Enter") {
this.showRoomAlias(this.refs.roomAlias.value);
}
},
/**
* Terrible temporary function that guess what network a public room
* entry is in, until synapse is able to tell us
@ -323,21 +338,30 @@ module.exports = React.createClass({
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
const NetworkDropdown = sdk.getComponent('directory.NetworkDropdown');
const ScrollPanel = sdk.getComponent("structures.ScrollPanel");
return (
<div className="mx_RoomDirectory">
<SimpleRoomHeader title="Directory" />
<div className="mx_RoomDirectory_list">
<div className="mx_RoomDirectory_listheader">
<input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
<input type="text" placeholder="Find a room by keyword or room ID (#foo:matrix.org)"
className="mx_RoomDirectory_input" size="64" onChange={this.onFilterChange}
/>
<NetworkDropdown config={this.props.config} onNetworkChange={this.onNetworkChange} />
</div>
<GeminiScrollbar className="mx_RoomDirectory_tableWrapper">
<ScrollPanel
className="mx_RoomDirectory_tableWrapper"
onFillRequest={ this.onFillRequest }
stickyBottom={false}
startAtBottom={false}
onResize={function(){}}
>
<table ref="directory_table" className="mx_RoomDirectory_table">
<tbody>
{ this.getRows(this.state.roomAlias) }
{ this.getRows() }
</tbody>
</table>
</GeminiScrollbar>
</ScrollPanel>
</div>
</div>
);

View File

@ -46,6 +46,11 @@ limitations under the License.
-webkit-flex-direction: column;
}
.mx_RoomDirectory_list .mx_RoomView_messageListWrapper {
justify-content: flex-start;
-webkit-justify-content: flex-start;
}
.mx_RoomDirectory_listheader {
display: table;
width: 100%;