Skip to content

Instantly share code, notes, and snippets.

@tghw
Last active July 17, 2019 23:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tghw/3ea2ea15b766728de3a649d1bf6b25ce to your computer and use it in GitHub Desktop.
Save tghw/3ea2ea15b766728de3a649d1bf6b25ce to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Fastmail Favicon Unread Count
// @author Tyler Hicks-Wright
// @author Rob Middleton
// @license MIT
// @description Adds a dynamic favicon to fastmail.com showing unread emails.
// @namespace rob@middlerob.com
// @grant none
// @version 2.2.1
// @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() {
console.log('Drawing...');
var text = totalUnread
var highlight = false
ctx.clearRect(0, 0, faviconWidth, faviconWidth)
if (animateFlashesRemaining > 0) {
highlight = animateFlashOn
} else {
highlight = focusedSinceNew;
}
var colors = [
'#00B82E',
'#FFCC33',
'#FFCC33',
'#FFCC33',
'#FFCC33',
'#FFCC33',
'#FF6633',
'#FF6633',
'#FF6633',
'#FF6633',
'#FF6633'
];
if (totalUnread > 10) {
ctx.fillStyle = '#ff2323';
}
else {
ctx.fillStyle = colors[totalUnread];
}
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)
}
var oldLinks = document.querySelectorAll('link[rel="shortcut icon"]');
oldLinks.forEach(function(e) { e.remove(); });
favicon.href = canvas.toDataURL('image/png');
var link = document.createElement('link');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon';
link.href = canvas.toDataURL('image/png');
document.head.appendChild(link);
}
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()
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment