Improve router experience

This commit is contained in:
Pavel Djundik 2019-11-11 21:18:55 +02:00
parent 5a0f1c1f4e
commit f2309c7c89
18 changed files with 60 additions and 84 deletions

View file

@ -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) {

View file

@ -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;
},
},

View file

@ -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'"
/></span>
<span
class="tooltipped tooltipped-n tooltipped-no-touch"
@ -37,12 +35,10 @@
tag="button"
active-class="active"
:class="['icon', 'connect']"
data-target="#connect"
data-component="Connect"
aria-label="Connect to network"
role="tab"
aria-controls="connect"
:aria-selected="$store.state.activeWindow === 'Connect'"
:aria-selected="$route.name === 'Connect'"
/></span>
<span class="tooltipped tooltipped-n tooltipped-no-touch" aria-label="Settings"
><router-link
@ -50,13 +46,10 @@
tag="button"
active-class="active"
:class="['icon', 'settings']"
class="icon settings"
data-target="#settings"
data-component="Settings"
aria-label="Settings"
role="tab"
aria-controls="settings"
:aria-selected="$store.state.activeWindow === 'Settings'"
:aria-selected="$route.name === 'Settings'"
/></span>
<span class="tooltipped tooltipped-n tooltipped-no-touch" aria-label="Help"
><router-link
@ -64,12 +57,10 @@
tag="button"
active-class="active"
:class="['icon', 'help']"
data-target="#help"
data-component="Help"
aria-label="Help"
role="tab"
aria-controls="help"
:aria-selected="$store.state.activeWindow === 'Help'"
:aria-selected="$route.name === 'Help'"
/></span>
</footer>
</aside>

View file

@ -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] : ""}`,

View file

@ -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({

View file

@ -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;

View file

@ -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}),
};

View file

@ -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");
}
}

View file

@ -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");
}
}
}

View file

@ -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);
});

View file

@ -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);
}
});
}

View file

@ -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);
});

View file

@ -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) {

View file

@ -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);

View file

@ -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");
}
});

View file

@ -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;
},

View file

@ -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) {

View file

@ -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);
}
}
});