Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support room dir 3rd party network filtering #2747

Merged
merged 5 commits into from Dec 15, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -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.<server_name>.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.<network_type>.name`: Human-readable name for the network. Required.
1. `roomDirectory.<network_type>.protocol`: Protocol as given by the server in
Expand Down
10 changes: 8 additions & 2 deletions src/components/structures/RoomDirectory.js
Expand Up @@ -131,6 +131,11 @@ module.exports = React.createClass({
if (my_server != MatrixClientPeg.getHomeServerName()) {
opts.server = my_server;
}
if (this.state.instance_id) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add instance_id to getInitialState?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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) => {
Expand Down Expand Up @@ -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({
Expand All @@ -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
Expand Down Expand Up @@ -615,7 +621,7 @@ module.exports = React.createClass({
onChange={this.onFilterChange} onClear={this.onFilterClear} onJoinClick={this.onJoinClick}
placeholder={placeholder} showJoinButton={showJoinButton}
/>
<NetworkDropdown config={this.props.config} onOptionChange={this.onOptionChange} />
<NetworkDropdown config={this.props.config} protocols={this.protocols} onOptionChange={this.onOptionChange} />
</div>
{content}
</div>
Expand Down
87 changes: 83 additions & 4 deletions src/components/views/directory/NetworkDropdown.js
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ev seems redundant

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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({
Expand Down Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is wire_onclick ever false? why is it called that anyway?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as we only want to wire the onclick handler when it's used as a selectable menu option, rather than the currently selected menu option (ie. in the unexpanded dropdown).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, but it doesn't seem to be set in either of the places it's called.

and oh, wire is a verb. How about handleClicks or something? (don't we do camelCase rather than underscores?)

or just have an onProtocolInstanceClicked parameter, and pass in this.onMenuOptionClickProtocolInstance or null.

if (wire_onclick === undefined) wire_onclick = true;

const name = instance.desc;
const icon = <img src={protocol.icon || DEFAULT_ICON_URL} width="16" />;
const key = instance.instance_id;
const click_handler = wire_onclick ? this.onMenuOptionClickProtocolInstance.bind(this, server, instance.instance_id) : null;

return <div key={key} className="mx_NetworkDropdown_networkoption" onClick={click_handler}>
{icon}
<span className="mx_NetworkDropdown_menu_network">{name}</span>
</div>;
}

_makeMenuOption(server, network, wire_onclick) {
if (wire_onclick === undefined) wire_onclick = true;
let icon;
Expand Down Expand Up @@ -202,6 +253,24 @@ export default class NetworkDropdown extends React.Component {
</div>;
}

protocolNameForInstanceId(instance_id) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs _ if it's private

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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;

Expand All @@ -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 <div className="mx_NetworkDropdown" ref={this.collectRoot}>
Expand All @@ -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: {},
};