diff --git a/client/components/Chat.vue b/client/components/Chat.vue index 14a05108..7920bf08 100644 --- a/client/components/Chat.vue +++ b/client/components/Chat.vue @@ -134,25 +134,19 @@ export default { }, }, watch: { - channel(_, previousChannel) { - this.channelChanged(previousChannel); + channel() { + this.channelChanged(); }, }, mounted() { this.channelChanged(); }, methods: { - channelChanged(previousChannel) { + channelChanged() { // Triggered when active channel is set or changed - - if (previousChannel) { - this.$root.switchOutOfChannel(previousChannel); - } - this.channel.highlight = 0; this.channel.unread = 0; - this.$store.commit("activeWindow", null); socket.emit("open", this.channel.id); if (this.channel.usersOutdated) { diff --git a/client/components/RoutedChat.vue b/client/components/RoutedChat.vue index 3186469f..b84a2e89 100644 --- a/client/components/RoutedChat.vue +++ b/client/components/RoutedChat.vue @@ -13,8 +13,8 @@ export default { }, computed: { activeChannel() { - const chan_id = parseInt(this.$route.params.pathMatch); - const channel = this.$store.getters.findChannel(chan_id); + const chanId = parseInt(this.$route.params.id, 10); + const channel = this.$store.getters.findChannel(chanId); return channel; }, }, diff --git a/client/components/Sidebar.vue b/client/components/Sidebar.vue index 55ef7343..9c70835d 100644 --- a/client/components/Sidebar.vue +++ b/client/components/Sidebar.vue @@ -22,12 +22,10 @@ tag="button" active-class="active" :class="['icon', 'sign-in']" - data-target="#sign-in" - data-component="SignIn" aria-label="Sign in" role="tab" aria-controls="sign-in" - :aria-selected="$store.state.activeWindow === 'SignIn'" + :aria-selected="$route.name === 'SignIn'" /> diff --git a/client/js/commands/join.js b/client/js/commands/join.js index fd50e717..acd3c4d8 100644 --- a/client/js/commands/join.js +++ b/client/js/commands/join.js @@ -2,10 +2,9 @@ const socket = require("../socket"); const store = require("../store").default; +const {switchToChannel} = require("../router"); exports.input = function(args) { - const {vueApp} = require("../vue"); - if (args.length > 0) { let channels = args[0]; @@ -26,7 +25,7 @@ exports.input = function(args) { const chan = store.getters.findChannelOnCurrentNetwork(channels); if (chan) { - vueApp.switchToChannel(chan); + switchToChannel(chan); } else { socket.emit("input", { text: `/join ${channels} ${args.length > 1 ? args[1] : ""}`, diff --git a/client/js/contextMenuFactory.js b/client/js/contextMenuFactory.js index c05e9970..3a199935 100644 --- a/client/js/contextMenuFactory.js +++ b/client/js/contextMenuFactory.js @@ -7,6 +7,7 @@ const ContextMenu = require("./contextMenu"); const contextMenuActions = []; const contextMenuItems = []; const {vueApp} = require("./vue"); +const {switchToChannel, navigate} = require("./router"); const store = require("./store").default; addDefaultItems(); @@ -51,7 +52,7 @@ function addWhoisItem() { const chan = store.getters.findChannelOnCurrentNetwork(itemData); if (chan) { - vueApp.switchToChannel(chan); + switchToChannel(chan); } socket.emit("input", { @@ -86,7 +87,7 @@ function addQueryItem() { const chan = store.getters.findChannelOnCurrentNetwork(itemData); if (chan) { - vueApp.switchToChannel(chan); + switchToChannel(chan); } socket.emit("input", { @@ -292,7 +293,7 @@ function addFocusItem() { function addEditNetworkItem() { function edit(networkUuid) { - vueApp.$router.push("/edit-network/" + networkUuid); + navigate("NetworkEdit", {uuid: networkUuid}); } addContextMenuItem({ diff --git a/client/js/keybinds.js b/client/js/keybinds.js index da01c839..78b8b0b6 100644 --- a/client/js/keybinds.js +++ b/client/js/keybinds.js @@ -2,8 +2,8 @@ const $ = require("jquery"); const Mousetrap = require("mousetrap"); -const {vueApp} = require("./vue"); const store = require("./store").default; +const {switchToChannel} = require("./router"); // Switch to the next/previous window in the channel list. Mousetrap.bind(["alt+up", "alt+down"], function(e, keys) { @@ -92,7 +92,7 @@ Mousetrap.bind(["alt+a"], function() { } if (targetchan) { - vueApp.switchToChannel(targetchan); + switchToChannel(targetchan); } return false; diff --git a/client/js/router.js b/client/js/router.js index 2ee8d370..d83f9597 100644 --- a/client/js/router.js +++ b/client/js/router.js @@ -36,14 +36,13 @@ const router = new VueRouter({ router.beforeEach((to, from, next) => { // Disallow navigating to non-existing routes - if (store.state.appLoaded && !to.matched.length) { next(false); return; } // Disallow navigating to invalid channels - if (to.name === "RoutedChat" && !store.getters.findChannel(Number(to.params.pathMatch))) { + if (to.name === "RoutedChat" && !store.getters.findChannel(Number(to.params.id))) { next(false); return; } @@ -65,22 +64,26 @@ router.beforeEach((to, from, next) => { next(); }); -router.afterEach((to) => { +router.afterEach(() => { if (store.state.appLoaded) { if (window.innerWidth <= constants.mobileViewportPixels) { store.commit("sidebarOpen", false); } } - if (to.name !== "RoutedChat") { - // Navigating out of a chat window - store.commit("activeWindow", to.name); + if (store.state.activeChannel) { + const channel = store.state.activeChannel.channel; + store.commit("activeChannel", null); - if (store.state.activeChannel && store.state.activeChannel.channel) { - router.app.switchOutOfChannel(store.state.activeChannel.channel); + // When switching out of a channel, mark everything as read + if (channel.messages.length > 0) { + channel.firstUnread = channel.messages[channel.messages.length - 1].id; } - store.commit("activeChannel", null); + if (channel.messages.length > 100) { + channel.messages.splice(0, channel.messages.length - 100); + channel.moreHistoryAvailable = true; + } } }); @@ -114,13 +117,19 @@ function initialize() { }, { name: "RoutedChat", - path: "/chan-*", + path: "/chan-:id", component: RoutedChat, }, ]); } +function navigate(routeName, params = {}) { + router.push({name: routeName, params}).catch(() => {}); +} + module.exports = { initialize, router, + navigate, + switchToChannel: (channel) => navigate("RoutedChat", {id: channel.id}), }; diff --git a/client/js/socket-events/auth.js b/client/js/socket-events/auth.js index 57a06ac1..a3791864 100644 --- a/client/js/socket-events/auth.js +++ b/client/js/socket-events/auth.js @@ -3,6 +3,7 @@ const socket = require("../socket"); const storage = require("../localStorage"); const {vueApp} = require("../vue"); +const {navigate} = require("../router"); const store = require("../store").default; let lastServerHash = null; @@ -76,7 +77,7 @@ function showSignIn() { } if (vueApp.$route.name !== "SignIn") { - vueApp.$router.push("/sign-in"); + navigate("SignIn"); } } diff --git a/client/js/socket-events/init.js b/client/js/socket-events/init.js index 5bc226c1..727c88a2 100644 --- a/client/js/socket-events/init.js +++ b/client/js/socket-events/init.js @@ -5,6 +5,7 @@ const webpush = require("../webpush"); const storage = require("../localStorage"); const constants = require("../constants"); const {vueApp, initChannel} = require("../vue"); +const {switchToChannel, navigate} = require("../router"); const router = require("../router"); const store = require("../store").default; @@ -49,13 +50,13 @@ socket.on("init", function(data) { const channel = store.getters.findChannel(data.active); if (channel) { - vueApp.switchToChannel(channel.channel); + switchToChannel(channel.channel); } else if (store.state.networks.length > 0) { // Server is telling us to open a channel that does not exist // For example, it can be unset if you first open the page after server start - vueApp.switchToChannel(store.state.networks[0].channels[0]); + switchToChannel(store.state.networks[0].channels[0]); } else { - vueApp.$router.push("/connect"); + navigate("Connect"); } } } diff --git a/client/js/socket-events/join.js b/client/js/socket-events/join.js index 52c296e0..619395d3 100644 --- a/client/js/socket-events/join.js +++ b/client/js/socket-events/join.js @@ -1,8 +1,9 @@ "use strict"; const socket = require("../socket"); -const {vueApp, initChannel} = require("../vue"); +const {initChannel} = require("../vue"); const store = require("../store").default; +const {switchToChannel} = require("../router"); socket.on("join", function(data) { initChannel(data.chan); @@ -20,5 +21,5 @@ socket.on("join", function(data) { return; } - vueApp.switchToChannel(store.getters.findChannel(data.chan.id).channel); + switchToChannel(store.getters.findChannel(data.chan.id).channel); }); diff --git a/client/js/socket-events/msg.js b/client/js/socket-events/msg.js index 718409fc..82c9e186 100644 --- a/client/js/socket-events/msg.js +++ b/client/js/socket-events/msg.js @@ -3,8 +3,8 @@ const socket = require("../socket"); const cleanIrcMessage = require("../helpers/ircmessageparser/cleanIrcMessage"); const webpush = require("../webpush"); -const {vueApp} = require("../vue"); const store = require("../store").default; +const {switchToChannel} = require("../router"); let pop; @@ -154,7 +154,7 @@ function notifyMessage(targetId, channel, activeChannel, msg) { const channelTarget = store.getters.findChannel(targetId); if (channelTarget) { - vueApp.switchToChannel(channelTarget); + switchToChannel(channelTarget); } }); } diff --git a/client/js/socket-events/msg_special.js b/client/js/socket-events/msg_special.js index fe8d1e88..3491988e 100644 --- a/client/js/socket-events/msg_special.js +++ b/client/js/socket-events/msg_special.js @@ -1,11 +1,11 @@ "use strict"; const socket = require("../socket"); -const {vueApp} = require("../vue"); const store = require("../store").default; +const {switchToChannel} = require("../router"); socket.on("msg:special", function(data) { const channel = store.getters.findChannel(data.chan); channel.channel.data = data.data; - vueApp.switchToChannel(channel.channel); + switchToChannel(channel.channel); }); diff --git a/client/js/socket-events/network.js b/client/js/socket-events/network.js index b89ba80c..bd7e93dd 100644 --- a/client/js/socket-events/network.js +++ b/client/js/socket-events/network.js @@ -3,6 +3,7 @@ const socket = require("../socket"); const {vueApp, initChannel} = require("../vue"); const store = require("../store").default; +const {switchToChannel} = require("../router"); socket.on("network", function(data) { const network = data.networks[0]; @@ -12,7 +13,7 @@ socket.on("network", function(data) { network.channels.forEach(initChannel); store.commit("networks", [...store.state.networks, network]); - vueApp.switchToChannel(network.channels[0]); + switchToChannel(network.channels[0]); }); socket.on("network:options", function(data) { diff --git a/client/js/socket-events/part.js b/client/js/socket-events/part.js index 716d97ca..fca18277 100644 --- a/client/js/socket-events/part.js +++ b/client/js/socket-events/part.js @@ -1,13 +1,13 @@ "use strict"; const socket = require("../socket"); -const {vueApp} = require("../vue"); const store = require("../store").default; +const {switchToChannel} = require("../router"); socket.on("part", function(data) { // When parting from the active channel/query, jump to the network's lobby if (store.state.activeChannel && store.state.activeChannel.channel.id === data.chan) { - vueApp.switchToChannel(store.state.activeChannel.network.channels[0]); + switchToChannel(store.state.activeChannel.network.channels[0]); } const channel = store.getters.findChannel(data.chan); diff --git a/client/js/socket-events/quit.js b/client/js/socket-events/quit.js index 8b6add37..74cbd075 100644 --- a/client/js/socket-events/quit.js +++ b/client/js/socket-events/quit.js @@ -1,7 +1,7 @@ "use strict"; const socket = require("../socket"); -const {vueApp} = require("../vue"); +const {switchToChannel, navigate} = require("../router"); const store = require("../store").default; socket.on("quit", function(data) { @@ -17,8 +17,8 @@ socket.on("quit", function(data) { } if (store.state.networks.length > 0) { - vueApp.switchToChannel(store.state.networks[0].channels[0]); + switchToChannel(store.state.networks[0].channels[0]); } else { - vueApp.$router.push("/connect"); + navigate("Connect"); } }); diff --git a/client/js/store.js b/client/js/store.js index bfec9f2a..a91eff14 100644 --- a/client/js/store.js +++ b/client/js/store.js @@ -26,7 +26,6 @@ const store = new Vuex.Store({ isAutoCompleting: false, isConnected: false, isFileUploadEnabled: false, - activeWindow: null, networks: [], pushNotificationState: "unsupported", serverConfiguration: {}, @@ -60,9 +59,6 @@ const store = new Vuex.Store({ isFileUploadEnabled(state, isFileUploadEnabled) { state.isFileUploadEnabled = isFileUploadEnabled; }, - activeWindow(state, payload) { - state.activeWindow = payload; - }, networks(state, networks) { state.networks = networks; }, diff --git a/client/js/vue.js b/client/js/vue.js index c5004b69..ed124f97 100644 --- a/client/js/vue.js +++ b/client/js/vue.js @@ -6,7 +6,7 @@ const store = require("./store").default; const App = require("../components/App.vue").default; const localetime = require("./helpers/localetime"); const storage = require("./localStorage"); -const {router} = require("./router"); +const {router, navigate} = require("./router"); const constants = require("./constants"); Vue.filter("localetime", localetime); @@ -35,25 +35,7 @@ const vueApp = new Vue({ }, methods: { switchToChannel(channel) { - if ( - this.$store.state.activeChannel && - this.$store.state.activeChannel.channel.id === channel.id - ) { - return; - } - - this.$router.push("/chan-" + channel.id); - }, - switchOutOfChannel(channel) { - // When switching out of a channel, mark everything as read - if (channel.messages.length > 0) { - channel.firstUnread = channel.messages[channel.messages.length - 1].id; - } - - if (channel.messages.length > 100) { - channel.messages.splice(0, channel.messages.length - 100); - channel.moreHistoryAvailable = true; - } + navigate("RoutedChat", {id: channel.id}); }, }, render(createElement) { diff --git a/client/js/webpush.js b/client/js/webpush.js index 8115f0e7..de3916ec 100644 --- a/client/js/webpush.js +++ b/client/js/webpush.js @@ -2,8 +2,8 @@ const storage = require("./localStorage"); const socket = require("./socket"); -const vueApp = require("./vue"); const store = require("./store").default; +const {switchToChannel} = require("./router"); let clientSubscribed = null; let applicationServerKey; @@ -15,7 +15,7 @@ if ("serviceWorker" in navigator) { const channelTarget = store.getters.findChannel(id); if (channelTarget) { - vueApp.switchToChannel(channelTarget); + switchToChannel(channelTarget); } } });