Compare commits

..

5 Commits

Author SHA1 Message Date
97b4e6d2fd Merge branch 'master' of github.com:Mastermindzh/tidal-hifi into pr-dest 2022-09-25 12:34:53 +02:00
058798be67 - icon is set to new static path based on Arch/Debian
- Name has changed to Tidal-Hifi
2022-09-25 12:31:59 +02:00
Ivo Šmerek
d26091d4aa Redesign of the settings window (#168)
* Pr dest (#166)

* Update configuration of the desktop file (#165)

* - Changed the category of the desktop file to AudioVideo
- Changed desktop file name to "TIDAL Hi-Fi"

Co-authored-by: Ivo Šmerek <ivo97@centrum.cz>

* Redesign of the settings window

* changed sass to scss, fixed color of switches and disabled rounded corners

Co-authored-by: Rick van Lieshout <info@rickvanlieshout.com>
2022-09-25 12:13:26 +02:00
0fe1f7a509 - Changed the category of the desktop file to AudioVideo
- Changed desktop file name to "TIDAL Hi-Fi"
2022-09-11 22:53:42 +02:00
Ivo Šmerek
87bb19a255 Update configuration of the desktop file (#165) 2022-09-11 22:48:55 +02:00
32 changed files with 6115 additions and 2791 deletions

View File

@@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build
@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build
@@ -36,6 +36,6 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build

1
.nvmrc
View File

@@ -1 +0,0 @@
19.8.1

View File

@@ -4,53 +4,13 @@ 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
- 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))
- @thanasistrisp updated Electron to 24.1.2 and fixed the tray bug :)
## 4.4.0
- Updated shortcut hint on the menubar to reflect the new `ctrl+=` shortcut.
- Reverted icon path to `icon.png` instead of the hardcoded linux path.
- Add support to autoHide the menubar and showing it with the `alt` key.
- Move the quit command from the system sub-menu to the main menu
- Added single click focus/show on the tray icon
- Doesn't work on all platforms. Nothing I can do about that unfortunately!
- Added a list of artists to automatically skip.
- I don't like the vast majority of dutch music so I added one of them to my list to test: [./docs/no-dutch-music.mp4](./docs/no-dutch-music.mp4)
## 4.3.1
- fix: App always requests a default-url-handler-scheme change on start
## 4.3.0
- Added a setting to disable background throttling ([docs](https://www.electronjs.org/docs/latest/api/browser-window))
## 4.2.0 ## 4.2.0
- New settings window by BlueManCZ - New settings window by BlueManCZ
- Fixed the desktop files in electron-builder - Fixed the desktop files in electron-builder
- icon is set to new static path based on Arch/Debian - icon is set to new static path based on Arch/Debian
- Name has changed to Tidal-Hifi - Name has changed to Tidal-Hifi
-
## 4.1.2 ## 4.1.2

View File

@@ -1,43 +1,39 @@
# Tidal-hifi<img src = "./build/icon.png" height="40" align="right"/> <h1>
Tidal-hifi
![GitHub release](https://img.shields.io/github/release/Mastermindzh/tidal-hifi.svg) <img src = "./build/icon.png" height="40" align="right" />
</h1>
The web version of [listen.tidal.com](https://listen.tidal.com) running in electron with hifi support thanks to widevine. The web version of [listen.tidal.com](https://listen.tidal.com) running in electron with hifi support thanks to widevine.
![tidal-hifi preview](./docs/preview.png) ![tidal-hifi preview](./docs/preview.png)
## Table of Contents ## Table of contents
<!-- toc --> <!-- toc -->
- [Installation](#installation) - [Installation](#installation)
- [Dependencies](#dependencies) * [Using releases](#using-releases)
- [Using releases](#using-releases) * [Snap](#snap)
- [Snap](#snap) * [Arch Linux](#arch-linux)
- [Arch Linux](#arch-linux) * [Flatpak](#flatpak)
- [Flatpak](#flatpak) * [Nix](#nix)
- [Nix](#nix) * [Using source](#using-source)
- [Using source](#using-source)
- [Features](#features) - [Features](#features)
- [Integrations](#integrations) - [Integrations](#integrations)
- [Known bugs](#known-bugs) * [Known bugs](#known-bugs)
- [last.fm doesn't work out of the box. Use rescrobbler as a workaround](#lastfm-doesnt-work-out-of-the-box-use-rescrobbler-as-a-workaround) + [last.fm doesn't work out of the box. Use rescrobbler as a workaround](#lastfm-doesnt-work-out-of-the-box-use-rescrobbler-as-a-workaround)
- [Why](#why) - [Why](#why)
- [Why not extend existing projects?](#why-not-extend-existing-projects) - [Why not extend existing projects?](#why-not-extend-existing-projects)
- [Special thanks to](#special-thanks-to) - [Special thanks to...](#special-thanks-to)
- [Buy me a coffee? Please don't](#buy-me-a-coffee-please-dont) - [Buy me a coffee? Please don't](#buy-me-a-coffee-please-dont)
- [Images](#images) - [Images](#images)
- [Settings window](#settings-window) * [Settings window](#settings-window)
- [User setups](#user-setups) * [User setups](#user-setups)
<!-- tocstop --> <!-- tocstop -->
## Installation ## Installation
### Dependencies
Note that you **need** a notification library such as [libnotify](https://github.com/GNOME/libnotify) or [dunst](https://github.com/dunst-project/dunst) in order for the software to work properly.
### Using releases ### Using releases
Various packaged versions of the software are available on the [releases](https://github.com/Mastermindzh/tidal-hifi/releases) tab. Various packaged versions of the software are available on the [releases](https://github.com/Mastermindzh/tidal-hifi/releases) tab.
@@ -97,7 +93,7 @@ To install and work with the code on this project follow these steps:
- Notifications - Notifications
- Custom hotkeys ([source](https://defkey.com/tidal-desktop-shortcuts)) - Custom hotkeys ([source](https://defkey.com/tidal-desktop-shortcuts))
- API for status and playback - API for status and playback
- Disabled audio & visual ads, unlocked lyrics, suggested track, track info, and unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495)) - [Mute artists automatically (defaults to "Tidal")]("./docs/muting-artists.md")
- Custom [integrations](#integrations) - Custom [integrations](#integrations)
- [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+=` or `ctrl+0`) - [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+=` or `ctrl+0`)
- AlbumArt in integrations ([best-effort](https://github.com/Mastermindzh/tidal-hifi/pull/88#pullrequestreview-840814847)) - AlbumArt in integrations ([best-effort](https://github.com/Mastermindzh/tidal-hifi/pull/88#pullrequestreview-840814847))
@@ -143,7 +139,7 @@ Whilst there are a handful of projects attempting to run Tidal on Electron they
Sometimes it's just easier to start over, cover my own needs and then making it available to the public :) Sometimes it's just easier to start over, cover my own needs and then making it available to the public :)
## Special thanks to ## Special thanks to...
- [Castlabs](https://castlabs.com/) - [Castlabs](https://castlabs.com/)
For maintaining Electron with Widevine CDM installation, Verified Media Path (VMP), and persistent licenses (StorageID) For maintaining Electron with Widevine CDM installation, Verified Media Path (VMP), and persistent licenses (StorageID)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,7 +1,7 @@
appId: com.rickvanlieshout.tidal-hifi appId: com.rickvanlieshout.tidal-hifi
electronVersion: 24.1.2 electronVersion: 19.0.5
electronDownload: electronDownload:
version: 24.1.2+wvcus version: 19.0.5+wvcus
mirror: https://github.com/castlabs/electron-releases/releases/download/v mirror: https://github.com/castlabs/electron-releases/releases/download/v
snap: snap:
plugs: plugs:
@@ -9,7 +9,7 @@ snap:
- screen-inhibit-control - screen-inhibit-control
linux: linux:
category: AudioVideo category: AudioVideo
icon: assets/icons icon: icon.png
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: tidal-hifi Icon: /usr/share/icons/hicolor/0x0/apps/tidal-hifi.png
StartupNotify: true StartupNotify: true
Terminal: false Terminal: false
Type: Application Type: Application

View File

@@ -1,4 +1,5 @@
extends: ./build/electron-builder.base.yml extends: ./build/electron-builder.base.yml
linux: linux:
icon: icon.png
target: target:
- pacman - pacman

11
docs/muting-artists.md Normal file
View File

@@ -0,0 +1,11 @@
# Muting artists
If you feel that some of your music is embarrassing for others you can mute specific artists in the settings window.
This functionality is inspired by the [adblock ticket](https://github.com/Mastermindzh/tidal-hifi/issues/112), and whilst I personally feel you should simply buy Tidal, I also believe in muting sound that you don't want to hear.
Anyway, to block an artist, open the settings window (see image below) and enter a list of artists in the textarea as seen below.
Don't forget to turn the feature on and Tidal-hifi will automatically mute the player whenever that artist is playing.
This will allow you to skip the song without anyone noticing. (you can always say "no idea, it seems to have no audio").
![muted artists settings window](./settings-muted-artists.png)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

8313
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "tidal-hifi", "name": "tidal-hifi",
"version": "5.1.0", "version": "4.2.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": {
@@ -31,24 +31,23 @@
"homepage": "https://github.com/Mastermindzh/tidal-hifi", "homepage": "https://github.com/Mastermindzh/tidal-hifi",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@electron/remote": "^2.0.9", "@electron/remote": "^2.0.8",
"discord-rpc": "^4.0.1", "discord-rpc": "^4.0.1",
"electron-store": "^8.1.0", "electron-store": "^8.1.0",
"express": "^4.18.2", "express": "^4.18.1",
"hotkeys-js": "^3.10.2", "hotkeys-js": "^3.9.4",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"request": "^2.88.2", "request": "^2.88.2",
"sass": "^1.62.0" "sass": "^1.54.9"
}, },
"devDependencies": { "devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0", "@mastermindzh/prettier-config": "^1.0.0",
"electron": "git+https://github.com/castlabs/electron-releases.git#v24.1.2+wvcus", "electron": "git+https://github.com/castlabs/electron-releases.git#v19.0.5+wvcus",
"electron-builder": "^24.2.1", "electron-builder": "^23.3.3",
"js-yaml": "^4.1.0", "js-yaml": "^3.14.1",
"markdown-toc": "^1.2.0", "prettier": "^2.7.1",
"prettier": "^2.8.7",
"sass-lint": "^1.13.1", "sass-lint": "^1.13.1",
"sass-lint-auto-fix": "^0.21.2" "sass-lint-auto-fix": "^0.21.2"
}, },
"prettier": "@mastermindzh/prettier-config" "prettier": "@mastermindzh/prettier-config"
} }

View File

@@ -9,36 +9,32 @@
* windowBounds: { width: 800, height: 600 }, * windowBounds: { width: 800, height: 600 },
*/ */
const settings = { const settings = {
adBlock: "adBlock", notifications: "notifications",
api: "api", api: "api",
menuBar: "menuBar",
playBackControl: "playBackControl",
muteArtists: "muteArtists",
mutedArtists: "mutedArtists",
apiSettings: { apiSettings: {
root: "apiSettings", root: "apiSettings",
port: "apiSettings.port", port: "apiSettings.port",
}, },
customCSS: "customCSS", singleInstance: "singleInstance",
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",
notifications: "notifications", enableCustomHotkeys: "enableCustomHotkeys",
playBackControl: "playBackControl",
singleInstance: "singleInstance",
skipArtists: "skipArtists",
skippedArtists: "skippedArtists",
trayIcon: "trayIcon", trayIcon: "trayIcon",
updateFrequency: "updateFrequency", enableDiscord: "enableDiscord",
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;

View File

@@ -1,13 +1,5 @@
require("@electron/remote/main").initialize(); require("@electron/remote/main").initialize();
const { const { app, BrowserWindow, components, globalShortcut, ipcMain, protocol } = require("electron");
app,
BrowserWindow,
components,
globalShortcut,
ipcMain,
protocol,
session,
} = require("electron");
const { const {
settings, settings,
store, store,
@@ -57,10 +49,7 @@ function setFlags() {
* *
*/ */
function syncMenuBarWithStore() { function syncMenuBarWithStore() {
const fixedMenuBar = store.get(settings.menuBar); mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
mainWindow.autoHideMenuBar = !fixedMenuBar;
mainWindow.setMenuBarVisibility(fixedMenuBar);
} }
/** /**
@@ -89,9 +78,7 @@ function createWindow(options = {}) {
height: store && store.get(settings.windowBounds.height), height: store && store.get(settings.windowBounds.height),
icon, icon,
backgroundColor: options.backgroundColor, backgroundColor: options.backgroundColor,
autoHideMenuBar: true,
webPreferences: { webPreferences: {
sandbox: false,
preload: path.join(__dirname, "preload.js"), preload: path.join(__dirname, "preload.js"),
plugins: true, plugins: true,
devTools: true, // I like tinkering, others might too devTools: true, // I like tinkering, others might too
@@ -104,11 +91,6 @@ function createWindow(options = {}) {
// load the Tidal website // load the Tidal website
mainWindow.loadURL(tidalUrl); mainWindow.loadURL(tidalUrl);
if (store.get(settings.disableBackgroundThrottle)) {
// prevent setInterval lag
mainWindow.webContents.setBackgroundThrottling(false);
}
// run stuff after first load // run stuff after first load
mainWindow.webContents.once("did-finish-load", () => {}); mainWindow.webContents.once("did-finish-load", () => {});
@@ -136,9 +118,7 @@ function registerHttpProtocols() {
protocol.registerHttpProtocol(PROTOCOL_PREFIX, (request, _callback) => { protocol.registerHttpProtocol(PROTOCOL_PREFIX, (request, _callback) => {
mainWindow.loadURL(`${tidalUrl}/${request.url.substring(PROTOCOL_PREFIX.length + 3)}`); mainWindow.loadURL(`${tidalUrl}/${request.url.substring(PROTOCOL_PREFIX.length + 3)}`);
}); });
if (!app.isDefaultProtocolClient(PROTOCOL_PREFIX)) { app.setAsDefaultProtocolClient(PROTOCOL_PREFIX);
app.setAsDefaultProtocolClient(PROTOCOL_PREFIX);
}
} }
function addGlobalShortcuts() { function addGlobalShortcuts() {
@@ -155,16 +135,6 @@ function addGlobalShortcuts() {
app.on("ready", async () => { app.on("ready", async () => {
if (isMainInstanceOrMultipleInstancesAllowed()) { if (isMainInstanceOrMultipleInstancesAllowed()) {
await components.whenReady(); await components.whenReady();
// Adblock
if (store.get(settings.adBlock)) {
const filter = { urls: ["https://listen.tidal.com/*"] };
session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
if (details.url.match(/\/users\/.*\d\?country/)) callback({ cancel: true });
else callback({ cancel: false });
});
}
createWindow(); createWindow();
addMenu(mainWindow); addMenu(mainWindow);
createSettingsWindow(); createSettingsWindow();
@@ -172,6 +142,7 @@ 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();
} }

View File

@@ -1,22 +1,18 @@
let adBlock, let trayIcon,
api,
customCSS,
disableBackgroundThrottle,
disableHardwareMediaKeys,
enableCustomHotkeys,
enableDiscord,
gpuRasterization,
menuBar,
minimizeOnClose, minimizeOnClose,
mpris, mpris,
enableCustomHotkeys,
enableDiscord,
muteArtists,
notifications, notifications,
playBackControl, playBackControl,
api,
port, port,
menuBar,
mutedArtists,
singleInstance, singleInstance,
skipArtists, disableHardwareMediaKeys,
skippedArtists, gpuRasterization;
trayIcon,
updateFrequency;
const { store, settings } = require("./../../scripts/settings"); const { store, settings } = require("./../../scripts/settings");
const { ipcRenderer } = require("electron"); const { ipcRenderer } = require("electron");
@@ -27,25 +23,21 @@ const { app } = remote;
* Sync the UI forms with the current settings * Sync the UI forms with the current settings
*/ */
function refreshSettings() { function refreshSettings() {
adBlock.checked = store.get(settings.adBlock);
api.checked = store.get(settings.api);
customCSS.value = store.get(settings.customCSS);
disableBackgroundThrottle.checked = store.get("disableBackgroundThrottle");
disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys);
enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
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);
mpris.checked = store.get(settings.mpris);
notifications.checked = store.get(settings.notifications); notifications.checked = store.get(settings.notifications);
playBackControl.checked = store.get(settings.playBackControl); playBackControl.checked = store.get(settings.playBackControl);
api.checked = store.get(settings.api);
port.value = store.get(settings.apiSettings.port); port.value = store.get(settings.apiSettings.port);
singleInstance.checked = store.get(settings.singleInstance); menuBar.checked = store.get(settings.menuBar);
skipArtists.checked = store.get(settings.skipArtists);
skippedArtists.value = store.get(settings.skippedArtists).join("\n");
trayIcon.checked = store.get(settings.trayIcon); trayIcon.checked = store.get(settings.trayIcon);
updateFrequency.value = store.get(settings.updateFrequency); mpris.checked = store.get(settings.mpris);
enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
enableDiscord.checked = store.get(settings.enableDiscord);
minimizeOnClose.checked = store.get(settings.minimizeOnClose);
muteArtists.checked = store.get(settings.muteArtists);
mutedArtists.value = store.get(settings.mutedArtists).join("\n");
singleInstance.checked = store.get(settings.singleInstance);
disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys);
gpuRasterization.checked = store.get(settings.flags.gpuRasterization);
} }
/** /**
@@ -68,7 +60,7 @@ function hide() {
*/ */
function restart() { function restart() {
app.relaunch(); app.relaunch();
app.exit(); app.quit();
} }
/** /**
@@ -113,45 +105,37 @@ window.addEventListener("DOMContentLoaded", () => {
document.getElementById(tab).click(); document.getElementById(tab).click();
}); });
adBlock = get("adBlock");
api = get("apiCheckbox");
customCSS = get("customCSS");
disableBackgroundThrottle = get("disableBackgroundThrottle");
disableHardwareMediaKeys = get("disableHardwareMediaKeys");
enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord");
gpuRasterization = get("gpuRasterization");
menuBar = get("menuBar");
minimizeOnClose = get("minimizeOnClose");
mpris = get("mprisCheckbox");
notifications = get("notifications"); notifications = get("notifications");
playBackControl = get("playBackControl"); playBackControl = get("playBackControl");
api = get("apiCheckbox");
port = get("port"); port = get("port");
menuBar = get("menuBar");
trayIcon = get("trayIcon"); trayIcon = get("trayIcon");
skipArtists = get("skipArtists"); minimizeOnClose = get("minimizeOnClose");
skippedArtists = get("skippedArtists"); mpris = get("mprisCheckbox");
enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord");
muteArtists = get("muteArtists");
mutedArtists = get("mutedArtists");
singleInstance = get("singleInstance"); singleInstance = get("singleInstance");
updateFrequency = get("updateFrequency"); disableHardwareMediaKeys = get("disableHardwareMediaKeys");
gpuRasterization = get("gpuRasterization");
refreshSettings(); refreshSettings();
addInputListener(adBlock, settings.adBlock);
addInputListener(api, settings.api);
addTextAreaListener(customCSS, settings.customCSS);
addInputListener(disableBackgroundThrottle, settings.disableBackgroundThrottle);
addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys);
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord);
addInputListener(gpuRasterization, settings.flags.gpuRasterization);
addInputListener(menuBar, settings.menuBar);
addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(mpris, settings.mpris);
addInputListener(notifications, settings.notifications); addInputListener(notifications, settings.notifications);
addInputListener(playBackControl, settings.playBackControl); addInputListener(playBackControl, settings.playBackControl);
addInputListener(api, settings.api);
addInputListener(port, settings.apiSettings.port); addInputListener(port, settings.apiSettings.port);
addInputListener(skipArtists, settings.skipArtists); addInputListener(menuBar, settings.menuBar);
addTextAreaListener(skippedArtists, settings.skippedArtists);
addInputListener(singleInstance, settings.singleInstance);
addInputListener(trayIcon, settings.trayIcon); addInputListener(trayIcon, settings.trayIcon);
addInputListener(updateFrequency, settings.updateFrequency); addInputListener(mpris, settings.mpris);
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord);
addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(muteArtists, settings.muteArtists);
addTextAreaListener(mutedArtists, settings.mutedArtists);
addInputListener(singleInstance, settings.singleInstance);
addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys);
addInputListener(gpuRasterization, settings.flags.gpuRasterization);
}); });

View File

@@ -48,44 +48,31 @@
<p>Show a notification when a new song starts.</p> <p>Show a notification when a new song starts.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="notifications" type="checkbox" /> <input id="notifications" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>Skip Artists automatically</h4> <h4>Mute Artists automatically</h4>
<p>The following list of artists (1 per line) will be skipped automatically.</p> <p>The following list of artists (1 per line) will be muted automatically.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="skipArtists" type="checkbox" /> <input id="muteArtists" type="checkbox">
<span class="switch__slider"></span>
</label>
</div>
<textarea id="skippedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
<div class="group__option">
<div class="group__description">
<h4>Block ads</h4>
<p>
Disabled audio & visual ads, unlocked lyrics, suggested track, track info,
unlimited skips
</p>
</div>
<label class="switch">
<input id="adBlock" type="checkbox" />
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
<textarea id="mutedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
</div> </div>
<div class="group"> <div class="group">
<p class="group__title">UI</p> <p class="group__title">UI</p>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>Fixed menubar</h4> <h4>Menubar</h4>
<p>Always show TIDAL Hi-Fi's menu bar.</p> <p>Show TIDAL Hi-Fi's menu bar.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="menuBar" type="checkbox" /> <input id="menuBar" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -98,7 +85,7 @@
<p>Show TIDAL Hi-Fi's tray icon.</p> <p>Show TIDAL Hi-Fi's tray icon.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="trayIcon" type="checkbox" /> <input id="trayIcon" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -108,7 +95,7 @@
<p>Minimize window on close instead.</p> <p>Minimize window on close instead.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="minimizeOnClose" type="checkbox" /> <input id="minimizeOnClose" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -121,7 +108,7 @@
</p> </p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="enableCustomHotkeys" type="checkbox" /> <input id="enableCustomHotkeys" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -131,7 +118,7 @@
<p>Prevent opening multiple TIDAL Hi-Fi's instances.</p> <p>Prevent opening multiple TIDAL Hi-Fi's instances.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="singleInstance" type="checkbox" /> <input id="singleInstance" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -143,8 +130,8 @@
<p class="group__title">API</p> <p class="group__title">API</p>
<div class="group__description"> <div class="group__description">
<p> <p>
TIDAL Hi-Fi has a built-in web API to allow users to get current song information. TIDAL Hi-Fi has a built-in web API to allow users to get current song information. You can optionally
You can optionally enable playback control as well. enable playback control as well.
</p> </p>
</div> </div>
<div class="group__option"> <div class="group__option">
@@ -153,14 +140,14 @@
<p>Enable the TIDAL Hi-Fi web API.</p> <p>Enable the TIDAL Hi-Fi web API.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="apiCheckbox" type="checkbox" /> <input id="apiCheckbox" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
<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="number" class="text-input" name="port" /> <input id="port" type="text" class="text-input" name="port">
</div> </div>
</div> </div>
<div class="group__option"> <div class="group__option">
@@ -169,7 +156,7 @@
<p>Enable playback control from the web API.</p> <p>Enable playback control from the web API.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="playBackControl" type="checkbox" /> <input id="playBackControl" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -181,20 +168,18 @@
<p class="group__title">Integrations</p> <p class="group__title">Integrations</p>
<div class="group__description"> <div class="group__description">
<p> <p>
TIDAL Hi-Fi is extensible through the use of integrations. You can enable or TIDAL Hi-Fi is extensible through the use of integrations.
disable them here. You can enable or disable them here.
</p> </p>
</div> </div>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>MPRIS</h4> <h4>MPRIS</h4>
<p> <p>Enable MPRIS interface which provides a mechanism for discovery, querying and basic playback control
Enable MPRIS interface which provides a mechanism for discovery, querying and on Linux systems.</p>
basic playback control on Linux systems.
</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="mprisCheckbox" type="checkbox" /> <input id="mprisCheckbox" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -204,7 +189,7 @@
<p>Show what you're listening to on Discord.</p> <p>Show what you're listening to on Discord.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="enableDiscord" type="checkbox" /> <input id="enableDiscord" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -212,43 +197,18 @@
</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">
<div class="group__description"> <div class="group__description">
<h4>Disable hardware built-in media keys</h4> <h4>Disable hardware built-in media keys</h4>
<p> <p>
Also prevents certain desktop environments from recognizing the chrome MPRIS Also prevents certain desktop environments from recognizing the chrome
client separately from the custom MPRIS client. MPRIS client separately from the custom MPRIS client.
</p> </p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="disableHardwareMediaKeys" type="checkbox" /> <input id="disableHardwareMediaKeys" type="checkbox">
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -258,19 +218,7 @@
<p>Move a part of the rendering to the GPU for increased performance.</p> <p>Move a part of the rendering to the GPU for increased performance.</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="gpuRasterization" type="checkbox" /> <input id="gpuRasterization" type="checkbox">
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<h4>Disable Background Throttling</h4>
<p>
Makes app more responsive while in the background, at the cost of performance.
</p>
</div>
<label class="switch">
<input id="disableBackgroundThrottle" type="checkbox" />
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
@@ -278,20 +226,17 @@
</section> </section>
<section id="about-section" class="tabs__section about-section"> <section id="about-section" class="tabs__section about-section">
<img alt="tidal icon" class="about-section__icon" src="./icon.png" /> <img alt="tidal icon" class="about-section__icon" src="./icon.png">
<p class="about-section__text"> <p class="about-section__text">
<a class="external-link" data-url="https://github.com/Mastermindzh/tidal-hifi">TIDAL Hi-Fi</a> <a class="external-link" data-url="https://github.com/Mastermindzh/tidal-hifi">TIDAL Hi-Fi</a>
is made by is made by <a class="external-link" data-url="https://www.rickvanlieshout.com">
<a class="external-link" data-url="https://www.rickvanlieshout.com"> Rick van Lieshout</a>. <br>It uses <a class="external-link" data-url="https://castlabs.com/">Castlabs'</a>
Rick van Lieshout</a>. <br />It uses
<a class="external-link" data-url="https://castlabs.com/">Castlabs'</a>
version of Electron for widevine support. version of Electron for widevine support.
</p> </p>
</section> </section>
<footer class="footer"> <footer class="footer">
<p class="footer__note"> <p class="footer__note">Some settings may require a restart of TIDAL Hi-Fi. To do so, click the button below:
Some settings may require a restart of TIDAL Hi-Fi. To do so, click the button below:
</p> </p>
<button class="footer__button" id="restart">Restart TIDAL Hi-Fi</button> <button class="footer__button" id="restart">Restart TIDAL Hi-Fi</button>
</footer> </footer>
@@ -300,4 +245,4 @@
</div> </div>
</body> </body>
</html> </html>

View File

@@ -7,12 +7,12 @@ 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, 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 = "";
let player; let player;
let currentPlayStatus = statuses.paused; let currentPlayStatus = statuses.paused;
let isMutedArtist = true;
const elements = { const elements = {
play: '*[data-test="play"]', play: '*[data-test="play"]',
@@ -65,27 +65,16 @@ 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.querySelectorAll(this.artists); const artists = footer.querySelector(this["artists"]);
if (artists) return Array.from(artists).map((artist) => artist.textContent); if (artists) {
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)";
}, },
@@ -143,29 +132,6 @@ 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
*/ */
@@ -323,18 +289,17 @@ 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.artists, icon: options.icon }).show(); new Notification({ title: options.title, body: options.message, 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.artists], "xesam:artist": [options.message],
"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,
"mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(),
}, },
}; };
player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing"; player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing";
@@ -347,54 +312,31 @@ function updateMediaInfo(options, notify) {
* If it's a song it returns the track URL, if not it will return undefined * If it's a song it returns the track URL, if not it will return undefined
*/ */
function getTrackURL() { function getTrackURL() {
const id = getTrackID();
return `https://tidal.com/browse/track/${id}`;
}
function getTrackID() {
const URLelement = elements.get("title").querySelector("a"); const URLelement = elements.get("title").querySelector("a");
if (URLelement !== null) { if (URLelement !== null) {
const id = URLelement.href.replace(/\D/g, ""); const id = URLelement.href.replace(/[^0-9]/g, "");
return id; return `https://tidal.com/browse/track/${id}`;
} }
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 artistsArray = elements.getArtistsArray(); const artists = elements.getArtists();
const artistsString = elements.getArtistsString(artistsArray); muteArtistIfFoundInMutedArtistsList(); // doing this here so that nothing can possibly fail before we call this function
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} - ${artistsString}`; const songDashArtistTitle = `${title} - ${artists}`;
const currentStatus = getCurrentlyPlayingStatus(); const currentStatus = getCurrentlyPlayingStatus();
const options = { const options = {
title, title,
artists: artistsString, message: artists,
album: album, album: album,
status: currentStatus, status: currentStatus,
url: getTrackURL(), url: getTrackURL(),
@@ -402,8 +344,11 @@ setInterval(function () {
duration, duration,
"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);
@@ -432,32 +377,29 @@ setInterval(function () {
} }
}).then( }).then(
() => { () => {
updateMediaInfo(options, titleOrArtistsChanged); updateMediaInfo(options, titleOrArtistChanged);
if (titleOrArtistsChanged) {
updateMediaSession(options);
}
}, },
() => {} () => {}
); );
/** /**
* automatically skip a song if the artists are found in the list of artists to skip * Checks whether the current artist is included in the "muted artists" list and if so it will automatically mute the player
* @param {*} artists array of artists
*/ */
function skipArtistsIfFoundInSkippedArtistsList(artists) { function muteArtistIfFoundInMutedArtistsList() {
if (store.get(skipArtists)) { if (store.get(settings.muteArtists)) {
const skippedArtists = store.get(settings.skippedArtists); const mutedArtists = store.get(settings.mutedArtists);
if (skippedArtists.length > 0) { if (mutedArtists.find((artist) => artist === artists) !== undefined) {
const artistsToSkip = skippedArtists.map((artist) => artist); if (!elements.isMuted()) {
const artistNames = Object.values(artists).map((artist) => artist); isMutedArtist = true;
const foundArtist = artistNames.some((artist) => artistsToSkip.includes(artist)); elements.click("volume");
if (foundArtist) {
elements.click("next");
} }
} else if (isMutedArtist && elements.isMuted()) {
elements.click("volume");
isMutedArtist = false;
} }
} }
} }
}, getUpdateFrequency()); }, 1000);
if (process.platform === "linux" && store.get(settings.mpris)) { if (process.platform === "linux" && store.get(settings.mpris)) {
try { try {
@@ -514,7 +456,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();

View File

@@ -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.artists state: mediaInfoModule.mediaInfo.artist
? mediaInfoModule.mediaInfo.artists ? mediaInfoModule.mediaInfo.artist
: "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.artists, state: mediaInfoModule.mediaInfo.artist,
startTimestamp: parseInt(now), startTimestamp: parseInt(now),
endTimestamp: parseInt(remaining), endTimestamp: parseInt(remaining),
}, },

View File

@@ -11,7 +11,7 @@ let expressInstance;
/** /**
* Function to enable tidal-hifi's express api * Function to enable tidal-hifi's express api
*/ */
expressModule.run = function (mainWindow) { expressModule.run = function(mainWindow) {
/** /**
* Shorthand to handle a fire and forget global event * Shorthand to handle a fire and forget global event
* @param {*} res * @param {*} res
@@ -24,14 +24,14 @@ 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, artist: mediaInfo.artists })); expressApp.get("/current", (req, res) => res.json(mediaInfo));
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() {
res.set("Content-Type", "image/png"); res.set("Content-Type", "image/png");
stream.pipe(res); stream.pipe(res);
}); });
stream.on("error", function () { stream.on("error", function() {
res.set("Content-Type", "text/plain"); res.set("Content-Type", "text/plain");
res.status(404).end("Not found"); res.status(404).end("Not found");
}); });
@@ -54,7 +54,7 @@ expressModule.run = function (mainWindow) {
let port = store.get(settings.apiSettings.port); let port = store.get(settings.apiSettings.port);
expressInstance = expressApp.listen(port, "127.0.0.1", () => {}); expressInstance = expressApp.listen(port, "127.0.0.1", () => {});
expressInstance.on("error", function (e) { expressInstance.on("error", function(e) {
let message = e.code; let message = e.code;
if (e.code === "EADDRINUSE") { if (e.code === "EADDRINUSE") {
message = `Port ${port} in use.`; message = `Port ${port} in use.`;

View File

@@ -2,14 +2,14 @@ const statuses = require("./../constants/statuses");
const mediaInfo = { const mediaInfo = {
title: "", title: "",
artists: "", artist: "",
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.artists = propOrDefault(arg.artists); mediaInfo.artist = propOrDefault(arg.message);
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);

View File

@@ -8,7 +8,7 @@ const settingsMenuEntry = {
click() { click() {
showSettingsWindow(); showSettingsWindow();
}, },
accelerator: "Control+=", accelerator: "Control+/",
}; };
const quitMenuEntry = { const quitMenuEntry = {
@@ -110,7 +110,6 @@ menuModule.getMenu = function (mainWindow) {
}, },
}, },
toggleWindow, toggleWindow,
quitMenuEntry,
]; ];
return Menu.buildFromTemplate(mainMenu); return Menu.buildFromTemplate(mainMenu);

View File

@@ -7,31 +7,27 @@ let settingsWindow;
const store = new Store({ const store = new Store({
defaults: { defaults: {
adBlock: false, notifications: true,
api: true, api: true,
playBackControl: true,
muteArtists: false,
mutedArtists: ["TIDAL"],
menuBar: true,
apiSettings: { apiSettings: {
port: 47836, port: 47836,
}, },
customCSS: "", singleInstance: true,
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) => {

View File

@@ -11,18 +11,6 @@ trayModule.addTray = function (mainWindow, options = { icon: "" }) {
const menu = getMenu(mainWindow); const menu = getMenu(mainWindow);
tray.setContextMenu(menu); tray.setContextMenu(menu);
tray.on("click", function () {
if (mainWindow.isVisible()) {
if (!mainWindow.isFocused()) {
mainWindow.focus();
} else {
mainWindow.hide();
}
} else {
mainWindow.show();
}
});
}; };
trayModule.refreshTray = function (mainWindow) { trayModule.refreshTray = function (mainWindow) {