1

I use the following code inside a Tampermonkey script.

function scriptMain () {
    setTimeout(function(){
        GM_notification ( {
            title: 'Refresh Business Manager', text: 'Your about to be logged out of staging, click here to refresh your login.', image: 'https://i.stack.imgur.com/geLPT.png',
            onclick: () => {
                console.log ("My notice was clicked.");
                location.reload();
            }
        } );
    }, 5*1000);
    console.log ("Script main code ran.");
}

The code shows a notification whenever a browser tab is open for more than 5 seconds which includes a button to refresh the current browser tab. I wanna use this script to alert me every 20 minutes or so, that one of the logins in the browser is about to auto-logout.

The functionality works as expected, but if I have 5 tabs open from the site where im logged in, I will get 5 notifications when the page is about to run out. I would love to be able to tell from within the Tampermonkey script if this script is already running on another tab, to not execute or to maybe just be able to only show the notification once.

I have been looking into the Tampermonkey documentation for the following Grants:

GM_getTab(callback)
GM_saveTab(tab)
GM_getTabs(callback)

But I dont seem to be able to work out if this functionality would be possible or not.

Can someone help me shine some light on this topic, or perhaps share a solution?

Mikkel Fennefoss
  • 857
  • 1
  • 9
  • 32
  • Maybe you can use local storage to simply save a flag and check if this was set: https://stackoverflow.com/questions/15730216/how-where-to-store-data-in-a-chrome-tampermonkey-script – D B Jun 07 '21 at 07:37

1 Answers1

1

On modern spec-compliant browsers, you can use BroadcastChannel inside the userscript to communicate with other tabs on the same domain. Make the timeout slightly random - add or subtract a few seconds to allow for all the open tabs to coordinate. When sending a notification, also send a message in the BroadcastChannel telling other instances of the userscript to reset their timers as well.

const channel = new BroadcastChannel('logout-notify');

let timeoutId;
function makeTimeout() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(function () {
        GM_notification({
            title: 'Refresh Business Manager', text: 'Your about to be logged out of staging, click here to refresh your login.', image: 'https://i.stack.imgur.com/geLPT.png',
            onclick: () => {
                console.log("My notice was clicked.");
                location.reload();
            }
        });
        channel.postMessage('notified');
    }, 1000 * 60 * 20 + (Math.random() * 10000)); // 20 minutes plus up to 10 seconds
}

// When below runs, another tab created a notification
// reset the timeout for this tab, schedule another one for 20ish minutes from now
channel.onmessage = makeTimeout;

// initialize timeout on pageload?
makeTimeout();

This code will result in alerts being shown only once every 20 minutes at most. If you close one tab you were working on, other tabs will take up the slack without interruption.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • This is exactly the kind of thing I am looking for. Thank you very much. I tried out this script, and the notifications did seem to go a bit nuts at one point, so it might not be working fully, but I might be able to figure out why :D – Mikkel Fennefoss Jun 07 '21 at 08:00
  • Actually the issue was that if I have 10 windows open where the script is being run, and they were all opened at the same time, and I wait for all the random 10 seconds to be over, I will get 10 notifications in a row asking me to refresh every single tab one by one. It would be great to be able to have them all refreshed on first click and not display all 10 notifications in a row. – Mikkel Fennefoss Jun 07 '21 at 08:31
  • Do you have the `clearTimeout` call and the `1000 * 60 * 20 + (Math.random() * 10000)` for the random timeout time? It shouldn't alert more than once in 20 minutes – CertainPerformance Jun 07 '21 at 13:24