commit
5490235f4d
@ -222,6 +222,7 @@ kbd {
|
|||||||
#viewport .rt::before { content: "\f0c0"; /* http://fontawesome.io/icon/users/ */ }
|
#viewport .rt::before { content: "\f0c0"; /* http://fontawesome.io/icon/users/ */ }
|
||||||
#chat button.menu::before { content: "\f142"; /* http://fontawesome.io/icon/ellipsis-v/ */ }
|
#chat button.menu::before { content: "\f142"; /* http://fontawesome.io/icon/ellipsis-v/ */ }
|
||||||
|
|
||||||
|
.context-menu-join::before { content: "\f067"; /* http://fontawesome.io/icon/plus/ */ }
|
||||||
.context-menu-user::before { content: "\f007"; /* http://fontawesome.io/icon/user/ */ }
|
.context-menu-user::before { content: "\f007"; /* http://fontawesome.io/icon/user/ */ }
|
||||||
.context-menu-close::before { content: "\f00d"; /* http://fontawesome.io/icon/times/ */ }
|
.context-menu-close::before { content: "\f00d"; /* http://fontawesome.io/icon/times/ */ }
|
||||||
.context-menu-list::before { content: "\f03a"; /* http://fontawesome.io/icon/list/ */ }
|
.context-menu-list::before { content: "\f03a"; /* http://fontawesome.io/icon/list/ */ }
|
||||||
@ -457,7 +458,6 @@ kbd {
|
|||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar button,
|
|
||||||
#sidebar .chan,
|
#sidebar .chan,
|
||||||
#sidebar .sign-out,
|
#sidebar .sign-out,
|
||||||
#sidebar .empty {
|
#sidebar .empty {
|
||||||
@ -551,6 +551,7 @@ kbd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .badge,
|
#sidebar .badge,
|
||||||
|
#sidebar .add-channel,
|
||||||
#sidebar .close {
|
#sidebar .close {
|
||||||
float: right;
|
float: right;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
@ -577,7 +578,6 @@ kbd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .close {
|
#sidebar .close {
|
||||||
border-radius: 3px;
|
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
display: none;
|
display: none;
|
||||||
@ -594,13 +594,38 @@ kbd {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar .lobby .add-channel {
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: opacity 0.2s, background-color 0.2s, transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .lobby .add-channel::before {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: normal;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
content: "+";
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .lobby .add-channel:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .lobby .add-channel.opened {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
#sidebar .chan.active .close {
|
#sidebar .chan.active .close {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
display: unset;
|
display: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .chan.active .close:hover {
|
#sidebar .chan.active .close:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +710,7 @@ kbd {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#windows .input {
|
.input {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid #cdd3da;
|
border: 1px solid #cdd3da;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
@ -894,6 +919,35 @@ kbd {
|
|||||||
touch-action: pan-y;
|
touch-action: pan-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggled via JavaScript
|
||||||
|
*/
|
||||||
|
#sidebar .join-form {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .join-form .input {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .join-form .btn {
|
||||||
|
display: block;
|
||||||
|
width: 80%;
|
||||||
|
padding: 1px;
|
||||||
|
margin: auto;
|
||||||
|
height: 29px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .add-channel-tooltip {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
#chat .show-more {
|
#chat .show-more {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<div class="input">
|
<div class="input">
|
||||||
<span id="nick">
|
<span id="nick">
|
||||||
<span id="nick-value" spellcheck="false"></span><!-- Comments here remove spaces between elements
|
<span id="nick-value" spellcheck="false"></span><!-- Comments here remove spaces between elements
|
||||||
--><span id="set-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Change nick"><button id="set-nick" type="button" aria-label="Change nick"></button></span><!--
|
--><span id="set-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Change nick…"><button id="set-nick" type="button" aria-label="Change nick…"></button></span><!--
|
||||||
--><span id="cancel-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Cancel"><button id="cancel-nick" type="button" aria-label="Cancel"></button></span><!--
|
--><span id="cancel-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Cancel"><button id="cancel-nick" type="button" aria-label="Cancel"></button></span><!--
|
||||||
--><span id="save-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Save"><button id="submit-nick" type="button" aria-label="Save"></button></span>
|
--><span id="save-nick-tooltip" class="tooltipped tooltipped-e" aria-label="Save"><button id="submit-nick" type="button" aria-label="Save"></button></span>
|
||||||
</span>
|
</span>
|
||||||
|
88
client/js/join-channel.js
Normal file
88
client/js/join-channel.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const $ = require("jquery");
|
||||||
|
const Mousetrap = require("mousetrap");
|
||||||
|
|
||||||
|
const socket = require("./socket");
|
||||||
|
const utils = require("./utils");
|
||||||
|
|
||||||
|
const sidebar = $("#sidebar");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
handleKeybinds,
|
||||||
|
openForm,
|
||||||
|
};
|
||||||
|
|
||||||
|
function toggleButton(network) {
|
||||||
|
// Transform the + button to a ×
|
||||||
|
network.find("button.add-channel").toggleClass("opened");
|
||||||
|
|
||||||
|
// Toggle content of tooltip
|
||||||
|
const tooltip = network.find(".add-channel-tooltip");
|
||||||
|
const altLabel = tooltip.data("alt-label");
|
||||||
|
tooltip.data("alt-label", tooltip.attr("aria-label"));
|
||||||
|
tooltip.attr("aria-label", altLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeForm(network) {
|
||||||
|
const form = network.find(".join-form");
|
||||||
|
|
||||||
|
if (form.is(":visible")) {
|
||||||
|
form.find("input[name='channel']").val("");
|
||||||
|
form.find("input[name='key']").val("");
|
||||||
|
form.hide();
|
||||||
|
toggleButton(network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openForm(network) {
|
||||||
|
const form = network.find(".join-form");
|
||||||
|
|
||||||
|
if (form.is(":hidden")) {
|
||||||
|
form.show();
|
||||||
|
toggleButton(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus the "Channel" field even if the form was already open
|
||||||
|
form.find(".input[name='channel']").focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebar.on("click", ".add-channel", function(e) {
|
||||||
|
const id = $(e.target).data("id");
|
||||||
|
const joinForm = $(`#join-channel-${id}`);
|
||||||
|
const network = joinForm.closest(".network");
|
||||||
|
|
||||||
|
if (joinForm.is(":visible")) {
|
||||||
|
closeForm(network);
|
||||||
|
} else {
|
||||||
|
openForm(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebar.on("submit", ".join-form", function() {
|
||||||
|
const form = $(this);
|
||||||
|
const channel = form.find("input[name='channel']");
|
||||||
|
const channelString = channel.val();
|
||||||
|
const key = form.find("input[name='key']");
|
||||||
|
const keyString = key.val();
|
||||||
|
const chan = utils.findCurrentNetworkChan(channelString);
|
||||||
|
if (chan.length) {
|
||||||
|
chan.click();
|
||||||
|
} else {
|
||||||
|
socket.emit("input", {
|
||||||
|
text: `/join ${channelString} ${keyString}`,
|
||||||
|
target: form.prev().data("id"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
closeForm(form.closest(".network"));
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleKeybinds() {
|
||||||
|
sidebar.find(".join-form input, .join-form button").each(function() {
|
||||||
|
const network = $(this).closest(".network");
|
||||||
|
Mousetrap(this).bind("esc", () => closeForm(network));
|
||||||
|
});
|
||||||
|
}
|
@ -20,6 +20,7 @@ const utils = require("./utils");
|
|||||||
require("./webpush");
|
require("./webpush");
|
||||||
require("./keybinds");
|
require("./keybinds");
|
||||||
require("./clipboard");
|
require("./clipboard");
|
||||||
|
const JoinChannel = require("./join-channel");
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
var sidebar = $("#sidebar, #footer");
|
var sidebar = $("#sidebar, #footer");
|
||||||
@ -132,6 +133,12 @@ $(function() {
|
|||||||
text: "List all channels",
|
text: "List all channels",
|
||||||
data: target.data("id"),
|
data: target.data("id"),
|
||||||
});
|
});
|
||||||
|
output += templates.contextmenu_item({
|
||||||
|
class: "join",
|
||||||
|
action: "join",
|
||||||
|
text: "Join a channel…",
|
||||||
|
data: target.data("id"),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (target.hasClass("channel")) {
|
if (target.hasClass("channel")) {
|
||||||
output += templates.contextmenu_item({
|
output += templates.contextmenu_item({
|
||||||
@ -478,6 +485,10 @@ $(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const contextMenuActions = {
|
const contextMenuActions = {
|
||||||
|
join: function(itemData) {
|
||||||
|
const network = $(`#join-channel-${itemData}`).closest(".network");
|
||||||
|
JoinChannel.openForm(network);
|
||||||
|
},
|
||||||
close: function(itemData) {
|
close: function(itemData) {
|
||||||
closeChan($(`.networks .chan[data-target="${itemData}"]`));
|
closeChan($(`.networks .chan[data-target="${itemData}"]`));
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@ const utils = require("./utils");
|
|||||||
const sorting = require("./sorting");
|
const sorting = require("./sorting");
|
||||||
const constants = require("./constants");
|
const constants = require("./constants");
|
||||||
const condensed = require("./condensed");
|
const condensed = require("./condensed");
|
||||||
|
const JoinChannel = require("./join-channel");
|
||||||
const helpers_parse = require("./libs/handlebars/parse");
|
const helpers_parse = require("./libs/handlebars/parse");
|
||||||
|
|
||||||
const chat = $("#chat");
|
const chat = $("#chat");
|
||||||
@ -183,6 +184,9 @@ function renderNetworks(data, singleNetwork) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add keyboard handlers to the "Join a channel…" form inputs/button
|
||||||
|
JoinChannel.handleKeybinds();
|
||||||
|
|
||||||
let newChannels;
|
let newChannels;
|
||||||
const channels = $.map(data.networks, function(n) {
|
const channels = $.map(data.networks, function(n) {
|
||||||
return n.channels;
|
return n.channels;
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
{{#each channels}}
|
{{#each channels}}
|
||||||
<div data-id="{{id}}" data-target="#chan-{{id}}" data-title="{{name}}" class="chan {{type}} chan-{{slugify name}}">
|
<div data-id="{{id}}" data-target="#chan-{{id}}" data-title="{{name}}" class="chan {{type}} chan-{{slugify name}}">
|
||||||
|
{{#equal type "lobby"}}
|
||||||
|
<span class="add-channel-tooltip tooltipped tooltipped-w tooltipped-no-touch" aria-label="Join a channel…" data-alt-label="Cancel">
|
||||||
|
<button class="add-channel" aria-label="Join a channel…" data-id="{{id}}"></button>
|
||||||
|
</span>
|
||||||
|
{{/equal}}
|
||||||
<span class="badge{{#if highlight}} highlight{{/if}}">{{#if unread}}{{roundBadgeNumber unread}}{{/if}}</span>
|
<span class="badge{{#if highlight}} highlight{{/if}}">{{#if unread}}{{roundBadgeNumber unread}}{{/if}}</span>
|
||||||
{{#notEqual type "lobby"}}<button class="close" aria-label="Close"></button>{{/notEqual}}
|
{{#notEqual type "lobby"}}<button class="close" aria-label="Close"></button>{{/notEqual}}
|
||||||
<span class="name" title="{{name}}">{{name}}</span>
|
<span class="name" title="{{name}}">{{name}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{{#equal type "lobby"}}
|
||||||
|
{{> join_channel}}
|
||||||
|
{{/equal}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -42,6 +42,7 @@ module.exports = {
|
|||||||
msg_unhandled: require("./msg_unhandled.tpl"),
|
msg_unhandled: require("./msg_unhandled.tpl"),
|
||||||
network: require("./network.tpl"),
|
network: require("./network.tpl"),
|
||||||
image_viewer: require("./image_viewer.tpl"),
|
image_viewer: require("./image_viewer.tpl"),
|
||||||
|
join_channel: require("./join_channel.tpl"),
|
||||||
session: require("./session.tpl"),
|
session: require("./session.tpl"),
|
||||||
unread_marker: require("./unread_marker.tpl"),
|
unread_marker: require("./unread_marker.tpl"),
|
||||||
user: require("./user.tpl"),
|
user: require("./user.tpl"),
|
||||||
|
5
client/views/join_channel.tpl
Normal file
5
client/views/join_channel.tpl
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<form id="join-channel-{{id}}" class="join-form" method="post" action="" autocomplete="off">
|
||||||
|
<input type="text" class="input" name="channel" placeholder="Channel" pattern="[^\s]+" maxlength="200" title="Should be a valid channel name" required>
|
||||||
|
<input type="password" class="input" name="key" placeholder="Password (optional)" pattern="[^\s]+" title="Should be a valid channel key" maxlength="200" >
|
||||||
|
<button type="submit" class="btn joinchan:submit" data-id="{{id}}">Join</button>
|
||||||
|
</form>
|
Loading…
Reference in New Issue
Block a user