diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index 90afff5c27..8a2b52b949 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -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}
/>
-
+
{content}
diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js
index e1de4ffea1..e98922f2c2 100644
--- a/src/components/views/directory/NetworkDropdown.js
+++ b/src/components/views/directory/NetworkDropdown.js
@@ -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 = ;
+ span_class = 'mx_NetworkDropdown_menu_network';
} else {
name = this.props.config.networkNames[network];
icon = ;
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
+ let key = server;
+ if (network !== null) {
+ key += '_' + network;
+ }
+
+ return
{icon}
{name}
;
}
+ 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 =
{menu_options}
;
+ current_value =
}
return
@@ -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,
};
diff --git a/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css b/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css
index cc15280261..b500ffa212 100644
--- a/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css
+++ b/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css
@@ -52,6 +52,10 @@ limitations under the License.
vertical-align: middle;
}
+input.mx_NetworkDropdown_networkoption, input.mx_NetworkDropdown_networkoption:focus {
+ border: 0;
+}
+
.mx_NetworkDropdown_menu {
position: absolute;
left: -1px;
diff --git a/src/skins/vector/img/network-matrix.svg b/src/skins/vector/img/network-matrix.svg
new file mode 100644
index 0000000000..bb8278ae39
--- /dev/null
+++ b/src/skins/vector/img/network-matrix.svg
@@ -0,0 +1,14 @@
+
+
+