mirror of
				https://github.com/Mastermindzh/tidal-hifi.git
				synced 2025-10-31 00:39:30 +01:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			c89fe5e573
			...
			develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d67f62c0dc | |||
| b2afd44dd6 | 
| @@ -4,12 +4,12 @@ name: default | ||||
|  | ||||
| steps: | ||||
|   - name: install | ||||
|     image: node:22.17.0 | ||||
|     image: node:19.4.0 | ||||
|     commands: | ||||
|       - npm install | ||||
|  | ||||
|   - name: build_with_linux | ||||
|     image: node:22.17.0 | ||||
|     image: node:19.4.0 | ||||
|     commands: | ||||
|       - apt-get update && apt-get upgrade -y | ||||
|       - apt-get install -y libarchive-tools rpm | ||||
|   | ||||
							
								
								
									
										42
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,30 +21,26 @@ jobs: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.12.0 | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|       # - uses: actions/upload-artifact@master | ||||
|       #   with: | ||||
|       #     name: linux-builds | ||||
|       #     path: dist/ | ||||
|  | ||||
|   # build_on_mac: | ||||
|   #   runs-on: macos-latest | ||||
|   #   steps: | ||||
|   #     - uses: actions/checkout@master | ||||
|   #     - uses: actions/setup-node@master | ||||
|   #       with: | ||||
|   #         node-version: 22.4 | ||||
|   #     - run: npm install | ||||
|   #     - run: npm run build | ||||
|   build_on_mac: | ||||
|     runs-on: macos-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|  | ||||
|   # build_on_win: | ||||
|   #   runs-on: windows-latest | ||||
|   #   steps: | ||||
|   #     - uses: actions/checkout@master | ||||
|   #     - uses: actions/setup-node@master | ||||
|   #       with: | ||||
|   #         node-version: 22.4 | ||||
|   #     - run: npm install | ||||
|   #     - run: npm run build | ||||
|   build_on_win: | ||||
|     runs-on: windows-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|   | ||||
							
								
								
									
										54
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.12.0 | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|       - uses: actions/upload-artifact@master | ||||
| @@ -29,30 +29,30 @@ jobs: | ||||
|           name: linux-builds | ||||
|           path: dist/ | ||||
|  | ||||
|   # build_on_mac: | ||||
|   #   runs-on: macos-latest | ||||
|   #   steps: | ||||
|   #     - uses: actions/checkout@master | ||||
|   #     - uses: actions/setup-node@master | ||||
|   #       with: | ||||
|   #         node-version: 22.4 | ||||
|   #     - run: npm install | ||||
|   #     - run: npm run build | ||||
|   #     - uses: actions/upload-artifact@master | ||||
|   #       with: | ||||
|   #         name: mac-builds | ||||
|   #         path: ./dist/ | ||||
|   build_on_mac: | ||||
|     runs-on: macos-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|       - uses: actions/upload-artifact@master | ||||
|         with: | ||||
|           name: mac-builds | ||||
|           path: ./dist/ | ||||
|  | ||||
|   # build_on_win: | ||||
|   #   runs-on: windows-latest | ||||
|   #   steps: | ||||
|   #     - uses: actions/checkout@master | ||||
|   #     - uses: actions/setup-node@master | ||||
|   #       with: | ||||
|   #         node-version: 22.4 | ||||
|   #     - run: npm install | ||||
|   #     - run: npm run build | ||||
|   #     - uses: actions/upload-artifact@master | ||||
|   #       with: | ||||
|   #         name: windows-builds | ||||
|   #         path: dist/ | ||||
|   build_on_win: | ||||
|     runs-on: windows-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@master | ||||
|       - uses: actions/setup-node@master | ||||
|         with: | ||||
|           node-version: 22.4 | ||||
|       - run: npm install | ||||
|       - run: npm run build | ||||
|       - uses: actions/upload-artifact@master | ||||
|         with: | ||||
|           name: windows-builds | ||||
|           path: dist/ | ||||
|   | ||||
| @@ -1,13 +1,7 @@ | ||||
| { | ||||
|   "plugins": [ | ||||
|     "stylelint-prettier" | ||||
|   ], | ||||
|   "extends": [ | ||||
|     "stylelint-config-standard-scss" | ||||
|   ], | ||||
|   "ignoreFiles": [ | ||||
|     "src/themes/**.scss" | ||||
|   ], | ||||
|   "plugins": ["stylelint-prettier"], | ||||
|   "extends": ["stylelint-config-standard-scss"], | ||||
|   "ignoreFiles": ["src/themes/**.scss"], | ||||
|   "rules": { | ||||
|     "prettier/prettier": true, | ||||
|     "scss/at-extend-no-missing-placeholder": null, | ||||
|   | ||||
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -17,9 +17,7 @@ | ||||
|     "trackid", | ||||
|     "tracklist", | ||||
|     "widevine", | ||||
|     "wvcus", | ||||
|     "xesam", | ||||
|     "xhayper" | ||||
|     "xesam" | ||||
|   ], | ||||
|   "sonarlint.connectedMode.project": { | ||||
|     "connectionId": "public-sonarcloud", | ||||
|   | ||||
							
								
								
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -4,42 +4,6 @@ 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). | ||||
|  | ||||
| ## [5.20.1] | ||||
|  | ||||
| - Updated electron to 37.2.5 | ||||
|  | ||||
| ## [5.20.0] | ||||
|  | ||||
| - Removes the `--enable-features=UseOzonePlatform` flag, as the Ozone platform has been the default on Linux since Electron 28 and this flag is no longer necessary. | ||||
| - Adds the `--enable-wayland-ime` flag to enable Input Method Editor (IME) support in Wayland environments, improving the input experience for CJK and other users. | ||||
| - Updated various dependencies | ||||
| - Updated Electron to 37, potentially fixing [#580](https://github.com/Mastermindzh/tidal-hifi/issues/580) | ||||
|  | ||||
| ## [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] | ||||
|  | ||||
| - Added an option to disable the dynamic title and set it to a static one, [#491](https://github.com/Mastermindzh/tidal-hifi/pull/491) | ||||
| @@ -57,6 +21,7 @@ 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) | ||||
| - Updated most dependency versions | ||||
|  | ||||
|   - This includes Electron 31! | ||||
|  | ||||
| - Added a channel selector so we can now use Tidal's staging environment directly from the app | ||||
| @@ -148,10 +113,12 @@ 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 dependencies to latest | ||||
|  | ||||
|   - added theme files to stylelint ignore | ||||
|   - fixed other stylelint errors | ||||
|  | ||||
| - 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 the "favorite" field in the `mediaInfo` and the API `/current` endpoint | ||||
|   - Added an endpoint to toggle favoriting a song: `http://localhost:47836/favorite/toggle` | ||||
|   | ||||
| @@ -8,4 +8,3 @@ Only the very latest 😄. | ||||
|  | ||||
| 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). | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| appId: com.rickvanlieshout.tidal-hifi | ||||
| electronVersion: 37.2.5 | ||||
| electronVersion: 28.1.1 | ||||
| electronDownload: | ||||
|   version: 37.2.5+wvcus | ||||
|   version: 28.1.1+wvcus | ||||
|   mirror: https://github.com/castlabs/electron-releases/releases/download/v | ||||
| snap: | ||||
|   plugs: | ||||
| @@ -17,25 +17,24 @@ linux: | ||||
|   executableName: tidal-hifi | ||||
|   executableArgs: | ||||
|     [ | ||||
|       "--enable-features=UseOzonePlatform", | ||||
|       "--ozone-platform-hint=auto", | ||||
|       "--enable-features=WaylandWindowDecorations", | ||||
|       "--enable-wayland-ime", | ||||
|       "--use-angle", | ||||
|     ] | ||||
|   desktop: | ||||
|     entry: | ||||
|       Encoding: "UTF-8" | ||||
|       Name: "TIDAL Hi-Fi" | ||||
|       GenericName: "TIDAL Hi-Fi" | ||||
|       Comment: "The web version of listen.tidal.com running in electron with hifi support thanks to widevine." | ||||
|       Icon: "tidal-hifi" | ||||
|       StartupNotify: "true" | ||||
|       Terminal: "false" | ||||
|       Type: "Application" | ||||
|       Categories: "Network;Application;AudioVideo;Audio;Video" | ||||
|       StartupWMClass: "tidal-hifi" | ||||
|       X-PulseAudio-Properties: "media.role=music" | ||||
|       MimeType: "x-scheme-handler/tidal;" | ||||
|     Encoding: UTF-8 | ||||
|     Name: TIDAL Hi-Fi | ||||
|     GenericName: TIDAL Hi-Fi | ||||
|     Comment: The web version of listen.tidal.com running in electron with hifi support thanks to widevine. | ||||
|     Icon: tidal-hifi | ||||
|     StartupNotify: true | ||||
|     Terminal: false | ||||
|     Type: Application | ||||
|     Categories: Network;Application;AudioVideo;Audio;Video | ||||
|     StartupWMClass: tidal-hifi | ||||
|     X-PulseAudio-Properties: media.role=music | ||||
|     MimeType: x-scheme-handler/tidal; | ||||
|  | ||||
| mac: | ||||
|   category: public.app-category.entertainment | ||||
| win: | ||||
|   | ||||
							
								
								
									
										5543
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5543
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										52
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,10 +1,10 @@ | ||||
| { | ||||
|   "name": "tidal-hifi", | ||||
|   "version": "5.20.1", | ||||
|   "version": "5.17.0", | ||||
|   "description": "Tidal on Electron with widevine(hifi) support", | ||||
|   "main": "ts-dist/main.js", | ||||
|   "scripts": { | ||||
|     "start": "electron --inspect=0.0.0.0:5858 --remote-debugging-port=8315 --remote-allow-origins=* .", | ||||
|     "start": "electron --inspect=0.0.0.0:5858 .", | ||||
|     "watchStart": "nodemon dist -x \"npm run start\"", | ||||
|     "compile": "tsc && npm run sass-and-copy", | ||||
|     "deps": "npm run watch", | ||||
| @@ -23,6 +23,7 @@ | ||||
|     "build-mac": "npm run builder -- -c ./build/electron-builder.yml -m", | ||||
|     "build-base": "npm run builder -- -c ./build/electron-builder.base.yml", | ||||
|     "prebuilder": "npm run compile", | ||||
|     "prettier": "prettier . --write", | ||||
|     "builder": "electron-builder --publish=never", | ||||
|     "sass": "sass ./src/pages/settings/settings.scss ./src/pages/settings/settings.css && sass --no-source-map src/themes:themes", | ||||
|     "style-lint": "npx stylelint **/*.scss", | ||||
| @@ -40,45 +41,44 @@ | ||||
|   "homepage": "https://github.com/Mastermindzh/tidal-hifi", | ||||
|   "license": "MIT", | ||||
|   "dependencies": { | ||||
|     "@electron/remote": "^2.1.3", | ||||
|     "@electron/remote": "^2.1.2", | ||||
|     "@types/swagger-jsdoc": "^6.0.4", | ||||
|     "@xhayper/discord-rpc": "1.3.0", | ||||
|     "axios": "^1.12.0", | ||||
|     "@xhayper/discord-rpc": "^1.2.0", | ||||
|     "axios": "^1.7.7", | ||||
|     "cors": "^2.8.5", | ||||
|     "electron-store": "^8.2.0", | ||||
|     "express": "^5.1.0", | ||||
|     "hotkeys-js": "^3.13.15", | ||||
|     "express": "^4.21.1", | ||||
|     "hotkeys-js": "^3.13.7", | ||||
|     "mpris-service": "^2.1.2", | ||||
|     "request": "^2.88.2", | ||||
|     "sass": "1.93.2", | ||||
|     "sass": "^1.79.4", | ||||
|     "swagger-ui-express": "^5.0.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@mastermindzh/prettier-config": "^1.0.0", | ||||
|     "@types/cors": "^2.8.19", | ||||
|     "@types/express": "^5.0.3", | ||||
|     "@types/node": "^22.16.2", | ||||
|     "@types/cors": "^2.8.17", | ||||
|     "@types/express": "^4.17.21", | ||||
|     "@types/node": "^20.14.10", | ||||
|     "@types/request": "^2.48.12", | ||||
|     "@types/swagger-ui-express": "^4.1.8", | ||||
|     "@typescript-eslint/eslint-plugin": "^8.36.0", | ||||
|     "@typescript-eslint/parser": "^8.36.0", | ||||
|     "@types/swagger-ui-express": "^4.1.6", | ||||
|     "@typescript-eslint/eslint-plugin": "^7.16.0", | ||||
|     "@typescript-eslint/parser": "^7.15.0", | ||||
|     "copyfiles": "^2.4.1", | ||||
|     "electron": "github:castlabs/electron-releases#v37.2.5+wvcus", | ||||
|     "electron-builder": "~26.0.12", | ||||
|     "eslint": "^9.30.1", | ||||
|     "electron": "git+https://github.com/castlabs/electron-releases#v31.1.0+wvcus", | ||||
|     "electron-builder": "~24.9.4", | ||||
|     "eslint": "^8.57.0", | ||||
|     "js-yaml": "^4.1.0", | ||||
|     "markdown-toc": "^1.2.0", | ||||
|     "node-abi": "^4.12.0", | ||||
|     "nodemon": "^3.1.10", | ||||
|     "prettier": "^3.6.2", | ||||
|     "stylelint": "^16.21.1", | ||||
|     "stylelint-config-standard": "^39.0.0", | ||||
|     "stylelint-config-standard-scss": "^16.0.0", | ||||
|     "stylelint-prettier": "^5.0.3", | ||||
|     "nodemon": "^3.1.4", | ||||
|     "prettier": "^3.3.2", | ||||
|     "stylelint": "^16.6.1", | ||||
|     "stylelint-config-standard": "^36.0.1", | ||||
|     "stylelint-config-standard-scss": "^13.1.0", | ||||
|     "stylelint-prettier": "^5.0.0", | ||||
|     "swagger-jsdoc": "^6.2.8", | ||||
|     "ts-node": "^10.9.2", | ||||
|     "tsc-watch": "^7.1.1", | ||||
|     "typescript": "^5.8.3" | ||||
|     "tsc-watch": "^6.2.0", | ||||
|     "typescript": "^5.5.3" | ||||
|   }, | ||||
|   "prettier": "@mastermindzh/prettier-config" | ||||
| } | ||||
|   | ||||
| @@ -1,4 +0,0 @@ | ||||
| { | ||||
|   "$schema": "https://docs.renovatebot.com/renovate-schema.json", | ||||
|   "ignoreDeps": ["@types/node", "electron-store", "@xhayper/discord-rpc"] | ||||
| } | ||||
| @@ -22,13 +22,12 @@ | ||||
|     media: '*[data-test="current-media-imagery"]', | ||||
|     image: "img", | ||||
|     current: '*[data-test="current-time"]', | ||||
|     duration: '*[class^=_playbackControlsContainer] *[data-test="duration"]', | ||||
|     duration: '*[class^=playbackControlsContainer] *[data-test="duration"]', | ||||
|     bar: '*[data-test="progress-bar"]', | ||||
|     footer: "#footerPlayer", | ||||
|     mediaItem: "[data-type='mediaItem']", | ||||
|     album_header_title: '*[class^="_playingFrom"] span:nth-child(2)', | ||||
|     playing_from: '*[class^="_playingFrom"] span:nth-child(2)', | ||||
|     queue_album: "*[class^=playQueueItemsContainer] *[class^=groupTitle] span:nth-child(2)", | ||||
|     album_header_title: '*[class^="playingFrom"] span:nth-child(2)', | ||||
|     playingFrom: '*[class^="playingFrom"] span:nth-child(2)', | ||||
|     currentlyPlaying: "[class^='isPlayingIcon'], [data-test-is-playing='true']", | ||||
|     album_name_cell: '[class^="album"]', | ||||
|     tracklist_row: '[data-test="tracklist-row"]', | ||||
|   | ||||
| @@ -88,9 +88,8 @@ export const addCurrentInfo = (expressApp: Router) => { | ||||
|    *             schema: | ||||
|    *               $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 | ||||
|    * /current/image: | ||||
|   | ||||
| @@ -21,12 +21,8 @@ export const startApi = (mainWindow: BrowserWindow) => { | ||||
|   expressApp.use(cors()); | ||||
|   expressApp.use(express.json()); | ||||
|   expressApp.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec)); | ||||
|   expressApp.get("/", (req, res) => { | ||||
|     res.send("Hello World!"); | ||||
|   }); | ||||
|   expressApp.get("/swagger.json", (req, res) => { | ||||
|     res.json(swaggerSpec); | ||||
|   }); | ||||
|   expressApp.get("/", (req, res) => res.send("Hello World!")); | ||||
|   expressApp.get("/swagger.json", (req, res) => res.json(swaggerSpec)); | ||||
|  | ||||
|   // add features | ||||
|   addLegacyApi(expressApp, mainWindow); | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|   "openapi": "3.1.0", | ||||
|   "info": { | ||||
|     "title": "TIDAL Hi-Fi API", | ||||
|     "version": "5.20.1", | ||||
|     "version": "5.17.0", | ||||
|     "description": "", | ||||
|     "license": { | ||||
|       "name": "MIT", | ||||
|   | ||||
| @@ -26,6 +26,7 @@ import { | ||||
| import { addTray, refreshTray } from "./scripts/tray"; | ||||
| let mainInhibitorId = -1; | ||||
|  | ||||
| initialize(); | ||||
| let mainWindow: BrowserWindow; | ||||
| const icon = path.join(__dirname, "../assets/icon.png"); | ||||
| const PROTOCOL_PREFIX = "tidal"; | ||||
| @@ -97,7 +98,6 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) { | ||||
|       }, | ||||
|     }, | ||||
|   }); | ||||
|  | ||||
|   enable(mainWindow.webContents); | ||||
|   registerHttpProtocols(); | ||||
|   syncMenuBarWithStore(); | ||||
| @@ -126,7 +126,6 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) { | ||||
|     } | ||||
|     return false; | ||||
|   }); | ||||
|  | ||||
|   // Emitted when the window is closed. | ||||
|   mainWindow.on("closed", function () { | ||||
|     releaseInhibitorIfActive(mainInhibitorId); | ||||
| @@ -179,7 +178,6 @@ app.on("ready", async () => { | ||||
|  | ||||
|   if (isMainInstance() || isMultipleInstancesAllowed()) { | ||||
|     await components.whenReady(); | ||||
|     initialize(); | ||||
|  | ||||
|     // Adblock | ||||
|     if (settingsStore.get(settings.adBlock)) { | ||||
| @@ -190,8 +188,6 @@ app.on("ready", async () => { | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     Logger.log("components ready:", components.status()); | ||||
|  | ||||
|     createWindow(); | ||||
|     addMenu(mainWindow); | ||||
|     createSettingsWindow(); | ||||
|   | ||||
| @@ -1,25 +1,34 @@ | ||||
| <!DOCTYPE html> | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
|  | ||||
|   <head> | ||||
|     <title>Tidal Hi-Fi 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" /> | ||||
|     <link rel="stylesheet" href="./settings.css" /> | ||||
|   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/font-awesome.min.css"> | ||||
|     <link | ||||
|       rel="stylesheet" | ||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" | ||||
|     /> | ||||
|   </head> | ||||
|  | ||||
|   <body class="settings-window"> | ||||
|     <div class="settings-window__wrapper"> | ||||
|       <div class="settings-window__drag-area"></div> | ||||
|       <a id="close" class="settings-window__close-button" title="Close settings"> | ||||
|       <svg xmlns="http://www.w3.org/2000/svg" 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 | ||||
|         <svg | ||||
|           xmlns="http://www.w3.org/2000/svg" | ||||
|           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.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 | ||||
|             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> | ||||
|       </a> | ||||
|  | ||||
| @@ -66,7 +75,13 @@ | ||||
|                   <span class="switch__slider"></span> | ||||
|                 </label> | ||||
|               </div> | ||||
|             <textarea id="skippedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea> | ||||
|               <textarea | ||||
|                 id="skippedArtists" | ||||
|                 class="textarea" | ||||
|                 cols="40" | ||||
|                 rows="5" | ||||
|                 spellcheck="false" | ||||
|               ></textarea> | ||||
|               <div class="group__option"> | ||||
|                 <div class="group__description"> | ||||
|                   <h4>Block ads</h4> | ||||
| @@ -109,7 +124,10 @@ | ||||
|               <div class="group__option"> | ||||
|                 <div class="group__description"> | ||||
|                   <h4>Static Window Title</h4> | ||||
|                 <p>Makes the window title "TIDAL Hi-Fi" instead of changing to the currently playing song.</p> | ||||
|                   <p> | ||||
|                     Makes the window title "TIDAL Hi-Fi" instead of changing to the currently | ||||
|                     playing song. | ||||
|                   </p> | ||||
|                 </div> | ||||
|                 <label class="switch"> | ||||
|                   <input id="staticWindowTitle" type="checkbox" /> | ||||
| @@ -131,7 +149,9 @@ | ||||
|                   <h4>Hotkeys</h4> | ||||
|                   <p> | ||||
|                     Enable extra hotkeys to achieve feature parity with the | ||||
|                   <a class="external-link" data-url="https://defkey.com/tidal-desktop-shortcuts">desktop apps</a>. | ||||
|                     <a class="external-link" data-url="https://defkey.com/tidal-desktop-shortcuts" | ||||
|                       >desktop apps</a | ||||
|                     >. | ||||
|                   </p> | ||||
|                 </div> | ||||
|                 <label class="switch"> | ||||
| @@ -157,8 +177,8 @@ | ||||
|               <p class="group__title">API</p> | ||||
|               <div class="group__description"> | ||||
|                 <p> | ||||
|                 TIDAL Hi-Fi has a built-in web API to allow users to get current media information. | ||||
|                 You can optionally enable playback control as well. | ||||
|                   TIDAL Hi-Fi has a built-in web API to allow users to get current media | ||||
|                   information. You can optionally enable playback control as well. | ||||
|                 </p> | ||||
|               </div> | ||||
|               <div class="group__option"> | ||||
| @@ -180,7 +200,8 @@ | ||||
|               <div class="group__option"> | ||||
|                 <div class="group__description"> | ||||
|                   <h4>API hostname</h4> | ||||
|                 <p>By default (127.0.0.1) only local apps can interface with the API. <br /> | ||||
|                   <p> | ||||
|                     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 /> | ||||
|                     Other options are available | ||||
|                   </p> | ||||
| @@ -236,7 +257,6 @@ | ||||
|                 </label> | ||||
|               </div> | ||||
|               <div id="discord_options"> | ||||
|  | ||||
|                 <div class="group__option" class="hidden"> | ||||
|                   <div class="group__description"> | ||||
|                     <h4>Show Idle Text</h4> | ||||
| @@ -252,15 +272,27 @@ | ||||
|                   <div class="group__description"> | ||||
|                     <h4>Idle Text</h4> | ||||
|                     <p>The text displayed on Discord's rich presence while idling in the app.</p> | ||||
|                   <input id="discord_idle_text" type="text" class="text-input" name="discord_idle_text" /> | ||||
|                     <input | ||||
|                       id="discord_idle_text" | ||||
|                       type="text" | ||||
|                       class="text-input" | ||||
|                       name="discord_idle_text" | ||||
|                     /> | ||||
|                   </div> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="group__option" class="hidden"> | ||||
|                   <div class="group__description"> | ||||
|                     <h4>Using Tidal Text</h4> | ||||
|                   <p>The text displayed on Discord's rich presence while "showSong" is turned off</p> | ||||
|                   <input id="discord_using_text" type="text" class="text-input" name="discord_using_text" /> | ||||
|                     <p> | ||||
|                       The text displayed on Discord's rich presence while "showSong" is turned off | ||||
|                     </p> | ||||
|                     <input | ||||
|                       id="discord_using_text" | ||||
|                       type="text" | ||||
|                       class="text-input" | ||||
|                       name="discord_using_text" | ||||
|                     /> | ||||
|                   </div> | ||||
|                 </div> | ||||
|  | ||||
| @@ -276,7 +308,6 @@ | ||||
|                 </div> | ||||
|  | ||||
|                 <div id="discord_show_song_options" class="hidden"> | ||||
|  | ||||
|                   <div class="group__option" class="hidden"> | ||||
|                     <div class="group__description"> | ||||
|                       <h4>Include timestamps</h4> | ||||
| @@ -292,7 +323,12 @@ | ||||
|                     <div class="group__description"> | ||||
|                       <h4>Details prefix</h4> | ||||
|                       <p>Prefix for the "details" field of Discord's rich presence.</p> | ||||
|                     <input id="discord_details_prefix" type="text" class="text-input" name="discord_details_prefix" /> | ||||
|                       <input | ||||
|                         id="discord_details_prefix" | ||||
|                         type="text" | ||||
|                         class="text-input" | ||||
|                         name="discord_details_prefix" | ||||
|                       /> | ||||
|                     </div> | ||||
|                   </div> | ||||
|  | ||||
| @@ -300,11 +336,15 @@ | ||||
|                     <div class="group__description"> | ||||
|                       <h4>Button text</h4> | ||||
|                       <p>Text to display on the button below the media information.</p> | ||||
|                     <input id="discord_button_text" type="text" class="text-input" name="discord_button_text" /> | ||||
|                       <input | ||||
|                         id="discord_button_text" | ||||
|                         type="text" | ||||
|                         class="text-input" | ||||
|                         name="discord_button_text" | ||||
|                       /> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|  | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="group"> | ||||
| @@ -323,23 +363,43 @@ | ||||
|                 <div class="group__option"> | ||||
|                   <div class="group__description"> | ||||
|                     <h4>ListenBrainz API Url</h4> | ||||
|                   <p>There are multiple instances for ListenBrainz you can set the corresponding API url below.</p> | ||||
|                   <input id="ListenBrainzAPI" type="text" class="text-input" name="ListenBrainzAPI" /> | ||||
|                     <p> | ||||
|                       There are multiple instances for ListenBrainz you can set the corresponding | ||||
|                       API url below. | ||||
|                     </p> | ||||
|                     <input | ||||
|                       id="ListenBrainzAPI" | ||||
|                       type="text" | ||||
|                       class="text-input" | ||||
|                       name="ListenBrainzAPI" | ||||
|                     /> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="group__option"> | ||||
|                   <div class="group__description"> | ||||
|                     <h4>ListenBrainz User Token</h4> | ||||
|                     <p>Provide the user token you can get from the settings page.</p> | ||||
|                   <input id="ListenBrainzToken" type="text" class="text-input" name="ListenBrainzToken" /> | ||||
|                     <input | ||||
|                       id="ListenBrainzToken" | ||||
|                       type="text" | ||||
|                       class="text-input" | ||||
|                       name="ListenBrainzToken" | ||||
|                     /> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="group__description"> | ||||
|                 <h4>ScrobbleDelay</h4> | ||||
|               <p>The delay (in ms) to send a listen to ListenBrainz. Prevents spamming the API when you fast forward | ||||
|                 immediately</p> | ||||
|               <input id="listenbrainz_delay" type="number" class="text-input" name="listenbrainz_delay" /> | ||||
|                 <p> | ||||
|                   The delay (in ms) to send a listen to ListenBrainz. Prevents spamming the API when | ||||
|                   you fast forward immediately | ||||
|                 </p> | ||||
|                 <input | ||||
|                   id="listenbrainz_delay" | ||||
|                   type="number" | ||||
|                   class="text-input" | ||||
|                   name="listenbrainz_delay" | ||||
|                 /> | ||||
|               </div> | ||||
|             </div> | ||||
|           </section> | ||||
| @@ -351,12 +411,16 @@ | ||||
|                 <div class="group__description"> | ||||
|                   <h4>Update frequency</h4> | ||||
|                   <p> | ||||
|                   The amount of time, in milliseconds, that TIDAL Hi-Fi 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. | ||||
|                     The amount of time, in milliseconds, that TIDAL Hi-Fi 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" /> | ||||
|                   <input | ||||
|                     id="updateFrequency" | ||||
|                     type="number" | ||||
|                     class="text-input" | ||||
|                     name="updateFrequency" | ||||
|                   /> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
| @@ -369,7 +433,9 @@ | ||||
|                   </p> | ||||
|                   <select class="select-input" id="channel" name="channel"> | ||||
|                     <option value="https://listen.tidal.com">Stable (listen.tidal.com)</option> | ||||
|                   <option value="https://listen.stage.tidal.com">Staging (listen.stage.tidal.com)</option> | ||||
|                     <option value="https://listen.stage.tidal.com"> | ||||
|                       Staging (listen.stage.tidal.com) | ||||
|                     </option> | ||||
|                   </select> | ||||
|                 </div> | ||||
|               </div> | ||||
| @@ -415,7 +481,8 @@ | ||||
|                 <div class="group__description"> | ||||
|                   <h4>Wayland support</h4> | ||||
|                   <p> | ||||
|                   Adds a couple of Electron flags to help TIDAL Hi-Fi run smoothly on the Wayland window system. | ||||
|                     Adds a couple of Electron flags to help TIDAL Hi-Fi run smoothly on the Wayland | ||||
|                     window system. | ||||
|                   </p> | ||||
|                 </div> | ||||
|                 <label class="switch"> | ||||
| @@ -433,12 +500,19 @@ | ||||
|                 <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. | ||||
|                     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> | ||||
|             <textarea | ||||
|               id="customCSS" | ||||
|               class="textarea" | ||||
|               cols="40" | ||||
|               rows="8" | ||||
|               spellcheck="false" | ||||
|             ></textarea> | ||||
|  | ||||
|             <div class="group"> | ||||
|               <p class="group__title">Theme files</p> | ||||
| @@ -448,9 +522,7 @@ | ||||
|                   <p> | ||||
|                     Select a theme below or "Tidal - Default" to return to the original Tidal look. | ||||
|                   </p> | ||||
|                 <select class="select-input" id="themesList" name="themesList"> | ||||
|  | ||||
|                 </select> | ||||
|                   <select class="select-input" id="themesList" name="themesList"></select> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
| @@ -458,14 +530,20 @@ | ||||
|                 <div class="group__description"> | ||||
|                   <h4>Upload new themes</h4> | ||||
|                   <p> | ||||
|                   Click the button and select the css files to import. They will be added to the theme list | ||||
|                   automatically. | ||||
|                     Click the button and select the css files to import. They will be added to the | ||||
|                     theme list automatically. | ||||
|                   </p> | ||||
|                   <div class="file-drop-area"> | ||||
|                     <div> | ||||
|                       <span class="file-btn">Choose files</span> | ||||
|                       <span id="file-message" class="file-msg">or drag and drop files here</span> | ||||
|                     <input id="theme-files" class="file-input" type="file" accept=".css" multiple> | ||||
|                       <input | ||||
|                         id="theme-files" | ||||
|                         class="file-input" | ||||
|                         type="file" | ||||
|                         accept=".css" | ||||
|                         multiple | ||||
|                       /> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
| @@ -477,17 +555,35 @@ | ||||
|             <img alt="tidal icon" class="about-section__icon" src="./icon.png" /> | ||||
|             <h4>TIDAL Hi-Fi</h4> | ||||
|             <div class="about-section__version"> | ||||
|             <a target="_blank" rel="noopener" | ||||
|               href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.20.1">5.20.1</a> | ||||
|               <a | ||||
|                 target="_blank" | ||||
|                 rel="noopener" | ||||
|                 href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.17.0" | ||||
|                 >5.17.0</a | ||||
|               > | ||||
|             </div> | ||||
|             <div class="about-section__links"> | ||||
|             <a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/" | ||||
|               class="about-section__button">Github | ||||
|               <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> | ||||
|               <a | ||||
|                 target="_blank" | ||||
|                 rel="noopener" | ||||
|                 href="https://github.com/mastermindzh/tidal-hifi/" | ||||
|                 class="about-section__button" | ||||
|                 >Github <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> | ||||
|           </section> | ||||
|  | ||||
| @@ -500,5 +596,4 @@ | ||||
|       </main> | ||||
|     </div> | ||||
|   </body> | ||||
|  | ||||
| </html> | ||||
| @@ -54,12 +54,12 @@ const elements = { | ||||
|   media: '*[data-test="current-media-imagery"]', | ||||
|   image: "img", | ||||
|   current: '*[data-test="current-time"]', | ||||
|   duration: '*[class^=_playbackControlsContainer] *[data-test="duration"]', | ||||
|   duration: '*[class^=playbackControlsContainer] *[data-test="duration"]', | ||||
|   bar: '*[data-test="progress-bar"]', | ||||
|   footer: "#footerPlayer", | ||||
|   mediaItem: "[data-type='mediaItem']", | ||||
|   album_header_title: '*[class^="_playingFrom"] span:nth-child(2)', | ||||
|   playing_from: '*[class^="_playingFrom"] span:nth-child(2)', | ||||
|   album_header_title: '*[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']", | ||||
|   album_name_cell: '[class^="album"]', | ||||
| @@ -115,19 +115,18 @@ const elements = { | ||||
|   }, | ||||
|  | ||||
|   getAlbumName: function () { | ||||
|     try { | ||||
|     //If listening to an album, get its name from the header title | ||||
|       if (globalThis.location.href.includes("/album/")) { | ||||
|         const albumName = globalThis.document.querySelector(this.album_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 ( | ||||
|         globalThis.location.href.includes("/playlist/") || | ||||
|         globalThis.location.href.includes("/mix/") | ||||
|       window.location.href.includes("/playlist/") || | ||||
|       window.location.href.includes("/mix/") | ||||
|     ) { | ||||
|         if (this.currentlyPlaying === MediaStatus.playing) { | ||||
|       if (currentPlayStatus === 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. | ||||
|         // 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); | ||||
| @@ -138,15 +137,12 @@ const elements = { | ||||
|     } | ||||
|  | ||||
|     // see whether we're on the queue page and get it from there | ||||
|       const queueAlbumName = this.getText("queue_album"); | ||||
|     const queueAlbumName = elements.getText("queue_album"); | ||||
|     if (queueAlbumName) { | ||||
|       return queueAlbumName; | ||||
|     } | ||||
|  | ||||
|     return ""; | ||||
|     } catch { | ||||
|       return ""; | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   isMuted: function () { | ||||
| @@ -487,7 +483,6 @@ function updateMpris(mediaInfo: MediaInfo) { | ||||
|         "xesam:title": mediaInfo.title, | ||||
|         "xesam:artist": [mediaInfo.artists], | ||||
|         "xesam:album": mediaInfo.album, | ||||
|         "xesam:url": mediaInfo.url, | ||||
|         "mpris:artUrl": mediaInfo.image, | ||||
|         "mpris:length": convertDuration(mediaInfo.duration) * 1000 * 1000, | ||||
|         "mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(), | ||||
|   | ||||
| @@ -26,7 +26,7 @@ const defaultPresence = { | ||||
|   largeImageKey: "tidal-hifi-icon", | ||||
|   largeImageText: `TIDAL Hi-Fi ${app.getVersion()}`, | ||||
|   instance: false, | ||||
|   type: ACTIVITY_LISTENING | ||||
|   type: ACTIVITY_LISTENING, | ||||
| }; | ||||
|  | ||||
| const updateActivity = () => { | ||||
| @@ -103,7 +103,8 @@ const getActivity = (): SetActivity => { | ||||
|     if (includeTimestamps) { | ||||
|       const currentSeconds = convertDurationToSeconds(mediaInfo.current); | ||||
|       const durationSeconds = convertDurationToSeconds(mediaInfo.duration); | ||||
|       const now = Math.trunc((Date.now() + 500) / 1000); | ||||
|       const date = new Date(); | ||||
|       const now = Math.floor(date.getTime() / 1000); | ||||
|       presence.startTimestamp = now - currentSeconds; | ||||
|       presence.endTimestamp = presence.startTimestamp + durationSeconds; | ||||
|     } | ||||
| @@ -117,15 +118,17 @@ const getActivity = (): SetActivity => { | ||||
| const connectWithRetry = async (retryCount = 0) => { | ||||
|   try { | ||||
|     await rpc.login(); | ||||
|     Logger.log('Connected to Discord'); | ||||
|     Logger.log("Connected to Discord"); | ||||
|     rpc.on("ready", updateActivity); | ||||
|     Object.values(globalEvents).forEach(event => ipcMain.on(event, observer)); | ||||
|     Object.values(globalEvents).forEach((event) => ipcMain.on(event, observer)); | ||||
|   } catch (error) { | ||||
|     if (retryCount < MAX_RETRIES) { | ||||
|       Logger.log(`Failed to connect to Discord, retrying in ${RETRY_DELAY/1000} seconds... (Attempt ${retryCount + 1}/${MAX_RETRIES})`); | ||||
|       Logger.log( | ||||
|         `Failed to connect to Discord, retrying in ${RETRY_DELAY / 1000} seconds... (Attempt ${retryCount + 1}/${MAX_RETRIES})` | ||||
|       ); | ||||
|       setTimeout(() => connectWithRetry(retryCount + 1), RETRY_DELAY); | ||||
|     } else { | ||||
|       Logger.log('Failed to connect to Discord after maximum retry attempts'); | ||||
|       Logger.log("Failed to connect to Discord after maximum retry attempts"); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user