From 808b2b249b55bcf386c7ca71a14ced60a6090ed8 Mon Sep 17 00:00:00 2001 From: Jay2k1 Date: Fri, 13 Apr 2018 17:53:41 +0200 Subject: [PATCH] add 'op' and 'voice' context menu entries --- client/css/style.css | 4 +- client/js/contextMenuFactory.js | 80 +++++++++++++++++++++++++++++++++ client/js/utils.js | 8 ++-- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/client/css/style.css b/client/css/style.css index a362209d..ba7bc969 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -279,6 +279,8 @@ kbd { .context-menu-list::before { content: "\f03a"; /* http://fontawesome.io/icon/list/ */ } .context-menu-action-whois::before { content: "\f05a"; /* http://fontawesome.io/icon/info-circle/ */ } .context-menu-action-kick::before { content: "\f05e"; /* http://fontawesome.io/icon/ban/ */ } +.context-menu-action-op::before { content: "\f1fa"; /* http://fontawesome.io/icon/at/ */ } +.context-menu-action-voice::before { content: "\f067"; /* http://fontawesome.io/icon/plus/ */ } .context-menu-network::before { content: "\f233"; /* https://fontawesome.com/icons/server?style=solid */ } #sidebar .not-secure-icon::before { @@ -1952,7 +1954,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */ list-style: none; margin: 0; padding: 0; - min-width: 160px; + min-width: 180px; font-size: 14px; background-color: #fff; box-shadow: 0 3px 12px rgba(0, 0, 0, 0.15); diff --git a/client/js/contextMenuFactory.js b/client/js/contextMenuFactory.js index a822deea..cc20957b 100644 --- a/client/js/contextMenuFactory.js +++ b/client/js/contextMenuFactory.js @@ -125,6 +125,82 @@ function addKickItem() { }); } +function addOpItem() { + function op(itemData) { + socket.emit("input", { + target: $("#chat").data("id"), + text: "/op " + itemData, + }); + } + + addContextMenuItem({ + check: (target) => + utils.hasRoleInChannel(target.closest(".chan"), ["op"]) && + !utils.hasRoleInChannel(target.closest(".chan"), ["op"], target.data("name")), + className: "action-op", + displayName: "Give operator (+o)", + data: (target) => target.data("name"), + callback: op, + }); +} + +function addDeopItem() { + function deop(itemData) { + socket.emit("input", { + target: $("#chat").data("id"), + text: "/deop " + itemData, + }); + } + + addContextMenuItem({ + check: (target) => + utils.hasRoleInChannel(target.closest(".chan"), ["op"]) && + utils.hasRoleInChannel(target.closest(".chan"), ["op"], target.data("name")), + className: "action-op", + displayName: "Revoke operator (-o)", + data: (target) => target.data("name"), + callback: deop, + }); +} + +function addVoiceItem() { + function voice(itemData) { + socket.emit("input", { + target: $("#chat").data("id"), + text: "/voice " + itemData, + }); + } + + addContextMenuItem({ + check: (target) => + utils.hasRoleInChannel(target.closest(".chan"), ["op"]) && + !utils.hasRoleInChannel(target.closest(".chan"), ["voice"], target.data("name")), + className: "action-voice", + displayName: "Give voice (+v)", + data: (target) => target.data("name"), + callback: voice, + }); +} + +function addDevoiceItem() { + function devoice(itemData) { + socket.emit("input", { + target: $("#chat").data("id"), + text: "/devoice " + itemData, + }); + } + + addContextMenuItem({ + check: (target) => + utils.hasRoleInChannel(target.closest(".chan"), ["op"]) && + utils.hasRoleInChannel(target.closest(".chan"), ["voice"], target.data("name")), + className: "action-voice", + displayName: "Revoke voice (-v)", + data: (target) => target.data("name"), + callback: devoice, + }); +} + function addFocusItem() { function focusChan(itemData) { $(`.networks .chan[data-target="${itemData}"]`).click(); @@ -206,6 +282,10 @@ function addDefaultItems() { addWhoisItem(); addQueryItem(); addKickItem(); + addOpItem(); + addDeopItem(); + addVoiceItem(); + addDevoiceItem(); addFocusItem(); addChannelListItem(); addBanListItem(); diff --git a/client/js/utils.js b/client/js/utils.js index 5433247b..7f269ea4 100644 --- a/client/js/utils.js +++ b/client/js/utils.js @@ -42,16 +42,16 @@ function resetHeight(element) { element.style.height = element.style.minHeight; } -// Given a channel element will determine if the lounge user is one of the supplied roles. -function hasRoleInChannel(channel, roles) { +// Given a channel element will determine if the lounge user or a given nick is one of the supplied roles. +function hasRoleInChannel(channel, roles, nick) { if (!channel || !roles) { return false; } const channelID = channel.data("id"); const network = $("#sidebar .network").has(`.chan[data-id="${channelID}"]`); - const ownNick = network.data("nick"); - const user = channel.find(`.names-original .user[data-name="${escape(ownNick)}"]`).first(); + const target = nick || network.data("nick"); + const user = channel.find(`.names-original .user[data-name="${escape(target)}"]`).first(); return user.parent().is("." + roles.join(", .")); }