After our recent election, I got elected as a moderator here on Code Review (Thank you, community members!). One of the first things I missed among the moderator tools was desktop notifications for when there were any flags.
As no current tool existed, I figured that I just have to create one...
Following the approach of "Disassemble your problems so you can assemble your solutions" (which I believe that I normally follow whether I am aware of it or not) I figured that I am gonna need the following things:
- Desktop Notifications
- Automatically reload the page (could also possibly work with AJAX requests)
- jQuery
- It should be functional on Stack Exchange
- Load/Save local data
At first I used some advice from SO and a general Stack Exchange userscript template, but later I realized I didn't need those things (and they just prevented me from using some GM_* functions).
The script adds a link on the /review
URL (of any Stack Exchange site) to /review/desktop-notifications
, which technically leads to a 404 page but gets some added information thanks to the user-script.
The /review
link looks like this:
and /review/desktop-notifications
looks like:
A desktop notification looks like the following:
The source code is available as a part of my SE-Scripts GitHub repository. Any feature-requests and pull requests are appreciated.
The code has been tested with Tampermonkey 3.11 for Google Chrome, but I believe it should work with other user-script handlers as well.
Code
// ==UserScript==
// @name Moderator Flag Notification
// @author Simon Forsberg
// @description Shows a desktop notification when there are flags or review items to be handled.
// @namespace https://github.com/Zomis/SE-Scripts
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_notification
// @match *://*.stackexchange.com/review*
// @match *://*.stackoverflow.com/review*
// @match *://*.superuser.com/review*
// @match *://*.serverfault.com/review*
// @match *://*.askubuntu.com/review*
// @match *://*.stackapps.com/review*
// @match *://*.mathoverflow.net/review*
// ==/UserScript==
if (window.location.href.indexOf('/desktop-notifications') === -1) {
$('.tools-rev h1').append('<span class="lsep">|</span><a href="/review/desktop-notifications">Desktop Notifications</a></h1>');
} else {
var KEY_NEXT = 'NextReload';
var DELAY = 60 * 1000;
var currentTime = Date.now ? Date.now() : new Date().getTime();
var lastTime = GM_getValue(KEY_NEXT, 0);
var nextTime = currentTime + DELAY;
GM_setValue(KEY_NEXT, nextTime);
var timeDiff = Math.abs(lastTime - currentTime);
setTimeout(function(){ window.location.reload(); }, DELAY);
$('.subheader h1').html('Desktop Notifications');
$('.leftcol').html('Keep your browser open on this page and it will be automatically reloaded and alert you when something wants your attention.').removeClass('leftcol');
$('.rightcol').remove();
var title = document.title.split(' - '); // keep the site name
document.title = 'Desktop Notifications - ' + title[1];
// a way to detect that the script is being executed because of an automatic script reload, not by the user.
if (timeDiff <= DELAY * 2) {
var notifications = [];
var topbarFlag = $('.topbar-links .mod-only .icon-flag .flag-count').html();
var topbarFlagCount = parseInt(topbarFlag);
if (topbarFlagCount > 0) {
notifications.push(topbarFlagCount + ' Flags');
}
var reviewItems = $('.icon-tools-flag span');
var reviewCount = 0;
if (reviewItems.length > 0) {
reviewCount = parseInt(reviewItems.html());
if (reviewCount > 0) {
notifications.push(reviewCount + ' Review Items');
}
}
if (notifications.length > 0) {
var details = {
title: document.title,
text: notifications.join('\n')
};
GM_notification(details, null);
}
}
}
Primary Concerns
- Is my code readable?
- Am I following best-practices?
- Am I using the GM_* features in a good way?
- Any other comments also appreciated.
Minor update:
With the new Stack Exchange topbar, change a line to this:
var topbarFlag = $('.top-bar .indicator-badge').html();