Port join-channel completely to Vue

This commit is contained in:
Pavel Djundik 2018-07-12 22:06:17 +03:00 committed by Pavel Djundik
parent 80a12d98b4
commit 8931570c02
9 changed files with 66 additions and 108 deletions

View File

@ -1,7 +1,6 @@
<template> <template>
<div <div
v-if="!network.isCollapsed || channel.highlight || channel.type === 'lobby'" v-if="!network.isCollapsed || channel.highlight || channel.type === 'lobby'"
:key="channel.id"
:class="[ channel.type, { active: activeChannel && channel === activeChannel.channel } ]" :class="[ channel.type, { active: activeChannel && channel === activeChannel.channel } ]"
:aria-label="channel.name" :aria-label="channel.name"
:title="channel.name" :title="channel.name"
@ -46,13 +45,13 @@
class="badge">{{ channel.unread | roundBadgeNumber }}</span> class="badge">{{ channel.unread | roundBadgeNumber }}</span>
</div> </div>
<span <span
class="add-channel-tooltip tooltipped tooltipped-w tooltipped-no-touch" :aria-label="joinChannelLabel"
aria-label="Join a channel…" class="add-channel-tooltip tooltipped tooltipped-w tooltipped-no-touch">
data-alt-label="Cancel">
<button <button
:class="['add-channel', { opened: isJoinChannelShown }]"
:aria-controls="'join-channel-' + channel.id" :aria-controls="'join-channel-' + channel.id"
class="add-channel" :aria-label="joinChannelLabel"
aria-label="Join a channel…"/> @click.stop="$emit('toggleJoinChannel')"/>
</span> </span>
</template> </template>
<template v-else> <template v-else>
@ -94,6 +93,12 @@ export default {
activeChannel: Object, activeChannel: Object,
network: Object, network: Object,
channel: Object, channel: Object,
isJoinChannelShown: Boolean,
},
computed: {
joinChannelLabel() {
return this.isJoinChannelShown ? "Cancel" : "Join a channel…";
},
}, },
methods: { methods: {
onCollapseClick() { onCollapseClick() {

View File

@ -5,8 +5,12 @@
method="post" method="post"
action="" action=""
autocomplete="off" autocomplete="off"
@keydown.esc.prevent="$emit('toggleJoinChannel')"
@submit.prevent="onSubmit"
> >
<input <input
v-focus
v-model="inputChannel"
type="text" type="text"
class="input" class="input"
name="channel" name="channel"
@ -17,6 +21,7 @@
required required
> >
<input <input
v-model="inputPassword"
type="password" type="password"
class="input" class="input"
name="key" name="key"
@ -33,10 +38,45 @@
</template> </template>
<script> <script>
import socket from "../js/socket";
export default { export default {
name: "JoinChannel", name: "JoinChannel",
directives: {
focus: {
inserted(el) {
el.focus();
},
},
},
props: { props: {
channel: Object, channel: Object,
}, },
data() {
return {
inputChannel: "",
inputPassword: "",
};
},
methods: {
onSubmit() {
const utils = require("../js/utils");
const existingChannel = utils.findCurrentNetworkChan(this.inputChannel);
if (existingChannel) {
const $ = require("jquery");
$(`#sidebar .chan[data-id="${existingChannel.id}"]`).trigger("click");
} else {
socket.emit("input", {
text: `/join ${this.inputChannel} ${this.inputPassword}`,
target: this.channel.id,
});
}
this.inputChannel = "";
this.inputPassword = "";
this.$emit("toggleJoinChannel");
},
},
}; };
</script> </script>

View File

@ -31,8 +31,14 @@
:channel="network.channels[0]" :channel="network.channels[0]"
:network="network" :network="network"
:active-channel="activeChannel" :active-channel="activeChannel"
:is-join-channel-shown="network.isJoinChannelShown"
@toggleJoinChannel="network.isJoinChannelShown = !network.isJoinChannelShown"
/>
<JoinChannel
v-if="network.isJoinChannelShown"
:channel="network.channels[0]"
@toggleJoinChannel="network.isJoinChannelShown = !network.isJoinChannelShown"
/> />
<JoinChannel :channel="network.channels[0]"/>
<Draggable <Draggable
:options="{ draggable: '.chan', ghostClass: 'chan-placeholder' }" :options="{ draggable: '.chan', ghostClass: 'chan-placeholder' }"

View File

@ -1056,7 +1056,6 @@ background on hover (unless active) */
* Toggled via JavaScript * Toggled via JavaScript
*/ */
#sidebar .join-form { #sidebar .join-form {
display: none;
padding: 0 18px 8px; padding: 0 18px 8px;
} }

View File

@ -1,11 +1,12 @@
"use strict"; "use strict";
const $ = require("jquery"); const $ = require("jquery");
const socket = require("./socket"); const socket = require("./socket");
const utils = require("./utils"); const utils = require("./utils");
const JoinChannel = require("./join-channel");
const ContextMenu = require("./contextMenu"); const ContextMenu = require("./contextMenu");
const contextMenuActions = []; const contextMenuActions = [];
const contextMenuItems = []; const contextMenuItems = [];
const {findChannel} = require("./vue");
module.exports = { module.exports = {
addContextMenuItem, addContextMenuItem,
@ -332,8 +333,7 @@ function addBanListItem() {
function addJoinItem() { function addJoinItem() {
function openJoinForm(itemData) { function openJoinForm(itemData) {
const network = $(`#join-channel-${itemData}`).closest(".network"); findChannel(Number(itemData)).network.isJoinChannelShown = true;
JoinChannel.openForm(network);
} }
addContextMenuItem({ addContextMenuItem({

View File

@ -1,96 +0,0 @@
"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']").trigger("focus");
}
sidebar.on("click", ".add-channel", function(e) {
const id = $(e.target).closest(".lobby").data("id");
const joinForm = $(`#join-channel-${id}`);
const network = joinForm.closest(".network");
if (joinForm.is(":visible")) {
closeForm(network);
} else {
openForm(network);
}
return false;
});
function handleKeybinds(networks) {
for (const network of networks) {
const form = $(`.network[data-uuid="${network.uuid}"] .join-form`);
form.find("input, button").each(function() {
Mousetrap(this).bind("esc", () => {
closeForm(form.closest(".network"));
return false;
});
});
form.on("submit", () => {
const networkElement = form.closest(".network");
const channel = form.find("input[name='channel']").val();
const key = form.find("input[name='key']").val();
const existingChannel = utils.findCurrentNetworkChan(channel);
if (existingChannel) {
$(`#sidebar .chan[data-id="${existingChannel.id}"]`).trigger("click");
} else {
socket.emit("input", {
text: `/join ${channel} ${key}`,
target: networkElement.find(".lobby").data("id"),
});
}
closeForm(networkElement);
return false;
});
}
}

View File

@ -23,6 +23,7 @@ socket.on("init", function(data) {
const networks = new Set(JSON.parse(storage.get("thelounge.networks.collapsed"))); const networks = new Set(JSON.parse(storage.get("thelounge.networks.collapsed")));
for (const network of data.networks) { for (const network of data.networks) {
network.isJoinChannelShown = false;
network.isCollapsed = networks.has(network.uuid); network.isCollapsed = networks.has(network.uuid);
for (const channel of network.channels) { for (const channel of network.channels) {

View File

@ -10,6 +10,9 @@ const {vueApp} = require("../vue");
socket.on("network", function(data) { socket.on("network", function(data) {
const network = data.networks[0]; const network = data.networks[0];
network.isJoinChannelShown = false;
network.isCollapsed = false;
for (const channel of network.channels) { for (const channel of network.channels) {
if (channel.type === "channel") { if (channel.type === "channel") {
channel.usersOutdated = true; channel.usersOutdated = true;

View File

@ -4,7 +4,7 @@ const socket = require("../socket");
const {findChannel} = require("../vue"); const {findChannel} = require("../vue");
socket.on("topic", function(data) { socket.on("topic", function(data) {
let channel = findChannel(data.chan); const channel = findChannel(data.chan);
if (channel) { if (channel) {
channel.channel.topic = data.topic; channel.channel.topic = data.topic;