Compare commits

..

6 Commits

Author SHA1 Message Date
Rowanda
16f98f4f1b Merge 256832dab6 into aaf7a1b662 2024-12-13 04:43:49 +00:00
Rowanda
256832dab6 fix formatting 2024-12-12 20:43:40 -08:00
Rowanda
977e50faa0 do axios requests through the main process 2024-12-12 20:42:24 -08:00
Rowanda
294701ec5f Merge branch 'Mastermindzh:master' into master 2024-12-12 20:37:31 -08:00
a44bf331e4 fixed indentation, removed request types 2024-12-09 11:16:34 +01:00
Rowanda
73051716e7 Replace request with axios 2024-12-07 11:42:23 -08:00
20 changed files with 1990 additions and 4186 deletions

View File

@@ -4,12 +4,12 @@ name: default
steps: steps:
- name: install - name: install
image: node:22.17.0 image: node:19.4.0
commands: commands:
- npm install - npm install
- name: build_with_linux - name: build_with_linux
image: node:22.17.0 image: node:19.4.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

@@ -21,30 +21,26 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 22.12.0 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

@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 22.12.0 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
@@ -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 @@
v22.12.0 19.8.1

View File

@@ -17,9 +17,7 @@
"trackid", "trackid",
"tracklist", "tracklist",
"widevine", "widevine",
"wvcus", "xesam"
"xesam",
"xhayper"
], ],
"sonarlint.connectedMode.project": { "sonarlint.connectedMode.project": {
"connectionId": "public-sonarcloud", "connectionId": "public-sonarcloud",

View File

@@ -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/), 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.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] ## [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)

View File

@@ -1,7 +1,7 @@
appId: com.rickvanlieshout.tidal-hifi appId: com.rickvanlieshout.tidal-hifi
electronVersion: 37.2.5 electronVersion: 28.1.1
electronDownload: electronDownload:
version: 37.2.5+wvcus version: 28.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,25 +17,24 @@ 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:
entry: Encoding: UTF-8
Encoding: "UTF-8" Name: TIDAL Hi-Fi
Name: "TIDAL Hi-Fi" GenericName: TIDAL Hi-Fi
GenericName: "TIDAL Hi-Fi" Comment: The web version of listen.tidal.com running in electron with hifi support thanks to widevine.
Comment: "The web version of listen.tidal.com running in electron with hifi support thanks to widevine." Icon: tidal-hifi
Icon: "tidal-hifi" StartupNotify: true
StartupNotify: "true" Terminal: false
Terminal: "false" Type: Application
Type: "Application" Categories: Network;Application;AudioVideo;Audio;Video
Categories: "Network;Application;AudioVideo;Audio;Video" StartupWMClass: tidal-hifi
StartupWMClass: "tidal-hifi" X-PulseAudio-Properties: media.role=music
X-PulseAudio-Properties: "media.role=music" MimeType: x-scheme-handler/tidal;
MimeType: "x-scheme-handler/tidal;"
mac: mac:
category: public.app-category.entertainment category: public.app-category.entertainment
win: win:

5696
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.20.1", "version": "5.17.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 --remote-debugging-port=8315 --remote-allow-origins=* .", "start": "electron --inspect=0.0.0.0:5858 .",
"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",
@@ -40,45 +40,42 @@
"homepage": "https://github.com/Mastermindzh/tidal-hifi", "homepage": "https://github.com/Mastermindzh/tidal-hifi",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@electron/remote": "^2.1.3", "@electron/remote": "^2.1.2",
"@types/swagger-jsdoc": "^6.0.4", "@types/swagger-jsdoc": "^6.0.4",
"@xhayper/discord-rpc": "1.3.0", "@xhayper/discord-rpc": "^1.2.0",
"axios": "^1.10.0", "axios": "^1.7.9",
"cors": "^2.8.5", "cors": "^2.8.5",
"electron-store": "^8.2.0", "electron-store": "^8.2.0",
"express": "^5.1.0", "express": "^4.21.2",
"hotkeys-js": "^3.13.15", "hotkeys-js": "^3.13.7",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"request": "^2.88.2", "sass": "^1.79.4",
"sass": "1.92.0",
"swagger-ui-express": "^5.0.1" "swagger-ui-express": "^5.0.1"
}, },
"devDependencies": { "devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0", "@mastermindzh/prettier-config": "^1.0.0",
"@types/cors": "^2.8.19", "@types/cors": "^2.8.17",
"@types/express": "^5.0.3", "@types/express": "^4.17.21",
"@types/node": "^22.16.2", "@types/node": "^20.14.10",
"@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": "^8.36.0", "@typescript-eslint/parser": "^7.15.0",
"@typescript-eslint/parser": "^8.36.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"electron": "github:castlabs/electron-releases#v38.0.0+wvcus", "electron": "git+https://github.com/castlabs/electron-releases#v31.1.0+wvcus",
"electron-builder": "~26.0.12", "electron-builder": "~24.9.4",
"eslint": "^9.30.1", "eslint": "^8.57.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"markdown-toc": "^1.2.0", "markdown-toc": "^1.2.0",
"node-abi": "^4.12.0", "nodemon": "^3.1.4",
"nodemon": "^3.1.10", "prettier": "^3.3.2",
"prettier": "^3.6.2", "stylelint": "^16.6.1",
"stylelint": "^16.21.1", "stylelint-config-standard": "^36.0.1",
"stylelint-config-standard": "^39.0.0", "stylelint-config-standard-scss": "^13.1.0",
"stylelint-config-standard-scss": "^15.0.1", "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": "^7.1.1", "tsc-watch": "^6.2.0",
"typescript": "^5.8.3" "typescript": "^5.5.3"
}, },
"prettier": "@mastermindzh/prettier-config" "prettier": "@mastermindzh/prettier-config"
} }

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"ignoreDeps": ["@types/node", "electron-store", "@xhayper/discord-rpc"]
}

View File

@@ -22,13 +22,12 @@
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)', playingFrom: '*[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

@@ -15,4 +15,6 @@ export const globalEvents = {
toggleFavorite: "toggleFavorite", toggleFavorite: "toggleFavorite",
toggleShuffle: "toggleShuffle", toggleShuffle: "toggleShuffle",
toggleRepeat: "toggleRepeat", toggleRepeat: "toggleRepeat",
axios: "axios",
axiosReply: "axiosReply",
}; };

View File

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

View File

@@ -21,12 +21,8 @@ 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) => { expressApp.get("/", (req, res) => res.send("Hello World!"));
res.send("Hello World!"); expressApp.get("/swagger.json", (req, res) => res.json(swaggerSpec));
});
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.20.1", "version": "5.17.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"
]
} }
} }
}, },
@@ -532,4 +579,4 @@
"description": "The settings management API" "description": "The settings management API"
} }
] ]
} }

View File

@@ -24,8 +24,10 @@ import {
showSettingsWindow, showSettingsWindow,
} from "./scripts/settings"; } from "./scripts/settings";
import { addTray, refreshTray } from "./scripts/tray"; import { addTray, refreshTray } from "./scripts/tray";
import { downloadFile } from "./scripts/download";
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";
@@ -97,7 +99,6 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
}, },
}, },
}); });
enable(mainWindow.webContents); enable(mainWindow.webContents);
registerHttpProtocols(); registerHttpProtocols();
syncMenuBarWithStore(); syncMenuBarWithStore();
@@ -126,7 +127,6 @@ 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);
@@ -179,7 +179,6 @@ 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)) {
@@ -190,8 +189,6 @@ app.on("ready", async () => {
}); });
} }
Logger.log("components ready:", components.status());
createWindow(); createWindow();
addMenu(mainWindow); addMenu(mainWindow);
createSettingsWindow(); createSettingsWindow();
@@ -254,6 +251,16 @@ ipcMain.on(globalEvents.error, (event) => {
console.log(event); console.log(event);
}); });
ipcMain.on(globalEvents.axios, (event, fileUrl: string, targetPath: string) => {
const download = downloadFile(fileUrl, targetPath);
download.then(() => {
event.reply(globalEvents.axiosReply, fileUrl, targetPath, false);
}).catch(() => {
// don't send error information, it isn't used anyways
event.reply(globalEvents.axiosReply, fileUrl, targetPath, true);
});
});
ipcMain.handle(globalEvents.getUniversalLink, async (event, url) => { ipcMain.handle(globalEvents.getUniversalLink, async (event, url) => {
return SharingService.getUniversalLink(url); return SharingService.getUniversalLink(url);
}); });

View File

@@ -7,7 +7,7 @@
<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 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> </head>
<body class="settings-window"> <body class="settings-window">
@@ -478,7 +478,7 @@
<h4>TIDAL Hi-Fi</h4> <h4>TIDAL Hi-Fi</h4>
<div class="about-section__version"> <div class="about-section__version">
<a target="_blank" rel="noopener" <a target="_blank" rel="noopener"
href="https://github.com/Mastermindzh/tidal-hifi/releases/tag/5.20.1">5.20.1</a> 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 target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/" <a target="_blank" rel="noopener" href="https://github.com/mastermindzh/tidal-hifi/"

View File

@@ -16,7 +16,7 @@ import { convertDurationToSeconds } from "./features/time/parse";
import { MediaInfo } from "./models/mediaInfo"; import { MediaInfo } from "./models/mediaInfo";
import { MediaStatus } from "./models/mediaStatus"; import { MediaStatus } from "./models/mediaStatus";
import { RepeatState } from "./models/repeatState"; import { RepeatState } from "./models/repeatState";
import { downloadFile } from "./scripts/download"; import { downloadFile } from "./scripts/downloadPreload";
import { addHotkey } from "./scripts/hotkeys"; import { addHotkey } from "./scripts/hotkeys";
import { ObjectToDotNotation } from "./scripts/objectUtilities"; import { ObjectToDotNotation } from "./scripts/objectUtilities";
import { settingsStore } from "./scripts/settings"; import { settingsStore } from "./scripts/settings";
@@ -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,38 +115,34 @@ 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); if (row) {
if (row) { return row.querySelector(this.album_name_cell).textContent;
return row.querySelector(this.album_name_cell).textContent;
}
} }
} }
// see whether we're on the queue page and get it from there
const queueAlbumName = this.getText("queue_album");
if (queueAlbumName) {
return queueAlbumName;
}
return "";
} catch {
return "";
} }
// see whether we're on the queue page and get it from there
const queueAlbumName = elements.getText("queue_album");
if (queueAlbumName) {
return queueAlbumName;
}
return "";
}, },
isMuted: function () { isMuted: function () {
@@ -487,7 +483,6 @@ 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

@@ -1,5 +1,5 @@
import fs from "fs"; import fs from "fs";
import request from "request"; import axios from "axios";
/** /**
* download and save a file * download and save a file
@@ -8,16 +8,20 @@ import request from "request";
*/ */
export const downloadFile = function (fileUrl: string, targetPath: string) { export const downloadFile = function (fileUrl: string, targetPath: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const req = request({ axios
method: "GET", .get(fileUrl, {
uri: fileUrl, responseType: "stream",
}); })
.then((res) => {
const out = fs.createWriteStream(targetPath);
const out = fs.createWriteStream(targetPath); res.data.pipe(out);
req.pipe(out);
req.on("end", resolve); out.on("finish", resolve);
req.on("error", reject); out.on("error", reject);
res.data.on("error", reject);
}).catch(reject);
}); });
}; };

View File

@@ -0,0 +1,23 @@
import { ipcRenderer } from "electron";
import { globalEvents } from "../constants/globalEvents";
/**
* download and save a file (renderer version)
* @param {string} fileUrl url to download
* @param {string} targetPath path to save it at
*/
export const downloadFile = function (fileUrl: string, targetPath: string) {
return new Promise<void>((resolve, reject) => {
const handler = (event: Electron.IpcRendererEvent, newFileUrl: string, newTargetPath: string, error: boolean) => {
// it's possible for 2 requests to be running at the same time, so make sure it is the right one
// if there is 2 requests with the same fileUrl and targetPath, then it doesn't matter which one we intercept because the data is the same
if (fileUrl === newFileUrl && targetPath === newTargetPath) {
ipcRenderer.removeListener(globalEvents.axiosReply, handler);
if (error) reject();
else resolve();
}
}
ipcRenderer.on(globalEvents.axiosReply, handler);
ipcRenderer.send(globalEvents.axios, fileUrl, targetPath);
});
};