Bullsquid / Flymer Desktop Notifications

// ==UserScript==
// @name         Flymer Desktop Notifications
// @namespace    https://t.me/bullsquid
// @version      1.1.0
// @description  Shows a notification whenever page title changes, e.g. when you get a new message.
// @author       Andrew Boyko
// @license      MIT
// @match        https://flymer.ru/*
// @grant        none
// @copyright    2018, Andrew Boyko (https://openuserjs.org/users/Bullsquid)
// @updateURL    https://openuserjs.org/meta/Bullsquid/Flymer_Desktop_Notifications.meta.js
// @githubURL    https://github.com/Bullsquid/flymer-desktop-notifications
// ==/UserScript==

const logPrefix = "[Flymer Desktop Notifications]";
const iconUrl = "/apple-touch-icon.png";
const notificationText = "Новое сообщение на flymer.ru";

function requestPermission() {
  Notification.requestPermission().then(function (result) {
    console.log(`${logPrefix} Notification permission status: ${result}`);
  });
}

function spawnNotification(title, body = notificationText, icon = iconUrl) {
  const options = {
    body: body,
    icon: icon
  };
  const n = new Notification(title, options);
  n.onclick = function () {
    parent.focus();
    window.focus(); // just in case
  };
}

let oldTitle = null;

function listenForChanges() {
  // select the target node
  const target = document.querySelector("title");

  // remember old title for detection if it really changed
  oldTitle = target.textContent;

  // create an observer instance
  const observer = new MutationObserver(function (mutations) {
    // We need only first event and only new value of the title
    const title = mutations[0].target.textContent;
    if (title !== oldTitle) {
      oldTitle = title;
      console.log(`${logPrefix} Title change detected: ${title}`);
      if (document.hasFocus()) {
        console.log(`${logPrefix} Tab is active. Skipping sending notification.`);
      } else {
        spawnNotification(title);
      }
    }
  });

  // configuration of the observer:
  const config = {
    characterData: true,
    childList: true,
    subtree: true
  };

  // pass in the target node, as well as the observer options
  observer.observe(target, config);
}

(function () {
  "use strict";
  window.addEventListener("load", function() {
    requestPermission();
    listenForChanges();
  });
})();