156 lines
4.0 KiB
TypeScript
156 lines
4.0 KiB
TypeScript
import { WorkflowRun } from '../types/github';
|
|
|
|
export class NotificationService {
|
|
private static instance: NotificationService;
|
|
private hasPermission = false;
|
|
|
|
private constructor() {
|
|
this.checkPermission();
|
|
}
|
|
|
|
static getInstance(): NotificationService {
|
|
if (!NotificationService.instance) {
|
|
NotificationService.instance = new NotificationService();
|
|
}
|
|
return NotificationService.instance;
|
|
}
|
|
|
|
private checkPermission(): void {
|
|
if (!('Notification' in window)) {
|
|
console.log('This browser does not support desktop notification');
|
|
return;
|
|
}
|
|
|
|
this.hasPermission = Notification.permission === 'granted';
|
|
}
|
|
|
|
async requestPermission(): Promise<boolean> {
|
|
if (!('Notification' in window)) {
|
|
console.log('This browser does not support desktop notification');
|
|
return false;
|
|
}
|
|
|
|
if (Notification.permission === 'granted') {
|
|
this.hasPermission = true;
|
|
return true;
|
|
}
|
|
|
|
if (Notification.permission !== 'denied') {
|
|
const permission = await Notification.requestPermission();
|
|
this.hasPermission = permission === 'granted';
|
|
return this.hasPermission;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
canShowNotifications(): boolean {
|
|
return this.hasPermission && 'Notification' in window;
|
|
}
|
|
|
|
showFailureNotification(failedRuns: WorkflowRun[]): void {
|
|
if (!this.canShowNotifications()) {
|
|
return;
|
|
}
|
|
|
|
const count = failedRuns.length;
|
|
const title = count === 1
|
|
? 'Build Failed'
|
|
: `${count} Builds Failed`;
|
|
|
|
const body = count === 1
|
|
? `${failedRuns[0].repository.full_name} - ${failedRuns[0].display_title}`
|
|
: `Multiple builds have failed across ${new Set(failedRuns.map(r => r.repository.full_name)).size} repositories`;
|
|
|
|
const notification = new Notification(title, {
|
|
body,
|
|
icon: '/favicon.ico',
|
|
badge: '/favicon.ico',
|
|
tag: 'build-failure',
|
|
renotify: true,
|
|
requireInteraction: false,
|
|
silent: false
|
|
});
|
|
|
|
// Auto-close after 5 seconds
|
|
setTimeout(() => {
|
|
notification.close();
|
|
}, 5000);
|
|
|
|
// Optional: Click to focus window
|
|
notification.onclick = () => {
|
|
window.focus();
|
|
notification.close();
|
|
};
|
|
}
|
|
|
|
showSuccessNotification(successRuns: WorkflowRun[]): void {
|
|
if (!this.canShowNotifications()) {
|
|
return;
|
|
}
|
|
|
|
const count = successRuns.length;
|
|
const title = count === 1
|
|
? 'Build Recovered'
|
|
: `${count} Builds Recovered`;
|
|
|
|
const body = count === 1
|
|
? `${successRuns[0].repository.full_name} - ${successRuns[0].display_title}`
|
|
: `Multiple builds have recovered across ${new Set(successRuns.map(r => r.repository.full_name)).size} repositories`;
|
|
|
|
const notification = new Notification(title, {
|
|
body,
|
|
icon: '/favicon.ico',
|
|
badge: '/favicon.ico',
|
|
tag: 'build-success',
|
|
renotify: true,
|
|
requireInteraction: false,
|
|
silent: false
|
|
});
|
|
|
|
// Auto-close after 3 seconds
|
|
setTimeout(() => {
|
|
notification.close();
|
|
}, 3000);
|
|
|
|
notification.onclick = () => {
|
|
window.focus();
|
|
notification.close();
|
|
};
|
|
}
|
|
|
|
showWaitingNotification(waitingRuns: WorkflowRun[]): void {
|
|
if (!this.canShowNotifications()) {
|
|
return;
|
|
}
|
|
|
|
const count = waitingRuns.length;
|
|
const title = count === 1
|
|
? 'Build Waiting'
|
|
: `${count} Builds Waiting`;
|
|
|
|
const body = count === 1
|
|
? `${waitingRuns[0].repository.full_name} - ${waitingRuns[0].display_title}`
|
|
: `Multiple builds are now waiting across ${new Set(waitingRuns.map(r => r.repository.full_name)).size} repositories`;
|
|
|
|
const notification = new Notification(title, {
|
|
body,
|
|
icon: '/favicon.ico',
|
|
badge: '/favicon.ico',
|
|
tag: 'build-waiting',
|
|
renotify: true,
|
|
requireInteraction: false,
|
|
silent: false
|
|
});
|
|
|
|
// Auto-close after 4 seconds
|
|
setTimeout(() => {
|
|
notification.close();
|
|
}, 4000);
|
|
|
|
notification.onclick = () => {
|
|
window.focus();
|
|
notification.close();
|
|
};
|
|
}
|
|
} |