NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Fastmail Favicon Unread Count // @author Rob Middleton // @license MIT // @description Adds a dynamic favicon to fastmail.com showing unread emails. // @namespace rob@middlerob.com // @grant none // @version 2.1.0 // @include https://www.fastmail.com/mail/* // ==/UserScript== ;(function() { var totalUnread = '?' var pageFocused = false var focusedSinceNew = true var animateFlashesRemaining = 0 var animateFlashOn var favicon = document.querySelector("link[sizes='64x64']") var defaultImage = new Image() defaultImage.onload = draw defaultImage.src = favicon.href var canvas = document.createElement('canvas') var ctx = canvas.getContext('2d') var faviconWidth = 64 canvas.width = faviconWidth canvas.height = faviconWidth function draw() { var text = totalUnread var highlight = false ctx.clearRect(0, 0, faviconWidth, faviconWidth) if (animateFlashesRemaining > 0) { highlight = animateFlashOn } else { highlight = focusedSinceNew } if (highlight) { ctx.drawImage(defaultImage, 0, 0, faviconWidth, faviconWidth) } else { ctx.fillStyle = '#ff2323' ctx.fillRect(0, 0, faviconWidth, faviconWidth) } ctx.font = 'bold ' + faviconWidth * 0.8 + 'px Arial' ctx.fillStyle = 'white' ctx.strokeStyle = 'black' var textWidth = ctx.measureText(text).width var centered = faviconWidth / 2 - textWidth / 2 if (textWidth <= faviconWidth) { ctx.strokeText(text, centered, faviconWidth * 0.8) ctx.fillText(text, centered, faviconWidth * 0.8) } else { ctx.strokeText(text, 0, faviconWidth * 0.8, faviconWidth) ctx.fillText(text, 0, faviconWidth * 0.8, faviconWidth) } favicon.href = canvas.toDataURL('image/png') } setInterval(function() { if (animateFlashesRemaining > 0) { animateFlashOn = !(animateFlashesRemaining % 2) animateFlashesRemaining-- draw() } }, 1000) window.addEventListener('focus', function() { pageFocused = true focusedSinceNew = true animateFlashesRemaining = 0 draw() }) window.addEventListener('blur', function() { pageFocused = false }) function updateTotal() { var el = document.querySelector('.v-MailboxSource--inbox .v-MailboxSource-badge') if (!el) return var unread = parseInt(el.innerHTML, 10) if (unread > parseInt(totalUnread, 10)) { // new unread message if (!pageFocused) { focusedSinceNew = false animateFlashesRemaining = 11 } } else if (unread === 0) { // for when they read all emails elsewhere focusedSinceNew = true animateFlashesRemaining = 0 } totalUnread = unread.toString() draw() } function pollForChanges() { setTimeout(pollForChanges, 1000) updateTotal() } pollForChanges() })()