@@ -12,6 +12,14 @@ type Favicon = HTMLLinkElement
12
12
13
13
type BestFavicon = Favicon | null
14
14
15
+ export const DefaultValue : Value = 0
16
+
17
+ export const DefaultOptions : Options = {
18
+ backgroundColor : '#424242' ,
19
+ color : '#ffffff' ,
20
+ indicator : '!' ,
21
+ }
22
+
15
23
// Get all favicons of the page
16
24
const getFavicons = ( ) : Favicon [ ] => {
17
25
const links = document . head . getElementsByTagName ( 'link' )
@@ -86,34 +94,34 @@ const getBestFavicon = (): BestFavicon => {
86
94
return bestFavicon
87
95
}
88
96
89
- // Calculate the size of the font and canvas element based on device's ratio
90
- const ratio = Math . ceil ( window . devicePixelRatio ) || 1
91
- const size = 16 * ratio
92
-
93
- // Options
94
- export const defaultOptions : Options = {
95
- backgroundColor : '#424242' ,
96
- color : '#ffffff' ,
97
- indicator : '!' ,
98
- }
99
-
100
97
// References to the favicons that we need to track in order to reset and update the counters
101
98
const current : {
102
- canvas : HTMLCanvasElement | null
103
- context : CanvasRenderingContext2D | null
104
99
favicons : Favicon [ ] | null
105
100
bestFavicon : BestFavicon
106
101
bestFaviconImage : HTMLImageElement | null
107
102
value : Value
108
103
options : Options
109
104
} = {
110
- canvas : null ,
111
- context : null ,
112
105
favicons : null ,
113
106
bestFavicon : null ,
114
107
bestFaviconImage : null ,
115
- value : 0 ,
116
- options : defaultOptions ,
108
+ value : DefaultValue ,
109
+ options : DefaultOptions ,
110
+ }
111
+
112
+ // Get size depending on screen density
113
+ const devicePixelRatioListener = window . matchMedia (
114
+ 'screen and (min-resolution: 2dppx)'
115
+ )
116
+ const getRatio = ( ) => {
117
+ return Math . ceil ( window . devicePixelRatio ) || 1
118
+ }
119
+ const handleRatioChange = ( ) => {
120
+ console . log ( 'handleRatioChange' )
121
+ set ( current . value , current . options )
122
+ }
123
+ const getSize = ( ) => {
124
+ return 16 * getRatio ( )
117
125
}
118
126
119
127
// Update favicon
@@ -145,31 +153,25 @@ const drawFavicon = (
145
153
value : Value ,
146
154
options : Options
147
155
) => {
148
- if ( ! current . canvas || ! current . context ) {
156
+ const size = getSize ( )
157
+ const canvas = document . createElement ( 'canvas' )
158
+ canvas . width = size
159
+ canvas . height = size
160
+ const context = canvas . getContext ( '2d' )
161
+ if ( ! context ) {
149
162
return
150
163
}
151
164
152
- // Clear old canvas
153
- current . context . clearRect ( 0 , 0 , size , size )
154
-
155
165
// 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
- )
166
+ image . width = size
167
+ image . height = size
168
+ context . drawImage ( image , 0 , 0 , image . width , image . height )
167
169
168
170
// Draw bubble on the top
169
- drawBubble ( current . context , value , options )
171
+ drawBubble ( context , value , options )
170
172
171
173
// Refresh tag in page
172
- setFavicon ( current . canvas . toDataURL ( ) )
174
+ setFavicon ( canvas . toDataURL ( ) )
173
175
}
174
176
175
177
// Draws the bubble on the canvas
@@ -198,14 +200,16 @@ const drawBubble = (
198
200
}
199
201
200
202
// Calculate position etc.
203
+ const size = getSize ( )
204
+ const ratio = getRatio ( )
201
205
const length = finalValue . length - 1
202
- const width = 8 * ratio + 4 * ratio * length
206
+ const width = Math . min ( 8 * ratio + 4 * ratio * length , size )
203
207
const height = 7 * ratio
204
208
const top = size - height
205
- const left = size - width - ratio
209
+ const left = size - width
206
210
const bottom = 16 * ratio
207
211
const right = 16 * ratio
208
- const radius = 5 * ratio
212
+ const radius = 3 * ratio
209
213
210
214
// Bubble
211
215
context . save ( )
@@ -232,21 +236,12 @@ const drawBubble = (
232
236
context . fillStyle = options . color
233
237
context . textAlign = 'center'
234
238
context . textBaseline = 'top'
235
- context . fillText ( finalValue , left + width / 2 + 1 , 9 * ratio + 1 )
239
+ context . fillText ( finalValue , left + width / 2 , 9 * ratio + 1 )
236
240
context . restore ( )
237
241
}
238
242
239
243
export function isAvailable ( ) {
240
- if ( ! current . context ) {
241
- const canvas = document . createElement ( 'canvas' )
242
- canvas . width = size
243
- canvas . height = size
244
-
245
- current . canvas = canvas
246
- current . context = canvas . getContext ? canvas . getContext ( '2d' ) : null
247
- }
248
-
249
- return ! ! current . context && ! ! getBestFavicon ( )
244
+ return ! ! getBestFavicon ( )
250
245
}
251
246
252
247
export function set ( value : Value , options ?: Partial < Options > ) {
@@ -264,8 +259,6 @@ export function set(value: Value, options?: Partial<Options>) {
264
259
265
260
if ( bestFavicon ) {
266
261
const bestFaviconImage = document . createElement ( 'img' )
267
- bestFaviconImage . width = size
268
- bestFaviconImage . height = size
269
262
270
263
// Allow cross origin resource requests if the image is not a data:uri
271
264
if ( ! bestFavicon . href . match ( / ^ d a t a / ) ) {
@@ -279,12 +272,15 @@ export function set(value: Value, options?: Partial<Options>) {
279
272
current . bestFavicon = bestFavicon
280
273
current . bestFaviconImage = bestFaviconImage
281
274
}
275
+
276
+ // Once the device pixel ratio changes we set the value again
277
+ devicePixelRatioListener . addListener ( handleRatioChange )
282
278
}
283
279
if ( ! current . favicons ) {
284
280
current . favicons = getFavicons ( )
285
281
}
286
282
287
- // Draw icon
283
+ // The image is required for setting the badge
288
284
if ( ! current . bestFaviconImage ) {
289
285
return false
290
286
}
@@ -308,6 +304,13 @@ export function clear() {
308
304
return
309
305
}
310
306
307
+ // Reset value and options
308
+ current . value = DefaultValue
309
+ current . options = DefaultOptions
310
+
311
+ // Remove old listener
312
+ devicePixelRatioListener . removeListener ( handleRatioChange )
313
+
311
314
if ( current . favicons ) {
312
315
// Remove current favicons
313
316
for ( const favicon of getFavicons ( ) ) {
0 commit comments