Initial attempt at supporting network/channel style URLs

This commit is contained in:
Max Leiter 2021-03-20 16:30:45 -07:00
parent 5329483a40
commit 58ba5a25e0
No known key found for this signature in database
GPG key ID: A3512F2F2F17EBDA
20 changed files with 82 additions and 34 deletions

View file

@ -72,7 +72,7 @@ export default {
return;
}
this.$root.switchToChannel(this.channel);
this.$root.switchToChannel(this.network, this.channel);
},
openContextMenu(event) {
eventbus.emit("contextmenu:channel", {

View file

@ -17,7 +17,7 @@ export default {
const existingChannel = this.$store.getters.findChannelOnCurrentNetwork(this.channel);
if (existingChannel) {
this.$root.switchToChannel(existingChannel);
this.$root.switchToChannel(this.$store.activeChannel.network, existingChannel);
}
socket.emit("input", {

View file

@ -64,7 +64,7 @@ export default {
);
if (existingChannel) {
this.$root.switchToChannel(existingChannel);
this.$root.switchToChannel(this.$store.activeChannel.network, existingChannel);
} else {
const chanTypes = this.network.serverOptions.CHANTYPES;
let channel = this.inputChannel;

View file

@ -355,14 +355,17 @@ export default {
channel = this.results[0].channel;
}
this.activeSearchItem = channel;
this.activeSearchItem = {channel, network};
},
selectResult() {
if (!this.searchText || !this.results.length) {
return;
}
this.$root.switchToChannel(this.activeSearchItem);
this.$root.switchToChannel(
this.activeSearchItem.network,
this.activeSearchItem.channel
);
this.deactivateSearch();
this.scrollToActive();
},

View file

@ -13,8 +13,10 @@ export default {
},
computed: {
activeChannel() {
const chanId = parseInt(this.$route.params.id, 10);
const channel = this.$store.getters.findChannel(chanId);
let channel = this.$store.getters.findChannelByName(
this.$route.params.networkHost,
this.$route.params.channelName
);
return channel;
},
},

View file

@ -15,6 +15,7 @@ export default {
queryParams: Object,
},
data() {
console.log(this.queryParams);
// Merge settings from url params into default settings
const defaults = Object.assign(
{},

View file

@ -43,7 +43,7 @@ export default {
const network = this.$store.getters.findNetwork(data.uuid);
network.name = network.channels[0].name = data.name;
this.$root.switchToChannel(network.channels[0]);
this.$root.switchToChannel(network, network.channels[0]);
},
},
};

View file

@ -98,7 +98,7 @@ export function generateChannelContextMenu($root, channel, network) {
class: "edit",
action() {
channel.editTopic = true;
$root.switchToChannel(channel);
$root.switchToChannel(network, channel);
},
});
items.push({
@ -122,7 +122,7 @@ export function generateChannelContextMenu($root, channel, network) {
type: "item",
class: "action-whois",
action() {
$root.switchToChannel(channel);
$root.switchToChannel(network, channel);
socket.emit("input", {
target: channel.id,
text: "/whois " + channel.name,
@ -191,7 +191,7 @@ export function generateUserContextMenu($root, channel, network, user) {
const chan = $root.$store.getters.findChannelOnCurrentNetwork(user.nick);
if (chan) {
$root.switchToChannel(chan);
$root.switchToChannel(network, chan);
}
socket.emit("input", {
@ -235,7 +235,7 @@ export function generateUserContextMenu($root, channel, network, user) {
const chan = $root.$store.getters.findChannelOnCurrentNetwork(user.nick);
if (chan) {
$root.switchToChannel(chan);
$root.switchToChannel(network, chan);
}
socket.emit("input", {

View file

@ -85,30 +85,32 @@ Mousetrap.bind(["alt+a"], function (e) {
return true;
}
let targetChannel;
let targetNetwork, targetChannel;
outer_loop: for (const network of store.state.networks) {
for (const chan of network.channels) {
if (chan.highlight) {
targetChannel = chan;
targetNetwork = network;
break outer_loop;
}
if (chan.unread && !targetChannel) {
targetChannel = chan;
targetNetwork = network;
}
}
}
if (targetChannel) {
jumpToChannel(targetChannel);
jumpToChannel(targetNetwork, targetChannel);
}
return false;
});
function jumpToChannel(targetChannel) {
switchToChannel(targetChannel);
function jumpToChannel(targetNetwork, targetChannel) {
switchToChannel(targetNetwork, targetChannel);
const element = document.querySelector(
`#sidebar .channel-list-item[aria-controls="#chan-${targetChannel.id}"]`

View file

@ -60,7 +60,7 @@ const router = new VueRouter({
},
{
name: "RoutedChat",
path: "/chan-:id",
path: "/:networkHost/:channelName?",
component: RoutedChat,
},
],
@ -88,8 +88,27 @@ router.beforeEach((to, from, next) => {
return;
}
// Disallow navigating to invalid channels
if (to.name === "RoutedChat" && !store.getters.findChannel(Number(to.params.id))) {
// If trying to navigate to an invalid channel,
// we attempt to either open a connection dialog to the network
// or populate the Join Channel field in the exiting network.
if (
to.name === "RoutedChat" &&
!store.getters.findChannelByName(to.params.networkHost, to.params.channelName)
) {
const existingNetwork = store.state.networks.find(
(network) => network.host === to.params.networkHost
);
if (existingNetwork) {
// Join UI
} else {
// Connect UI
next({
path: "/connect",
query: {...to.query, host: to.params.networkHost, channels: to.params.channelName},
});
return;
}
next(false);
return;
}
@ -154,8 +173,8 @@ function navigate(routeName, params = {}) {
}
}
function switchToChannel(channel) {
return navigate("RoutedChat", {id: channel.id});
function switchToChannel(network, channel) {
return navigate("RoutedChat", {networkHost: network.host, channelName: channel.name});
}
if ("serviceWorker" in navigator) {
@ -164,9 +183,8 @@ if ("serviceWorker" in navigator) {
const id = parseInt(event.data.channel.substr(5), 10); // remove "chan-" prefix
const channelTarget = store.getters.findChannel(id);
if (channelTarget) {
switchToChannel(channelTarget.channel);
switchToChannel(channelTarget.network, channelTarget.channel);
}
}
});

View file

@ -35,11 +35,14 @@ socket.on("init", function (data) {
const channel = store.getters.findChannel(data.active);
if (channel) {
switchToChannel(channel.channel);
switchToChannel(channel.network, 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
switchToChannel(store.state.networks[0].channels[0]);
switchToChannel(
store.state.networks[0],
store.state.networks[0].channels[0]
);
} else {
navigate("Connect");
}

View file

@ -20,5 +20,7 @@ socket.on("join", function (data) {
return;
}
switchToChannel(store.getters.findChannel(data.chan.id).channel);
const channel = store.getters.findChannel(data.chan.id);
switchToChannel(channel.network, channel.channel);
});

View file

@ -158,7 +158,7 @@ function notifyMessage(targetId, channel, activeChannel, msg) {
const channelTarget = store.getters.findChannel(targetId);
if (channelTarget) {
switchToChannel(channelTarget);
switchToChannel(channelTarget.network, channelTarget.channel);
}
});
}

View file

@ -7,5 +7,5 @@ import {switchToChannel} from "../router";
socket.on("msg:special", function (data) {
const channel = store.getters.findChannel(data.chan);
channel.channel.data = data.data;
switchToChannel(channel.channel);
switchToChannel(channel.network, channel.channel);
});

View file

@ -16,7 +16,7 @@ socket.on("network", function (data) {
store.commit("networks", [...store.state.networks, network]);
// Open last channel specified in `join`
switchToChannel(network.channels[network.channels.length - 1]);
switchToChannel(network, network.channels[network.channels.length - 1]);
});
socket.on("network:options", function (data) {

View file

@ -7,7 +7,10 @@ import {switchToChannel} from "../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) {
switchToChannel(store.state.activeChannel.network.channels[0]);
switchToChannel(
store.state.activeChannel.network,
store.state.activeChannel.network.channels[0]
);
}
const channel = store.getters.findChannel(data.chan);

View file

@ -17,7 +17,7 @@ socket.on("quit", function (data) {
}
if (store.state.networks.length > 0) {
switchToChannel(store.state.networks[0].channels[0]);
switchToChannel(store.state.networks[0], store.state.networks[0].channels[0]);
} else {
navigate("Connect");
}

View file

@ -129,6 +129,19 @@ const store = new Vuex.Store({
return null;
},
findChannelByName: (state) => (networkHost, channelName) => {
for (const network of state.networks) {
if (network.host.toLowerCase() === networkHost.toLowerCase()) {
for (const channel of network.channels) {
if (channel.name.toLowerCase() === channelName.toLowerCase()) {
return {network, channel};
}
}
}
}
return null;
},
findNetwork: (state) => (uuid) => {
for (const network of state.networks) {
if (network.uuid === uuid) {

View file

@ -7,7 +7,7 @@ import Vue from "vue";
import store from "./store";
import App from "../components/App.vue";
import storage from "./localStorage";
import {router, navigate} from "./router";
import {router, switchToChannel} from "./router";
import socket from "./socket";
import eventbus from "./eventbus";
@ -26,8 +26,8 @@ new Vue({
socket.open();
},
methods: {
switchToChannel(channel) {
navigate("RoutedChat", {id: channel.id});
switchToChannel(network, channel) {
switchToChannel(network, channel);
},
closeChannel(channel) {
if (channel.type === "lobby") {

View file

@ -19,6 +19,7 @@ const fieldsForClient = {
name: true,
nick: true,
serverOptions: true,
host: true,
};
function Network(attr) {