Compare commits

...

30 Commits
2.2.1 ... 2.8.1

Author SHA1 Message Date
7f5f5e7f62 Merge branch 'master' of github.com:Mastermindzh/tidal-hifi 2022-04-21 17:52:50 +02:00
6a1a1efe74 add apt-get update 2022-04-21 17:52:31 +02:00
94e1bb1780 add apt-get update 2022-04-21 17:51:21 +02:00
d66dd8cc9e 2.8.1 release 2022-04-21 17:49:11 +02:00
Cukmekerb
de97ac8a00 make quit button actually quit app (#123) 2022-04-21 17:46:49 +02:00
Marie
82ac5edf22 Update build version to fit with package.json electron version (#128)
* Update build version to fit with package.json electron version

* Update electron-builder.yml

* Use wvcus.2 for additional fixes

* Also use wvcus.2 for package.json
2022-04-21 17:46:05 +02:00
Bruno Unna
909c8ee8ba Fix the link to donations for kwf (#120)
Co-authored-by: Bruno Unna <bunna@getvisibility.com>
2022-04-11 12:07:55 +02:00
Marie
15b6b13e14 Change tidal-hifi to tidal-hifi-bin for AUR (#118) 2022-04-01 15:41:30 +02:00
89589b75e1 changed muted artists to TIDAL 2022-03-31 17:42:34 +02:00
6a7b3eefd4 Muting artists automatically (#116)
Co-authored-by: Cukmekerb <cukmekerb@gmail.com>
2022-03-31 17:37:12 +02:00
dependabot[bot]
0583c4a188 Bump plist from 3.0.4 to 3.0.5 (#115)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-28 08:53:36 +02:00
dependabot[bot]
8855e7f89f Bump minimist from 1.2.5 to 1.2.6 (#114)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-26 18:59:52 +01:00
dependabot[bot]
4fbb598c50 Bump node-fetch from 2.6.1 to 2.6.7 (#105)
Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-17 16:47:48 +01:00
101fe967d3 version bump and changelog 2022-02-17 12:58:35 +01:00
Marie
53468e0dc3 Fix issue causing the app to crash (#104) 2022-02-17 12:57:26 +01:00
53cecbcd18 added a hotkey on ctrl+0 for settings. fixes #91 2022-01-23 11:02:28 +01:00
5a65f60cc5 Fixed bug: Triggering fullscreen from the Tidal web app would cause the menubar to be visible even if it was disabled in the settings (#96)
Co-authored-by: Diogo Oliveira <dromarques@outlook.com>
2022-01-23 10:55:50 +01:00
d51d5cdc24 Use native electron notifications and album text (#90)
Co-authored-by: Diogo Oliveira <dromarques@outlook.com>
2021-12-28 17:31:10 +01:00
0dec967e71 Add album image to media module and discord (#86)
Co-authored-by: Diogo Oliveira <diogoomarques98@gmail.com>
Co-authored-by: Marie <marie@kaifa.ch>
2021-12-19 13:18:39 +01:00
Kevin Yuan
c940d0991d Generate pacman builds using Github workflows (#81)
* Show "Tidal Hifi" as application name for notify-send

Set the 'app-name' variable for notify-send under Linux

* Generate pacman builds using Github workflows
Previous builds failed due to missing build dependencies when building the package using the Github workflow Linux environment
2021-12-08 18:35:39 +01:00
662ef6ad7b new deps (#77) 2021-12-04 12:51:19 +01:00
5313ab13d3 Merge pull request #76 from Mastermindzh/develop 2021-12-04 11:23:32 +01:00
f43f227191 added changelog and bumped version 2021-12-04 11:23:03 +01:00
Kevin Yuan
ae25d88e94 Show "Tidal Hifi" as application name for notify-send notifications (#75) 2021-12-04 11:21:14 +01:00
5ef6074015 Release 2.4.0 (#74)
Update MPRIS functionality to provide length, artist, and current position.
Also added rescrobbler explanation to the README.

Co-authored-by: Vinay V <cool00geek@yahoo.com>
2021-11-29 22:43:51 +01:00
8fea5265e7 Merge branch 'master' of github.com:Mastermindzh/tidal-hifi 2021-06-17 20:51:15 +02:00
8d2e03ca6b Merge branch 'master' of github.com:Mastermindzh/tidal-hifi 2021-06-17 20:45:33 +02:00
1074de228b Merge branch 'master' of github.com:Mastermindzh/tidal-hifi 2021-06-17 20:44:30 +02:00
Ignacio Brasca
64d1aa4041 Implement minimized action to hide the application on close (#60)
* Implement minimzed action to hide the application on close instead of
closing it.

* Add close event on the tray icon

* Add all items in the menu (not only Show/Close app)

* Changes on mainWindow. Toggle instead of Open/Close pair button
2021-06-17 20:44:23 +02:00
Ignacio Brasca
6608330ed3 Implement minimized action to hide the application on close (#60)
* Implement minimzed action to hide the application on close instead of
closing it.

* Add close event on the tray icon

* Add all items in the menu (not only Show/Close app)

* Changes on mainWindow. Toggle instead of Open/Close pair button
2021-06-17 20:37:14 +02:00
21 changed files with 3469 additions and 2337 deletions

View File

@@ -9,10 +9,14 @@ jobs:
build_on_linux:
runs-on: ubuntu-latest
steps:
- name: update apt
run: sudo apt-get update
- name: Install libarchive-tools
run: sudo apt-get install -y libarchive-tools
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build
@@ -22,7 +26,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build
@@ -32,6 +36,6 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build

View File

@@ -9,10 +9,14 @@ jobs:
build_on_linux:
runs-on: ubuntu-latest
steps:
- name: update apt
run: sudo apt-get update
- name: Install libarchive-tools
run: sudo apt-get install -y libarchive-tools
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master
@@ -26,7 +30,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master
@@ -40,7 +44,7 @@ jobs:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
node-version: 12
node-version: 16
- run: npm install
- run: npm run build
- uses: actions/upload-artifact@master

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"cSpell.words": ["hifi", "rescrobbler", "widevine"]
}

View File

@@ -4,6 +4,56 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.8.1
- Mar0xy fixed some build issues (thanks!)
- vincens2005 fixed the quit button in the menubar
## 2.8.0
- Added the ability to mute artists automatically
- Added better error handling for discord rpc
## 2.7.2
- Disabled sandboxing to fix a display compositor issue on Linux.
## 2.7.1
- Fixed bug: Triggering full screen from the Tidal web app would cause the menubar to be visible even if it was disabled in the settings
## 2.7.0
- Switched to the native Notifier (removed node-notifier)
- Album art now also has a name, based on [best effort](https://github.com/Mastermindzh/tidal-hifi/pull/88#pullrequestreview-840814847)
## 2.6.0
- Add album images to media info and discord
## 2.5.0
- Notify-send now correctly shows "Tidal HiFi" as the program name
- Updated dependencies (including electron itself)
### known issues
- Requires older version of nodejs due to electron-builder (use lts/gallium)
### builds
updated to nodejs 16 in actions
## 2.4.0
- Added more MPRIS settings
- Added instruction for rescrobbler to get last.fm working without sandbox mode
## 2.3.0
- Added a setting to minimize to tray on app close (off by default)
- Added the main menu to the tray icon
## 2.2.1
- artists is now gotten specifically from the footer. This fixes the [unknown artists bug](https://github.com/Mastermindzh/tidal-hifi/issues/45).
@@ -16,10 +66,10 @@ moved to: [https://github.com/Mastermindzh/tidal-hifi-aur](https://github.com/Ma
## 2.2.0
- The discord integration now adds a time remaining field based on the song duration
- All fields (current, remaining, and url are also available in the API*)
- All fields (current, remaining, and url are also available in the API\*)
- the artist field is now correctly identified
* current time only updates on play/pause.
\* current time only updates on play/pause.
## 2.1.1
@@ -44,7 +94,7 @@ moved to: [https://github.com/Mastermindzh/tidal-hifi-aur](https://github.com/Ma
## 1.3.0
-- re-enabled mpris-service wit the electron downloader fixes
-- re-enabled MPRIS-service wit the electron downloader fixes
## 1.2.0
@@ -59,7 +109,7 @@ Bugfixes:
## 1.1.0
- updated to electron 8.0.0
- Added a beta-version of the mpris service
- Added a beta-version of the MPRIS service
- Bugfixes:
- icon on gnome not showing in launcher

View File

@@ -20,6 +20,7 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
- [Integrations](#integrations)
- [not included](#not-included)
- [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)
- [Why](#why)
- [Why not extend existing projects?](#why-not-extend-existing-projects)
- [Special thanks to...](#special-thanks-to)
@@ -57,7 +58,7 @@ snap install --dangerous <path> #for instance: tidal-hifi_1.0.0_amd64.snap
Arch Linux users can use the AUR to install tidal-hifi:
```sh
trizen tidal-hifi
trizen tidal-hifi-bin
```
### Using source
@@ -75,8 +76,10 @@ To install and work with the code on this project follow these steps:
- Notifications
- Custom hotkeys ([source](https://defkey.com/tidal-desktop-shortcuts))
- API for status and playback
- [Mute artists automatically (defaults to "Tidal")]("./docs/muting-artists.md")
- Custom [integrations](#integrations)
- [Settings feature](./docs/settings.png) to disable certain functionality. (`ctrl+=`)
- [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))
## Integrations
@@ -87,7 +90,7 @@ You can find these in the settings menu (`ctrl + =` by default) under the "integ
It currently includes:
- mpris - mpris media player controls/status
- MPRIS - MPRIS media player controls/status
- Discord - Shows what you're listening to on Discord.
### not included
@@ -96,7 +99,11 @@ It currently includes:
### Known bugs
- [Last.fm login doesn't work](https://github.com/Mastermindzh/tidal-hifi/issues/4).
#### last.fm doesn't work out of the box. Use rescrobbler as a workaround
The last.fm login doesn't work, as is evident from the following issue: [Last.fm login doesn't work](https://github.com/Mastermindzh/tidal-hifi/issues/4).
However, in that same issue you can read about a workaround using [rescrobbler](https://github.com/InputUsername/rescrobbled).
For now that will be the default workaround.
## Why
@@ -122,7 +129,7 @@ Sometimes it's just easier to start over, cover my own needs and then making it
## Buy me a coffee? Please don't
Instead spend some money on a charity I care for: [kwf.nl](https://secure.kwf.nl/donation).
Instead spend some money on a charity I care for: [kwf.nl](https://www.kwf.nl/donatie/donation).
Inspired by [haydenjames' issue](https://github.com/Mastermindzh/tidal-hifi/issues/27#issuecomment-704198429)
## Images

View File

@@ -1,7 +1,7 @@
appId: com.rickvanlieshout.tidal-hifi
electronVersion: 8.5.2
electronVersion: 16.0.4
electronDownload:
version: 8.5.2-wvvmp
version: 16.0.4+wvcus.2
mirror: https://github.com/castlabs/electron-releases/releases/download/v
snap:
plugs:
@@ -10,7 +10,7 @@ snap:
linux:
category: Audio
target:
# - pacman
- pacman
- tar.gz
- deb
- rpm
@@ -34,3 +34,7 @@ mac:
category: public.app-category.entertainment
win:
target: msi
icon: build/icon.png
artifactName: "tidalhifi"
appId: com.rickvanlieshout.tidalhifi
executableName: tidalhifi

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.

After

Width:  |  Height:  |  Size: 103 KiB

5360
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "2.2.1",
"version": "2.8.1",
"description": "Tidal on Electron with widevine(hifi) support",
"main": "src/main.js",
"scripts": {
@@ -23,21 +23,19 @@
"homepage": "https://github.com/Mastermindzh/tidal-hifi",
"license": "MIT",
"dependencies": {
"discord-rpc": "^3.2.0",
"electron-store": "^5.1.1",
"discord-rpc": "^4.0.1",
"electron-store": "^8.0.1",
"express": "^4.17.1",
"hotkeys-js": "^3.7.6",
"mpris-service": "^2.1.0",
"node-notifier": "^9.0.1",
"hotkeys-js": "^3.8.7",
"mpris-service": "^2.1.2",
"request": "^2.88.2"
},
"devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0",
"dot-prop": ">=4.2.1",
"electron": "git+https://github.com/castlabs/electron-releases.git#v10.4.3-wvvmp",
"electron-builder": "^21.2.0",
"electron": "git+https://github.com/castlabs/electron-releases.git#v16.0.4+wvcus.2",
"electron-builder": "^22.14.5",
"electron-reload": "^1.5.0",
"prettier": "^2.0.4"
"prettier": "^2.5.0"
},
"prettier": "@mastermindzh/prettier-config"
}
}

View File

@@ -6,6 +6,7 @@ const globalEvents = {
previous: "previous",
updateInfo: "update-info",
hideSettings: "hideSettings",
refreshMenuBar: "refreshMenubar",
showSettings: "showSettings",
storeChanged: "storeChanged",
error: "error",

View File

@@ -13,6 +13,8 @@ const settings = {
api: "api",
menuBar: "menuBar",
playBackControl: "playBackControl",
muteArtists: "muteArtists",
mutedArtists: "mutedArtists",
apiSettings: {
root: "apiSettings",
port: "apiSettings.port",
@@ -26,6 +28,7 @@ const settings = {
width: "windowBounds.width",
height: "windowBounds.height",
},
minimizeOnClose: "minimizeOnClose",
};
module.exports = settings;

View File

@@ -29,6 +29,19 @@ if (!app.isPackaged) {
});
}
/**
* Fix Display Compositor issue.
*/
app.commandLine.appendSwitch('disable-seccomp-filter-sandbox');
/**
* Update the menuBarVisbility according to the store value
*
*/
function syncMenuBarWithStore() {
mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
}
function createWindow(options = {}) {
// Create the browser window.
mainWindow = new BrowserWindow({
@@ -48,7 +61,7 @@ function createWindow(options = {}) {
},
});
mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
syncMenuBarWithStore();
// load the Tidal website
mainWindow.loadURL(tidalUrl);
@@ -56,6 +69,14 @@ function createWindow(options = {}) {
// run stuff after first load
mainWindow.webContents.once("did-finish-load", () => {});
mainWindow.on("close", function (event) {
if (!app.isQuiting && store.get(settings.minimizeOnClose)) {
event.preventDefault();
mainWindow.hide();
refreshTray(mainWindow);
}
return false;
});
// Emitted when the window is closed.
mainWindow.on("closed", function () {
closeSettingsWindow();
@@ -87,6 +108,7 @@ app.on("ready", () => {
store.get(settings.trayIcon) && addTray({ icon }) && refreshTray();
store.get(settings.api) && expressModule.run(mainWindow);
store.get(settings.enableDiscord) && discordModule.initRPC();
// mainWindow.webContents.openDevTools();
});
app.on("activate", function () {
@@ -109,8 +131,12 @@ ipcMain.on(globalEvents.showSettings, (event, arg) => {
showSettingsWindow();
});
ipcMain.on(globalEvents.refreshMenuBar, (event, arg) => {
syncMenuBarWithStore();
});
ipcMain.on(globalEvents.storeChanged, (event, arg) => {
mainWindow.setMenuBarVisibility(store.get(settings.menuBar));
syncMenuBarWithStore();
if (store.get(settings.enableDiscord) && !discordModule.rpc) {
discordModule.initRPC();

View File

@@ -1,8 +1,15 @@
let notifications;
let playBackControl;
let api;
let port;
let menuBar;
let trayIcon,
minimizeOnClose,
mpris,
enableCustomHotkeys,
enableDiscord,
muteArtists,
notifications,
playBackControl,
api,
port,
menuBar,
mutedArtists;
const { store, settings } = require("./../../scripts/settings");
const { ipcRenderer } = require("electron");
@@ -21,6 +28,9 @@ function refreshSettings() {
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");
}
/**
@@ -66,6 +76,13 @@ window.addEventListener("DOMContentLoaded", () => {
});
}
function addTextAreaListener(source, key) {
source.addEventListener("input", function (event, data) {
store.set(key, source.value.split("\n"));
ipcRenderer.send(globalEvents.storeChanged);
});
}
ipcRenderer.on("refreshData", () => {
refreshSettings();
});
@@ -80,9 +97,12 @@ window.addEventListener("DOMContentLoaded", () => {
port = get("port");
menuBar = get("menuBar");
trayIcon = get("trayIcon");
minimizeOnClose = get("minimizeOnClose");
mpris = get("mprisCheckbox");
enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord");
muteArtists = get("muteArtists");
mutedArtists = get("mutedArtists");
refreshSettings();
@@ -95,4 +115,7 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(mpris, settings.mpris);
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord);
addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(muteArtists, settings.muteArtists);
addTextAreaListener(mutedArtists, settings.mutedArtists);
});

View File

@@ -2,6 +2,7 @@
<html lang="en">
<head>
<title>Tidal-hifi settings</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
@@ -54,6 +55,17 @@
<span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Mute Artists automatically</h4>
<p>
The following list of artists (1 per line) will be muted automatically.
</p>
<label class="switch" style="margin-bottom:10px">
<input id="muteArtists" type="checkbox">
<span class="slider round" ></span>
</label>
<textarea id="mutedArtists" cols="40" rows="5"></textarea>
</div>
</div>
<div class="section">
<h3>UI</h3>
@@ -80,6 +92,16 @@
<span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Minimize on Close</h4>
<p>
Minimize window on close instead <br />
</p>
<label class="switch">
<input id="minimizeOnClose" type="checkbox">
<span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Hotkeys</h4>
<p>
@@ -129,12 +151,12 @@
<div class="section">
<h3>integrations</h3>
<p style="margin-bottom: 15px;">
Tidal-hifi is extensible trough the use of integrations. You can enable or disable integrations here
Tidal-hifi is extensible through the use of integrations. You can enable or disable integrations here
</p>
<div class="option">
<h4>mpris-player</h4>
<h4>MPRIS-player</h4>
<p>
Whether to enable the mpris media player controls for Linux systems
Whether to enable the MPRIS media player controls for Linux systems
</p>
<label class="switch">
<input id="mprisCheckbox" type="checkbox">
@@ -155,16 +177,16 @@
</section>
<section id="about" class="tab-panel">
<div class="section">
<img style="width: 100px; height: auto; display: block; margin: 0 auto; margin-bottom: 20px; margin-top: 20px;" src = "./icon.png">
<img alt="tidal icon" style="width: 100px; height: auto; display: block; margin: 0 auto; margin-bottom: 20px; margin-top: 20px;" src = "./icon.png">
<p style="max-width: 350px; display:block; margin: 0 auto; text-align: center;">
<a href ="javascript:openExternal('https://github.com/Mastermindzh/tidal-hifi');">Tidal-hifi</a> is made by <a href ="javascript:openExternal('https://www.rickvanlieshout.com')">Rick van Lieshout</a>.<br />
It uses <a href="javascript:openExternal('https://castlabs.com/');">castlabs</a> versions of Electron for widevine support.
It uses <a href="javascript:openExternal('https://castlabs.com/');">Castlabs'</a> versions of Electron for widevine support.
</p>
</div>
</section>
<small>Some settings require a restart of Tidal-hifi. To do so click the button below:</small>
<small>Some settings require a restart of Tidal-hifi. To do so, click the button below:</small>
<button onClick="restart()" style ="width: 100%">Restart Tidal-hifi</button>
</div>
</div>
@@ -459,5 +481,19 @@
button:hover{
background-color: rgba(229,238,255,.3);
}
textarea {
color: #72777f;
background: #242528;
border: 0;
width: 100%;
color: rgba(229, 238, 255, .6);
padding: 0 0 12px;
display:block;
}
textarea:focus {
outline: none;
border: 0;
border-bottom: 1px solid #0ff;
}
</style>
</html>

View File

@@ -1,5 +1,5 @@
const { setTitle } = require("./scripts/window-functions");
const { dialog, process } = require("electron").remote;
const { dialog, process, Notification } = require("electron").remote;
const { store, settings } = require("./scripts/settings");
const { ipcRenderer } = require("electron");
const { app } = require("electron").remote;
@@ -7,8 +7,8 @@ const { downloadFile } = require("./scripts/download");
const statuses = require("./constants/statuses");
const hotkeys = require("./scripts/hotkeys");
const globalEvents = require("./constants/globalEvents");
const notifier = require("node-notifier");
const notificationPath = `${app.getPath("userData")}/notification.jpg`;
const appName = "Tidal Hifi";
let currentSong = "";
let player;
let currentPlayStatus = statuses.paused;
@@ -16,6 +16,7 @@ let progressBarTime;
let currentTimeChanged = false;
let currentTime;
let currentURL = undefined;
let isMutedArtist = false;
const elements = {
play: '*[data-test="play"]',
@@ -39,7 +40,11 @@ const elements = {
duration: '*[data-test="duration-time"]',
bar: '*[data-test="progress-bar"]',
footer: "#footerPlayer",
album_header_title: '.header-details [data-test="title"]',
playing_title: 'span[data-test="table-cell-title"].css-geqnfr',
album_name_cell: '[data-test="table-cell-album"]',
tracklist_row: '[data-test="tracklist-row"]',
volume: '*[data-test="volume"]',
/**
* Get an element from the dom
* @param {*} key key in elements object to fetch
@@ -57,7 +62,7 @@ const elements = {
if (figure) {
const mediaElement = figure.querySelector(this["image"]);
if (mediaElement) {
return mediaElement.src;
return mediaElement.src.replace("80x80", "640x640");
}
}
@@ -77,6 +82,33 @@ const elements = {
return "unknown artist(s)";
},
getAlbumName: function () {
//If listening to an album, get its name from the header title
if (window.location.href.includes("/album/")) {
const albumName = window.document.querySelector(this.album_header_title);
if (albumName) {
return albumName.textContent;
}
//If listening to a playlist or a mix, get album name from the list
} else if (
window.location.href.includes("/playlist/") ||
window.location.href.includes("/mix/")
) {
if (currentPlayStatus === statuses.playing) {
const row = window.document.querySelector(this.playing_title).closest(this.tracklist_row);
if (row) {
return row.querySelector(this.album_name_cell).textContent;
}
}
}
return "";
},
isMuted: function () {
return this.get("volume").getAttribute("aria-checked") === "false"; // it's muted if aria-checked is false
},
/**
* Shorthand function to get the text of a dom element
* @param {*} key key in elements object to fetch
@@ -157,6 +189,9 @@ function addHotKeys() {
hotkeys.add("control+=", function () {
ipcRenderer.send(globalEvents.showSettings);
});
hotkeys.add("control+0", function () {
ipcRenderer.send(globalEvents.showSettings);
});
}
/**
@@ -190,13 +225,19 @@ function handleLogout() {
);
}
function addFullScreenListeners() {
window.document.addEventListener("fullscreenchange", () => {
ipcRenderer.send(globalEvents.refreshMenuBar);
});
}
/**
* Add ipc event listeners.
* Some actions triggered outside of the site need info from the site.
*/
function addIPCEventListeners() {
window.addEventListener("DOMContentLoaded", () => {
ipcRenderer.on("globalEvent", (event, args) => {
ipcRenderer.on("globalEvent", (_event, args) => {
switch (args) {
case globalEvents.playPause:
playPause();
@@ -234,6 +275,15 @@ function getCurrentlyPlayingStatus() {
return status;
}
/**
* Convert the duration from MM:SS to seconds
* @param {*} duration
*/
function convertDuration(duration) {
const parts = duration.split(":");
return parseInt(parts[1]) + 60 * parseInt(parts[0]);
}
/**
* Update Tidal-hifi's media info
*
@@ -242,15 +292,18 @@ function getCurrentlyPlayingStatus() {
function updateMediaInfo(options, notify) {
if (options) {
ipcRenderer.send(globalEvents.updateInfo, options);
store.get(settings.notifications) && notify && notifier.notify(options);
if (store.get(settings.notifications) && notify) {
new Notification({ title: options.title, body: options.message, icon: options.icon }).show();
}
if (player) {
player.metadata = {
...player.metadata,
...{
"xesam:title": options.title,
"xesam:artist": [options.artists],
"xesam:artist": [options.message],
"xesam:album": options.album,
"mpris:artUrl": options.image,
"mpris:length": convertDuration(options.duration) * 1000 * 1000,
},
};
player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing";
@@ -281,6 +334,7 @@ function updateURL() {
setInterval(function () {
const title = elements.getText("title");
const artists = elements.getArtists();
const album = elements.getAlbumName();
const current = elements.getText("current");
const duration = elements.getText("duration");
const progressBarcurrentTime = elements.get("bar").getAttribute("aria-valuenow");
@@ -289,16 +343,20 @@ setInterval(function () {
const options = {
title,
message: artists,
album: album,
status: currentStatus,
url: currentURL,
current: current,
duration: duration,
"app-name": appName,
};
const playStatusChanged = currentStatus !== currentPlayStatus;
const progressBarTimeChanged = progressBarcurrentTime !== progressBarTime;
const titleOrArtistChanged = currentSong !== songDashArtistTitle;
muteArtistIfFoundInMutedArtistsList();
if (titleOrArtistChanged || playStatusChanged || progressBarTimeChanged || currentTimeChanged) {
// update title, url and play info with new info
setTitle(songDashArtistTitle);
@@ -331,6 +389,7 @@ setInterval(function () {
new Promise((resolve) => {
if (image.startsWith("http")) {
options.image = image;
downloadFile(image, notificationPath).then(
() => {
options.icon = notificationPath;
@@ -352,6 +411,24 @@ setInterval(function () {
() => {}
);
}
/**
* Checks whether the current artist is included in the "muted artists" list and if so it will automatically mute the player
*/
function muteArtistIfFoundInMutedArtistsList() {
if (store.get(settings.muteArtists)) {
const mutedArtists = store.get(settings.mutedArtists);
if (mutedArtists.find((artist) => artist === artists) !== undefined) {
if (!elements.isMuted()) {
isMutedArtist = true;
elements.click("volume");
}
} else if (currentStatus === statuses.playing && isMutedArtist && elements.isMuted()) {
elements.click("volume");
isMutedArtist = false;
}
}
}
}, 200);
if (process.platform === "linux" && store.get(settings.mpris)) {
@@ -397,6 +474,10 @@ if (process.platform === "linux" && store.get(settings.mpris)) {
}
});
});
// Override get position function
player.getPosition = function () {
return convertDuration(elements.getText("current")) * 1000 * 1000;
};
player.on("quit", function () {
app.quit();
@@ -408,3 +489,4 @@ if (process.platform === "linux" && store.get(settings.mpris)) {
addHotKeys();
addIPCEventListeners();
addFullScreenListeners();

View File

@@ -31,6 +31,10 @@ const observer = (event, arg) => {
: "unknown artist(s)",
startTimestamp: parseInt(now),
endTimestamp: parseInt(remaining),
largeImageKey: mediaInfoModule.mediaInfo.image,
largeImageText: mediaInfoModule.mediaInfo.album
? mediaInfoModule.mediaInfo.album
: `${idleStatus.largeImageText}`,
buttons: [{ label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url }],
},
});
@@ -60,24 +64,32 @@ const idleStatus = {
*/
discordModule.initRPC = function () {
rpc = new discordrpc.Client({ transport: "ipc" });
rpc.login({ clientId }).catch(console.error);
discordModule.rpc = rpc;
rpc.login({ clientId }).then(
() => {
discordModule.rpc = rpc;
rpc.on("ready", () => {
rpc.setActivity(idleStatus);
});
ipcMain.on(globalEvents.updateInfo, observer);
rpc.on("ready", () => {
rpc.setActivity(idleStatus);
});
ipcMain.on(globalEvents.updateInfo, observer);
},
() => {
console.error("Can't connect to Discord, is it running?");
}
);
};
/**
* Remove any RPC connection with discord and remove the event listener on globalEvents.updateInfo
*/
discordModule.unRPC = function () {
rpc.clearActivity();
rpc.destroy();
rpc = false;
discordModule.rpc = rpc;
ipcMain.removeListener(globalEvents.updateInfo, observer);
if (rpc) {
rpc.clearActivity();
rpc.destroy();
rpc = false;
discordModule.rpc = undefined;
ipcMain.removeListener(globalEvents.updateInfo, observer);
}
};
module.exports = discordModule;

View File

@@ -3,11 +3,13 @@ const statuses = require("./../constants/statuses");
const mediaInfo = {
title: "",
artist: "",
album: "",
icon: "",
status: statuses.paused,
url: "",
current: "",
duration: ""
duration: "",
image: "tidal-hifi-icon"
};
const mediaInfoModule = {
mediaInfo,
@@ -19,11 +21,13 @@ const mediaInfoModule = {
mediaInfoModule.update = function (arg) {
mediaInfo.title = propOrDefault(arg.title);
mediaInfo.artist = propOrDefault(arg.message);
mediaInfo.album = propOrDefault(arg.album);
mediaInfo.icon = propOrDefault(arg.icon);
mediaInfo.url = propOrDefault(arg.url);
mediaInfo.status = propOrDefault(arg.status);
mediaInfo.current = propOrDefault(arg.current);
mediaInfo.duration = propOrDefault(arg.duration);
mediaInfo.image = propOrDefault(arg.image);
};
/**

View File

@@ -1,4 +1,4 @@
const { Menu } = require("electron");
const { Menu, app } = require("electron");
const { showSettingsWindow } = require("./settings");
const isMac = process.platform === "darwin";
@@ -10,6 +10,14 @@ const settingsMenuEntry = {
accelerator: "Control+/",
};
const quitMenuEntry = {
label: "Quit",
click() {
app.exit(0);
},
accelerator: "Control+Q"
};
const mainMenu = [
...(isMac
? [
@@ -25,7 +33,7 @@ const mainMenu = [
{ role: "hideothers" },
{ role: "unhide" },
{ type: "separator" },
{ role: "quit" },
quitMenuEntry,
],
},
]
@@ -33,7 +41,7 @@ const mainMenu = [
// { role: 'fileMenu' }
{
label: "File",
submenu: [settingsMenuEntry, isMac ? { role: "close" } : { role: "quit" }],
submenu: [settingsMenuEntry, isMac ? { role: "close" } : quitMenuEntry],
},
// { role: 'editMenu' }
{

View File

@@ -10,11 +10,14 @@ const store = new Store({
notifications: true,
api: true,
playBackControl: true,
muteArtists: false,
mutedArtists: ["TIDAL"],
menuBar: true,
apiSettings: {
port: 47836,
},
trayIcon: true,
minimizeOnClose: false,
mpris: false,
enableCustomHotkeys: false,
enableDiscord: false,

View File

@@ -1,5 +1,7 @@
const { Tray } = require("electron");
const { getMenu } = require("./menu");
const { Tray, app } = require("electron");
const { Menu } = require("electron");
const { getMenu, mainMenu } = require("./menu");
const { store, settings } = require("./settings");
const trayModule = {};
let tray;
@@ -7,16 +9,41 @@ trayModule.addTray = function (options = { icon: "" }) {
tray = new Tray(options.icon);
};
trayModule.refreshTray = function () {
trayModule.refreshTray = function (mainWindow) {
if (!tray) {
trayModule.addTray();
}
tray.on("click", function (e) {
// do nothing on click
if (mainWindow) {
mainWindow.show();
}
});
tray.setToolTip("Tidal-hifi");
tray.setContextMenu(getMenu());
if (mainWindow && store.get(settings.minimizeOnClose)) {
tray.setContextMenu(
Menu.buildFromTemplate([
{
label: "Toggle Window",
click: function () {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
},
},
{
label: "Quit",
click: function () {
mainWindow.destroy();
app.quit();
},
},
...mainMenu, //we add menu items from the other context
])
);
} else {
tray.setContextMenu(getMenu());
}
};
module.exports = trayModule;