Initial commit
This commit is contained in:
156
src/services/notifications.ts
Normal file
156
src/services/notifications.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
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();
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user