fix notification dot

1) the `crossOrigin='anonymous'` tells the browser to actually honour
	 CORS on the image

2) the dot is now always 1/5 of the icon, even for large icons

3) we use `toBlob` instead of `toDataURL` because
	 https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
	 says so

4) the test now blinks the dot, so it tests the actual code

5) if there's a problem during the test, we log the error, so people
	 can tell it to us

Thanks to Ares on Discord for reporting the problems.
This commit is contained in:
dakkar 2025-03-18 19:35:21 +00:00
parent 62d35a56c1
commit a9bad939ba

View file

@ -28,6 +28,7 @@ class FavIconDot {
this.ctx = this.canvas.getContext('2d'); this.ctx = this.canvas.getContext('2d');
this.faviconImage = document.createElement('img'); this.faviconImage = document.createElement('img');
this.faviconImage.crossOrigin = 'anonymous';
this.hasLoaded = new Promise((resolve, reject) => { this.hasLoaded = new Promise((resolve, reject) => {
(this.faviconImage as HTMLImageElement).addEventListener('load', () => { (this.faviconImage as HTMLImageElement).addEventListener('load', () => {
@ -76,7 +77,8 @@ class FavIconDot {
private drawDot() { private drawDot() {
if (!this.ctx || !this.faviconImage) return; if (!this.ctx || !this.faviconImage) return;
this.ctx.beginPath(); this.ctx.beginPath();
this.ctx.arc(this.faviconImage.width - 10, 10, 10, 0, 2 * Math.PI); const radius = Math.min(this.faviconImage.width, this.faviconImage.height) * 0.2;
this.ctx.arc(this.faviconImage.width - radius, radius, radius, 0, 2 * Math.PI);
const computedStyle = getComputedStyle(document.documentElement); const computedStyle = getComputedStyle(document.documentElement);
this.ctx.fillStyle = tinycolor(computedStyle.getPropertyValue('--MI_THEME-navIndicator')).toHexString(); this.ctx.fillStyle = tinycolor(computedStyle.getPropertyValue('--MI_THEME-navIndicator')).toHexString();
this.ctx.strokeStyle = 'white'; this.ctx.strokeStyle = 'white';
@ -85,7 +87,17 @@ class FavIconDot {
} }
private setFavicon() { private setFavicon() {
if (this.faviconEL) this.faviconEL.href = this.canvas.toDataURL('image/png'); if (this.faviconEL) {
try {
URL.revokeObjectURL(this.faviconEL.href);
} catch (error) {
// the href was probably not an object URL
}
this.canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
this.faviconEL.href = url;
});
}
} }
public async setVisible(isVisible: boolean) { public async setVisible(isVisible: boolean) {
@ -98,12 +110,11 @@ class FavIconDot {
public async worksOnInstance() { public async worksOnInstance() {
try { try {
// Wait for it to have loaded the icon await this.setVisible(true);
await this.hasLoaded; await new Promise((resolve) => setTimeout(resolve, 1000));
this.drawIcon(); await this.setVisible(false);
this.drawDot();
this.canvas.toDataURL('image/png');
} catch (error) { } catch (error) {
console.error('error setting notification dot', error);
return false; return false;
} }
return true; return true;