mirror of
https://codeberg.org/emersion/gamja.git
synced 2024-11-14 19:05:01 -05:00
Add dialog for join form
This commit is contained in:
parent
996d7d06d4
commit
30157383e8
4 changed files with 165 additions and 10 deletions
|
@ -5,8 +5,10 @@ import BufferList from "./buffer-list.js";
|
|||
import BufferHeader from "./buffer-header.js";
|
||||
import MemberList from "./member-list.js";
|
||||
import Connect from "./connect.js";
|
||||
import Join from "./join.js";
|
||||
import Composer from "./composer.js";
|
||||
import ScrollManager from "./scroll-manager.js";
|
||||
import Dialog from "./dialog.js";
|
||||
import { html, Component, createRef } from "../lib/index.js";
|
||||
import { strip as stripANSI } from "../lib/ansi.js";
|
||||
import { SERVER_BUFFER, BufferType, ReceiptType, NetworkStatus, Unread } from "../state.js";
|
||||
|
@ -151,6 +153,7 @@ export default class App extends Component {
|
|||
networks: new Map(),
|
||||
buffers: new Map(),
|
||||
activeBuffer: null,
|
||||
dialog: null,
|
||||
error: null,
|
||||
};
|
||||
clients = new Map();
|
||||
|
@ -165,11 +168,13 @@ export default class App extends Component {
|
|||
super(props);
|
||||
|
||||
this.handleConnectSubmit = this.handleConnectSubmit.bind(this);
|
||||
this.handleJoinSubmit = this.handleJoinSubmit.bind(this);
|
||||
this.handleBufferListClick = this.handleBufferListClick.bind(this);
|
||||
this.handleComposerSubmit = this.handleComposerSubmit.bind(this);
|
||||
this.handleNickClick = this.handleNickClick.bind(this);
|
||||
this.autocomplete = this.autocomplete.bind(this);
|
||||
this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this);
|
||||
this.handleDialogDismiss = this.handleDialogDismiss.bind(this);
|
||||
this.dismissError = this.dismissError.bind(this);
|
||||
|
||||
this.saveReceipts = debounce(this.saveReceipts.bind(this), 500);
|
||||
|
@ -833,14 +838,15 @@ export default class App extends Component {
|
|||
}
|
||||
|
||||
handleJoinClick(netID) {
|
||||
var channel = prompt("Join channel:");
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
this.setState({ dialog: "join", joinDialog: { network: netID } });
|
||||
}
|
||||
|
||||
var client = this.clients.get(netID);
|
||||
handleJoinSubmit(data) {
|
||||
var client = this.clients.get(this.state.joinDialog.network);
|
||||
|
||||
client.send({ command: "JOIN", params: [channel] });
|
||||
client.send({ command: "JOIN", params: [data.channel] });
|
||||
|
||||
this.setState({ dialog: null, joinDialog: null });
|
||||
}
|
||||
|
||||
autocomplete(prefix) {
|
||||
|
@ -903,6 +909,10 @@ export default class App extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
handleDialogDismiss() {
|
||||
this.setState({ dialog: null });
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.state.connectParams.autoconnect) {
|
||||
this.connect(this.state.connectParams);
|
||||
|
@ -947,6 +957,17 @@ export default class App extends Component {
|
|||
`;
|
||||
}
|
||||
|
||||
var dialog = null;
|
||||
switch (this.state.dialog) {
|
||||
case "join":
|
||||
dialog = html`
|
||||
<${Dialog} title="Join channel" onDismiss=${this.handleDialogDismiss}>
|
||||
<${Join} onSubmit=${this.handleJoinSubmit}/>
|
||||
</>
|
||||
`;
|
||||
break;
|
||||
}
|
||||
|
||||
var error = null;
|
||||
if (this.state.error) {
|
||||
error = html`
|
||||
|
@ -966,6 +987,7 @@ export default class App extends Component {
|
|||
</>
|
||||
${memberList}
|
||||
<${Composer} ref=${this.composer} readOnly=${activeBuffer && activeBuffer.type == BufferType.SERVER} onSubmit=${this.handleComposerSubmit} autocomplete=${this.autocomplete}/>
|
||||
${dialog}
|
||||
${error}
|
||||
`;
|
||||
}
|
||||
|
|
61
components/dialog.js
Normal file
61
components/dialog.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { html, Component, createRef } from "../lib/index.js";
|
||||
|
||||
export default class Dialog extends Component {
|
||||
body = createRef();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleCloseClick = this.handleCloseClick.bind(this);
|
||||
this.handleBackdropClick = this.handleBackdropClick.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
this.props.onDismiss();
|
||||
}
|
||||
|
||||
handleCloseClick(event) {
|
||||
event.preventDefault();
|
||||
this.dismiss();
|
||||
}
|
||||
|
||||
handleBackdropClick(event) {
|
||||
if (event.target.className == "dialog") {
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown(event) {
|
||||
if (event.key == "Escape") {
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("keydown", this.handleKeyDown);
|
||||
|
||||
var autofocus = this.body.current.querySelector("input[autofocus]");
|
||||
if (autofocus) {
|
||||
autofocus.focus();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("keydown", this.handleKeyDown);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="dialog" onClick=${this.handleBackdropClick}>
|
||||
<div class="dialog-body" ref=${this.body}>
|
||||
<div class="dialog-header">
|
||||
<a href="#" class="dialog-close" onClick=${this.handleCloseClick}>×</span>
|
||||
<h2>${this.props.title}</h2>
|
||||
</div>
|
||||
${this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
45
components/join.js
Normal file
45
components/join.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { html, Component } from "../lib/index.js";
|
||||
|
||||
export default class Join extends Component {
|
||||
state = {
|
||||
channel: "#",
|
||||
};
|
||||
|
||||
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 = {
|
||||
channel: this.state.channel,
|
||||
};
|
||||
|
||||
this.props.onSubmit(params);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<form onChange=${this.handleChange} onSubmit=${this.handleSubmit}>
|
||||
<label>
|
||||
Channel:<br/>
|
||||
<input type="text" name="channel" value=${this.state.channel} autofocus required/>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<br/>
|
||||
<button>Join</button>
|
||||
</form>
|
||||
`;
|
||||
}
|
||||
}
|
35
style.css
35
style.css
|
@ -136,10 +136,11 @@ body {
|
|||
margin: 0 auto;
|
||||
max-width: 300px;
|
||||
}
|
||||
#connect input[type="text"],
|
||||
#connect input[type="username"],
|
||||
#connect input[type="password"],
|
||||
#connect input[type="url"] {
|
||||
|
||||
form input[type="text"],
|
||||
form input[type="username"],
|
||||
form input[type="password"],
|
||||
form input[type="url"] {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -274,3 +275,29 @@ details summary {
|
|||
.error-text {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.dialog .dialog-body {
|
||||
background-color: white;
|
||||
margin: auto;
|
||||
margin-top: 20px;
|
||||
max-width: 500px;
|
||||
padding: 15px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.dialog a.dialog-close {
|
||||
float: right;
|
||||
text-decoration: none;
|
||||
font-size: 1.5em;
|
||||
color: inherit;
|
||||
}
|
||||
.dialog h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue