-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Classify objects #59
Classify objects #59
Changes from all commits
da62d7b
c4fa6ef
059661c
06f5846
b5d5ccb
87a6734
541334c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// @ts-check | ||
'use strict'; | ||
|
||
/** | ||
* Manages the favicon state and updates including message count and ping status | ||
*/ | ||
class FaviconManager { | ||
/** | ||
* @type {number} | ||
*/ | ||
#messageCount = 0; | ||
|
||
/** | ||
* @type {boolean} | ||
*/ | ||
#hasPing = false; | ||
|
||
constructor() { | ||
// Set up visibility change handler | ||
document.addEventListener('visibilitychange', () => { | ||
if (document.visibilityState === 'visible') { | ||
this.clear(); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Clear the favicon state and update the display | ||
*/ | ||
clear() { | ||
this.#messageCount = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Private variables! I've never use those in JS. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah they are quite neat. Relatively recent but old enough that they are supported in any browser of the last few years. |
||
this.#hasPing = false; | ||
this.#updateFavicon(); | ||
} | ||
|
||
/** | ||
* Increment the message count and update ping status if tab is not visible | ||
* @param {boolean} isPing - Whether this message is a ping | ||
* @param {boolean} isHistory - Whether this message is from history | ||
*/ | ||
handleNewMessage(isPing, isHistory = false) { | ||
if (document.visibilityState !== 'visible') { | ||
if (!isHistory && isPing) { | ||
this.#hasPing = true; | ||
} | ||
this.#messageCount++; | ||
this.#updateFavicon(); | ||
} | ||
} | ||
|
||
/** | ||
* Get the current message count | ||
* @returns {number} | ||
*/ | ||
getMessageCount() { | ||
return this.#messageCount; | ||
} | ||
|
||
/** | ||
* Get the current ping status | ||
* @returns {boolean} | ||
*/ | ||
getHasPing() { | ||
return this.#hasPing; | ||
} | ||
|
||
/** | ||
* Render a favicon with the current counter and ping indicator | ||
*/ | ||
#updateFavicon() { | ||
const sizes = [16, 32]; | ||
|
||
sizes.forEach((size) => { | ||
/** @type {HTMLLinkElement | null} */ | ||
const link = document.querySelector( | ||
`link[rel="icon"][sizes="${size}x${size}"]`, | ||
); | ||
|
||
if (!link) { | ||
return; | ||
} | ||
|
||
const canvas = document.createElement('canvas'); | ||
canvas.width = size; | ||
canvas.height = size; | ||
const ctx = canvas.getContext('2d'); | ||
|
||
if (!ctx) { | ||
return; | ||
} | ||
|
||
const img = new Image(); | ||
|
||
// Pings should not happen without a count | ||
if (this.#hasPing && this.#messageCount > 0) { | ||
img.src = `img/icon_${size}_ping.png`; | ||
} else if (this.#messageCount > 0) { | ||
img.src = `img/icon_${size}_blank.png`; | ||
} else { | ||
// Default image, will restore the favicon | ||
img.src = `img/icon_${size}.png`; | ||
} | ||
|
||
img.onload = () => { | ||
ctx.drawImage(img, 0, 0, size, size); | ||
|
||
if (this.#messageCount > 0) { | ||
const x = size / 2; | ||
const y = size / 2 - size * 0.05; // The middle of the chat icon is not exactly in the center | ||
|
||
ctx.font = `bold ${size * 0.5}px "Arial Black"`; | ||
ctx.textAlign = 'center'; | ||
ctx.textBaseline = 'middle'; | ||
ctx.fillStyle = '#000000'; | ||
ctx.fillText( | ||
this.#messageCount > 99 | ||
? '99+' | ||
: `${this.#messageCount}`, | ||
x, | ||
y, | ||
); | ||
} | ||
|
||
link.href = canvas.toDataURL(); | ||
}; | ||
}); | ||
} | ||
} | ||
|
||
// Export a singleton instance since we only need one favicon manager | ||
export const faviconManager = new FaviconManager(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥹 it's so beautiful