Room dir: New filtering & 3rd party networks
Changes filtering on 3rd party networks to divide into portal / non portal rooms and not show portal rooms by default. Adds a special '_matrix' network for all rooms that aren't portal rooms. Also adds ability to query 3rd party directory servers.
This commit is contained in:
parent
7b258bc229
commit
85ea45a64a
4 changed files with 129 additions and 36 deletions
|
@ -53,6 +53,7 @@ module.exports = React.createClass({
|
|||
publicRooms: [],
|
||||
loading: true,
|
||||
filterByNetwork: null,
|
||||
roomServer: null,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -76,10 +77,6 @@ module.exports = React.createClass({
|
|||
// });
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.refreshRoomList();
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// dis.dispatch({
|
||||
// action: 'ui_opacity',
|
||||
|
@ -102,6 +99,9 @@ module.exports = React.createClass({
|
|||
|
||||
const my_filter_string = this.filterString;
|
||||
const opts = {limit: 20};
|
||||
if (this.state.roomServer != MatrixClientPeg.getHomeServerName()) {
|
||||
opts.server = this.state.roomServer;
|
||||
}
|
||||
if (this.nextBatch) opts.since = this.nextBatch;
|
||||
if (this.filterString) opts.filter = { generic_search_term: my_filter_string } ;
|
||||
return MatrixClientPeg.get().publicRooms(opts).then((data) => {
|
||||
|
@ -194,18 +194,11 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
onNetworkChange: function(network) {
|
||||
onOptionChange: function(server, network) {
|
||||
this.setState({
|
||||
roomServer: server,
|
||||
filterByNetwork: network,
|
||||
}, () => {
|
||||
// we just filtered out a bunch of rooms, so check to see if
|
||||
// we need to fill up the scrollpanel again
|
||||
// NB. Because we filter the results, the HS can keep giving
|
||||
// us more rooms and we'll keep requesting more if none match
|
||||
// the filter, which is pretty terrible. We need a way
|
||||
// to filter by network on the server.
|
||||
if (this.scrollPanel) this.scrollPanel.checkFillState();
|
||||
});
|
||||
}, this.refreshRoomList);
|
||||
},
|
||||
|
||||
onFillRequest: function(backwards) {
|
||||
|
@ -295,7 +288,7 @@ module.exports = React.createClass({
|
|||
|
||||
var rooms = this.state.publicRooms.filter((a) => {
|
||||
if (this.state.filterByNetwork) {
|
||||
if (!this._isRoomInNetwork(a, this.state.filterByNetwork)) return false;
|
||||
if (!this._isRoomInNetwork(a, this.state.roomServer, this.state.filterByNetwork)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -365,14 +358,30 @@ module.exports = React.createClass({
|
|||
* Terrible temporary function that guess what network a public room
|
||||
* entry is in, until synapse is able to tell us
|
||||
*/
|
||||
_isRoomInNetwork(room, network) {
|
||||
if (room.aliases && this.networkPatterns[network]) {
|
||||
for (const alias of room.aliases) {
|
||||
if (this.networkPatterns[network].test(alias)) return true;
|
||||
_isRoomInNetwork(room, server, network) {
|
||||
// We carve rooms into two categories here. 'portal' rooms are
|
||||
// rooms created by a user joining a bridge 'portal' alias to
|
||||
// participate in that room or a foreign network. A room is a
|
||||
// portal room if it has exactly one alias and that alias matches
|
||||
// a pattern defined in the config. It's network is the key
|
||||
// of the pattern that it matches.
|
||||
// All other rooms are considered 'native matrix' rooms, and
|
||||
// go into the special '_matrix' network.
|
||||
|
||||
let roomNetwork = '_matrix';
|
||||
if (room.aliases && room.aliases.length == 1) {
|
||||
if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
|
||||
for (const n of this.props.config.serverConfig[server].networks) {
|
||||
const pat = this.networkPatterns[n];
|
||||
if (pat && pat) {
|
||||
if (this.networkPatterns[n].test(room.aliases[0])) {
|
||||
roomNetwork = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return roomNetwork == network;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
@ -411,7 +420,7 @@ module.exports = React.createClass({
|
|||
className="mx_RoomDirectory_searchbox"
|
||||
onChange={this.onFilterChange} onClear={this.onFilterClear} onJoinClick={this.onJoinClick}
|
||||
/>
|
||||
<NetworkDropdown config={this.props.config} onNetworkChange={this.onNetworkChange} />
|
||||
<NetworkDropdown config={this.props.config} onOptionChange={this.onOptionChange} />
|
||||
</div>
|
||||
{content}
|
||||
</div>
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
|
||||
export default class NetworkDropdown extends React.Component {
|
||||
constructor() {
|
||||
|
@ -26,12 +27,17 @@ export default class NetworkDropdown extends React.Component {
|
|||
this.onInputClick = this.onInputClick.bind(this);
|
||||
this.onRootClick = this.onRootClick.bind(this);
|
||||
this.onDocumentClick = this.onDocumentClick.bind(this);
|
||||
this.onNetworkClick = this.onNetworkClick.bind(this);
|
||||
this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
|
||||
this.onInputKeyUp = this.onInputKeyUp.bind(this);
|
||||
this.collectRoot = this.collectRoot.bind(this);
|
||||
this.collectInputTextBox = this.collectInputTextBox.bind(this);
|
||||
|
||||
this.inputTextBox = null;
|
||||
|
||||
this.state = {
|
||||
expanded: false,
|
||||
selectedNetwork: null,
|
||||
selectedServer: MatrixClientPeg.getHomeServerName(),
|
||||
selectedNetwork: '_matrix',
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,6 +45,9 @@ export default class NetworkDropdown extends React.Component {
|
|||
// Listen for all clicks on the document so we can close the
|
||||
// menu when the user clicks somewhere else
|
||||
document.addEventListener('click', this.onDocumentClick, false);
|
||||
|
||||
// fire this now so the defaults can be set up
|
||||
this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -72,12 +81,24 @@ export default class NetworkDropdown extends React.Component {
|
|||
ev.preventDefault();
|
||||
}
|
||||
|
||||
onNetworkClick(network, ev) {
|
||||
onMenuOptionClick(server, network, ev) {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: server,
|
||||
selectedNetwork: network,
|
||||
});
|
||||
this.props.onNetworkChange(network);
|
||||
this.props.onOptionChange(server, network);
|
||||
}
|
||||
|
||||
onInputKeyUp(e) {
|
||||
if (e.key == 'Enter') {
|
||||
this.setState({
|
||||
expanded: false,
|
||||
selectedServer: e.target.value,
|
||||
selectedNetwork: null,
|
||||
});
|
||||
this.props.onOptionChange(e.target.value, null);
|
||||
}
|
||||
}
|
||||
|
||||
collectRoot(e) {
|
||||
|
@ -90,41 +111,86 @@ export default class NetworkDropdown extends React.Component {
|
|||
this.dropdownRootElement = e;
|
||||
}
|
||||
|
||||
_optionForNetwork(network, wire_onclick) {
|
||||
collectInputTextBox(e) {
|
||||
this.inputTextBox = e;
|
||||
}
|
||||
|
||||
_getMenuOptions() {
|
||||
const options = [];
|
||||
|
||||
let servers = [];
|
||||
if (this.props.config.servers) {
|
||||
servers = servers.concat(this.props.config.servers);
|
||||
}
|
||||
|
||||
if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
|
||||
servers.unshift(MatrixClientPeg.getHomeServerName());
|
||||
}
|
||||
|
||||
for (const server of servers) {
|
||||
options.push(this._makeMenuOption(server, null));
|
||||
if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
|
||||
for (const network of this.props.config.serverConfig[server].networks) {
|
||||
options.push(this._makeMenuOption(server, network));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
_makeMenuOption(server, network, wire_onclick) {
|
||||
if (wire_onclick === undefined) wire_onclick = true;
|
||||
let icon;
|
||||
let name;
|
||||
let span_class;
|
||||
|
||||
if (network === null) {
|
||||
name = 'All networks';
|
||||
name = server;
|
||||
span_class = 'mx_NetworkDropdown_menu_all';
|
||||
} else if (network == '_matrix') {
|
||||
name = 'Matrix';
|
||||
icon = <img src="/img/network-matrix.svg" width="16" height="16" />;
|
||||
span_class = 'mx_NetworkDropdown_menu_network';
|
||||
} else {
|
||||
name = this.props.config.networkNames[network];
|
||||
icon = <img src={this.props.config.networkIcons[network]} />;
|
||||
span_class = 'mx_NetworkDropdown_menu_network';
|
||||
}
|
||||
|
||||
const click_handler = wire_onclick ? this.onNetworkClick.bind(this, network) : null;
|
||||
const click_handler = wire_onclick ? this.onMenuOptionClick.bind(this, server, network) : null;
|
||||
|
||||
return <div key={network} className="mx_NetworkDropdown_networkoption" onClick={click_handler}>
|
||||
let key = server;
|
||||
if (network !== null) {
|
||||
key += '_' + network;
|
||||
}
|
||||
|
||||
return <div key={key} className="mx_NetworkDropdown_networkoption" onClick={click_handler}>
|
||||
{icon}
|
||||
<span className={span_class}>{name}</span>
|
||||
</div>;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.state.expanded && this.inputTextBox) {
|
||||
this.inputTextBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const current_value = this._optionForNetwork(this.state.selectedNetwork, false);
|
||||
let current_value = this._makeMenuOption(
|
||||
this.state.selectedServer, this.state.selectedNetwork, false
|
||||
);
|
||||
|
||||
let menu;
|
||||
if (this.state.expanded) {
|
||||
const menu_options = [this._optionForNetwork(null)];
|
||||
for (const network of this.props.config.networks) {
|
||||
menu_options.push(this._optionForNetwork(network));
|
||||
}
|
||||
const menu_options = this._getMenuOptions();
|
||||
menu = <div className="mx_NetworkDropdown_menu">
|
||||
{menu_options}
|
||||
</div>;
|
||||
current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
|
||||
ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
|
||||
/>
|
||||
}
|
||||
|
||||
return <div className="mx_NetworkDropdown" ref={this.collectRoot}>
|
||||
|
@ -138,7 +204,7 @@ export default class NetworkDropdown extends React.Component {
|
|||
}
|
||||
|
||||
NetworkDropdown.propTypes = {
|
||||
onNetworkChange: React.PropTypes.func.isRequired,
|
||||
onOptionChange: React.PropTypes.func.isRequired,
|
||||
config: React.PropTypes.object,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue