From f5bd8abfdac612b4fddad343b92c31db86302b33 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 14 Dec 2016 15:41:15 +0000 Subject: [PATCH 1/5] Support room dir 3rd party network filtering As per https://github.com/matrix-org/synapse/pull/1676 The existing local config system still exists and is used for remote home server directories (since /thirdparty/protocols doesn't support listing remote home servers, and also because people are using it). --- README.md | 3 +- src/components/structures/RoomDirectory.js | 10 ++- .../views/directory/NetworkDropdown.js | 87 ++++++++++++++++++- 3 files changed, 93 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9a410529e1..066802c072 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,8 @@ You can configure the app by copying `config.sample.json` to down list. Optional. 1. `roomDirectory.serverConfig`: Config for each server in `roomDirectory.servers`. Optional. 1. `roomDirectory.serverConfig..networks`: List of networks (named - in `roomDirectory.networks`) to include for this server. Optional. + in `roomDirectory.networks`) to include for this server. Optional. If set, this will + override any networks sent by the Home Server (eg. if ASes are configured). 1. `roomDirectory.networks`: config for each network type. Optional. 1. `roomDirectory..name`: Human-readable name for the network. Required. 1. `roomDirectory..protocol`: Protocol as given by the server in diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index e369a26ec2..2483247cef 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -131,6 +131,11 @@ module.exports = React.createClass({ if (my_server != MatrixClientPeg.getHomeServerName()) { opts.server = my_server; } + if (this.state.instance_id) { + opts.third_party_instance_id = this.state.instance_id; + } else if (this.state.network !== '_matrix') { + opts.include_all_networks = true; + } if (this.nextBatch) opts.since = this.nextBatch; if (my_filter_string) opts.filter = { generic_search_term: my_filter_string } ; return MatrixClientPeg.get().publicRooms(opts).then((data) => { @@ -231,7 +236,7 @@ module.exports = React.createClass({ } }, - onOptionChange: function(server, network) { + onOptionChange: function(server, network, instance_id) { // clear next batch so we don't try to load more rooms this.nextBatch = null; this.setState({ @@ -241,6 +246,7 @@ module.exports = React.createClass({ publicRooms: [], roomServer: server, network: network, + instance_id: instance_id, }, this.refreshRoomList); // We also refresh the room list each time even though this // filtering is client-side. It hopefully won't be client side @@ -615,7 +621,7 @@ module.exports = React.createClass({ onChange={this.onFilterChange} onClear={this.onFilterClear} onJoinClick={this.onJoinClick} placeholder={placeholder} showJoinButton={showJoinButton} /> - + {content} diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index eb60c4a5a5..ad49264ff6 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -17,6 +17,8 @@ limitations under the License. import React from 'react'; import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; +const DEFAULT_ICON_URL = "img/network-matrix.svg"; + export default class NetworkDropdown extends React.Component { constructor(props) { super(props); @@ -28,6 +30,7 @@ export default class NetworkDropdown extends React.Component { this.onRootClick = this.onRootClick.bind(this); this.onDocumentClick = this.onDocumentClick.bind(this); this.onMenuOptionClick = this.onMenuOptionClick.bind(this); + this.onMenuOptionClickProtocolInstance = this.onMenuOptionClickProtocolInstance.bind(this); this.onInputKeyUp = this.onInputKeyUp.bind(this); this.collectRoot = this.collectRoot.bind(this); this.collectInputTextBox = this.collectInputTextBox.bind(this); @@ -103,10 +106,21 @@ export default class NetworkDropdown extends React.Component { expanded: false, selectedServer: server, selectedNetwork: network, + selectedInstanceId: null, }); this.props.onOptionChange(server, network); } + onMenuOptionClickProtocolInstance(server, instance_id, ev) { + this.setState({ + expanded: false, + selectedServer: server, + selectedNetwork: null, + selectedInstanceId: instance_id, + }); + this.props.onOptionChange(server, null, instance_id); + } + onInputKeyUp(e) { if (e.key == 'Enter') { this.setState({ @@ -144,18 +158,55 @@ export default class NetworkDropdown extends React.Component { servers.unshift(MatrixClientPeg.getHomeServerName()); } + // if the thirdparty/protocols entries have instance_ids, + // we can get the local server listings from here. If not, + // the server is too old. + let use_protocols = true; + for (const proto of Object.keys(this.props.protocols)) { + if (!this.props.protocols[proto].instances) continue; + for (const instance of this.props.protocols[proto].instances) { + if (!instance.instance_id) use_protocols = false; + } + } + + // For our own HS, we can use the instance_ids given in the third party protocols + // response to get the server to filter the room list by network for us (if the + // server is new enough), although for now we prefer the config if it exists. + // For remote HSes, we use the data from the config. 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)); } + } else if (server == MatrixClientPeg.getHomeServerName() && use_protocols) { + options.push(this._makeMenuOption(server, '_matrix')); + for (const proto of Object.keys(this.props.protocols)) { + if (!this.props.protocols[proto].instances) continue; + for (const instance of this.props.protocols[proto].instances) { + options.push(this._makeMenuOptionFromProtocolInstance(server, this.props.protocols[proto], instance)); + } + } } } return options; } + _makeMenuOptionFromProtocolInstance(server, protocol, instance, wire_onclick) { + if (wire_onclick === undefined) wire_onclick = true; + + const name = instance.desc; + const icon = ; + const key = instance.instance_id; + const click_handler = wire_onclick ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null; + + return
+ {icon} + {name} +
; + } + _makeMenuOption(server, network, wire_onclick) { if (wire_onclick === undefined) wire_onclick = true; let icon; @@ -202,6 +253,24 @@ export default class NetworkDropdown extends React.Component { ; } + protocolNameForInstanceId(instance_id) { + for (const proto of Object.keys(this.props.protocols)) { + if (!this.props.protocols[proto].instances) continue; + for (const instance of this.props.protocols[proto].instances) { + if (instance.instance_id == instance_id) return proto; + } + } + } + + instanceForInstanceId(instance_id) { + for (const proto of Object.keys(this.props.protocols)) { + if (!this.props.protocols[proto].instances) continue; + for (const instance of this.props.protocols[proto].instances) { + if (instance.instance_id == instance_id) return instance; + } + } + } + render() { let current_value; @@ -216,9 +285,17 @@ export default class NetworkDropdown extends React.Component { placeholder="matrix.org" // 'matrix.org' as an example of an HS name /> } else { - current_value = this._makeMenuOption( - this.state.selectedServer, this.state.selectedNetwork, false - ); + if (this.state.selectedInstanceId) { + const protocolName = this.protocolNameForInstanceId(this.state.selectedInstanceId); + const instance = this.instanceForInstanceId(this.state.selectedInstanceId); + current_value = this._makeMenuOptionFromProtocolInstance( + this.state.selectedServer, this.props.protocols[protocolName], instance + ); + } else { + current_value = this._makeMenuOption( + this.state.selectedServer, this.state.selectedNetwork, false + ); + } } return
@@ -234,11 +311,13 @@ export default class NetworkDropdown extends React.Component { NetworkDropdown.propTypes = { onOptionChange: React.PropTypes.func.isRequired, config: React.PropTypes.object, + protocols: React.PropTypes.object, }; NetworkDropdown.defaultProps = { config: { networks: [], - } + }, + protocols: {}, }; From fc597ba86ead5560f2d4241c3e2359d19ec83127 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 15 Dec 2016 10:41:22 +0000 Subject: [PATCH 2/5] Underscore for private method --- src/components/views/directory/NetworkDropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index ad49264ff6..2c0b73baba 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -253,7 +253,7 @@ export default class NetworkDropdown extends React.Component {
; } - protocolNameForInstanceId(instance_id) { + _protocolNameForInstanceId(instance_id) { for (const proto of Object.keys(this.props.protocols)) { if (!this.props.protocols[proto].instances) continue; for (const instance of this.props.protocols[proto].instances) { @@ -286,7 +286,7 @@ export default class NetworkDropdown extends React.Component { /> } else { if (this.state.selectedInstanceId) { - const protocolName = this.protocolNameForInstanceId(this.state.selectedInstanceId); + const protocolName = this._protocolNameForInstanceId(this.state.selectedInstanceId); const instance = this.instanceForInstanceId(this.state.selectedInstanceId); current_value = this._makeMenuOptionFromProtocolInstance( this.state.selectedServer, this.props.protocols[protocolName], instance From 98cad8779c47b7dabbe1605738fea93e0f609411 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 15 Dec 2016 10:42:11 +0000 Subject: [PATCH 3/5] Add instance_id to initial state --- src/components/structures/RoomDirectory.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js index 2483247cef..7960b4cf86 100644 --- a/src/components/structures/RoomDirectory.js +++ b/src/components/structures/RoomDirectory.js @@ -53,6 +53,7 @@ module.exports = React.createClass({ publicRooms: [], loading: true, network: null, + instance_id: null, roomServer: null, filterString: null, } From 901c0e7e41b86c581fb9eade5083bab28a92f2bd Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 15 Dec 2016 14:24:55 +0000 Subject: [PATCH 4/5] Remove unused event params --- src/components/views/directory/NetworkDropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index 2c0b73baba..717fc00721 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -101,7 +101,7 @@ export default class NetworkDropdown extends React.Component { ev.preventDefault(); } - onMenuOptionClick(server, network, ev) { + onMenuOptionClick(server, network) { this.setState({ expanded: false, selectedServer: server, @@ -111,7 +111,7 @@ export default class NetworkDropdown extends React.Component { this.props.onOptionChange(server, network); } - onMenuOptionClickProtocolInstance(server, instance_id, ev) { + onMenuOptionClickProtocolInstance(server, instance_id) { this.setState({ expanded: false, selectedServer: server, From 5f7cdb8d425956d84b7e783148d4d5eeb6890524 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 15 Dec 2016 14:29:16 +0000 Subject: [PATCH 5/5] s/wire_onclick/handleClicks/ and actually pass handleClicks false as appropriate --- src/components/views/directory/NetworkDropdown.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index 717fc00721..0de48bf6a8 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -193,13 +193,13 @@ export default class NetworkDropdown extends React.Component { return options; } - _makeMenuOptionFromProtocolInstance(server, protocol, instance, wire_onclick) { - if (wire_onclick === undefined) wire_onclick = true; + _makeMenuOptionFromProtocolInstance(server, protocol, instance, handleClicks) { + if (handleClicks === undefined) handleClicks = true; const name = instance.desc; const icon = ; const key = instance.instance_id; - const click_handler = wire_onclick ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null; + const click_handler = handleClicks ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null; return
{icon} @@ -207,8 +207,8 @@ export default class NetworkDropdown extends React.Component {
; } - _makeMenuOption(server, network, wire_onclick) { - if (wire_onclick === undefined) wire_onclick = true; + _makeMenuOption(server, network, handleClicks) { + if (handleClicks === undefined) wire_onclick = true; let icon; let name; let span_class; @@ -240,7 +240,7 @@ export default class NetworkDropdown extends React.Component { span_class = 'mx_NetworkDropdown_menu_network'; } - const click_handler = wire_onclick ? this.onMenuOptionClick.bind(this, server, network) : null; + const click_handler = handleClicks ? this.onMenuOptionClick.bind(this, server, network) : null; let key = server; if (network !== null) { @@ -289,7 +289,7 @@ export default class NetworkDropdown extends React.Component { const protocolName = this._protocolNameForInstanceId(this.state.selectedInstanceId); const instance = this.instanceForInstanceId(this.state.selectedInstanceId); current_value = this._makeMenuOptionFromProtocolInstance( - this.state.selectedServer, this.props.protocols[protocolName], instance + this.state.selectedServer, this.props.protocols[protocolName], instance, false ); } else { current_value = this._makeMenuOption(