Create an event bus

This commit is contained in:
Pavel Djundik 2020-03-16 19:58:40 +02:00
parent 96a983b310
commit f0253075d8
15 changed files with 95 additions and 37 deletions

View File

@ -13,6 +13,7 @@
<script>
const constants = require("../js/constants");
import eventbus from "../js/eventbus";
import Mousetrap from "mousetrap";
import throttle from "lodash/throttle";
import storage from "../js/localStorage";
@ -53,14 +54,14 @@ export default {
// Make a single throttled resize listener available to all components
this.debouncedResize = throttle(() => {
this.$root.$emit("resize");
eventbus.emit("resize");
}, 100);
window.addEventListener("resize", this.debouncedResize, {passive: true});
// Emit a daychange event every time the day changes so date markers know when to update themselves
const emitDayChange = () => {
this.$root.$emit("daychange");
eventbus.emit("daychange");
// This should always be 24h later but re-computing exact value just in case
this.dayChangeTimeout = setTimeout(emitDayChange, this.msUntilNextDay());
};
@ -77,7 +78,7 @@ export default {
},
methods: {
escapeKey() {
this.$root.$emit("escapekey");
eventbus.emit("escapekey");
},
toggleSidebar(e) {
if (isIgnoredKeybind(e)) {

View File

@ -30,6 +30,7 @@
</template>
<script>
import eventbus from "../js/eventbus";
import isChannelCollapsed from "../js/helpers/isChannelCollapsed";
export default {
@ -74,7 +75,7 @@ export default {
this.$root.switchToChannel(this.channel);
},
openContextMenu(event) {
this.$root.$emit("contextmenu:channel", {
eventbus.emit("contextmenu:channel", {
event: event,
channel: this.channel,
network: this.network,

View File

@ -102,6 +102,7 @@
<script>
import socket from "../js/socket";
import eventbus from "../js/eventbus";
import ParsedMessage from "./ParsedMessage.vue";
import MessageList from "./MessageList.vue";
import ChatInput from "./ChatInput.vue";
@ -197,14 +198,14 @@ export default {
}
},
openContextMenu(event) {
this.$root.$emit("contextmenu:channel", {
eventbus.emit("contextmenu:channel", {
event: event,
channel: this.channel,
network: this.network,
});
},
openMentions() {
this.$root.$emit("mentions:toggle", {
eventbus.emit("mentions:toggle", {
event: event,
});
},

View File

@ -56,6 +56,7 @@ import autocompletion from "../js/autocompletion";
import commands from "../js/commands/index";
import socket from "../js/socket";
import upload from "../js/upload";
import eventbus from "../js/eventbus";
const formattingHotkeys = {
"mod+k": "\x03",
@ -101,7 +102,7 @@ export default {
},
},
mounted() {
this.$root.$on("escapekey", this.blurInput);
eventbus.on("escapekey", this.blurInput);
if (this.$store.state.settings.autocomplete) {
autocompletionRef = autocompletion(this.$refs.input);
@ -163,7 +164,7 @@ export default {
}
},
destroyed() {
this.$root.$off("escapekey", this.blurInput);
eventbus.off("escapekey", this.blurInput);
if (autocompletionRef) {
autocompletionRef.destroy();

View File

@ -51,6 +51,8 @@
</style>
<script>
import eventbus from "../js/eventbus";
export default {
name: "ConfirmDialog",
data() {
@ -60,12 +62,12 @@ export default {
};
},
mounted() {
this.$root.$on("escapekey", this.close);
this.$root.$on("confirm-dialog", this.open);
eventbus.on("escapekey", this.close);
eventbus.on("confirm-dialog", this.open);
},
destroyed() {
this.$root.$off("escapekey", this.close);
this.$root.$off("confirm-dialog", this.open);
eventbus.off("escapekey", this.close);
eventbus.off("confirm-dialog", this.open);
},
methods: {
open(data, callback) {

View File

@ -39,6 +39,7 @@
<script>
import {generateUserContextMenu, generateChannelContextMenu} from "../js/helpers/contextMenu.js";
import eventbus from "../js/eventbus";
export default {
name: "ContextMenu",
@ -58,14 +59,14 @@ export default {
};
},
mounted() {
this.$root.$on("escapekey", this.close);
this.$root.$on("contextmenu:user", this.openUserContextMenu);
this.$root.$on("contextmenu:channel", this.openChannelContextMenu);
eventbus.on("escapekey", this.close);
eventbus.on("contextmenu:user", this.openUserContextMenu);
eventbus.on("contextmenu:channel", this.openChannelContextMenu);
},
destroyed() {
this.$root.$off("escapekey", this.close);
this.$root.$off("contextmenu:user", this.openUserContextMenu);
this.$root.$off("contextmenu:channel", this.openChannelContextMenu);
eventbus.off("escapekey", this.close);
eventbus.off("contextmenu:user", this.openUserContextMenu);
eventbus.off("contextmenu:channel", this.openChannelContextMenu);
this.close();
},

View File

@ -9,6 +9,7 @@
<script>
import dayjs from "dayjs";
import calendar from "dayjs/plugin/calendar";
import eventbus from "../js/eventbus";
dayjs.extend(calendar);
@ -24,11 +25,11 @@ export default {
},
mounted() {
if (this.hoursPassed() < 48) {
this.$root.$on("daychange", this.dayChange);
eventbus.on("daychange", this.dayChange);
}
},
beforeDestroy() {
this.$root.$off("daychange", this.dayChange);
eventbus.off("daychange", this.dayChange);
},
methods: {
hoursPassed() {
@ -38,7 +39,7 @@ export default {
this.$forceUpdate();
if (this.hoursPassed() >= 48) {
this.$root.$off("daychange", this.dayChange);
eventbus.off("daychange", this.dayChange);
}
},
friendlyDate() {

View File

@ -40,6 +40,7 @@
<script>
import Mousetrap from "mousetrap";
import eventbus from "../js/eventbus";
export default {
name: "ImageViewer",
@ -79,8 +80,8 @@ export default {
link(newLink, oldLink) {
// TODO: history.pushState
if (newLink === null) {
this.$root.$off("escapekey", this.closeViewer);
this.$root.$off("resize", this.correctPosition);
eventbus.off("escapekey", this.closeViewer);
eventbus.off("resize", this.correctPosition);
Mousetrap.unbind("left", this.previous);
Mousetrap.unbind("right", this.next);
return;
@ -89,8 +90,8 @@ export default {
this.setPrevNextImages();
if (!oldLink) {
this.$root.$on("escapekey", this.closeViewer);
this.$root.$on("resize", this.correctPosition);
eventbus.on("escapekey", this.closeViewer);
eventbus.on("resize", this.correctPosition);
Mousetrap.bind("left", this.previous);
Mousetrap.bind("right", this.next);
}

View File

@ -130,6 +130,7 @@
</template>
<script>
import eventbus from "../js/eventbus";
import friendlysize from "../js/helpers/friendlysize";
export default {
@ -167,12 +168,12 @@ export default {
this.updateShownState();
},
mounted() {
this.$root.$on("resize", this.handleResize);
eventbus.on("resize", this.handleResize);
this.onPreviewUpdate();
},
beforeDestroy() {
this.$root.$off("resize", this.handleResize);
eventbus.off("resize", this.handleResize);
},
destroyed() {
// Let this preview go through load/canplay events again,

View File

@ -125,6 +125,7 @@
import Username from "./Username.vue";
import ParsedMessage from "./ParsedMessage.vue";
import socket from "../js/socket";
import eventbus from "../js/eventbus";
import localetime from "../js/helpers/localetime";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
@ -161,10 +162,10 @@ export default {
},
},
mounted() {
this.$root.$on("mentions:toggle", this.openPopup);
eventbus.on("mentions:toggle", this.openPopup);
},
destroyed() {
this.$root.$off("mentions:toggle", this.openPopup);
eventbus.off("mentions:toggle", this.openPopup);
},
methods: {
messageTime(time) {

View File

@ -56,6 +56,7 @@
<script>
const constants = require("../js/constants");
import eventbus from "../js/eventbus";
import clipboard from "../js/clipboard";
import socket from "../js/socket";
import Message from "./Message.vue";
@ -173,7 +174,7 @@ export default {
mounted() {
this.$refs.chat.addEventListener("scroll", this.handleScroll, {passive: true});
this.$root.$on("resize", this.handleResize);
eventbus.on("resize", this.handleResize);
this.$nextTick(() => {
if (this.historyObserver) {
@ -185,7 +186,7 @@ export default {
this.unreadMarkerShown = false;
},
beforeDestroy() {
this.$root.$off("resize", this.handleResize);
eventbus.off("resize", this.handleResize);
this.$refs.chat.removeEventListener("scroll", this.handleScroll);
},
destroyed() {

View File

@ -11,6 +11,7 @@
</template>
<script>
import eventbus from "../js/eventbus";
import colorClass from "../js/helpers/colorClass";
export default {
@ -30,7 +31,7 @@ export default {
return this.onHover(this.user);
},
openContextMenu(event) {
this.$root.$emit("contextmenu:user", {
eventbus.emit("contextmenu:user", {
event: event,
user: this.user,
});

43
client/js/eventbus.js Normal file
View File

@ -0,0 +1,43 @@
const events = new Map();
class EventBus {
/**
* Register an event handler for the given type.
*
* @param {String} type Type of event to listen for.
* @param {Function} handler Function to call in response to given event.
*/
on(type, handler) {
if (events.has(type)) {
events[type].push(handler);
} else {
events[type] = [handler];
}
}
/**
* Remove an event handler for the given type.
*
* @param {String} type Type of event to unregister `handler` from.
* @param {Function} handler Handler function to remove.
*/
off(type, handler) {
if (events.has(type)) {
events[type] = events[type].filter((item) => item !== handler);
}
}
/**
* Invoke all handlers for the given type.
*
* @param {String} type The event type to invoke.
* @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler.
*/
emit(type, evt) {
if (events.has(type)) {
events[type].slice().map((handler) => handler(evt));
}
}
}
export default new EventBus();

View File

@ -1,6 +1,7 @@
"use strict";
import socket from "../socket";
import eventbus from "../eventbus";
export function generateChannelContextMenu($root, channel, network) {
const typeMap = {
@ -135,7 +136,7 @@ export function generateChannelContextMenu($root, channel, network) {
type: "item",
class: "clear-history",
action() {
$root.$emit(
eventbus.emit(
"confirm-dialog",
{
title: "Clear history",

View File

@ -9,6 +9,7 @@ import App from "../components/App.vue";
import storage from "./localStorage";
import {router, navigate} from "./router";
import socket from "./socket";
import eventbus from "./eventbus";
import "./socket-events";
import "./webpush";
@ -18,7 +19,7 @@ const favicon = document.getElementById("favicon");
const faviconNormal = favicon.getAttribute("href");
const faviconAlerted = favicon.dataset.other;
const vueApp = new Vue({
new Vue({
el: "#viewport",
router,
mounted() {
@ -30,7 +31,7 @@ const vueApp = new Vue({
},
closeChannel(channel) {
if (channel.type === "lobby") {
this.$root.$emit(
eventbus.emit(
"confirm-dialog",
{
title: "Remove network",
@ -75,7 +76,7 @@ store.watch(
(sidebarOpen) => {
if (window.innerWidth > constants.mobileViewportPixels) {
storage.set("thelounge.state.sidebar", sidebarOpen);
vueApp.$emit("resize");
eventbus.emit("resize");
}
}
);
@ -84,7 +85,7 @@ store.watch(
(state) => state.userlistOpen,
(userlistOpen) => {
storage.set("thelounge.state.userlist", userlistOpen);
vueApp.$emit("resize");
eventbus.emit("resize");
}
);