Compare commits
	
		
			10 Commits
		
	
	
		
			5.0.0
			...
			bccc979f43
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bccc979f43 | |||
| 6849952c41 | |||
| 07be74af9f | |||
| fc6adc25ca | |||
| 4498e8a73e | |||
| 3d2a9c3992 | |||
| af6bfaf55e | |||
|  | 8bac90e0f1 | ||
|  | 887c75f61a | ||
|  | cde7408cc4 | 
							
								
								
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @@ -4,9 +4,24 @@ All notable changes to this project will be documented in this file. | |||||||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||||||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||||||
|  |  | ||||||
|  | ## 5.1.0 | ||||||
|  |  | ||||||
|  | ### New features | ||||||
|  |  | ||||||
|  | - Added proper updates through the MediaSession API | ||||||
|  | - You can now add custom CSS in the "advanced" settings tab | ||||||
|  | - You can now configure the updateFrequency in the settings window | ||||||
|  |   - Default value is set to 500 and will overwrite the hardcoded value of 100 | ||||||
|  |  | ||||||
|  | ### Fixes | ||||||
|  |  | ||||||
|  | - Any songs **including** an artist listed in the `skipped artists` setting will now be skipped even if the song is a collaboration. | ||||||
|  | - Linux desktop icons have been fixed. See [#222](https://github.com/Mastermindzh/tidal-hifi/pull/222) for details. | ||||||
|  |  | ||||||
| ## 5.0.0 | ## 5.0.0 | ||||||
|  |  | ||||||
| - Replaced "muting artists" with a full implementation of an Adblock mechanism | - Replaced "muting artists" with a full implementation of an Adblock mechanism | ||||||
|  |  | ||||||
|   > Disabled audio & visual ads, unlocked lyrics, suggested track, track info, unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495)) |   > Disabled audio & visual ads, unlocked lyrics, suggested track, track info, unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495)) | ||||||
|  |  | ||||||
| - @thanasistrisp updated Electron to 24.1.2 and fixed the tray bug :) | - @thanasistrisp updated Electron to 24.1.2 and fixed the tray bug :) | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/128x128.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 16 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/16x16.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 5.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/22x22.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/24x24.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 9.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/256x256.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/32x32.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/384x384.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 46 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/48x48.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/64x64.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
| @@ -9,7 +9,7 @@ snap: | |||||||
|     - screen-inhibit-control |     - screen-inhibit-control | ||||||
| linux: | linux: | ||||||
|   category: AudioVideo |   category: AudioVideo | ||||||
|   icon: icon.png |   icon: assets/icons | ||||||
|   target: |   target: | ||||||
|     - dir |     - dir | ||||||
|   executableName: tidal-hifi |   executableName: tidal-hifi | ||||||
| @@ -18,7 +18,7 @@ linux: | |||||||
|     Name: TIDAL Hi-Fi |     Name: TIDAL Hi-Fi | ||||||
|     GenericName: TIDAL Hi-Fi |     GenericName: TIDAL Hi-Fi | ||||||
|     Comment: The web version of listen.tidal.com running in electron with hifi support thanks to widevine. |     Comment: The web version of listen.tidal.com running in electron with hifi support thanks to widevine. | ||||||
|     Icon: icon.png |     Icon: tidal-hifi | ||||||
|     StartupNotify: true |     StartupNotify: true | ||||||
|     Terminal: false |     Terminal: false | ||||||
|     Type: Application |     Type: Application | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| extends: ./build/electron-builder.base.yml | extends: ./build/electron-builder.base.yml | ||||||
| linux: | linux: | ||||||
|   icon: icon.png |  | ||||||
|   target: |   target: | ||||||
|     - pacman |     - pacman | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @@ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|   "name": "tidal-hifi", |   "name": "tidal-hifi", | ||||||
|   "version": "5.0.0", |   "version": "5.1.0", | ||||||
|   "lockfileVersion": 3, |   "lockfileVersion": 3, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "name": "tidal-hifi", |       "name": "tidal-hifi", | ||||||
|       "version": "5.0.0", |       "version": "5.1.0", | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@electron/remote": "^2.0.9", |         "@electron/remote": "^2.0.9", | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "tidal-hifi", |   "name": "tidal-hifi", | ||||||
|   "version": "5.0.0", |   "version": "5.1.0", | ||||||
|   "description": "Tidal on Electron with widevine(hifi) support", |   "description": "Tidal on Electron with widevine(hifi) support", | ||||||
|   "main": "src/main.js", |   "main": "src/main.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|   | |||||||
| @@ -9,34 +9,36 @@ | |||||||
|  *    windowBounds: { width: 800, height: 600 }, |  *    windowBounds: { width: 800, height: 600 }, | ||||||
|  */ |  */ | ||||||
| const settings = { | const settings = { | ||||||
|   notifications: "notifications", |  | ||||||
|   api: "api", |  | ||||||
|   menuBar: "menuBar", |  | ||||||
|   playBackControl: "playBackControl", |  | ||||||
|   skipArtists: "skipArtists", |  | ||||||
|   skippedArtists: "skippedArtists", |  | ||||||
|   adBlock: "adBlock", |   adBlock: "adBlock", | ||||||
|   disableBackgroundThrottle: "disableBackgroundThrottle", |   api: "api", | ||||||
|   apiSettings: { |   apiSettings: { | ||||||
|     root: "apiSettings", |     root: "apiSettings", | ||||||
|     port: "apiSettings.port", |     port: "apiSettings.port", | ||||||
|   }, |   }, | ||||||
|   singleInstance: "singleInstance", |   customCSS: "customCSS", | ||||||
|  |   disableBackgroundThrottle: "disableBackgroundThrottle", | ||||||
|   disableHardwareMediaKeys: "disableHardwareMediaKeys", |   disableHardwareMediaKeys: "disableHardwareMediaKeys", | ||||||
|  |   enableCustomHotkeys: "enableCustomHotkeys", | ||||||
|  |   enableDiscord: "enableDiscord", | ||||||
|   flags: { |   flags: { | ||||||
|     disableHardwareMediaKeys: "flags.disableHardwareMediaKeys", |     disableHardwareMediaKeys: "flags.disableHardwareMediaKeys", | ||||||
|     gpuRasterization: "flags.gpuRasterization", |     gpuRasterization: "flags.gpuRasterization", | ||||||
|   }, |   }, | ||||||
|  |   menuBar: "menuBar", | ||||||
|  |   minimizeOnClose: "minimizeOnClose", | ||||||
|   mpris: "mpris", |   mpris: "mpris", | ||||||
|   enableCustomHotkeys: "enableCustomHotkeys", |   notifications: "notifications", | ||||||
|  |   playBackControl: "playBackControl", | ||||||
|  |   singleInstance: "singleInstance", | ||||||
|  |   skipArtists: "skipArtists", | ||||||
|  |   skippedArtists: "skippedArtists", | ||||||
|   trayIcon: "trayIcon", |   trayIcon: "trayIcon", | ||||||
|   enableDiscord: "enableDiscord", |   updateFrequency: "updateFrequency", | ||||||
|   windowBounds: { |   windowBounds: { | ||||||
|     root: "windowBounds", |     root: "windowBounds", | ||||||
|     width: "windowBounds.width", |     width: "windowBounds.width", | ||||||
|     height: "windowBounds.height", |     height: "windowBounds.height", | ||||||
|   }, |   }, | ||||||
|   minimizeOnClose: "minimizeOnClose", |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| module.exports = settings; | module.exports = settings; | ||||||
|   | |||||||
| @@ -172,7 +172,6 @@ app.on("ready", async () => { | |||||||
|     store.get(settings.trayIcon) && addTray(mainWindow, { icon }) && refreshTray(); |     store.get(settings.trayIcon) && addTray(mainWindow, { icon }) && refreshTray(); | ||||||
|     store.get(settings.api) && expressModule.run(mainWindow); |     store.get(settings.api) && expressModule.run(mainWindow); | ||||||
|     store.get(settings.enableDiscord) && discordModule.initRPC(); |     store.get(settings.enableDiscord) && discordModule.initRPC(); | ||||||
|     // mainWindow.webContents.openDevTools(); |  | ||||||
|   } else { |   } else { | ||||||
|     app.quit(); |     app.quit(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,20 +1,22 @@ | |||||||
| let trayIcon, | let adBlock, | ||||||
|   minimizeOnClose, |   api, | ||||||
|   mpris, |   customCSS, | ||||||
|  |   disableBackgroundThrottle, | ||||||
|  |   disableHardwareMediaKeys, | ||||||
|   enableCustomHotkeys, |   enableCustomHotkeys, | ||||||
|   enableDiscord, |   enableDiscord, | ||||||
|   skipArtists, |   gpuRasterization, | ||||||
|  |   menuBar, | ||||||
|  |   minimizeOnClose, | ||||||
|  |   mpris, | ||||||
|   notifications, |   notifications, | ||||||
|   playBackControl, |   playBackControl, | ||||||
|   api, |  | ||||||
|   port, |   port, | ||||||
|   menuBar, |  | ||||||
|   skippedArtists, |  | ||||||
|   adBlock, |  | ||||||
|   disableBackgroundThrottle, |  | ||||||
|   singleInstance, |   singleInstance, | ||||||
|   disableHardwareMediaKeys, |   skipArtists, | ||||||
|   gpuRasterization; |   skippedArtists, | ||||||
|  |   trayIcon, | ||||||
|  |   updateFrequency; | ||||||
|  |  | ||||||
| const { store, settings } = require("./../../scripts/settings"); | const { store, settings } = require("./../../scripts/settings"); | ||||||
| const { ipcRenderer } = require("electron"); | const { ipcRenderer } = require("electron"); | ||||||
| @@ -25,23 +27,25 @@ const { app } = remote; | |||||||
|  * Sync the UI forms with the current settings |  * Sync the UI forms with the current settings | ||||||
|  */ |  */ | ||||||
| function refreshSettings() { | function refreshSettings() { | ||||||
|   notifications.checked = store.get(settings.notifications); |   adBlock.checked = store.get(settings.adBlock); | ||||||
|   playBackControl.checked = store.get(settings.playBackControl); |  | ||||||
|   api.checked = store.get(settings.api); |   api.checked = store.get(settings.api); | ||||||
|   port.value = store.get(settings.apiSettings.port); |   customCSS.value = store.get(settings.customCSS); | ||||||
|   menuBar.checked = store.get(settings.menuBar); |   disableBackgroundThrottle.checked = store.get("disableBackgroundThrottle"); | ||||||
|   trayIcon.checked = store.get(settings.trayIcon); |   disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys); | ||||||
|   mpris.checked = store.get(settings.mpris); |  | ||||||
|   enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys); |   enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys); | ||||||
|   enableDiscord.checked = store.get(settings.enableDiscord); |   enableDiscord.checked = store.get(settings.enableDiscord); | ||||||
|  |   gpuRasterization.checked = store.get(settings.flags.gpuRasterization); | ||||||
|  |   menuBar.checked = store.get(settings.menuBar); | ||||||
|   minimizeOnClose.checked = store.get(settings.minimizeOnClose); |   minimizeOnClose.checked = store.get(settings.minimizeOnClose); | ||||||
|  |   mpris.checked = store.get(settings.mpris); | ||||||
|  |   notifications.checked = store.get(settings.notifications); | ||||||
|  |   playBackControl.checked = store.get(settings.playBackControl); | ||||||
|  |   port.value = store.get(settings.apiSettings.port); | ||||||
|  |   singleInstance.checked = store.get(settings.singleInstance); | ||||||
|   skipArtists.checked = store.get(settings.skipArtists); |   skipArtists.checked = store.get(settings.skipArtists); | ||||||
|   skippedArtists.value = store.get(settings.skippedArtists).join("\n"); |   skippedArtists.value = store.get(settings.skippedArtists).join("\n"); | ||||||
|   adBlock.checked = store.get(settings.adBlock); |   trayIcon.checked = store.get(settings.trayIcon); | ||||||
|   singleInstance.checked = store.get(settings.singleInstance); |   updateFrequency.value = store.get(settings.updateFrequency); | ||||||
|   disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys); |  | ||||||
|   gpuRasterization.checked = store.get(settings.flags.gpuRasterization); |  | ||||||
|   disableBackgroundThrottle.checked = store.get("disableBackgroundThrottle"); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -109,41 +113,45 @@ window.addEventListener("DOMContentLoaded", () => { | |||||||
|     document.getElementById(tab).click(); |     document.getElementById(tab).click(); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   notifications = get("notifications"); |   adBlock = get("adBlock"); | ||||||
|   playBackControl = get("playBackControl"); |  | ||||||
|   api = get("apiCheckbox"); |   api = get("apiCheckbox"); | ||||||
|   port = get("port"); |   customCSS = get("customCSS"); | ||||||
|   menuBar = get("menuBar"); |   disableBackgroundThrottle = get("disableBackgroundThrottle"); | ||||||
|   trayIcon = get("trayIcon"); |   disableHardwareMediaKeys = get("disableHardwareMediaKeys"); | ||||||
|   minimizeOnClose = get("minimizeOnClose"); |  | ||||||
|   mpris = get("mprisCheckbox"); |  | ||||||
|   enableCustomHotkeys = get("enableCustomHotkeys"); |   enableCustomHotkeys = get("enableCustomHotkeys"); | ||||||
|   enableDiscord = get("enableDiscord"); |   enableDiscord = get("enableDiscord"); | ||||||
|  |   gpuRasterization = get("gpuRasterization"); | ||||||
|  |   menuBar = get("menuBar"); | ||||||
|  |   minimizeOnClose = get("minimizeOnClose"); | ||||||
|  |   mpris = get("mprisCheckbox"); | ||||||
|  |   notifications = get("notifications"); | ||||||
|  |   playBackControl = get("playBackControl"); | ||||||
|  |   port = get("port"); | ||||||
|  |   trayIcon = get("trayIcon"); | ||||||
|   skipArtists = get("skipArtists"); |   skipArtists = get("skipArtists"); | ||||||
|   skippedArtists = get("skippedArtists"); |   skippedArtists = get("skippedArtists"); | ||||||
|   adBlock = get("adBlock"); |  | ||||||
|   disableBackgroundThrottle = get("disableBackgroundThrottle"); |  | ||||||
|   singleInstance = get("singleInstance"); |   singleInstance = get("singleInstance"); | ||||||
|   disableHardwareMediaKeys = get("disableHardwareMediaKeys"); |   updateFrequency = get("updateFrequency"); | ||||||
|   gpuRasterization = get("gpuRasterization"); |  | ||||||
|  |  | ||||||
|   refreshSettings(); |   refreshSettings(); | ||||||
|  |  | ||||||
|   addInputListener(notifications, settings.notifications); |   addInputListener(adBlock, settings.adBlock); | ||||||
|   addInputListener(playBackControl, settings.playBackControl); |  | ||||||
|   addInputListener(api, settings.api); |   addInputListener(api, settings.api); | ||||||
|   addInputListener(port, settings.apiSettings.port); |   addTextAreaListener(customCSS, settings.customCSS); | ||||||
|   addInputListener(menuBar, settings.menuBar); |   addInputListener(disableBackgroundThrottle, settings.disableBackgroundThrottle); | ||||||
|   addInputListener(trayIcon, settings.trayIcon); |   addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys); | ||||||
|   addInputListener(mpris, settings.mpris); |  | ||||||
|   addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys); |   addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys); | ||||||
|   addInputListener(enableDiscord, settings.enableDiscord); |   addInputListener(enableDiscord, settings.enableDiscord); | ||||||
|  |   addInputListener(gpuRasterization, settings.flags.gpuRasterization); | ||||||
|  |   addInputListener(menuBar, settings.menuBar); | ||||||
|   addInputListener(minimizeOnClose, settings.minimizeOnClose); |   addInputListener(minimizeOnClose, settings.minimizeOnClose); | ||||||
|  |   addInputListener(mpris, settings.mpris); | ||||||
|  |   addInputListener(notifications, settings.notifications); | ||||||
|  |   addInputListener(playBackControl, settings.playBackControl); | ||||||
|  |   addInputListener(port, settings.apiSettings.port); | ||||||
|   addInputListener(skipArtists, settings.skipArtists); |   addInputListener(skipArtists, settings.skipArtists); | ||||||
|   addTextAreaListener(skippedArtists, settings.skippedArtists); |   addTextAreaListener(skippedArtists, settings.skippedArtists); | ||||||
|   addInputListener(adBlock, settings.adBlock); |  | ||||||
|   addInputListener(disableBackgroundThrottle, settings.disableBackgroundThrottle); |  | ||||||
|   addInputListener(singleInstance, settings.singleInstance); |   addInputListener(singleInstance, settings.singleInstance); | ||||||
|   addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys); |   addInputListener(trayIcon, settings.trayIcon); | ||||||
|   addInputListener(gpuRasterization, settings.flags.gpuRasterization); |   addInputListener(updateFrequency, settings.updateFrequency); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -160,7 +160,7 @@ | |||||||
|             <div class="group__option"> |             <div class="group__option"> | ||||||
|               <div class="group__description"> |               <div class="group__description"> | ||||||
|                 <label for="port">API port</label> |                 <label for="port">API port</label> | ||||||
|                 <input id="port" type="text" class="text-input" name="port" /> |                 <input id="port" type="number" class="text-input" name="port" /> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|             <div class="group__option"> |             <div class="group__option"> | ||||||
| @@ -212,6 +212,31 @@ | |||||||
|         </section> |         </section> | ||||||
|  |  | ||||||
|         <section id="advanced-section" class="tabs__section"> |         <section id="advanced-section" class="tabs__section"> | ||||||
|  |           <div class="group"> | ||||||
|  |             <p class="group__title">Settings</p> | ||||||
|  |             <div class="group__option"> | ||||||
|  |               <div class="group__description"> | ||||||
|  |                 <h4>Update frequency</h4> | ||||||
|  |                 <p> | ||||||
|  |                   The amount of time, in milliseconds, that tidal-hifi will refresh its playback info by scraping the | ||||||
|  |                   website. | ||||||
|  |                   The default of 500 seems to work in more cases but if you are fine with a bit more resource usage you | ||||||
|  |                   can decrease it as well. | ||||||
|  |                 </p> | ||||||
|  |                 <input id="updateFrequency" type="number" class="text-input" name="updateFrequency" /> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="group__option"> | ||||||
|  |               <div class="group__description"> | ||||||
|  |                 <h4>Custom CSS</h4> | ||||||
|  |                 <p> | ||||||
|  |                   The css that you put in here will be injected into a style tag in the head of the document. | ||||||
|  |                 </p> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <textarea id="customCSS" class="textarea" cols="40" rows="8" spellcheck="false"></textarea> | ||||||
|  |  | ||||||
|           <div class="group"> |           <div class="group"> | ||||||
|             <p class="group__title">Flags</p> |             <p class="group__title">Flags</p> | ||||||
|             <div class="group__option"> |             <div class="group__option"> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ const { downloadFile } = require("./scripts/download"); | |||||||
| const statuses = require("./constants/statuses"); | const statuses = require("./constants/statuses"); | ||||||
| const hotkeys = require("./scripts/hotkeys"); | const hotkeys = require("./scripts/hotkeys"); | ||||||
| const globalEvents = require("./constants/globalEvents"); | const globalEvents = require("./constants/globalEvents"); | ||||||
| const { skipArtists } = require("./constants/settings"); | const { skipArtists, updateFrequency, customCSS } = require("./constants/settings"); | ||||||
| const notificationPath = `${app.getPath("userData")}/notification.jpg`; | const notificationPath = `${app.getPath("userData")}/notification.jpg`; | ||||||
| const appName = "Tidal Hifi"; | const appName = "Tidal Hifi"; | ||||||
| let currentSong = ""; | let currentSong = ""; | ||||||
| @@ -65,16 +65,27 @@ const elements = { | |||||||
|     return ""; |     return ""; | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   getArtists: function () { |   /** | ||||||
|  |    * returns an array of all artists in the current song | ||||||
|  |    * @returns {Array} artists | ||||||
|  |    */ | ||||||
|  |   getArtistsArray: function () { | ||||||
|     const footer = this.get("footer"); |     const footer = this.get("footer"); | ||||||
|  |  | ||||||
|     if (footer) { |     if (footer) { | ||||||
|       const artists = footer.querySelector(this["artists"]); |       const artists = footer.querySelectorAll(this.artists); | ||||||
|       if (artists) { |       if (artists) return Array.from(artists).map((artist) => artist.textContent); | ||||||
|         return artists.innerText; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|  |     return []; | ||||||
|  |   }, | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * unify the artists array into a string separated by commas | ||||||
|  |    * @param {Array} artistsArray | ||||||
|  |    * @returns {String} artists | ||||||
|  |    */ | ||||||
|  |   getArtistsString: function (artistsArray) { | ||||||
|  |     if (artistsArray.length > 0) return artistsArray.join(", "); | ||||||
|     return "unknown artist(s)"; |     return "unknown artist(s)"; | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
| @@ -132,6 +143,29 @@ const elements = { | |||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | function addCustomCss() { | ||||||
|  |   window.addEventListener("DOMContentLoaded", () => { | ||||||
|  |     const style = document.createElement("style"); | ||||||
|  |     style.innerHTML = store.get(customCSS); | ||||||
|  |     document.head.appendChild(style); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the update frequency from the store | ||||||
|  |  * make sure it returns a number, if not use the default | ||||||
|  |  */ | ||||||
|  | function getUpdateFrequency() { | ||||||
|  |   const storeValue = store.get(updateFrequency); | ||||||
|  |   const defaultValue = 500; | ||||||
|  |  | ||||||
|  |   if (!isNaN(storeValue)) { | ||||||
|  |     return storeValue; | ||||||
|  |   } else { | ||||||
|  |     return defaultValue; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Play or pause the current song |  * Play or pause the current song | ||||||
|  */ |  */ | ||||||
| @@ -289,14 +323,14 @@ function updateMediaInfo(options, notify) { | |||||||
|   if (options) { |   if (options) { | ||||||
|     ipcRenderer.send(globalEvents.updateInfo, options); |     ipcRenderer.send(globalEvents.updateInfo, options); | ||||||
|     if (store.get(settings.notifications) && notify) { |     if (store.get(settings.notifications) && notify) { | ||||||
|       new Notification({ title: options.title, body: options.message, icon: options.icon }).show(); |       new Notification({ title: options.title, body: options.artists, icon: options.icon }).show(); | ||||||
|     } |     } | ||||||
|     if (player) { |     if (player) { | ||||||
|       player.metadata = { |       player.metadata = { | ||||||
|         ...player.metadata, |         ...player.metadata, | ||||||
|         ...{ |         ...{ | ||||||
|           "xesam:title": options.title, |           "xesam:title": options.title, | ||||||
|           "xesam:artist": [options.message], |           "xesam:artist": [options.artists], | ||||||
|           "xesam:album": options.album, |           "xesam:album": options.album, | ||||||
|           "mpris:artUrl": options.image, |           "mpris:artUrl": options.image, | ||||||
|           "mpris:length": convertDuration(options.duration) * 1000 * 1000, |           "mpris:length": convertDuration(options.duration) * 1000 * 1000, | ||||||
| @@ -327,22 +361,40 @@ function getTrackID() { | |||||||
|   return window.location; |   return window.location; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function updateMediaSession(options) { | ||||||
|  |   if ("mediaSession" in navigator) { | ||||||
|  |     navigator.mediaSession.metadata = new MediaMetadata({ | ||||||
|  |       title: options.title, | ||||||
|  |       artist: options.artists, | ||||||
|  |       album: options.album, | ||||||
|  |       artwork: [ | ||||||
|  |         { | ||||||
|  |           src: options.icon, | ||||||
|  |           sizes: "640x640", | ||||||
|  |           type: "image/png", | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Watch for song changes and update title + notify |  * Watch for song changes and update title + notify | ||||||
|  */ |  */ | ||||||
| setInterval(function () { | setInterval(function () { | ||||||
|   const title = elements.getText("title"); |   const title = elements.getText("title"); | ||||||
|   const artists = elements.getArtists(); |   const artistsArray = elements.getArtistsArray(); | ||||||
|   skipArtistsIfFoundInSkippedArtistsList(artists); |   const artistsString = elements.getArtistsString(artistsArray); | ||||||
|  |   skipArtistsIfFoundInSkippedArtistsList(artistsArray); | ||||||
|  |  | ||||||
|   const album = elements.getAlbumName(); |   const album = elements.getAlbumName(); | ||||||
|   const current = elements.getText("current"); |   const current = elements.getText("current"); | ||||||
|   const duration = elements.getText("duration"); |   const duration = elements.getText("duration"); | ||||||
|   const songDashArtistTitle = `${title} - ${artists}`; |   const songDashArtistTitle = `${title} - ${artistsString}`; | ||||||
|   const currentStatus = getCurrentlyPlayingStatus(); |   const currentStatus = getCurrentlyPlayingStatus(); | ||||||
|   const options = { |   const options = { | ||||||
|     title, |     title, | ||||||
|     message: artists, |     artists: artistsString, | ||||||
|     album: album, |     album: album, | ||||||
|     status: currentStatus, |     status: currentStatus, | ||||||
|     url: getTrackURL(), |     url: getTrackURL(), | ||||||
| @@ -351,7 +403,7 @@ setInterval(function () { | |||||||
|     "app-name": appName, |     "app-name": appName, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   const titleOrArtistChanged = currentSong !== songDashArtistTitle; |   const titleOrArtistsChanged = currentSong !== songDashArtistTitle; | ||||||
|  |  | ||||||
|   // update title, url and play info with new info |   // update title, url and play info with new info | ||||||
|   setTitle(songDashArtistTitle); |   setTitle(songDashArtistTitle); | ||||||
| @@ -380,24 +432,32 @@ setInterval(function () { | |||||||
|     } |     } | ||||||
|   }).then( |   }).then( | ||||||
|     () => { |     () => { | ||||||
|       updateMediaInfo(options, titleOrArtistChanged); |       updateMediaInfo(options, titleOrArtistsChanged); | ||||||
|  |       if (titleOrArtistsChanged) { | ||||||
|  |         updateMediaSession(options); | ||||||
|  |       } | ||||||
|     }, |     }, | ||||||
|     () => {} |     () => {} | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * automatically skip a song if the artists are found in the list of artists to skip |    * automatically skip a song if the artists are found in the list of artists to skip | ||||||
|    * @param {*} artists list of artists to skip |    * @param {*} artists array of artists | ||||||
|    */ |    */ | ||||||
|   function skipArtistsIfFoundInSkippedArtistsList(artists) { |   function skipArtistsIfFoundInSkippedArtistsList(artists) { | ||||||
|     if (store.get(skipArtists)) { |     if (store.get(skipArtists)) { | ||||||
|       const skippedArtists = store.get(settings.skippedArtists); |       const skippedArtists = store.get(settings.skippedArtists); | ||||||
|       if (skippedArtists.find((artist) => artist === artists) !== undefined) { |       if (skippedArtists.length > 0) { | ||||||
|  |         const artistsToSkip = skippedArtists.map((artist) => artist); | ||||||
|  |         const artistNames = Object.values(artists).map((artist) => artist); | ||||||
|  |         const foundArtist = artistNames.some((artist) => artistsToSkip.includes(artist)); | ||||||
|  |         if (foundArtist) { | ||||||
|           elements.click("next"); |           elements.click("next"); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| }, 100); |   } | ||||||
|  | }, getUpdateFrequency()); | ||||||
|  |  | ||||||
| if (process.platform === "linux" && store.get(settings.mpris)) { | if (process.platform === "linux" && store.get(settings.mpris)) { | ||||||
|   try { |   try { | ||||||
| @@ -454,7 +514,7 @@ if (process.platform === "linux" && store.get(settings.mpris)) { | |||||||
|     console.log("player api not working"); |     console.log("player api not working"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | addCustomCss(); | ||||||
| addHotKeys(); | addHotKeys(); | ||||||
| addIPCEventListeners(); | addIPCEventListeners(); | ||||||
| addFullScreenListeners(); | addFullScreenListeners(); | ||||||
|   | |||||||
| @@ -26,8 +26,8 @@ const observer = (event, arg) => { | |||||||
|         ...idleStatus, |         ...idleStatus, | ||||||
|         ...{ |         ...{ | ||||||
|           details: `Listening to ${mediaInfoModule.mediaInfo.title}`, |           details: `Listening to ${mediaInfoModule.mediaInfo.title}`, | ||||||
|           state: mediaInfoModule.mediaInfo.artist |           state: mediaInfoModule.mediaInfo.artists | ||||||
|             ? mediaInfoModule.mediaInfo.artist |             ? mediaInfoModule.mediaInfo.artists | ||||||
|             : "unknown artist(s)", |             : "unknown artist(s)", | ||||||
|           startTimestamp: parseInt(now), |           startTimestamp: parseInt(now), | ||||||
|           endTimestamp: parseInt(remaining), |           endTimestamp: parseInt(remaining), | ||||||
| @@ -43,7 +43,7 @@ const observer = (event, arg) => { | |||||||
|         ...idleStatus, |         ...idleStatus, | ||||||
|         ...{ |         ...{ | ||||||
|           details: `Watching ${mediaInfoModule.mediaInfo.title}`, |           details: `Watching ${mediaInfoModule.mediaInfo.title}`, | ||||||
|           state: mediaInfoModule.mediaInfo.artist, |           state: mediaInfoModule.mediaInfo.artists, | ||||||
|           startTimestamp: parseInt(now), |           startTimestamp: parseInt(now), | ||||||
|           endTimestamp: parseInt(remaining), |           endTimestamp: parseInt(remaining), | ||||||
|         }, |         }, | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ expressModule.run = function(mainWindow) { | |||||||
|  |  | ||||||
|   const expressApp = express(); |   const expressApp = express(); | ||||||
|   expressApp.get("/", (req, res) => res.send("Hello World!")); |   expressApp.get("/", (req, res) => res.send("Hello World!")); | ||||||
|   expressApp.get("/current", (req, res) => res.json(mediaInfo)); |   expressApp.get("/current", (req, res) => res.json({ ...mediaInfo, artist: mediaInfo.artists })); | ||||||
|   expressApp.get("/image", (req, res) => { |   expressApp.get("/image", (req, res) => { | ||||||
|     var stream = fs.createReadStream(mediaInfo.icon); |     var stream = fs.createReadStream(mediaInfo.icon); | ||||||
|     stream.on("open", function () { |     stream.on("open", function () { | ||||||
|   | |||||||
| @@ -2,14 +2,14 @@ const statuses = require("./../constants/statuses"); | |||||||
|  |  | ||||||
| const mediaInfo = { | const mediaInfo = { | ||||||
|   title: "", |   title: "", | ||||||
|   artist: "", |   artists: "", | ||||||
|   album: "", |   album: "", | ||||||
|   icon: "", |   icon: "", | ||||||
|   status: statuses.paused, |   status: statuses.paused, | ||||||
|   url: "", |   url: "", | ||||||
|   current: "", |   current: "", | ||||||
|   duration: "", |   duration: "", | ||||||
|   image: "tidal-hifi-icon" |   image: "tidal-hifi-icon", | ||||||
| }; | }; | ||||||
| const mediaInfoModule = { | const mediaInfoModule = { | ||||||
|   mediaInfo, |   mediaInfo, | ||||||
| @@ -20,7 +20,7 @@ const mediaInfoModule = { | |||||||
|  */ |  */ | ||||||
| mediaInfoModule.update = function (arg) { | mediaInfoModule.update = function (arg) { | ||||||
|   mediaInfo.title = propOrDefault(arg.title); |   mediaInfo.title = propOrDefault(arg.title); | ||||||
|   mediaInfo.artist = propOrDefault(arg.message); |   mediaInfo.artists = propOrDefault(arg.artists); | ||||||
|   mediaInfo.album = propOrDefault(arg.album); |   mediaInfo.album = propOrDefault(arg.album); | ||||||
|   mediaInfo.icon = propOrDefault(arg.icon); |   mediaInfo.icon = propOrDefault(arg.icon); | ||||||
|   mediaInfo.url = propOrDefault(arg.url); |   mediaInfo.url = propOrDefault(arg.url); | ||||||
|   | |||||||
| @@ -7,29 +7,31 @@ let settingsWindow; | |||||||
|  |  | ||||||
| const store = new Store({ | const store = new Store({ | ||||||
|   defaults: { |   defaults: { | ||||||
|     notifications: true, |  | ||||||
|     api: true, |  | ||||||
|     playBackControl: true, |  | ||||||
|     skipArtists: false, |  | ||||||
|     skippedArtists: [""], |  | ||||||
|     adBlock: false, |     adBlock: false, | ||||||
|     disableBackgroundThrottle: true, |     api: true, | ||||||
|     menuBar: true, |  | ||||||
|     apiSettings: { |     apiSettings: { | ||||||
|       port: 47836, |       port: 47836, | ||||||
|     }, |     }, | ||||||
|     singleInstance: true, |     customCSS: "", | ||||||
|  |     disableBackgroundThrottle: true, | ||||||
|     disableHardwareMediaKeys: false, |     disableHardwareMediaKeys: false, | ||||||
|     trayIcon: true, |  | ||||||
|     minimizeOnClose: false, |  | ||||||
|     mpris: false, |  | ||||||
|     enableCustomHotkeys: false, |     enableCustomHotkeys: false, | ||||||
|     enableDiscord: false, |     enableDiscord: false, | ||||||
|     windowBounds: { width: 800, height: 600 }, |  | ||||||
|     flags: { |     flags: { | ||||||
|       gpuRasterization: true, |       gpuRasterization: true, | ||||||
|       disableHardwareMediaKeys: false, |       disableHardwareMediaKeys: false, | ||||||
|     }, |     }, | ||||||
|  |     menuBar: true, | ||||||
|  |     minimizeOnClose: false, | ||||||
|  |     mpris: false, | ||||||
|  |     notifications: true, | ||||||
|  |     playBackControl: true, | ||||||
|  |     singleInstance: true, | ||||||
|  |     skipArtists: false, | ||||||
|  |     skippedArtists: [""], | ||||||
|  |     trayIcon: true, | ||||||
|  |     updateFrequency: 500, | ||||||
|  |     windowBounds: { width: 800, height: 600 }, | ||||||
|   }, |   }, | ||||||
|   migrations: { |   migrations: { | ||||||
|     "3.1.0": (migrationStore) => { |     "3.1.0": (migrationStore) => { | ||||||
|   | |||||||