summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/frontend/src/app/shared/services/favicon.service.ts
blob: 87ce8fcad91638ce4d99d7284675102652bb080a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, OnDestroy } from '@angular/core';

import { Subscription } from 'rxjs';

import { CssHelper } from '~/app/shared/classes/css-helper';
import { HealthColor } from '~/app/shared/enum/health-color.enum';
import { SummaryService } from './summary.service';

@Injectable()
export class FaviconService implements OnDestroy {
  sub: Subscription;
  oldStatus: string;
  url: string;

  constructor(
    @Inject(DOCUMENT) private document: HTMLDocument,
    private summaryService: SummaryService,
    private cssHelper: CssHelper
  ) {}

  init() {
    this.url = this.document.getElementById('cdFavicon')?.getAttribute('href');

    this.sub = this.summaryService.subscribe((summary) => {
      this.changeIcon(summary.health_status);
    });
  }

  changeIcon(status?: string) {
    if (status === this.oldStatus) {
      return;
    }

    this.oldStatus = status;

    const favicon = this.document.getElementById('cdFavicon');
    const faviconSize = 16;
    const radius = faviconSize / 4;

    const canvas = this.document.createElement('canvas');
    canvas.width = faviconSize;
    canvas.height = faviconSize;

    const context = canvas.getContext('2d');
    const img = this.document.createElement('img');
    img.src = this.url;

    img.onload = () => {
      // Draw Original Favicon as Background
      context.drawImage(img, 0, 0, faviconSize, faviconSize);

      if (Object.keys(HealthColor).includes(status as HealthColor)) {
        // Cut notification circle area
        context.save();
        context.globalCompositeOperation = 'destination-out';
        context.beginPath();
        context.arc(canvas.width - radius, radius, radius + 2, 0, 2 * Math.PI);
        context.fill();
        context.restore();

        // Draw Notification Circle
        context.beginPath();
        context.arc(canvas.width - radius, radius, radius, 0, 2 * Math.PI);

        context.fillStyle = this.cssHelper.propertyValue(HealthColor[status]);
        context.fill();
      }

      // Replace favicon
      favicon.setAttribute('href', canvas.toDataURL('image/png'));
    };
  }

  ngOnDestroy() {
    this.changeIcon();
    this.sub?.unsubscribe();
  }
}