Skip to content

Commit

Permalink
fix: cache image of favicon
Browse files Browse the repository at this point in the history
  • Loading branch information
jaulz committed Jun 14, 2020
1 parent f8c1a71 commit d5aafc4
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 38 deletions.
15 changes: 13 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
href="./assets/favicon-16x16.png"
/>
<link rel="icon" href="./assets/favicon.ico" />

<title>badgin Demo</title>
<!-- Renew at https://developers.chrome.com/origintrials/#/trials/my latest by 16 Sep 2020 -->
<meta
Expand All @@ -26,7 +27,7 @@
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"
/>
<script src="/build/index.iife.js"></script>

<style>
@media (display-mode: standalone) {
#requiresStandalone {
Expand Down Expand Up @@ -168,6 +169,8 @@ <h1 class="title">Value</h1>
</style>

<script>
const isLocalhost =
location.hostname === 'localhost' || location.hostname === '127.0.0.1'
let value = 0
const options = {
favicon: {},
Expand Down Expand Up @@ -218,11 +221,19 @@ <h1 class="title">Value</h1>
})

// Add service worker
if ('serviceWorker' in navigator) {
if (!isLocalhost && 'serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js').then(() => {
console.log('Service Worker Registered')
})
}

// Load script
const script = document.createElement('script')
script.src = isLocalhost
? '/build/index.iife.js'
: 'https://unpkg.com/badgin/build/index.iife.js'

document.head.appendChild(script)
</script>
</body>
</html>
115 changes: 79 additions & 36 deletions src/favicon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,23 @@ export const defaultOptions: Options = {

// References to the favicons that we need to track in order to reset and update the counters
const current: {
canvas: HTMLCanvasElement | null
context: CanvasRenderingContext2D | null
favicons: Favicon[] | null
bestFavicon: BestFavicon
bestFaviconImage: HTMLImageElement | null
value: Value
options: Options
} = {
canvas: null,
context: null,
favicons: null,
bestFavicon: null,
bestFaviconImage: null,
value: 0,
options: defaultOptions,
}

// Setup the source canvas element which we use to generate the favicon's data-url's from
let canvas: HTMLCanvasElement | null = null
let context: CanvasRenderingContext2D | null = null

// Update favicon
const setFavicon = (url: string) => {
if (!url) {
Expand All @@ -138,33 +140,36 @@ const setFavicon = (url: string) => {
}

// Draw the favicon
const drawFavicon = (value: Value, options: Options) => {
const image = document.createElement('img')
image.onload = () => {
if (!canvas) {
return
}

// Draw image in canvas
context!.clearRect(0, 0, size, size)
context!.drawImage(image, 0, 0, image.width, image.height, 0, 0, size, size)

// Draw bubble over the top
drawBubble(context!, value, options)

// Refresh tag in page
setFavicon(canvas.toDataURL())
const drawFavicon = (
image: HTMLImageElement,
value: Value,
options: Options
) => {
if (!current.canvas || !current.context) {
return
}

// Load image of best favicon so we can manipulate it
if (current.bestFavicon) {
// Allow cross origin resource requests if the image is not a data:uri
if (!current.bestFavicon.href.match(/^data/)) {
image.crossOrigin = 'anonymous'
}

image.src = current.bestFavicon.href
}
// Clear old canvas
current.context.clearRect(0, 0, size, size)

// Draw new image
current.context.drawImage(
image,
0,
0,
image.width,
image.height,
0,
0,
size,
size
)

// Draw bubble on the top
drawBubble(current.context, value, options)

// Refresh tag in page
setFavicon(current.canvas.toDataURL())
}

// Draws the bubble on the canvas
Expand Down Expand Up @@ -232,14 +237,16 @@ const drawBubble = (
}

export function isAvailable() {
if (!context) {
canvas = document.createElement('canvas')
if (!current.context) {
const canvas = document.createElement('canvas')
canvas.width = size
canvas.height = size
context = canvas.getContext ? canvas.getContext('2d') : null

current.canvas = canvas
current.context = canvas.getContext ? canvas.getContext('2d') : null
}

return !!context && !!getBestFavicon()
return !!current.context && !!getBestFavicon()
}

export function set(value: Value, options?: Partial<Options>) {
Expand All @@ -252,11 +259,47 @@ export function set(value: Value, options?: Partial<Options>) {
}

// Remember favicons
current.bestFavicon = current.bestFavicon || getBestFavicon()
current.favicons = current.favicons || getFavicons()
if (!current.bestFavicon) {
const bestFavicon = getBestFavicon()

if (bestFavicon) {
const bestFaviconImage = document.createElement('img')
bestFaviconImage.width = size
bestFaviconImage.height = size

// Allow cross origin resource requests if the image is not a data:uri
if (!bestFavicon.href.match(/^data/)) {
bestFaviconImage.crossOrigin = 'anonymous'
}

// Load image
bestFaviconImage.src = bestFavicon.href

// Store for next time
current.bestFavicon = bestFavicon
current.bestFaviconImage = bestFaviconImage
}
}
if (!current.favicons) {
current.favicons = getFavicons()
}

// Draw icon
drawFavicon(current.value, current.options)
if (!current.bestFaviconImage) {
return false
}

// If we have the image, we can draw immediately
if (current.bestFaviconImage.complete) {
drawFavicon(current.bestFaviconImage, current.value, current.options)
return true
}

// Otherwise we will wait for the load event
current.bestFaviconImage.addEventListener('load', function() {
drawFavicon(this, current.value, current.options)
})

return true
}

Expand Down

0 comments on commit d5aafc4

Please sign in to comment.