From 2a6c57abaab623aedf45728626f3511723410c20 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sat, 23 Nov 2019 16:26:20 +0200 Subject: [PATCH] Fix context menu generation --- client/components/App.vue | 22 -------- client/components/ChannelWrapper.vue | 8 +-- client/components/Chat.vue | 8 +-- client/components/ChatUserList.vue | 8 --- client/components/ContextMenu.vue | 22 ++++++++ client/components/Message.vue | 17 ++---- client/components/ParsedMessage.vue | 3 +- client/components/Username.vue | 14 ++--- client/components/UsernameFiltered.vue | 19 +++---- client/css/style.css | 1 + client/js/helpers/contextMenu.js | 72 ++++++++++++-------------- client/js/helpers/parse.js | 25 ++++----- test/client/js/helpers/parse.js | 2 +- 13 files changed, 97 insertions(+), 124 deletions(-) diff --git a/client/components/App.vue b/client/components/App.vue index b788a86e..09841cde 100644 --- a/client/components/App.vue +++ b/client/components/App.vue @@ -15,7 +15,6 @@ import throttle from "lodash/throttle"; import constants from "../js/constants"; import storage from "../js/localStorage"; -import {generateUserContextMenu} from "../js/helpers/contextMenu"; import Sidebar from "./Sidebar.vue"; import ImageViewer from "./ImageViewer.vue"; @@ -89,27 +88,6 @@ export default { this.$store.commit("userlistOpen", isUserlistOpen === "true"); }, - openContextMenu(event, items) { - // TODO: maybe move this method to the store or some other more accessible place - this.$refs.contextMenu.open(event, items); - }, - openContextMenuForMentionedNick(event, network, nick) { - // TODO: Find a better way to do this - - const channel = this.$store.state.activeChannel.channel; - let user = channel.users.find((u) => u.nick === nick); - - if (!user) { - user = { - nick: nick, - mode: "", - }; - } - - const items = generateUserContextMenu(this.$root, channel, network, user); - - this.openContextMenu(event, items); - }, }, }; diff --git a/client/components/ChannelWrapper.vue b/client/components/ChannelWrapper.vue index c7d1ffd4..83a53201 100644 --- a/client/components/ChannelWrapper.vue +++ b/client/components/ChannelWrapper.vue @@ -25,7 +25,6 @@ diff --git a/client/components/ContextMenu.vue b/client/components/ContextMenu.vue index ff2cd94c..fd07da25 100644 --- a/client/components/ContextMenu.vue +++ b/client/components/ContextMenu.vue @@ -35,6 +35,7 @@ diff --git a/client/components/ParsedMessage.vue b/client/components/ParsedMessage.vue index 52538a9a..842cbb34 100644 --- a/client/components/ParsedMessage.vue +++ b/client/components/ParsedMessage.vue @@ -16,8 +16,7 @@ export default { ? context.props.text : context.props.message.text, context.props.message, - context.props.network, - context.parent.$root + context.props.network ); }, }; diff --git a/client/components/Username.vue b/client/components/Username.vue index 64444f21..8e3a255a 100644 --- a/client/components/Username.vue +++ b/client/components/Username.vue @@ -4,8 +4,8 @@ :data-name="user.nick" role="button" v-on="onHover ? {mouseover: hover} : {}" - @click.prevent="rightClick($event)" - @contextmenu.prevent="rightClick($event)" + @click.prevent="openContextMenu" + @contextmenu.prevent="openContextMenu" >{{ user.mode }}{{ user.nick }} @@ -19,7 +19,6 @@ export default { user: Object, active: Boolean, onHover: Function, - contextMenuCallback: Function, }, computed: { nickColor() { @@ -30,10 +29,11 @@ export default { hover() { return this.onHover(this.user); }, - rightClick($event) { - if (this.contextMenuCallback) { - this.contextMenuCallback($event, this.user); - } + openContextMenu(event) { + this.$root.$emit("contextmenu:user", { + event: event, + user: this.user, + }); }, }, }; diff --git a/client/components/UsernameFiltered.vue b/client/components/UsernameFiltered.vue index 62881a17..d8e68380 100644 --- a/client/components/UsernameFiltered.vue +++ b/client/components/UsernameFiltered.vue @@ -3,9 +3,9 @@ :class="['user', nickColor, {active: active}]" :data-name="user.original.nick" role="button" - @mouseover="hover" - @click.prevent="rightClick($event)" - @contextmenu.prevent="rightClick($event)" + @mouseover="onHover(user.original)" + @click.prevent="openContextMenu" + @contextmenu.prevent="openContextMenu" v-html="user.original.mode + user.string" /> @@ -19,7 +19,6 @@ export default { user: Object, active: Boolean, onHover: Function, - contextMenuCallback: Function, }, computed: { nickColor() { @@ -27,13 +26,11 @@ export default { }, }, methods: { - hover() { - this.onHover ? this.onHover(this.user.original) : null; - }, - rightClick($event) { - if (this.contextMenuCallback) { - this.contextMenuCallback($event, this.user); - } + openContextMenu(event) { + this.$root.$emit("contextmenu:user", { + event: event, + user: this.user.original, + }); }, }, }; diff --git a/client/css/style.css b/client/css/style.css index 86233b5e..2d86edcc 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -2133,6 +2133,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */ line-height: 1.4; transition: background-color 0.2s; border-radius: 3px; + white-space: nowrap; } .context-menu-item.active, diff --git a/client/js/helpers/contextMenu.js b/client/js/helpers/contextMenu.js index ef7cfd2a..334ab25e 100644 --- a/client/js/helpers/contextMenu.js +++ b/client/js/helpers/contextMenu.js @@ -91,52 +91,46 @@ export function generateChannelContextMenu($root, channel, network) { // Add menu items for channels if (channel.type === "channel") { - items = [ - ...items, - { - label: "Edit topic", - type: "item", - class: "edit", - action() { - channel.editTopic = true; - $root.switchToChannel(channel); + items.push({ + label: "Edit topic", + type: "item", + class: "edit", + action() { + channel.editTopic = true; + $root.switchToChannel(channel); - $root.$nextTick(() => - document.querySelector(`#chan-${channel.id} .topic-input`).focus() - ); - }, + $root.$nextTick(() => + document.querySelector(`#chan-${channel.id} .topic-input`).focus() + ); }, - { - label: "List banned users", - type: "item", - class: "list", - action() { - socket.emit("input", { - target: channel.id, - text: "/banlist", - }); - }, + }); + items.push({ + label: "List banned users", + type: "item", + class: "list", + action() { + socket.emit("input", { + target: channel.id, + text: "/banlist", + }); }, - ]; + }); } // Add menu items for queries if (channel.type === "query") { - items = [ - ...items, - { - label: "User information", - type: "item", - class: "action-whois", - action() { - $root.switchToChannel(channel); - socket.emit("input", { - target: $root.$store.state.activeChannel.channel.id, - text: "/whois " + channel.name, - }); - }, + items.push({ + label: "User information", + type: "item", + class: "action-whois", + action() { + $root.switchToChannel(channel); + socket.emit("input", { + target: channel.id, + text: "/whois " + channel.name, + }); }, - ]; + }); } // Add close menu item @@ -159,7 +153,7 @@ export function generateChannelContextMenu($root, channel, network) { } export function generateUserContextMenu($root, channel, network, user) { - const currentChannelUser = channel.users.filter((u) => u.nick === network.nick)[0]; + const currentChannelUser = channel.users.find((u) => u.nick === network.nick) || {}; const whois = () => { const chan = $root.$store.getters.findChannelOnCurrentNetwork(user.nick); diff --git a/client/js/helpers/parse.js b/client/js/helpers/parse.js index f50f0181..61a388a1 100644 --- a/client/js/helpers/parse.js +++ b/client/js/helpers/parse.js @@ -6,11 +6,11 @@ import findLinks from "./ircmessageparser/findLinks"; import findEmoji from "./ircmessageparser/findEmoji"; import findNames from "./ircmessageparser/findNames"; import merge from "./ircmessageparser/merge"; -import colorClass from "./colorClass"; import emojiMap from "./fullnamemap.json"; import LinkPreviewToggle from "../../components/LinkPreviewToggle.vue"; import LinkPreviewFileSize from "../../components/LinkPreviewFileSize.vue"; import InlineChannel from "../../components/InlineChannel.vue"; +import Username from "../../components/Username.vue"; const emojiModifiersRegex = /[\u{1f3fb}-\u{1f3ff}]/gu; @@ -70,7 +70,7 @@ function createFragment(fragment, createElement) { // Transform an IRC message potentially filled with styling control codes, URLs, // nicknames, and channels into a string of HTML elements to display on the client. -function parse(createElement, text, message = undefined, network = undefined, $root) { +function parse(createElement, text, message = undefined, network = undefined) { // Extract the styling information and get the plain text version from it const styleFragments = parseStyle(text); const cleanText = styleFragments.map((fragment) => fragment.text).join(""); @@ -180,23 +180,16 @@ function parse(createElement, text, message = undefined, network = undefined, $r fragments ); } else if (textPart.nick) { - // TODO: This really does not belong here, find a better way - const openContextMenu = (event) => { - $root.$refs.app.openContextMenuForMentionedNick(event, network, textPart.nick); - }; - return createElement( - "span", + Username, { - class: ["user", colorClass(textPart.nick)], - attrs: { - role: "button", - dir: "auto", - "data-name": textPart.nick, + props: { + user: { + nick: textPart.nick, + }, }, - on: { - contextmenu: openContextMenu, - click: openContextMenu, + attrs: { + dir: "auto", }, }, fragments diff --git a/test/client/js/helpers/parse.js b/test/client/js/helpers/parse.js index 6fe009b7..9cdce2b8 100644 --- a/test/client/js/helpers/parse.js +++ b/test/client/js/helpers/parse.js @@ -358,7 +358,7 @@ describe("IRC formatted message parser", () => { input: "test, MaxLeiter", expected: "test, " + - '' + + '' + "MaxLeiter" + "", },