Skip to content

Commit 39a3fae

Browse files
authored
Merge pull request #20 from jaulz/fix/cache-image
fix: cache image
2 parents 03cfc2d + a2721b2 commit 39a3fae

File tree

2 files changed

+93
-38
lines changed

2 files changed

+93
-38
lines changed

index.html

+13-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
href="./assets/favicon-16x16.png"
1515
/>
1616
<link rel="icon" href="./assets/favicon.ico" />
17+
1718
<title>badgin Demo</title>
1819
<!-- Renew at https://developers.chrome.com/origintrials/#/trials/my latest by 16 Sep 2020 -->
1920
<meta
@@ -26,7 +27,7 @@
2627
rel="stylesheet"
2728
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"
2829
/>
29-
<script src="/build/index.iife.js"></script>
30+
3031
<style>
3132
@media (display-mode: standalone) {
3233
#requiresStandalone {
@@ -168,6 +169,8 @@ <h1 class="title">Value</h1>
168169
</style>
169170

170171
<script>
172+
const isLocalhost =
173+
location.hostname === 'localhost' || location.hostname === '127.0.0.1'
171174
let value = 0
172175
const options = {
173176
favicon: {},
@@ -218,11 +221,19 @@ <h1 class="title">Value</h1>
218221
})
219222

220223
// Add service worker
221-
if ('serviceWorker' in navigator) {
224+
if (!isLocalhost && 'serviceWorker' in navigator) {
222225
navigator.serviceWorker.register('./sw.js').then(() => {
223226
console.log('Service Worker Registered')
224227
})
225228
}
229+
230+
// Load script
231+
const script = document.createElement('script')
232+
script.src = isLocalhost
233+
? '/build/index.iife.js'
234+
: 'https://unpkg.com/badgin/build/index.iife.js'
235+
236+
document.head.appendChild(script)
226237
</script>
227238
</body>
228239
</html>

src/favicon.ts

+80-36
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,23 @@ export const defaultOptions: Options = {
9999

100100
// References to the favicons that we need to track in order to reset and update the counters
101101
const current: {
102+
canvas: HTMLCanvasElement | null
103+
context: CanvasRenderingContext2D | null
102104
favicons: Favicon[] | null
103105
bestFavicon: BestFavicon
106+
bestFaviconImage: HTMLImageElement | null
104107
value: Value
105108
options: Options
106109
} = {
110+
canvas: null,
111+
context: null,
107112
favicons: null,
108113
bestFavicon: null,
114+
bestFaviconImage: null,
109115
value: 0,
110116
options: defaultOptions,
111117
}
112118

113-
// Setup the source canvas element which we use to generate the favicon's data-url's from
114-
let canvas: HTMLCanvasElement | null = null
115-
let context: CanvasRenderingContext2D | null = null
116-
117119
// Update favicon
118120
const setFavicon = (url: string) => {
119121
if (!url) {
@@ -138,33 +140,36 @@ const setFavicon = (url: string) => {
138140
}
139141

140142
// Draw the favicon
141-
const drawFavicon = (value: Value, options: Options) => {
142-
const image = document.createElement('img')
143-
image.onload = () => {
144-
if (!canvas) {
145-
return
146-
}
147-
148-
// Draw image in canvas
149-
context!.clearRect(0, 0, size, size)
150-
context!.drawImage(image, 0, 0, image.width, image.height, 0, 0, size, size)
151-
152-
// Draw bubble over the top
153-
drawBubble(context!, value, options)
154-
155-
// Refresh tag in page
156-
setFavicon(canvas.toDataURL())
143+
const drawFavicon = (
144+
image: HTMLImageElement,
145+
value: Value,
146+
options: Options
147+
) => {
148+
if (!current.canvas || !current.context) {
149+
return
157150
}
158151

159-
// Load image of best favicon so we can manipulate it
160-
if (current.bestFavicon) {
161-
// Allow cross origin resource requests if the image is not a data:uri
162-
if (!current.bestFavicon.href.match(/^data/)) {
163-
image.crossOrigin = 'anonymous'
164-
}
165-
166-
image.src = current.bestFavicon.href
167-
}
152+
// Clear old canvas
153+
current.context.clearRect(0, 0, size, size)
154+
155+
// Draw new image
156+
current.context.drawImage(
157+
image,
158+
0,
159+
0,
160+
image.width,
161+
image.height,
162+
0,
163+
0,
164+
size,
165+
size
166+
)
167+
168+
// Draw bubble on the top
169+
drawBubble(current.context, value, options)
170+
171+
// Refresh tag in page
172+
setFavicon(current.canvas.toDataURL())
168173
}
169174

170175
// Draws the bubble on the canvas
@@ -232,14 +237,16 @@ const drawBubble = (
232237
}
233238

234239
export function isAvailable() {
235-
if (!context) {
236-
canvas = document.createElement('canvas')
240+
if (!current.context) {
241+
const canvas = document.createElement('canvas')
237242
canvas.width = size
238243
canvas.height = size
239-
context = canvas.getContext ? canvas.getContext('2d') : null
244+
245+
current.canvas = canvas
246+
current.context = canvas.getContext ? canvas.getContext('2d') : null
240247
}
241248

242-
return !!context && !!getBestFavicon()
249+
return !!current.context && !!getBestFavicon()
243250
}
244251

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

254261
// Remember favicons
255-
current.bestFavicon = current.bestFavicon || getBestFavicon()
256-
current.favicons = current.favicons || getFavicons()
262+
if (!current.bestFavicon) {
263+
const bestFavicon = getBestFavicon()
264+
265+
if (bestFavicon) {
266+
const bestFaviconImage = document.createElement('img')
267+
bestFaviconImage.width = size
268+
bestFaviconImage.height = size
269+
270+
// Allow cross origin resource requests if the image is not a data:uri
271+
if (!bestFavicon.href.match(/^data/)) {
272+
bestFaviconImage.crossOrigin = 'anonymous'
273+
}
274+
275+
// Load image
276+
bestFaviconImage.src = bestFavicon.href
277+
278+
// Store for next time
279+
current.bestFavicon = bestFavicon
280+
current.bestFaviconImage = bestFaviconImage
281+
}
282+
}
283+
if (!current.favicons) {
284+
current.favicons = getFavicons()
285+
}
257286

258287
// Draw icon
259-
drawFavicon(current.value, current.options)
288+
if (!current.bestFaviconImage) {
289+
return false
290+
}
291+
292+
// If we have the image, we can draw immediately
293+
if (current.bestFaviconImage.complete) {
294+
drawFavicon(current.bestFaviconImage, current.value, current.options)
295+
return true
296+
}
297+
298+
// Otherwise we will wait for the load event
299+
current.bestFaviconImage.addEventListener('load', function() {
300+
drawFavicon(this, current.value, current.options)
301+
})
302+
260303
return true
261304
}
262305

@@ -279,5 +322,6 @@ export function clear() {
279322
}
280323
current.favicons = null
281324
current.bestFavicon = null
325+
current.bestFaviconImage = null
282326
}
283327
}

0 commit comments

Comments
 (0)