Implement network editing UI and object updating
This commit is contained in:
parent
682d3070e9
commit
f86d73972d
@ -417,6 +417,7 @@ kbd {
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.context-menu-edit::before,
|
||||
#set-nick::before {
|
||||
content: "\f303"; /* https://fontawesome.com/icons/pencil-alt?style=solid */
|
||||
}
|
||||
|
@ -153,6 +153,21 @@ function addFocusItem() {
|
||||
});
|
||||
}
|
||||
|
||||
function addEditNetworkItem() {
|
||||
function edit(itemData) {
|
||||
socket.emit("network:get", itemData);
|
||||
$('button[data-target="#connect"]').trigger("click");
|
||||
}
|
||||
|
||||
addContextMenuItem({
|
||||
check: (target) => target.hasClass("lobby"),
|
||||
className: "edit",
|
||||
displayName: "Edit this network…",
|
||||
data: (target) => target.closest(".network").data("uuid"),
|
||||
callback: edit,
|
||||
});
|
||||
}
|
||||
|
||||
function addChannelListItem() {
|
||||
function list(itemData) {
|
||||
socket.emit("input", {
|
||||
@ -207,6 +222,7 @@ function addDefaultItems() {
|
||||
addQueryItem();
|
||||
addKickItem();
|
||||
addFocusItem();
|
||||
addEditNetworkItem();
|
||||
addChannelListItem();
|
||||
addBanListItem();
|
||||
addJoinItem();
|
||||
|
@ -18,7 +18,6 @@ const utils = require("./utils");
|
||||
require("./webpush");
|
||||
require("./keybinds");
|
||||
require("./clipboard");
|
||||
const Changelog = require("./socket-events/changelog");
|
||||
const contextMenuFactory = require("./contextMenuFactory");
|
||||
const contextMenuContainer = $("#context-menu-container");
|
||||
|
||||
@ -322,15 +321,6 @@ $(function() {
|
||||
socket.emit("names", {target: self.data("id")});
|
||||
}
|
||||
|
||||
if (target === "#settings") {
|
||||
$("#session-list").html("<p>Loading…</p>");
|
||||
socket.emit("sessions:get");
|
||||
}
|
||||
|
||||
if (target === "#help" || target === "#changelog") {
|
||||
Changelog.requestIfNeeded();
|
||||
}
|
||||
|
||||
// Pushes states to history web API when clicking elements with a data-target attribute.
|
||||
// States are very trivial and only contain a single `clickTarget` property which
|
||||
// contains a CSS selector that targets elements which takes the user to a different view
|
||||
|
@ -4,10 +4,6 @@ const $ = require("jquery");
|
||||
const socket = require("../socket");
|
||||
const templates = require("../../views");
|
||||
|
||||
module.exports = {
|
||||
requestIfNeeded,
|
||||
};
|
||||
|
||||
// Requests version information if it hasn't been retrieved before (or if it has
|
||||
// been removed from the page, i.e. when clicking on "Check now". Displays a
|
||||
// loading state until received.
|
||||
@ -54,6 +50,8 @@ socket.on("changelog", function(data) {
|
||||
}
|
||||
});
|
||||
|
||||
$("#help, #changelog").on("show", requestIfNeeded);
|
||||
|
||||
// When clicking the "Check now" button, remove current checker information and
|
||||
// request a new one. Loading will be displayed in the meantime.
|
||||
$("#help").on("click", "#check-now", () => {
|
||||
|
@ -5,6 +5,7 @@ const socket = require("../socket");
|
||||
const templates = require("../../views");
|
||||
const options = require("../options");
|
||||
const webpush = require("../webpush");
|
||||
const connect = $("#connect");
|
||||
|
||||
socket.on("configuration", function(data) {
|
||||
if (options.initialized) {
|
||||
@ -14,10 +15,14 @@ socket.on("configuration", function(data) {
|
||||
}
|
||||
|
||||
$("#settings").html(templates.windows.settings(data));
|
||||
$("#connect").html(templates.windows.connect(data));
|
||||
$("#help").html(templates.windows.help(data));
|
||||
$("#changelog").html(templates.windows.changelog());
|
||||
|
||||
$("#settings").on("show", () => {
|
||||
$("#session-list").html("<p>Loading…</p>");
|
||||
socket.emit("sessions:get");
|
||||
});
|
||||
|
||||
$("#play").on("click", () => {
|
||||
const pop = new Audio();
|
||||
pop.src = "audio/pop.ogg";
|
||||
@ -33,9 +38,7 @@ socket.on("configuration", function(data) {
|
||||
options.processSetting("theme", data.defaultTheme, true);
|
||||
}
|
||||
|
||||
const forms = $("#connect form, #change-password form");
|
||||
|
||||
forms.on("submit", function() {
|
||||
function handleFormSubmit() {
|
||||
const form = $(this);
|
||||
const event = form.data("event");
|
||||
|
||||
@ -51,27 +54,34 @@ socket.on("configuration", function(data) {
|
||||
socket.emit(event, values);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$("#change-password form").on("submit", handleFormSubmit);
|
||||
connect.on("submit", "form", handleFormSubmit);
|
||||
|
||||
connect.on("show", function() {
|
||||
connect
|
||||
.html(templates.windows.connect(data))
|
||||
.find("#connect\\:nick")
|
||||
.on("focusin", function() {
|
||||
// Need to set the first "lastvalue", so it can be used in the below function
|
||||
const nick = $(this);
|
||||
nick.data("lastvalue", nick.val());
|
||||
})
|
||||
.on("input", function() {
|
||||
const nick = $(this).val();
|
||||
const usernameInput = connect.find(".username");
|
||||
|
||||
// Because this gets called /after/ it has already changed, we need use the previous value
|
||||
const lastValue = $(this).data("lastvalue");
|
||||
|
||||
// They were the same before the change, so update the username field
|
||||
if (usernameInput.val() === lastValue) {
|
||||
usernameInput.val(nick);
|
||||
}
|
||||
|
||||
// Store the "previous" value, for next time
|
||||
$(this).data("lastvalue", nick);
|
||||
});
|
||||
});
|
||||
|
||||
$(".nick")
|
||||
.on("focusin", function() {
|
||||
// Need to set the first "lastvalue", so it can be used in the below function
|
||||
const nick = $(this);
|
||||
nick.data("lastvalue", nick.val());
|
||||
})
|
||||
.on("input", function() {
|
||||
const nick = $(this).val();
|
||||
const usernameInput = forms.find(".username");
|
||||
|
||||
// Because this gets called /after/ it has already changed, we need use the previous value
|
||||
const lastValue = $(this).data("lastvalue");
|
||||
|
||||
// They were the same before the change, so update the username field
|
||||
if (usernameInput.val() === lastValue) {
|
||||
usernameInput.val(nick);
|
||||
}
|
||||
|
||||
// Store the "previous" value, for next time
|
||||
$(this).data("lastvalue", nick);
|
||||
});
|
||||
});
|
||||
|
@ -3,6 +3,7 @@
|
||||
const $ = require("jquery");
|
||||
const socket = require("../socket");
|
||||
const render = require("../render");
|
||||
const templates = require("../../views");
|
||||
const sidebar = $("#sidebar");
|
||||
|
||||
socket.on("network", function(data) {
|
||||
@ -27,3 +28,17 @@ socket.on("network:status", function(data) {
|
||||
.toggleClass("not-connected", !data.connected)
|
||||
.toggleClass("not-secure", !data.secure);
|
||||
});
|
||||
|
||||
socket.on("network:info", function(data) {
|
||||
$("#connect")
|
||||
.html(templates.windows.connect(data))
|
||||
.find("form").on("submit", function() {
|
||||
const uuid = $(this).find("input[name=uuid]").val();
|
||||
const newName = $(this).find("#connect\\:name").val();
|
||||
|
||||
sidebar.find(`.network[data-uuid="${uuid}"] .chan.lobby .name`)
|
||||
.attr("title", newName)
|
||||
.text(newName)
|
||||
.click();
|
||||
});
|
||||
});
|
||||
|
@ -1,20 +1,26 @@
|
||||
<div class="header">
|
||||
<button class="lt" aria-label="Toggle channel list"></button>
|
||||
</div>
|
||||
<form class="container" method="post" action="" data-event="conn">
|
||||
<form class="container" method="post" action="" data-event="{{#if defaults.uuid}}network:edit{{else}}network:new{{/if}}">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h1 class="title">
|
||||
{{#if public}}The Lounge - {{/if}}
|
||||
Connect
|
||||
{{#unless displayNetwork}}
|
||||
{{#if lockNetwork}}
|
||||
to {{defaults.name}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{#if defaults.uuid}}
|
||||
<input type="hidden" name="uuid" value="{{defaults.uuid}}">
|
||||
|
||||
Edit {{defaults.name}}
|
||||
{{else}}
|
||||
{{#if public}}The Lounge - {{/if}}
|
||||
Connect
|
||||
{{#unless displayNetwork}}
|
||||
{{#if lockNetwork}}
|
||||
to {{defaults.name}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</h1>
|
||||
</div>
|
||||
{{#if displayNetwork}}
|
||||
{{#if displayNetwork}}
|
||||
<div>
|
||||
<div class="col-sm-12">
|
||||
<h2>Network settings</h2>
|
||||
@ -29,7 +35,7 @@
|
||||
<label for="connect:host">Server</label>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xs-8">
|
||||
<input class="input" id="connect:host" name="host" value="{{defaults.host}}" aria-label="Server address" {{#if lockNetwork}}disabled{{/if}}>
|
||||
<input class="input" id="connect:host" name="host" value="{{defaults.host}}" aria-label="Server address" required {{#if lockNetwork}}disabled{{/if}}>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-4">
|
||||
<div class="port">
|
||||
@ -51,7 +57,7 @@
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div class="col-sm-12">
|
||||
<h2>User preferences</h2>
|
||||
</div>
|
||||
@ -59,16 +65,16 @@
|
||||
<label for="connect:nick">Nick</label>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<input class="input nick" id="connect:nick" name="nick" value="{{defaults.nick}}">
|
||||
<input class="input nick" id="connect:nick" name="nick" value="{{defaults.nick}}" required>
|
||||
</div>
|
||||
{{#unless useHexIp}}
|
||||
{{#unless useHexIp}}
|
||||
<div class="col-sm-3">
|
||||
<label for="connect:username">Username</label>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<input class="input username" id="connect:username" name="username" value="{{defaults.username}}">
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
<div class="col-sm-3">
|
||||
<label for="connect:password">Password</label>
|
||||
</div>
|
||||
@ -81,6 +87,18 @@
|
||||
<div class="col-sm-9">
|
||||
<input class="input" id="connect:realname" name="realname" value="{{defaults.realname}}">
|
||||
</div>
|
||||
{{#if defaults.uuid}}
|
||||
<div class="col-sm-3">
|
||||
<label for="connect:commands">Commands</label>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="input" id="connect:commands" name="commands" placeholder="One raw command per line, each command will be executed on new connection">{{~#each defaults.commands~}}{{~this}}
|
||||
{{/each~}}</textarea>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3">
|
||||
<button type="submit" class="btn">Save</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="col-sm-3">
|
||||
<label for="connect:channels">Channels</label>
|
||||
</div>
|
||||
@ -90,5 +108,6 @@
|
||||
<div class="col-sm-9 col-sm-offset-3">
|
||||
<button type="submit" class="btn">Connect</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</form>
|
||||
|
@ -164,6 +164,63 @@ Network.prototype.createWebIrc = function(client) {
|
||||
};
|
||||
};
|
||||
|
||||
Network.prototype.edit = function(client, args) {
|
||||
const oldNick = this.nick;
|
||||
|
||||
this.nick = args.nick;
|
||||
this.host = String(args.host || "");
|
||||
this.name = String(args.name || "") || this.host;
|
||||
this.port = parseInt(args.port, 10);
|
||||
this.tls = !!args.tls;
|
||||
this.rejectUnauthorized = !!args.rejectUnauthorized;
|
||||
this.password = String(args.password || "");
|
||||
this.username = String(args.username || "");
|
||||
this.realname = String(args.realname || "");
|
||||
|
||||
// Split commands into an array
|
||||
this.commands = String(args.commands || "")
|
||||
.replace(/\r\n|\r|\n/g, "\n")
|
||||
.split("\n")
|
||||
.filter((command) => command.length > 0);
|
||||
|
||||
// Sync lobby channel name
|
||||
this.channels[0].name = this.name;
|
||||
|
||||
if (!this.validate(client)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.irc) {
|
||||
if (this.nick !== oldNick) {
|
||||
if (this.irc.connection && this.irc.connection.connected) {
|
||||
// Send new nick straight away
|
||||
this.irc.raw("NICK", this.nick);
|
||||
} else {
|
||||
this.irc.options.nick = this.irc.user.nick = this.nick;
|
||||
|
||||
// Update UI nick straight away if IRC is not connected
|
||||
client.emit("nick", {
|
||||
network: this.id,
|
||||
nick: this.nick,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.irc.options.host = this.host;
|
||||
this.irc.options.port = this.port;
|
||||
this.irc.options.password = this.password;
|
||||
this.irc.options.gecos = this.irc.user.gecos = this.realname;
|
||||
this.irc.options.tls = this.tls;
|
||||
this.irc.options.rejectUnauthorized = this.rejectUnauthorized;
|
||||
|
||||
if (!Helper.config.useHexIp) {
|
||||
this.irc.options.username = this.irc.user.username = this.username;
|
||||
}
|
||||
}
|
||||
|
||||
client.save();
|
||||
};
|
||||
|
||||
Network.prototype.destroy = function() {
|
||||
this.channels.forEach((channel) => channel.destroy());
|
||||
};
|
||||
|
@ -301,7 +301,7 @@ function initializeClient(socket, client, token, lastMessage) {
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("conn", (data) => {
|
||||
socket.on("network:new", (data) => {
|
||||
if (typeof data === "object") {
|
||||
// prevent people from overriding webirc settings
|
||||
data.ip = null;
|
||||
|
@ -88,7 +88,7 @@ describe("Server", function() {
|
||||
|
||||
it("should create network", (done) => {
|
||||
client.on("init", () => {
|
||||
client.emit("conn", {
|
||||
client.emit("network:new", {
|
||||
username: "test-user",
|
||||
realname: "The Lounge Test",
|
||||
nick: "test-user",
|
||||
|
Loading…
Reference in New Issue
Block a user