Compare commits

..

60 Commits

Author SHA1 Message Date
Renovate Bot
fdf23511cf chore(deps): update electron to v37.2.0+wvcus 2025-07-07 14:32:18 +02:00
985bc0f1d5 Merge pull request #610 from Mastermindzh/renovate/electron-35.x
chore(deps): update electron to v35.7.0+wvcus
2025-07-07 14:31:22 +02:00
1f9b3a297a Merge pull request #611 from Mastermindzh/renovate/node-19.x
chore(deps): update node.js to v19.9.0
2025-07-07 14:28:41 +02:00
98ca73d17d Merge pull request #608 from Mastermindzh/renovate/sass-1.x
fix(deps): update sass to 1.89.2
2025-07-07 14:27:35 +02:00
396ed223d3 Merge pull request #603 from Mastermindzh/renovate/cors-2.x-lockfile
chore(deps): update @types/cors to 2.8.19
2025-07-07 13:27:08 +02:00
Renovate Bot
b0458f4de5 chore(deps): update node.js to v19.9.0 2025-07-07 13:09:34 +02:00
Renovate Bot
b875d091ec chore(deps): update electron to v35.7.0+wvcus 2025-07-07 13:09:30 +02:00
Renovate Bot
1a0b69d042 fix(deps): update sass to 1.89.2 2025-07-07 13:09:16 +02:00
Renovate Bot
e23a71a1a6 chore(deps): update @types/cors to 2.8.19 2025-07-07 13:08:49 +02:00
510ffa1509 Merge pull request #602 from Mastermindzh/renovate/configure
chore: Configure Renovate
2025-07-07 13:05:04 +02:00
Renovate Bot
e17ef32cde Add renovate.json 2025-07-07 12:00:56 +02:00
d4c3999d9c Merge pull request #593 from edocli/master
feat(build): Update Wayland launch flags for Linux
2025-07-07 09:11:38 +02:00
b0695600b1 Merge pull request #599 from Mastermindzh/snyk-upgrade-c222f288d19352ce1096b7bea79acbab
[Snyk] Upgrade hotkeys-js from 3.13.10 to 3.13.11
2025-07-07 09:10:17 +02:00
snyk-bot
22ecc7ade7 fix: upgrade hotkeys-js from 3.13.10 to 3.13.11
Snyk has created this PR to upgrade hotkeys-js from 3.13.10 to 3.13.11.

See this package in npm:
hotkeys-js

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-07-05 06:52:09 +00:00
a5102ebd03 Merge pull request #596 from Mastermindzh/snyk-upgrade-8471eaf4e087a1ad71b342b81e6741ae
[Snyk] Upgrade sass from 1.89.0 to 1.89.1
2025-06-23 12:46:05 +02:00
snyk-bot
d01f08508f fix: upgrade sass from 1.89.0 to 1.89.1
Snyk has created this PR to upgrade sass from 1.89.0 to 1.89.1.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-06-21 09:48:24 +00:00
e87d8f6922 Merge pull request #594 from Mastermindzh/snyk-upgrade-2487864f695c4105f8d0392b9d406127
[Snyk] Upgrade sass from 1.87.0 to 1.89.0
2025-06-15 10:13:13 +02:00
snyk-bot
c044476014 fix: upgrade sass from 1.87.0 to 1.89.0
Snyk has created this PR to upgrade sass from 1.87.0 to 1.89.0.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-06-14 11:15:21 +00:00
75df43864b Merge pull request #588 from Mastermindzh/snyk-upgrade-5a5f2fcd2f171f53dcc34ab5933a3c09
[Snyk] Upgrade sass from 1.86.3 to 1.87.0
2025-06-09 11:00:33 +03:00
Edoc
174d0a38a1 Update electron-builder.base.yml
Adds the `--use-angle` flag to work around driver compatibility issues that cause the NVIDIA GPU process to crash repeatedly on Wayland. The native EGL/GBM backend fails with "Cannot create bo" errors.
2025-06-09 03:09:37 -04:00
Edoc
cf1aeefe67 Update electron-builder.base.yml
- Remove obsolete --enable-features=UseOzonePlatform flag
- Add --enable-wayland-ime for IME support on Wayland
2025-06-08 18:46:01 -04:00
280d927a03 Merge pull request #590 from Mastermindzh/snyk-upgrade-218353a4201f743fe837fca092089385
[Snyk] Upgrade hotkeys-js from 3.13.9 to 3.13.10
2025-05-31 14:16:42 +02:00
snyk-bot
f62294ef20 fix: upgrade hotkeys-js from 3.13.9 to 3.13.10
Snyk has created this PR to upgrade hotkeys-js from 3.13.9 to 3.13.10.

See this package in npm:
hotkeys-js

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-05-31 08:20:25 +00:00
237e354f80 Merge pull request #587 from Mastermindzh/snyk-upgrade-7cf34416a89cb7ffe31756c1f2c4b62d
[Snyk] Upgrade axios from 1.8.4 to 1.9.0
2025-05-26 09:46:38 +02:00
snyk-bot
3a5172cb23 fix: upgrade sass from 1.86.3 to 1.87.0
Snyk has created this PR to upgrade sass from 1.86.3 to 1.87.0.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-05-24 08:12:39 +00:00
snyk-bot
f8f12cca62 fix: upgrade axios from 1.8.4 to 1.9.0
Snyk has created this PR to upgrade axios from 1.8.4 to 1.9.0.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-05-24 08:12:36 +00:00
79bbab6a82 Merge pull request #584 from Mastermindzh/next
albumInfo fix, updated dependencies
2025-04-22 11:40:41 +02:00
7376df7f30 albumInfo fix, updated dependencies 2025-04-22 11:14:19 +02:00
7f8760c4e9 Merge pull request #583 from Mastermindzh/snyk-upgrade-36ee0aede4ca42df3db4bef87530e654
[Snyk] Upgrade sass from 1.85.1 to 1.86.0
2025-04-20 13:24:05 +02:00
snyk-bot
1cf5a01ad7 fix: upgrade sass from 1.85.1 to 1.86.0
Snyk has created this PR to upgrade sass from 1.85.1 to 1.86.0.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-04-19 09:04:54 +00:00
8fc49f500e Merge pull request #577 from Mastermindzh/snyk-upgrade-b144be84df6292449bfe4eacd9662b97
[Snyk] Upgrade sass from 1.79.4 to 1.85.1
2025-04-18 14:50:52 +02:00
snyk-bot
49f5a01b58 fix: upgrade sass from 1.79.4 to 1.85.1
Snyk has created this PR to upgrade sass from 1.79.4 to 1.85.1.

See this package in npm:
sass

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-04-05 07:45:32 +00:00
48f4fe47ef Merge pull request #573 from Mastermindzh/next
Next
2025-03-30 13:10:28 +02:00
a819e1eb45 removing mac/win builds, they aren't targetted anyway 2025-03-30 12:52:48 +02:00
57e6342b5f Merge branch 'next' of github.com:Mastermindzh/tidal-hifi into next 2025-03-30 12:50:31 +02:00
58a543a3c8 fixed .desktop file 2025-03-30 12:50:27 +02:00
1c915d99fe Merge pull request #572 from QF0xB/fix/nix-build-temporarily
Reverted sass to 1.79.4
2025-03-30 12:49:29 +02:00
Quirin Brändli
8994360415 Reverted sass to 1.79.4 2025-03-30 00:06:46 +01:00
a5c0d9e6e8 Merge pull request #570 from Mastermindzh/fix/login
Fix/login
2025-03-29 20:45:40 +01:00
f8eb36f4c7 bumped versions 2025-03-29 17:12:28 +01:00
5ca90c25d3 update builder to v35 as well 2025-03-29 17:05:17 +01:00
cf86969cfc updated builder, removed abstract-socket 2025-03-29 16:27:24 +01:00
afd05ae88b updated electron, deps, and moved remote calls after start 2025-03-29 15:58:28 +01:00
72c25dfdc1 Merge pull request #564 from Mastermindzh/snyk-fix-1995dd90a05e86ea7c2e4f0f7a284930
[Snyk] Security upgrade @xhayper/discord-rpc from 1.2.0 to 1.2.1
2025-03-23 21:32:20 +01:00
snyk-bot
25b30edf31 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-UNDICI-8641354
2025-03-22 08:54:58 +00:00
35ed4807e3 Merge pull request #558 from Mastermindzh/next
Next
2025-03-18 09:10:40 +01:00
deff9524a8 album & playingfrom info added to mediaInfo again. fixes #548 2025-03-17 11:05:10 +01:00
34c7777eeb Merge pull request #554 from Dianoga/duration-fix
fix duration selector
2025-03-17 10:27:42 +01:00
048e949f30 Merge branch 'master' of github.com:Mastermindzh/tidal-hifi into next 2025-03-17 09:54:06 +01:00
Brian Steere
4a976bc58c fix duration selector
Should fix the MPRIS issue as long as duration doesn't break again.
2025-03-12 14:21:13 -05:00
ff4c51234b Merge pull request #524 from Mastermindzh/snyk-upgrade-278f4ec84db5f4ebc26d987909c6c73f
[Snyk] Upgrade hotkeys-js from 3.13.7 to 3.13.9
2025-01-06 17:48:43 +01:00
snyk-bot
c4ee6b51b9 fix: upgrade hotkeys-js from 3.13.7 to 3.13.9
Snyk has created this PR to upgrade hotkeys-js from 3.13.7 to 3.13.9.

See this package in npm:
hotkeys-js

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2025-01-04 01:22:24 +00:00
45fe336598 Merge pull request #522 from Mastermindzh/snyk-upgrade-7f82ddec0efc65c72c6f7f2f182ace7c
[Snyk] Upgrade axios from 1.7.8 to 1.7.9
2024-12-28 12:45:52 +01:00
snyk-bot
fe9f50aaf5 fix: upgrade axios from 1.7.8 to 1.7.9
Snyk has created this PR to upgrade axios from 1.7.8 to 1.7.9.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/mastermindzh/project/dade8f03-2064-49a3-8957-edbacec3887c?utm_source=github&utm_medium=referral&page=upgrade-pr
2024-12-27 23:17:27 +00:00
aaf7a1b662 Merge pull request #504 from darkiox/master
Fix Discord RPC Timestamp jitter
2024-12-09 11:21:27 +01:00
755be0ee30 Merge pull request #515 from Mastermindzh/snyk-fix-82857ea1745fc2cfbc5f06a87a8ff0b8
[Snyk] Security upgrade express from 4.21.1 to 4.21.2
2024-12-09 11:05:23 +01:00
snyk-bot
9d736b2bd9 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PATHTOREGEXP-8482416
2024-12-06 20:33:54 +00:00
f4d4b1a1df Merge pull request #508 from Mastermindzh/snyk-fix-a6630fbdb3c8f0161d0b939cf0ec3ca3
[Snyk] Security upgrade axios from 1.7.7 to 1.7.8
2024-12-02 09:03:11 +01:00
snyk-bot
0c27c815f5 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-AXIOS-6671926
2024-11-30 06:57:38 +00:00
Darkiox
a3aa45a96b fix: discord rpc timestamp jitter 2024-11-25 19:15:26 -03:00
19 changed files with 4090 additions and 2265 deletions

View File

@@ -4,12 +4,12 @@ name: default
steps: steps:
- name: install - name: install
image: node:19.4.0 image: node:19.9.0
commands: commands:
- npm install - npm install
- name: build_with_linux - name: build_with_linux
image: node:19.4.0 image: node:19.9.0
commands: commands:
- apt-get update && apt-get upgrade -y - apt-get update && apt-get upgrade -y
- apt-get install -y libarchive-tools rpm - apt-get install -y libarchive-tools rpm

View File

@@ -24,23 +24,27 @@ jobs:
node-version: 22.4 node-version: 22.4
- run: npm install - run: npm install
- run: npm run build - run: npm run build
# - uses: actions/upload-artifact@master
# with:
# name: linux-builds
# path: dist/
build_on_mac: # build_on_mac:
runs-on: macos-latest # runs-on: macos-latest
steps: # steps:
- uses: actions/checkout@master # - uses: actions/checkout@master
- uses: actions/setup-node@master # - uses: actions/setup-node@master
with: # with:
node-version: 22.4 # node-version: 22.4
- run: npm install # - run: npm install
- run: npm run build # - run: npm run build
build_on_win: # build_on_win:
runs-on: windows-latest # runs-on: windows-latest
steps: # steps:
- uses: actions/checkout@master # - uses: actions/checkout@master
- uses: actions/setup-node@master # - uses: actions/setup-node@master
with: # with:
node-version: 22.4 # node-version: 22.4
- run: npm install # - run: npm install
- run: npm run build # - run: npm run build

View File

@@ -29,30 +29,30 @@ jobs:
name: linux-builds name: linux-builds
path: dist/ path: dist/
build_on_mac: # build_on_mac:
runs-on: macos-latest # runs-on: macos-latest
steps: # steps:
- uses: actions/checkout@master # - uses: actions/checkout@master
- uses: actions/setup-node@master # - uses: actions/setup-node@master
with: # with:
node-version: 22.4 # node-version: 22.4
- run: npm install # - run: npm install
- run: npm run build # - run: npm run build
- uses: actions/upload-artifact@master # - uses: actions/upload-artifact@master
with: # with:
name: mac-builds # name: mac-builds
path: ./dist/ # path: ./dist/
build_on_win: # build_on_win:
runs-on: windows-latest # runs-on: windows-latest
steps: # steps:
- uses: actions/checkout@master # - uses: actions/checkout@master
- uses: actions/setup-node@master # - uses: actions/setup-node@master
with: # with:
node-version: 22.4 # node-version: 22.4
- run: npm install # - run: npm install
- run: npm run build # - run: npm run build
- uses: actions/upload-artifact@master # - uses: actions/upload-artifact@master
with: # with:
name: windows-builds # name: windows-builds
path: dist/ # path: dist/

2
.nvmrc
View File

@@ -1 +1 @@
19.8.1 19.9.0

View File

@@ -1,7 +1,13 @@
{ {
"plugins": ["stylelint-prettier"], "plugins": [
"extends": ["stylelint-config-standard-scss"], "stylelint-prettier"
"ignoreFiles": ["src/themes/**.scss"], ],
"extends": [
"stylelint-config-standard-scss"
],
"ignoreFiles": [
"src/themes/**.scss"
],
"rules": { "rules": {
"prettier/prettier": true, "prettier/prettier": true,
"scss/at-extend-no-missing-placeholder": null, "scss/at-extend-no-missing-placeholder": null,

View File

@@ -4,6 +4,31 @@ 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.19.0]
- Fixed the issue where media updates would cease to work after album names can't be found
- Will simply report an empty string when it can't find the album
- Updated various dependencies
## [5.18.2]
- Reverted to sass 1.79.4 to fix `Nix` builds
- Changed electron-builder.base.yml to now generate the correct .desktop entries again
- Should fix flatpak build
## [5.18.1]
- Fixed the login bug
- Upgraded electron to 35.1.1
- Added Widevine/CDM info to startup
- delayed remote electron initializer
## [5.18.0]
- [Dianoga](https://github.com/Dianoga) fixed the duration selector, restoring mpris & partial API data.
- PR: #554
- Added `xesam:url` property to mpris metadata fixes [#506](https://github.com/Mastermindzh/tidal-hifi/issues/506)
## [5.17.0] ## [5.17.0]
- Added an option to disable the dynamic title and set it to a static one, [#491](https://github.com/Mastermindzh/tidal-hifi/pull/491) - Added an option to disable the dynamic title and set it to a static one, [#491](https://github.com/Mastermindzh/tidal-hifi/pull/491)
@@ -21,7 +46,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added all missing swagger/openApi info with the help of [Times-Z](https://github.com/Times-Z) - Added all missing swagger/openApi info with the help of [Times-Z](https://github.com/Times-Z)
- Updated most dependency versions - Updated most dependency versions
- This includes Electron 31! - This includes Electron 31!
- Added a channel selector so we can now use Tidal's staging environment directly from the app - Added a channel selector so we can now use Tidal's staging environment directly from the app
@@ -113,12 +137,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated Electron to 28.1.1 (fixes [325](https://github.com/Mastermindzh/tidal-hifi/issues/325)) - Updated Electron to 28.1.1 (fixes [325](https://github.com/Mastermindzh/tidal-hifi/issues/325))
- Updated dependencies to latest - Updated dependencies to latest
- added theme files to stylelint ignore - added theme files to stylelint ignore
- fixed other stylelint errors - fixed other stylelint errors
- Added functionality to favorite a song (fixes [#323](https://github.com/Mastermindzh/tidal-hifi/issues/323)) - Added functionality to favorite a song (fixes [#323](https://github.com/Mastermindzh/tidal-hifi/issues/323))
- Added a hotkey to favorite ("Add to collection") songs: Control+a - Added a hotkey to favorite ("Add to collection") songs: Control+a
- Added the "favorite" field in the `mediaInfo` and the API `/current` endpoint - Added the "favorite" field in the `mediaInfo` and the API `/current` endpoint
- Added an endpoint to toggle favoriting a song: `http://localhost:47836/favorite/toggle` - Added an endpoint to toggle favoriting a song: `http://localhost:47836/favorite/toggle`

View File

@@ -8,3 +8,4 @@ Only the very latest 😄.
If you find a vulnerability just add it as an issue. If you find a vulnerability just add it as an issue.
If there's an especially bad vulnerability that you don't want to make public just send me a private message (email, discord, wherever). If there's an especially bad vulnerability that you don't want to make public just send me a private message (email, discord, wherever).

View File

@@ -1,7 +1,7 @@
appId: com.rickvanlieshout.tidal-hifi appId: com.rickvanlieshout.tidal-hifi
electronVersion: 28.1.1 electronVersion: 35.1.1
electronDownload: electronDownload:
version: 28.1.1+wvcus version: 35.1.1+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:
@@ -17,24 +17,25 @@ linux:
executableName: tidal-hifi executableName: tidal-hifi
executableArgs: executableArgs:
[ [
"--enable-features=UseOzonePlatform",
"--ozone-platform-hint=auto", "--ozone-platform-hint=auto",
"--enable-features=WaylandWindowDecorations", "--enable-features=WaylandWindowDecorations",
"--enable-wayland-ime",
"--use-angle",
] ]
desktop: desktop:
Encoding: UTF-8 entry:
Name: TIDAL Hi-Fi Encoding: "UTF-8"
GenericName: TIDAL Hi-Fi Name: "TIDAL Hi-Fi"
Comment: The web version of listen.tidal.com running in electron with hifi support thanks to widevine. GenericName: "TIDAL Hi-Fi"
Icon: tidal-hifi Comment: "The web version of listen.tidal.com running in electron with hifi support thanks to widevine."
StartupNotify: true Icon: "tidal-hifi"
Terminal: false StartupNotify: "true"
Type: Application Terminal: "false"
Categories: Network;Application;AudioVideo;Audio;Video Type: "Application"
StartupWMClass: tidal-hifi Categories: "Network;Application;AudioVideo;Audio;Video"
X-PulseAudio-Properties: media.role=music StartupWMClass: "tidal-hifi"
MimeType: x-scheme-handler/tidal; X-PulseAudio-Properties: "media.role=music"
MimeType: "x-scheme-handler/tidal;"
mac: mac:
category: public.app-category.entertainment category: public.app-category.entertainment
win: win:

4963
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
{ {
"name": "tidal-hifi", "name": "tidal-hifi",
"version": "5.17.0", "version": "5.19.0",
"description": "Tidal on Electron with widevine(hifi) support", "description": "Tidal on Electron with widevine(hifi) support",
"main": "ts-dist/main.js", "main": "ts-dist/main.js",
"scripts": { "scripts": {
"start": "electron --inspect=0.0.0.0:5858 .", "start": "electron --inspect=0.0.0.0:5858 --remote-debugging-port=8315 --remote-allow-origins=* .",
"watchStart": "nodemon dist -x \"npm run start\"", "watchStart": "nodemon dist -x \"npm run start\"",
"compile": "tsc && npm run sass-and-copy", "compile": "tsc && npm run sass-and-copy",
"deps": "npm run watch", "deps": "npm run watch",
@@ -23,7 +23,6 @@
"build-mac": "npm run builder -- -c ./build/electron-builder.yml -m", "build-mac": "npm run builder -- -c ./build/electron-builder.yml -m",
"build-base": "npm run builder -- -c ./build/electron-builder.base.yml", "build-base": "npm run builder -- -c ./build/electron-builder.base.yml",
"prebuilder": "npm run compile", "prebuilder": "npm run compile",
"prettier": "prettier . --write",
"builder": "electron-builder --publish=never", "builder": "electron-builder --publish=never",
"sass": "sass ./src/pages/settings/settings.scss ./src/pages/settings/settings.css && sass --no-source-map src/themes:themes", "sass": "sass ./src/pages/settings/settings.scss ./src/pages/settings/settings.css && sass --no-source-map src/themes:themes",
"style-lint": "npx stylelint **/*.scss", "style-lint": "npx stylelint **/*.scss",
@@ -43,42 +42,42 @@
"dependencies": { "dependencies": {
"@electron/remote": "^2.1.2", "@electron/remote": "^2.1.2",
"@types/swagger-jsdoc": "^6.0.4", "@types/swagger-jsdoc": "^6.0.4",
"@xhayper/discord-rpc": "^1.2.0", "@xhayper/discord-rpc": "^1.2.1",
"axios": "^1.7.7", "axios": "^1.9.0",
"cors": "^2.8.5",
"electron-store": "^8.2.0", "electron-store": "^8.2.0",
"express": "^4.21.1", "express": "^5.1.0",
"hotkeys-js": "^3.13.7", "hotkeys-js": "^3.13.11",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"request": "^2.88.2", "sass": "1.89.2",
"sass": "^1.79.4", "swagger-ui-express": "^5.0.1",
"swagger-ui-express": "^5.0.1" "cors": "^2.8.5",
"request": "^2.88.2"
}, },
"devDependencies": { "devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0", "@mastermindzh/prettier-config": "^1.0.0",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/express": "^4.17.21", "@types/express": "^5.0.1",
"@types/node": "^20.14.10", "@types/node": "^20.17.30",
"@types/request": "^2.48.12", "@types/request": "^2.48.12",
"@types/swagger-ui-express": "^4.1.6", "@types/swagger-ui-express": "^4.1.8",
"@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.15.0", "@typescript-eslint/parser": "^7.18.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"electron": "git+https://github.com/castlabs/electron-releases#v31.1.0+wvcus", "electron": "github:castlabs/electron-releases#v37.2.0+wvcus",
"electron-builder": "~24.9.4", "electron-builder": "~26.0.12",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"markdown-toc": "^1.2.0", "markdown-toc": "^1.2.0",
"nodemon": "^3.1.4", "nodemon": "^3.1.9",
"prettier": "^3.3.2", "prettier": "^3.5.3",
"stylelint": "^16.6.1", "stylelint": "^16.18.0",
"stylelint-config-standard": "^36.0.1", "stylelint-config-standard": "^36.0.1",
"stylelint-config-standard-scss": "^13.1.0", "stylelint-config-standard-scss": "^13.1.0",
"stylelint-prettier": "^5.0.0", "stylelint-prettier": "^5.0.3",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsc-watch": "^6.2.0", "tsc-watch": "^6.2.1",
"typescript": "^5.5.3" "typescript": "^5.8.3"
}, },
"prettier": "@mastermindzh/prettier-config" "prettier": "@mastermindzh/prettier-config"
} }

3
renovate.json Normal file
View File

@@ -0,0 +1,3 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

View File

@@ -22,12 +22,13 @@
media: '*[data-test="current-media-imagery"]', media: '*[data-test="current-media-imagery"]',
image: "img", image: "img",
current: '*[data-test="current-time"]', current: '*[data-test="current-time"]',
duration: '*[class^=playbackControlsContainer] *[data-test="duration"]', duration: '*[class^=_playbackControlsContainer] *[data-test="duration"]',
bar: '*[data-test="progress-bar"]', bar: '*[data-test="progress-bar"]',
footer: "#footerPlayer", footer: "#footerPlayer",
mediaItem: "[data-type='mediaItem']", mediaItem: "[data-type='mediaItem']",
album_header_title: '*[class^="playingFrom"] span:nth-child(2)', album_header_title: '*[class^="_playingFrom"] span:nth-child(2)',
playingFrom: '*[class^="playingFrom"] span:nth-child(2)', playing_from: '*[class^="_playingFrom"] span:nth-child(2)',
queue_album: "*[class^=playQueueItemsContainer] *[class^=groupTitle] span:nth-child(2)",
currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']", currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']",
album_name_cell: '[class^="album"]', album_name_cell: '[class^="album"]',
tracklist_row: '[data-test="tracklist-row"]', tracklist_row: '[data-test="tracklist-row"]',

View File

@@ -88,8 +88,9 @@ export const addCurrentInfo = (expressApp: Router) => {
* schema: * schema:
* $ref: '#/components/schemas/MediaInfo' * $ref: '#/components/schemas/MediaInfo'
*/ */
expressApp.get("/current", (req, res) => res.json({ ...mediaInfo, artist: mediaInfo.artists })); expressApp.get("/current", (_req, res) => {
res.json({ ...mediaInfo, artist: mediaInfo.artists });
});
/** /**
* @swagger * @swagger
* /current/image: * /current/image:

View File

@@ -21,8 +21,12 @@ export const startApi = (mainWindow: BrowserWindow) => {
expressApp.use(cors()); expressApp.use(cors());
expressApp.use(express.json()); expressApp.use(express.json());
expressApp.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); expressApp.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
expressApp.get("/", (req, res) => res.send("Hello World!")); expressApp.get("/", (req, res) => {
expressApp.get("/swagger.json", (req, res) => res.json(swaggerSpec)); res.send("Hello World!");
});
expressApp.get("/swagger.json", (req, res) => {
res.json(swaggerSpec);
});
// add features // add features
addLegacyApi(expressApp, mainWindow); addLegacyApi(expressApp, mainWindow);

View File

@@ -2,7 +2,7 @@
"openapi": "3.1.0", "openapi": "3.1.0",
"info": { "info": {
"title": "TIDAL Hi-Fi API", "title": "TIDAL Hi-Fi API",
"version": "5.17.0", "version": "5.19.0",
"description": "", "description": "",
"license": { "license": {
"name": "MIT", "name": "MIT",
@@ -21,7 +21,9 @@
"/current": { "/current": {
"get": { "get": {
"summary": "Get current media info", "summary": "Get current media info",
"tags": ["current"], "tags": [
"current"
],
"responses": { "responses": {
"200": { "200": {
"description": "Current media info", "description": "Current media info",
@@ -39,7 +41,9 @@
"/current/image": { "/current/image": {
"get": { "get": {
"summary": "Get current media image", "summary": "Get current media image",
"tags": ["current"], "tags": [
"current"
],
"responses": { "responses": {
"200": { "200": {
"description": "Current media image", "description": "Current media image",
@@ -61,7 +65,9 @@
"/player/play": { "/player/play": {
"post": { "post": {
"summary": "Play the current media", "summary": "Play the current media",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -79,7 +85,9 @@
"/player/favorite/toggle": { "/player/favorite/toggle": {
"post": { "post": {
"summary": "Add the current media to your favorites, or remove it if its already added to your favorites", "summary": "Add the current media to your favorites, or remove it if its already added to your favorites",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -97,7 +105,9 @@
"/player/pause": { "/player/pause": {
"post": { "post": {
"summary": "Pause the current media", "summary": "Pause the current media",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -115,7 +125,9 @@
"/player/next": { "/player/next": {
"post": { "post": {
"summary": "Play the next song", "summary": "Play the next song",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -133,7 +145,9 @@
"/player/previous": { "/player/previous": {
"post": { "post": {
"summary": "Play the previous song", "summary": "Play the previous song",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -151,7 +165,9 @@
"/player/shuffle/toggle": { "/player/shuffle/toggle": {
"post": { "post": {
"summary": "Play the previous song", "summary": "Play the previous song",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -169,7 +185,9 @@
"/player/repeat/toggle": { "/player/repeat/toggle": {
"post": { "post": {
"summary": "Toggle the repeat status, toggles between \"off\" , \"single\" and \"all\"", "summary": "Toggle the repeat status, toggles between \"off\" , \"single\" and \"all\"",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -187,7 +205,9 @@
"/player/playpause": { "/player/playpause": {
"post": { "post": {
"summary": "Start playing the media if paused, or pause the media if playing", "summary": "Start playing the media if paused, or pause the media if playing",
"tags": ["player"], "tags": [
"player"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok", "description": "Ok",
@@ -205,7 +225,9 @@
"/settings/skipped-artists": { "/settings/skipped-artists": {
"get": { "get": {
"summary": "get a list of artists that TIDAL Hi-Fi will skip if skipping is enabled", "summary": "get a list of artists that TIDAL Hi-Fi will skip if skipping is enabled",
"tags": ["settings"], "tags": [
"settings"
],
"responses": { "responses": {
"200": { "200": {
"description": "The list book.", "description": "The list book.",
@@ -221,7 +243,9 @@
}, },
"post": { "post": {
"summary": "Add new artists to the list of skipped artists", "summary": "Add new artists to the list of skipped artists",
"tags": ["settings"], "tags": [
"settings"
],
"requestBody": { "requestBody": {
"required": true, "required": true,
"content": { "content": {
@@ -242,7 +266,9 @@
"/settings/skipped-artists/delete": { "/settings/skipped-artists/delete": {
"post": { "post": {
"summary": "Remove artists from the list of skipped artists", "summary": "Remove artists from the list of skipped artists",
"tags": ["settings"], "tags": [
"settings"
],
"requestBody": { "requestBody": {
"required": true, "required": true,
"content": { "content": {
@@ -263,7 +289,9 @@
"/settings/skipped-artists/current": { "/settings/skipped-artists/current": {
"post": { "post": {
"summary": "Add the current artist to the list of skipped artists", "summary": "Add the current artist to the list of skipped artists",
"tags": ["settings"], "tags": [
"settings"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok" "description": "Ok"
@@ -272,7 +300,9 @@
}, },
"delete": { "delete": {
"summary": "Remove the current artist from the list of skipped artists", "summary": "Remove the current artist from the list of skipped artists",
"tags": ["settings"], "tags": [
"settings"
],
"responses": { "responses": {
"200": { "200": {
"description": "Ok" "description": "Ok"
@@ -283,7 +313,9 @@
"/image": { "/image": {
"get": { "get": {
"summary": "Get current image", "summary": "Get current image",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -306,7 +338,9 @@
"/play": { "/play": {
"get": { "get": {
"summary": "Play the current media", "summary": "Play the current media",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -325,7 +359,9 @@
"/favorite/toggle": { "/favorite/toggle": {
"get": { "get": {
"summary": "Add the current media to your favorites, or remove it if its already added to your favorites", "summary": "Add the current media to your favorites, or remove it if its already added to your favorites",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -344,7 +380,9 @@
"/pause": { "/pause": {
"get": { "get": {
"summary": "Pause the current media", "summary": "Pause the current media",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -363,7 +401,9 @@
"/next": { "/next": {
"get": { "get": {
"summary": "Play the next song", "summary": "Play the next song",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -382,7 +422,9 @@
"/previous": { "/previous": {
"get": { "get": {
"summary": "Play the previous song", "summary": "Play the previous song",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -401,7 +443,9 @@
"/playpause": { "/playpause": {
"get": { "get": {
"summary": "Toggle play/pause", "summary": "Toggle play/pause",
"tags": ["legacy"], "tags": [
"legacy"
],
"deprecated": true, "deprecated": true,
"responses": { "responses": {
"200": { "200": {
@@ -514,7 +558,10 @@
"items": { "items": {
"type": "string" "type": "string"
}, },
"example": ["Artist1", "Artist2"] "example": [
"Artist1",
"Artist2"
]
} }
} }
}, },

View File

@@ -26,7 +26,6 @@ import {
import { addTray, refreshTray } from "./scripts/tray"; import { addTray, refreshTray } from "./scripts/tray";
let mainInhibitorId = -1; let mainInhibitorId = -1;
initialize();
let mainWindow: BrowserWindow; let mainWindow: BrowserWindow;
const icon = path.join(__dirname, "../assets/icon.png"); const icon = path.join(__dirname, "../assets/icon.png");
const PROTOCOL_PREFIX = "tidal"; const PROTOCOL_PREFIX = "tidal";
@@ -98,6 +97,7 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
}, },
}, },
}); });
enable(mainWindow.webContents); enable(mainWindow.webContents);
registerHttpProtocols(); registerHttpProtocols();
syncMenuBarWithStore(); syncMenuBarWithStore();
@@ -126,6 +126,7 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
} }
return false; return false;
}); });
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on("closed", function () { mainWindow.on("closed", function () {
releaseInhibitorIfActive(mainInhibitorId); releaseInhibitorIfActive(mainInhibitorId);
@@ -178,6 +179,7 @@ app.on("ready", async () => {
if (isMainInstance() || isMultipleInstancesAllowed()) { if (isMainInstance() || isMultipleInstancesAllowed()) {
await components.whenReady(); await components.whenReady();
initialize();
// Adblock // Adblock
if (settingsStore.get(settings.adBlock)) { if (settingsStore.get(settings.adBlock)) {
@@ -188,6 +190,8 @@ app.on("ready", async () => {
}); });
} }
Logger.log("components ready:", components.status());
createWindow(); createWindow();
addMenu(mainWindow); addMenu(mainWindow);
createSettingsWindow(); createSettingsWindow();

View File

@@ -1,34 +1,25 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<title>Tidal Hi-Fi settings</title> <title>Tidal Hi-Fi settings</title>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="./settings.css" /> <link rel="stylesheet" href="./settings.css" />
<link <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
rel="stylesheet" </head>
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
</head>
<body class="settings-window"> <body class="settings-window">
<div class="settings-window__wrapper"> <div class="settings-window__wrapper">
<div class="settings-window__drag-area"></div> <div class="settings-window__drag-area"></div>
<a id="close" class="settings-window__close-button" title="Close settings"> <a id="close" class="settings-window__close-button" title="Close settings">
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 348.333 348.334" class="settings-window__svg-icon">
xmlns="http://www.w3.org/2000/svg" <path fill="white" d="M336.559,68.611L231.016,174.165l105.543,105.549c15.699,15.705,15.699,41.145,0,56.85
viewBox="0 0 348.333 348.334"
class="settings-window__svg-icon"
>
<path
fill="white"
d="M336.559,68.611L231.016,174.165l105.543,105.549c15.699,15.705,15.699,41.145,0,56.85
c-7.844,7.844-18.128,11.769-28.407,11.769c-10.296,0-20.581-3.919-28.419-11.769L174.167,231.003L68.609,336.563 c-7.844,7.844-18.128,11.769-28.407,11.769c-10.296,0-20.581-3.919-28.419-11.769L174.167,231.003L68.609,336.563
c-7.843,7.844-18.128,11.769-28.416,11.769c-10.285,0-20.563-3.919-28.413-11.769c-15.699-15.698-15.699-41.139,0-56.85 c-7.843,7.844-18.128,11.769-28.416,11.769c-10.285,0-20.563-3.919-28.413-11.769c-15.699-15.698-15.699-41.139,0-56.85
l105.54-105.549L11.774,68.611c-15.699-15.699-15.699-41.145,0-56.844c15.696-15.687,41.127-15.687,56.829,0l105.563,105.554 l105.54-105.549L11.774,68.611c-15.699-15.699-15.699-41.145,0-56.844c15.696-15.687,41.127-15.687,56.829,0l105.563,105.554
L279.721,11.767c15.705-15.687,41.139-15.687,56.832,0C352.258,27.466,352.258,52.912,336.559,68.611z" L279.721,11.767c15.705-15.687,41.139-15.687,56.832,0C352.258,27.466,352.258,52.912,336.559,68.611z" />
/>
</svg> </svg>
</a> </a>
@@ -75,13 +66,7 @@
<span class="switch__slider"></span> <span class="switch__slider"></span>
</label> </label>
</div> </div>
<textarea <textarea id="skippedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
id="skippedArtists"
class="textarea"
cols="40"
rows="5"
spellcheck="false"
></textarea>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>Block ads</h4> <h4>Block ads</h4>
@@ -124,10 +109,7 @@
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>Static Window Title</h4> <h4>Static Window Title</h4>
<p> <p>Makes the window title "TIDAL Hi-Fi" instead of changing to the currently playing song.</p>
Makes the window title "TIDAL Hi-Fi" instead of changing to the currently
playing song.
</p>
</div> </div>
<label class="switch"> <label class="switch">
<input id="staticWindowTitle" type="checkbox" /> <input id="staticWindowTitle" type="checkbox" />
@@ -149,9 +131,7 @@
<h4>Hotkeys</h4> <h4>Hotkeys</h4>
<p> <p>
Enable extra hotkeys to achieve feature parity with the Enable extra hotkeys to achieve feature parity with the
<a class="external-link" data-url="https://defkey.com/tidal-desktop-shortcuts" <a class="external-link" data-url="https://defkey.com/tidal-desktop-shortcuts">desktop apps</a>.
>desktop apps</a
>.
</p> </p>
</div> </div>
<label class="switch"> <label class="switch">
@@ -177,8 +157,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 media TIDAL Hi-Fi has a built-in web API to allow users to get current media information.
information. You can optionally enable playback control as well. You can optionally enable playback control as well.
</p> </p>
</div> </div>
<div class="group__option"> <div class="group__option">
@@ -200,8 +180,7 @@
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>API hostname</h4> <h4>API hostname</h4>
<p> <p>By default (127.0.0.1) only local apps can interface with the API. <br />
By default (127.0.0.1) only local apps can interface with the API. <br />
Change to 0.0.0.0 to allow <strong>anyone</strong> to interact with it. <br /> Change to 0.0.0.0 to allow <strong>anyone</strong> to interact with it. <br />
Other options are available Other options are available
</p> </p>
@@ -257,6 +236,7 @@
</label> </label>
</div> </div>
<div id="discord_options"> <div id="discord_options">
<div class="group__option" class="hidden"> <div class="group__option" class="hidden">
<div class="group__description"> <div class="group__description">
<h4>Show Idle Text</h4> <h4>Show Idle Text</h4>
@@ -272,27 +252,15 @@
<div class="group__description"> <div class="group__description">
<h4>Idle Text</h4> <h4>Idle Text</h4>
<p>The text displayed on Discord's rich presence while idling in the app.</p> <p>The text displayed on Discord's rich presence while idling in the app.</p>
<input <input id="discord_idle_text" type="text" class="text-input" name="discord_idle_text" />
id="discord_idle_text"
type="text"
class="text-input"
name="discord_idle_text"
/>
</div> </div>
</div> </div>
<div class="group__option" class="hidden"> <div class="group__option" class="hidden">
<div class="group__description"> <div class="group__description">
<h4>Using Tidal Text</h4> <h4>Using Tidal Text</h4>
<p> <p>The text displayed on Discord's rich presence while "showSong" is turned off</p>
The text displayed on Discord's rich presence while "showSong" is turned off <input id="discord_using_text" type="text" class="text-input" name="discord_using_text" />
</p>
<input
id="discord_using_text"
type="text"
class="text-input"
name="discord_using_text"
/>
</div> </div>
</div> </div>
@@ -308,6 +276,7 @@
</div> </div>
<div id="discord_show_song_options" class="hidden"> <div id="discord_show_song_options" class="hidden">
<div class="group__option" class="hidden"> <div class="group__option" class="hidden">
<div class="group__description"> <div class="group__description">
<h4>Include timestamps</h4> <h4>Include timestamps</h4>
@@ -323,12 +292,7 @@
<div class="group__description"> <div class="group__description">
<h4>Details prefix</h4> <h4>Details prefix</h4>
<p>Prefix for the "details" field of Discord's rich presence.</p> <p>Prefix for the "details" field of Discord's rich presence.</p>
<input <input id="discord_details_prefix" type="text" class="text-input" name="discord_details_prefix" />
id="discord_details_prefix"
type="text"
class="text-input"
name="discord_details_prefix"
/>
</div> </div>
</div> </div>
@@ -336,15 +300,11 @@
<div class="group__description"> <div class="group__description">
<h4>Button text</h4> <h4>Button text</h4>
<p>Text to display on the button below the media information.</p> <p>Text to display on the button below the media information.</p>
<input <input id="discord_button_text" type="text" class="text-input" name="discord_button_text" />
id="discord_button_text"
type="text"
class="text-input"
name="discord_button_text"
/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="group"> <div class="group">
@@ -363,43 +323,23 @@
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>ListenBrainz API Url</h4> <h4>ListenBrainz API Url</h4>
<p> <p>There are multiple instances for ListenBrainz you can set the corresponding API url below.</p>
There are multiple instances for ListenBrainz you can set the corresponding <input id="ListenBrainzAPI" type="text" class="text-input" name="ListenBrainzAPI" />
API url below.
</p>
<input
id="ListenBrainzAPI"
type="text"
class="text-input"
name="ListenBrainzAPI"
/>
</div> </div>
</div> </div>
<div class="group__option"> <div class="group__option">
<div class="group__description"> <div class="group__description">
<h4>ListenBrainz User Token</h4> <h4>ListenBrainz User Token</h4>
<p>Provide the user token you can get from the settings page.</p> <p>Provide the user token you can get from the settings page.</p>
<input <input id="ListenBrainzToken" type="text" class="text-input" name="ListenBrainzToken" />
id="ListenBrainzToken"
type="text"
class="text-input"
name="ListenBrainzToken"
/>
</div> </div>
</div> </div>
</div> </div>
<div class="group__description"> <div class="group__description">
<h4>ScrobbleDelay</h4> <h4>ScrobbleDelay</h4>
<p> <p>The delay (in ms) to send a listen to ListenBrainz. Prevents spamming the API when you fast forward
The delay (in ms) to send a listen to ListenBrainz. Prevents spamming the API when immediately</p>
you fast forward immediately <input id="listenbrainz_delay" type="number" class="text-input" name="listenbrainz_delay" />
</p>
<input
id="listenbrainz_delay"
type="number"
class="text-input"
name="listenbrainz_delay"
/>
</div> </div>
</div> </div>
</section> </section>
@@ -411,16 +351,12 @@
<div class="group__description"> <div class="group__description">
<h4>Update frequency</h4> <h4>Update frequency</h4>
<p> <p>
The amount of time, in milliseconds, that TIDAL Hi-Fi will refresh its playback The amount of time, in milliseconds, that TIDAL Hi-Fi will refresh its playback info by scraping the
info by scraping the website. The default of 500 seems to work in more cases but website.
if you are fine with a bit more resource usage you can decrease it as well. 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> </p>
<input <input id="updateFrequency" type="number" class="text-input" name="updateFrequency" />
id="updateFrequency"
type="number"
class="text-input"
name="updateFrequency"
/>
</div> </div>
</div> </div>
@@ -433,9 +369,7 @@
</p> </p>
<select class="select-input" id="channel" name="channel"> <select class="select-input" id="channel" name="channel">
<option value="https://listen.tidal.com">Stable (listen.tidal.com)</option> <option value="https://listen.tidal.com">Stable (listen.tidal.com)</option>
<option value="https://listen.stage.tidal.com"> <option value="https://listen.stage.tidal.com">Staging (listen.stage.tidal.com)</option>
Staging (listen.stage.tidal.com)
</option>
</select> </select>
</div> </div>
</div> </div>
@@ -481,8 +415,7 @@
<div class="group__description"> <div class="group__description">
<h4>Wayland support</h4> <h4>Wayland support</h4>
<p> <p>
Adds a couple of Electron flags to help TIDAL Hi-Fi run smoothly on the Wayland Adds a couple of Electron flags to help TIDAL Hi-Fi run smoothly on the Wayland window system.
window system.
</p> </p>
</div> </div>
<label class="switch"> <label class="switch">
@@ -500,19 +433,12 @@
<div class="group__description"> <div class="group__description">
<h4>Custom CSS</h4> <h4>Custom CSS</h4>
<p> <p>
The css that you put in here will be injected into a style tag in the head of The css that you put in here will be injected into a style tag in the head of the document.
the document.
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<textarea <textarea id="customCSS" class="textarea" cols="40" rows="8" spellcheck="false"></textarea>
id="customCSS"
class="textarea"
cols="40"
rows="8"
spellcheck="false"
></textarea>
<div class="group"> <div class="group">
<p class="group__title">Theme files</p> <p class="group__title">Theme files</p>
@@ -522,7 +448,9 @@
<p> <p>
Select a theme below or "Tidal - Default" to return to the original Tidal look. Select a theme below or "Tidal - Default" to return to the original Tidal look.
</p> </p>
<select class="select-input" id="themesList" name="themesList"></select> <select class="select-input" id="themesList" name="themesList">
</select>
</div> </div>
</div> </div>
@@ -530,20 +458,14 @@
<div class="group__description"> <div class="group__description">
<h4>Upload new themes</h4> <h4>Upload new themes</h4>
<p> <p>
Click the button and select the css files to import. They will be added to the Click the button and select the css files to import. They will be added to the theme list
theme list automatically. automatically.
</p> </p>
<div class="file-drop-area"> <div class="file-drop-area">
<div> <div>
<span class="file-btn">Choose files</span> <span class="file-btn">Choose files</span>
<span id="file-message" class="file-msg">or drag and drop files here</span> <span id="file-message" class="file-msg">or drag and drop files here</span>
<input <input id="theme-files" class="file-input" type="file" accept=".css" multiple>
id="theme-files"
class="file-input"
type="file"
accept=".css"
multiple
/>
</div> </div>
</div> </div>
</div> </div>
@@ -555,35 +477,17 @@
<img alt="tidal icon" class="about-section__icon" src="./icon.png" /> <img alt="tidal icon" class="about-section__icon" src="./icon.png" />
<h4>TIDAL Hi-Fi</h4> <h4>TIDAL Hi-Fi</h4>
<div class="about-section__version"> <div class="about-section__version">
<a <a target="_blank" rel="noopener"
target="_blank" href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.19.0">5.19.0</a>
rel="noopener"
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.17.0"
>5.17.0</a
>
</div> </div>
<div class="about-section__links"> <div class="about-section__links">
<a <a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/"
target="_blank" class="about-section__button">Github
rel="noopener" <i class="fa fa-external-link"></i></a>
href="https://github.com/mastermindzh/tidal-hifi/" <a target="_blank" rel="noopener" href="https://github.com/Mastermindzh/tidal-hifi/issues"
class="about-section__button" class="about-section__button">Report an issue <i class="fa fa-external-link"></i></a>
>Github <i class="fa fa-external-link"></i <a target="_blank" rel="noopener" href="https://github.com/Mastermindzh/tidal-hifi/graphs/contributors"
></a> class="about-section__button">Contributors <i class="fa fa-external-link"></i></a>
<a
target="_blank"
rel="noopener"
href="https://github.com/Mastermindzh/tidal-hifi/issues"
class="about-section__button"
>Report an issue <i class="fa fa-external-link"></i
></a>
<a
target="_blank"
rel="noopener"
href="https://github.com/Mastermindzh/tidal-hifi/graphs/contributors"
class="about-section__button"
>Contributors <i class="fa fa-external-link"></i
></a>
</div> </div>
</section> </section>
@@ -595,5 +499,6 @@
</div> </div>
</main> </main>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -54,12 +54,12 @@ const elements = {
media: '*[data-test="current-media-imagery"]', media: '*[data-test="current-media-imagery"]',
image: "img", image: "img",
current: '*[data-test="current-time"]', current: '*[data-test="current-time"]',
duration: '*[class^=playbackControlsContainer] *[data-test="duration"]', duration: '*[class^=_playbackControlsContainer] *[data-test="duration"]',
bar: '*[data-test="progress-bar"]', bar: '*[data-test="progress-bar"]',
footer: "#footerPlayer", footer: "#footerPlayer",
mediaItem: "[data-type='mediaItem']", mediaItem: "[data-type='mediaItem']",
album_header_title: '*[class^="playingFrom"] span:nth-child(2)', album_header_title: '*[class^="_playingFrom"] span:nth-child(2)',
playing_from: '*[class^="playingFrom"] span:nth-child(2)', playing_from: '*[class^="_playingFrom"] span:nth-child(2)',
queue_album: "*[class^=playQueueItemsContainer] *[class^=groupTitle] span:nth-child(2)", queue_album: "*[class^=playQueueItemsContainer] *[class^=groupTitle] span:nth-child(2)",
currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']", currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']",
album_name_cell: '[class^="album"]', album_name_cell: '[class^="album"]',
@@ -115,18 +115,19 @@ const elements = {
}, },
getAlbumName: function () { getAlbumName: function () {
try {
//If listening to an album, get its name from the header title //If listening to an album, get its name from the header title
if (window.location.href.includes("/album/")) { if (globalThis.location.href.includes("/album/")) {
const albumName = window.document.querySelector(this.album_header_title); const albumName = globalThis.document.querySelector(this.album_header_title);
if (albumName) { if (albumName) {
return albumName.textContent; return albumName.textContent;
} }
//If listening to a playlist or a mix, get album name from the list //If listening to a playlist or a mix, get album name from the list
} else if ( } else if (
window.location.href.includes("/playlist/") || globalThis.location.href.includes("/playlist/") ||
window.location.href.includes("/mix/") globalThis.location.href.includes("/mix/")
) { ) {
if (currentPlayStatus === MediaStatus.playing) { if (this.currentlyPlaying === MediaStatus.playing) {
// find the currently playing element from the list (which might be in an album icon), traverse back up to the mediaItem (row) and select the album cell. // find the currently playing element from the list (which might be in an album icon), traverse back up to the mediaItem (row) and select the album cell.
// document.querySelector("[class^='isPlayingIcon'], [data-test-is-playing='true']").closest('[data-type="mediaItem"]').querySelector('[class^="album"]').textContent // document.querySelector("[class^='isPlayingIcon'], [data-test-is-playing='true']").closest('[data-type="mediaItem"]').querySelector('[class^="album"]').textContent
const row = window.document.querySelector(this.currentlyPlaying).closest(this.mediaItem); const row = window.document.querySelector(this.currentlyPlaying).closest(this.mediaItem);
@@ -137,12 +138,15 @@ const elements = {
} }
// see whether we're on the queue page and get it from there // see whether we're on the queue page and get it from there
const queueAlbumName = elements.getText("queue_album"); const queueAlbumName = this.getText("queue_album");
if (queueAlbumName) { if (queueAlbumName) {
return queueAlbumName; return queueAlbumName;
} }
return ""; return "";
} catch {
return "";
}
}, },
isMuted: function () { isMuted: function () {
@@ -483,6 +487,7 @@ function updateMpris(mediaInfo: MediaInfo) {
"xesam:title": mediaInfo.title, "xesam:title": mediaInfo.title,
"xesam:artist": [mediaInfo.artists], "xesam:artist": [mediaInfo.artists],
"xesam:album": mediaInfo.album, "xesam:album": mediaInfo.album,
"xesam:url": mediaInfo.url,
"mpris:artUrl": mediaInfo.image, "mpris:artUrl": mediaInfo.image,
"mpris:length": convertDuration(mediaInfo.duration) * 1000 * 1000, "mpris:length": convertDuration(mediaInfo.duration) * 1000 * 1000,
"mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(), "mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(),

View File

@@ -26,7 +26,7 @@ const defaultPresence = {
largeImageKey: "tidal-hifi-icon", largeImageKey: "tidal-hifi-icon",
largeImageText: `TIDAL Hi-Fi ${app.getVersion()}`, largeImageText: `TIDAL Hi-Fi ${app.getVersion()}`,
instance: false, instance: false,
type: ACTIVITY_LISTENING, type: ACTIVITY_LISTENING
}; };
const updateActivity = () => { const updateActivity = () => {
@@ -103,8 +103,7 @@ const getActivity = (): SetActivity => {
if (includeTimestamps) { if (includeTimestamps) {
const currentSeconds = convertDurationToSeconds(mediaInfo.current); const currentSeconds = convertDurationToSeconds(mediaInfo.current);
const durationSeconds = convertDurationToSeconds(mediaInfo.duration); const durationSeconds = convertDurationToSeconds(mediaInfo.duration);
const date = new Date(); const now = Math.trunc((Date.now() + 500) / 1000);
const now = Math.floor(date.getTime() / 1000);
presence.startTimestamp = now - currentSeconds; presence.startTimestamp = now - currentSeconds;
presence.endTimestamp = presence.startTimestamp + durationSeconds; presence.endTimestamp = presence.startTimestamp + durationSeconds;
} }
@@ -118,17 +117,15 @@ const getActivity = (): SetActivity => {
const connectWithRetry = async (retryCount = 0) => { const connectWithRetry = async (retryCount = 0) => {
try { try {
await rpc.login(); await rpc.login();
Logger.log("Connected to Discord"); Logger.log('Connected to Discord');
rpc.on("ready", updateActivity); rpc.on("ready", updateActivity);
Object.values(globalEvents).forEach((event) => ipcMain.on(event, observer)); Object.values(globalEvents).forEach(event => ipcMain.on(event, observer));
} catch (error) { } catch (error) {
if (retryCount < MAX_RETRIES) { if (retryCount < MAX_RETRIES) {
Logger.log( Logger.log(`Failed to connect to Discord, retrying in ${RETRY_DELAY/1000} seconds... (Attempt ${retryCount + 1}/${MAX_RETRIES})`);
`Failed to connect to Discord, retrying in ${RETRY_DELAY / 1000} seconds... (Attempt ${retryCount + 1}/${MAX_RETRIES})`
);
setTimeout(() => connectWithRetry(retryCount + 1), RETRY_DELAY); setTimeout(() => connectWithRetry(retryCount + 1), RETRY_DELAY);
} else { } else {
Logger.log("Failed to connect to Discord after maximum retry attempts"); Logger.log('Failed to connect to Discord after maximum retry attempts');
} }
} }
}; };
@@ -137,7 +134,7 @@ const connectWithRetry = async (retryCount = 0) => {
* Set up the discord rpc and listen on globalEvents.updateInfo * Set up the discord rpc and listen on globalEvents.updateInfo
*/ */
export const initRPC = () => { export const initRPC = () => {
rpc = new Client({ transport: { type: "ipc" }, clientId }); rpc = new Client({ transport: {type: "ipc"}, clientId });
connectWithRetry(); connectWithRetry();
}; };