thelounge/client/js/utils.js

132 lines
3.3 KiB
JavaScript
Raw Normal View History

2017-05-18 20:08:54 +00:00
"use strict";
const $ = require("jquery");
const escape = require("css.escape");
const {vueApp} = require("./vue");
2017-05-18 20:08:54 +00:00
2018-01-11 11:33:36 +00:00
var serverHash = -1; // eslint-disable-line no-var
2017-05-18 20:08:54 +00:00
module.exports = {
// Same value as media query in CSS that forces sidebars to become overlays
mobileViewportPixels: 768,
findCurrentNetworkChan,
serverHash,
2017-05-18 20:08:54 +00:00
confirmExit,
scrollIntoViewNicely,
hasRoleInChannel,
2017-05-18 20:08:54 +00:00
move,
synchronizeNotifiedState,
requestIdleCallback,
2017-05-18 20:08:54 +00:00
};
function findCurrentNetworkChan(name) {
name = name.toLowerCase();
2018-07-09 17:31:48 +00:00
return vueApp.activeChannel.network.channels.find((c) => c.name.toLowerCase() === name);
}
// Given a channel element will determine if the lounge user or a given nick is one of the supplied roles.
function hasRoleInChannel(channel, roles, nick) {
if (!channel || !roles) {
return false;
}
2018-07-19 10:46:30 +00:00
const channelID = channel.attr("data-id");
const network = $("#sidebar .network").has(`.chan[data-id="${channelID}"]`);
const target = nick || network.attr("data-nick");
2019-01-22 14:33:20 +00:00
const user = channel.find(`.names .user[data-name="${escape(target)}"]`).first();
return user.parent().is("." + roles.join(", ."));
}
// Reusable scrollIntoView parameters for channel list / user list
function scrollIntoViewNicely(el) {
// Ideally this would use behavior: "smooth", but that does not consistently work in e.g. Chrome
// https://github.com/iamdustan/smoothscroll/issues/28#issuecomment-364061459
el.scrollIntoView({block: "center", inline: "nearest"});
}
2017-05-18 20:08:54 +00:00
const favicon = $("#favicon");
function synchronizeNotifiedState() {
updateTitle();
let hasAnyHighlights = false;
for (const network of vueApp.networks) {
for (const chan of network.channels) {
if (chan.highlight > 0) {
hasAnyHighlights = true;
break;
}
}
}
toggleNotificationMarkers(hasAnyHighlights);
}
2017-05-18 20:08:54 +00:00
function toggleNotificationMarkers(newState) {
2019-02-27 14:15:34 +00:00
if (vueApp.$store.state.isNotified !== newState) {
// Toggles a dot on the menu icon when there are unread notifications
vueApp.$store.commit("isNotified", newState);
2019-02-27 14:15:34 +00:00
// Toggles the favicon to red when there are unread notifications
2018-01-11 11:33:36 +00:00
const old = favicon.prop("href");
favicon.prop("href", favicon.data("other"));
2017-05-18 20:08:54 +00:00
favicon.data("other", old);
}
}
2018-06-01 17:32:30 +00:00
function updateTitle() {
let title = vueApp.appName;
2018-06-01 17:32:30 +00:00
if (vueApp.activeChannel) {
title = `${vueApp.activeChannel.channel.name}${title}`;
2018-06-01 17:32:30 +00:00
}
// add highlight count to title
let alertEventCount = 0;
for (const network of vueApp.networks) {
for (const channel of network.channels) {
alertEventCount += channel.highlight;
}
}
2018-06-01 17:32:30 +00:00
if (alertEventCount > 0) {
title = `(${alertEventCount}) ${title}`;
}
document.title = title;
}
2017-05-18 20:08:54 +00:00
function confirmExit() {
if ($(document.body).hasClass("public")) {
2017-05-18 20:08:54 +00:00
window.onbeforeunload = function() {
return "Are you sure you want to navigate away from this page?";
};
}
}
function move(array, old_index, new_index) {
if (new_index >= array.length) {
let k = new_index - array.length;
2019-07-17 09:33:59 +00:00
while (k-- + 1) {
2017-05-18 20:08:54 +00:00
this.push(undefined);
}
}
2017-05-18 20:08:54 +00:00
array.splice(new_index, 0, array.splice(old_index, 1)[0]);
return array;
}
function requestIdleCallback(callback, timeout) {
if (window.requestIdleCallback) {
// During an idle period the user agent will run idle callbacks in FIFO order
// until either the idle period ends or there are no more idle callbacks eligible to be run.
window.requestIdleCallback(callback, {timeout});
} else {
callback();
}
}