diff --git a/package.json b/package.json index 4e4080a2..3c025836 100644 --- a/package.json +++ b/package.json @@ -228,7 +228,10 @@ "darkModeSupport": true, "target": [ "dmg" - ] + ], + "extendInfo": { + "NSUserNotificationAlertStyle": "alert" + } } } } diff --git a/src/main/plugins/playbackNotifications.ts b/src/main/plugins/playbackNotifications.ts new file mode 100644 index 00000000..b9807d53 --- /dev/null +++ b/src/main/plugins/playbackNotifications.ts @@ -0,0 +1,118 @@ +import fetch from "electron-fetch"; +import {nativeImage, Notification} from "electron"; +import NativeImage = Electron.NativeImage; + +export default class playbackNotifications { + + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'Playback Notifications'; + public description: string = 'Creates notifications on playback.'; + public version: string = '1.0.0'; + public author: string = 'Core'; + public contributors: string[] = ['Core', 'Monochromish']; + + private _utils: any; + private _notification: Notification | undefined; + private _artworkImage: { [key: string]: NativeImage } = {}; + private _artworkNums: Array = []; + + /** + * Creates playback notification + * @param a: Music Attributes + */ + createNotification(a: any): void { + if (this._notification) { + this._notification.close(); + } + + this._notification = new Notification({ + title: a.name, + body: `${a.artistName} — ${a.albumName}`, + silent: true, + icon: this._artworkImage[a.artwork.url], + urgency: 'low', + actions: [ + { + 'type': 'button', + 'text': 'Play/Pause' + }, + { + 'type': 'button', + 'text': 'Next' + } + ], + toastXml: ` + + + + ${a?.name.replace(/&/g, '&')} + ${a?.artistName.replace(/&/g, '&')} — ${a?.albumName.replace(/&/g, '&')} + + + + + + + ` + }); + + // image implementation in windows toasts + //img + + this._notification.on('click', (_: any) => { + this._utils.getWindow().show() + this._utils.getWindow().focus() + }) + + this._notification.on('close', (_: any) => { + this._notification = undefined; + }) + + this._notification.on('action', (event: any, action: any) => { + if (action === 0) { + this._utils.playback.playPause() + } else if (action === 1) { + this._utils.playback.next() + } + }) + + this._notification.show(); + + } + + + /******************************************************************************************* + * Public Methods + * ****************************************************************************************/ + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(utils: any) { + this._utils = utils; + console.debug(`[Plugin][${this.name}] Loading Complete.`); + + utils.getIPCMain().on('playbackNotifications:create', (event: any, a: any) => { + a.artwork.url = a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb'); + + if (this._artworkNums.length > 20) { + delete this._artworkImage[this._artworkNums[0]]; + this._artworkNums.shift(); + } + + if (this._artworkImage[a.artwork.url]) { + this.createNotification(a); + } else { + fetch(a.artwork.url).then(async blob => { + this._artworkImage[a.artwork.url] = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer())); + this._artworkNums[this._artworkNums.length] = a.artwork.url; + this.createNotification(a); + }); + } + }) + } + +} diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index 9eccc0ca..33fc5a91 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -44,6 +44,10 @@ const MusicKitInterop = { global.ipcRenderer.send('lastfm:nowPlayingChange', attributes); } + if (app.cfg.general.playbackNotifications && !document.hasFocus() && attributes.artistName && attributes.artwork && attributes.name) { + global.ipcRenderer.send('playbackNotifications:create', attributes); + } + if (MusicKit.getInstance().nowPlayingItem) { await this.sleep(750); MusicKit.getInstance().playbackRate = app.cfg.audio.playbackRate; diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index ff70b7a7..431fca42 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -1074,17 +1074,6 @@ const app = new Vue({ app.getNowPlayingArtworkBG(32); app.loadLyrics(); - // Playback Notifications - if (this.cfg.general.playbackNotifications && !document.hasFocus() && a.artistName && a.artwork && a.name) { - if (this.notification) { - this.notification.close() - } - this.notification = new Notification(a.name, { - body: `${a.artistName} — ${a.albumName}`, - icon: a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb'), - silent: true, - }); - } setTimeout(() => { let i = (document.querySelector('#apple-music-player')?.src ?? "") if (i.endsWith(".m3u8") || i.endsWith(".m3u")) {