From f84334c31ef4e952f15a9de059985f809cb380d5 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 8 Mar 2021 18:15:04 +0100 Subject: [PATCH] Add UI to add a new bouncer network --- components/app.js | 34 ++++++++++++++ components/buffer-header.js | 10 +++- components/buffer-list.js | 7 +-- components/network-form.js | 91 +++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 components/network-form.js diff --git a/components/app.js b/components/app.js index cc4044d..d098e1c 100644 --- a/components/app.js +++ b/components/app.js @@ -7,6 +7,7 @@ import MemberList from "./member-list.js"; import ConnectForm from "./connect-form.js"; import JoinForm from "./join-form.js"; import Help from "./help.js"; +import NetworkForm from "./network-form.js"; import Composer from "./composer.js"; import ScrollManager from "./scroll-manager.js"; import Dialog from "./dialog.js"; @@ -185,6 +186,8 @@ export default class App extends Component { this.autocomplete = this.autocomplete.bind(this); this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this); this.handleDialogDismiss = this.handleDialogDismiss.bind(this); + this.handleAddNetworkClick = this.handleAddNetworkClick.bind(this); + this.handleAddNetworkSubmit = this.handleAddNetworkSubmit.bind(this); this.dismissError = this.dismissError.bind(this); this.saveReceipts = debounce(this.saveReceipts.bind(this), 500); @@ -980,6 +983,23 @@ export default class App extends Component { this.setState({ dialog: null }); } + handleAddNetworkClick() { + this.setState({ dialog: "add-network" }); + } + + handleAddNetworkSubmit(attrs) { + var client = this.clients.values().next().value; + client.send({ + command: "BOUNCER", + params: ["ADDNETWORK", irc.formatTags({ + ...attrs, + name: attrs.host, + tls: 1, + })], + }); + this.setState({ dialog: null }); + } + componentDidMount() { if (this.state.connectParams.autoconnect) { this.connect(this.state.connectParams); @@ -990,9 +1010,13 @@ export default class App extends Component { render() { var activeBuffer = null, activeNetwork = null; + var isBouncer = false; if (this.state.buffers.get(this.state.activeBuffer)) { activeBuffer = this.state.buffers.get(this.state.activeBuffer); activeNetwork = this.state.networks.get(activeBuffer.network); + + var activeClient = this.clients.get(activeBuffer.network); + isBouncer = activeClient && activeClient.enabledCaps["soju.im/bouncer-networks"]; } if (!activeNetwork || (activeNetwork.status !== NetworkStatus.REGISTERED && !activeBuffer)) { @@ -1017,8 +1041,10 @@ export default class App extends Component { <${BufferHeader} buffer=${activeBuffer} network=${activeNetwork} + isBouncer=${isBouncer} onClose=${() => this.close(activeBuffer)} onJoin=${() => this.handleJoinClick(activeBuffer.network)} + onAddNetwork=${this.handleAddNetworkClick} /> `; @@ -1041,6 +1067,13 @@ export default class App extends Component { var dialog = null; switch (this.state.dialog) { + case "add-network": + dialog = html` + <${Dialog} title="Add network" onDismiss=${this.handleDialogDismiss}> + <${NetworkForm} onSubmit=${this.handleAddNetworkSubmit}/> + + `; + break; case "help": dialog = html` <${Dialog} title="Help" onDismiss=${this.handleDialogDismiss}> @@ -1074,6 +1107,7 @@ export default class App extends Component { buffers=${this.state.buffers} networks=${this.state.networks} bouncerNetworks=${this.state.bouncerNetworks} + isBouncer=${isBouncer} activeBuffer=${this.state.activeBuffer} onBufferClick=${this.handleBufferListClick} /> diff --git a/components/buffer-header.js b/components/buffer-header.js index 66d717a..a2bf9e4 100644 --- a/components/buffer-header.js +++ b/components/buffer-header.js @@ -28,6 +28,10 @@ export default function BufferHeader(props) { event.preventDefault(); props.onJoin(); } + function handleAddNetworkClick(event) { + event.preventDefault(); + props.onAddNetwork(); + } var description = null; if (props.buffer.serverInfo) { @@ -71,7 +75,11 @@ export default function BufferHeader(props) { var closeText = "Close"; switch (props.buffer.type) { case BufferType.SERVER: - actions = html`Join`; + if (props.isBouncer && !props.network.isupport.get("BOUNCER_NETID")) { + actions = html`Add network`; + } else { + actions = html`Join`; + } closeText = "Disconnect"; break; case BufferType.CHANNEL: diff --git a/components/buffer-list.js b/components/buffer-list.js index 704912d..0e667e2 100644 --- a/components/buffer-list.js +++ b/components/buffer-list.js @@ -26,7 +26,7 @@ function BufferItem(props) { var name = props.buffer.name; if (props.buffer.type == BufferType.SERVER) { - name = getNetworkName(props.network, props.bouncerNetwork, props.bouncer); + name = getNetworkName(props.network, props.bouncerNetwork, props.isBouncer); } var classes = ["type-" + props.buffer.type]; @@ -46,9 +46,6 @@ function BufferItem(props) { export default function BufferList(props) { - // TODO: check bouncer-networks cap instead - var bouncer = props.bouncerNetworks.size > 0; - var items = Array.from(props.buffers.values()).map((buf) => { var network = props.networks.get(buf.network); @@ -59,7 +56,7 @@ export default function BufferList(props) { } return html` - <${BufferItem} key=${buf.id} buffer=${buf} network=${network} bouncer=${bouncer} bouncerNetwork=${bouncerNetwork} onClick=${() => props.onBufferClick(buf)} active=${props.activeBuffer == buf.id}/> + <${BufferItem} key=${buf.id} buffer=${buf} network=${network} isBouncer=${props.isBouncer} bouncerNetwork=${bouncerNetwork} onClick=${() => props.onBufferClick(buf)} active=${props.activeBuffer == buf.id}/> `; }); diff --git a/components/network-form.js b/components/network-form.js new file mode 100644 index 0000000..eab98b2 --- /dev/null +++ b/components/network-form.js @@ -0,0 +1,91 @@ +import { html, Component } from "../lib/index.js"; + +export default class NetworkForm extends Component { + state = { + host: "", + port: 6697, + nickname: "", + username: "", + realname: "", + pass: "", + }; + + constructor(props) { + super(props); + + this.handleChange = this.handleChange.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + } + + handleChange(event) { + var target = event.target; + var value = target.type == "checkbox" ? target.checked : target.value; + this.setState({ [target.name]: value }); + } + + handleSubmit(event) { + event.preventDefault(); + + var params = { + host: this.state.host, + port: this.state.port, + nickname: this.state.nickname, + username: this.state.username, + realname: this.state.realname, + pass: this.state.pass, + }; + + this.props.onSubmit(params); + } + + render() { + return html` +
+ +

+ +
+ Advanced options + +
+ + +

+ + +

+ + +

+ + +

+ + +
+
+ +
+ +
+ `; + } +}