Compare commits

..

2 Commits

Author SHA1 Message Date
0fe1f7a509 - Changed the category of the desktop file to AudioVideo
- Changed desktop file name to "TIDAL Hi-Fi"
2022-09-11 22:53:42 +02:00
Ivo Šmerek
87bb19a255 Update configuration of the desktop file (#165) 2022-09-11 22:48:55 +02:00
31 changed files with 5303 additions and 4896 deletions

View File

@@ -16,17 +16,17 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build
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: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build
@@ -36,6 +36,6 @@ jobs:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 19 node-version: 16
- run: npm install - run: npm install
- run: npm run build - run: npm run build

5
.gitignore vendored
View File

@@ -7,8 +7,3 @@ build/linux/arch/*
!build/linux/arch/.SRCINFO !build/linux/arch/.SRCINFO
!build/linux/arch/tidal-hifi.desktop !build/linux/arch/tidal-hifi.desktop
!build/linux/arch/install.sh !build/linux/arch/install.sh
*.css
*.css.map
# JetBrains IDE configuration
.idea

1
.nvmrc
View File

@@ -1 +0,0 @@
19.8.1

View File

@@ -4,39 +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.0.0
- Replaced "muting artists" with a full implementation of an Adblock mechanism
> Disabled audio & visual ads, unlocked lyrics, suggested track, track info, unlimited skips thanks to uBlockOrigin custom filters ([source](https://github.com/uBlockOrigin/uAssets/issues/17495))
- @thanasistrisp updated Electron to 24.1.2 and fixed the tray bug :)
## 4.4.0
- Updated shortcut hint on the menubar to reflect the new `ctrl+=` shortcut.
- Reverted icon path to `icon.png` instead of the hardcoded linux path.
- Add support to autoHide the menubar and showing it with the `alt` key.
- Move the quit command from the system sub-menu to the main menu
- Added single click focus/show on the tray icon
- Doesn't work on all platforms. Nothing I can do about that unfortunately!
- Added a list of artists to automatically skip.
- I don't like the vast majority of dutch music so I added one of them to my list to test: [./docs/no-dutch-music.mp4](./docs/no-dutch-music.mp4)
## 4.3.1
- fix: App always requests a default-url-handler-scheme change on start
## 4.3.0
- Added a setting to disable background throttling ([docs](https://www.electronjs.org/docs/latest/api/browser-window))
## 4.2.0
- New settings window by BlueManCZ
- Fixed the desktop files in electron-builder
- icon is set to new static path based on Arch/Debian
- Name has changed to Tidal-Hifi
## 4.1.2 ## 4.1.2
- Changed the category of the desktop file to AudioVideo - Changed the category of the desktop file to AudioVideo

View File

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

View File

@@ -1,7 +1,7 @@
appId: com.rickvanlieshout.tidal-hifi appId: com.rickvanlieshout.tidal-hifi
electronVersion: 24.1.2 electronVersion: 19.0.5
electronDownload: electronDownload:
version: 24.1.2+wvcus version: 19.0.5+wvcus
mirror: https://github.com/castlabs/electron-releases/releases/download/v mirror: https://github.com/castlabs/electron-releases/releases/download/v
snap: snap:
plugs: plugs:
@@ -9,7 +9,6 @@ snap:
- screen-inhibit-control - screen-inhibit-control
linux: linux:
category: AudioVideo category: AudioVideo
icon: icon.png
target: target:
- dir - dir
executableName: tidal-hifi executableName: tidal-hifi

View File

@@ -1,4 +1,6 @@
extends: ./build/electron-builder.base.yml extends: ./build/electron-builder.base.yml
linux: linux:
category: Audio
icon: icon.png
target: target:
- deb - deb

View File

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

View File

@@ -1,4 +1,6 @@
extends: ./build/electron-builder.base.yml extends: ./build/electron-builder.base.yml
linux: linux:
category: Audio
icon: icon.png
target: target:
- rpm - rpm

View File

@@ -1,4 +1,6 @@
extends: ./build/electron-builder.base.yml extends: ./build/electron-builder.base.yml
linux: linux:
category: Audio
icon: icon.png
target: target:
- snap - snap

View File

@@ -1,5 +1,9 @@
extends: ./build/electron-builder.base.yml electronVersion: 19.0.5
electronDownload:
version: 19.0.5+wvcus
mirror: https://github.com/castlabs/electron-releases/releases/download/v
linux: linux:
category: Audio
target: target:
- pacman - pacman
- tar.gz - tar.gz

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

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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

8773
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,19 @@
{ {
"name": "tidal-hifi", "name": "tidal-hifi",
"version": "5.0.0", "version": "4.1.2",
"description": "Tidal on Electron with widevine(hifi) support", "description": "Tidal on Electron with widevine(hifi) support",
"main": "src/main.js", "main": "src/main.js",
"scripts": { "scripts": {
"start": "electron .", "start": "electron .",
"build": "npm run builder -- -c ./build/electron-builder.yml", "build": "electron-builder --publish=never -c ./build/electron-builder.yml",
"build-deb": "npm run builder -- -c ./build/electron-builder.deb.yml", "build-deb": "electron-builder --publish=never -c ./build/electron-builder.deb.yml",
"build-unpacked": "npm run builder -- -c ./build/electron-builder.unpacked.yml", "build-unpacked": "electron-builder --publish=never -c ./build/electron-builder.unpacked.yml",
"build-rpm": "npm run builder -- -c ./build/electron-builder.rpm.yml", "build-rpm": "electron-builder --publish=never -c ./build/electron-builder.rpm.yml",
"build-snap": "npm run builder -- -c ./build/electron-builder.snap.yml", "build-snap": "electron-builder --publish=never -c ./build/electron-builder.snap.yml",
"build-arch": "npm run builder -- -c ./build/electron-builder.pacman.yml", "build-arch": "electron-builder --publish=never -c ./build/electron-builder.pacman.yml",
"build-wl": "npm run builder -- -c ./build/electron-builder.yml -wl", "build-wl": "electron-builder --publish=never -c ./build/electron-builder.yml -wl",
"build-mac": "npm run builder -- -c ./build/electron-builder.yml -m", "build-mac": "electron-builder --publish=never -c ./build/electron-builder.yml -m",
"build-base": "npm run builder -- -c ./build/electron-builder.base.yml", "build-base": "electron-builder --publish=never -c ./build/electron-builder.base.yml"
"prestart": "npm run sass",
"prebuilder": "npm run sass",
"builder": "electron-builder --publish=never",
"sass": "sass ./src/pages/settings/settings.scss ./src/pages/settings/settings.css",
"sass-lint": "sass-lint -vc ./sass-lint.yml ./src/pages/settings/settings.scss",
"sass-lint-fix": "sass-lint-auto-fix ./src/pages/settings/settings.scss --config-sass-lint ./sass-lint.yml"
}, },
"keywords": [ "keywords": [
"electron", "electron",
@@ -31,24 +25,19 @@
"homepage": "https://github.com/Mastermindzh/tidal-hifi", "homepage": "https://github.com/Mastermindzh/tidal-hifi",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@electron/remote": "^2.0.9", "@electron/remote": "^2.0.8",
"discord-rpc": "^4.0.1", "discord-rpc": "^4.0.1",
"electron-store": "^8.1.0", "electron-store": "^8.1.0",
"express": "^4.18.2", "express": "^4.18.1",
"hotkeys-js": "^3.10.2", "hotkeys-js": "^3.9.4",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"request": "^2.88.2", "request": "^2.88.2"
"sass": "^1.62.0"
}, },
"devDependencies": { "devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0", "@mastermindzh/prettier-config": "^1.0.0",
"electron": "git+https://github.com/castlabs/electron-releases.git#v24.1.2+wvcus", "electron": "git+https://github.com/castlabs/electron-releases.git#v19.0.5+wvcus",
"electron-builder": "^24.2.1", "electron-builder": "^23.3.3",
"js-yaml": "^4.1.0", "prettier": "^2.7.1"
"markdown-toc": "^1.2.0",
"prettier": "^2.8.7",
"sass-lint": "^1.13.1",
"sass-lint-auto-fix": "^0.21.2"
}, },
"prettier": "@mastermindzh/prettier-config" "prettier": "@mastermindzh/prettier-config"
} }

View File

@@ -1,21 +0,0 @@
rules:
property-sort-order:
- 1
- order: "smacss"
class-name-format:
- 1
- convention: "hyphenatedbem"
quotes:
- 1
- style: "double"
nesting-depth:
- 1
- max-depth: 3
placeholder-in-extend:
- 0
no-vendor-prefixes:
- 0
empty-line-between-blocks:
- 0
force-pseudo-nesting:
- 0

View File

@@ -13,10 +13,8 @@ const settings = {
api: "api", api: "api",
menuBar: "menuBar", menuBar: "menuBar",
playBackControl: "playBackControl", playBackControl: "playBackControl",
skipArtists: "skipArtists", muteArtists: "muteArtists",
skippedArtists: "skippedArtists", mutedArtists: "mutedArtists",
adBlock: "adBlock",
disableBackgroundThrottle: "disableBackgroundThrottle",
apiSettings: { apiSettings: {
root: "apiSettings", root: "apiSettings",
port: "apiSettings.port", port: "apiSettings.port",

View File

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

View File

@@ -3,15 +3,13 @@ let trayIcon,
mpris, mpris,
enableCustomHotkeys, enableCustomHotkeys,
enableDiscord, enableDiscord,
skipArtists, muteArtists,
notifications, notifications,
playBackControl, playBackControl,
api, api,
port, port,
menuBar, menuBar,
skippedArtists, mutedArtists,
adBlock,
disableBackgroundThrottle,
singleInstance, singleInstance,
disableHardwareMediaKeys, disableHardwareMediaKeys,
gpuRasterization; gpuRasterization;
@@ -35,13 +33,11 @@ function refreshSettings() {
enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys); enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
enableDiscord.checked = store.get(settings.enableDiscord); enableDiscord.checked = store.get(settings.enableDiscord);
minimizeOnClose.checked = store.get(settings.minimizeOnClose); minimizeOnClose.checked = store.get(settings.minimizeOnClose);
skipArtists.checked = store.get(settings.skipArtists); muteArtists.checked = store.get(settings.muteArtists);
skippedArtists.value = store.get(settings.skippedArtists).join("\n"); mutedArtists.value = store.get(settings.mutedArtists).join("\n");
adBlock.checked = store.get(settings.adBlock);
singleInstance.checked = store.get(settings.singleInstance); singleInstance.checked = store.get(settings.singleInstance);
disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys); disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys);
gpuRasterization.checked = store.get(settings.flags.gpuRasterization); gpuRasterization.checked = store.get(settings.flags.gpuRasterization);
disableBackgroundThrottle.checked = store.get("disableBackgroundThrottle");
} }
/** /**
@@ -64,7 +60,7 @@ function hide() {
*/ */
function restart() { function restart() {
app.relaunch(); app.relaunch();
app.exit(); app.quit();
} }
/** /**
@@ -77,7 +73,7 @@ window.addEventListener("DOMContentLoaded", () => {
document.getElementById("close").addEventListener("click", hide); document.getElementById("close").addEventListener("click", hide);
document.getElementById("restart").addEventListener("click", restart); document.getElementById("restart").addEventListener("click", restart);
document.querySelectorAll(".external-link").forEach((elem) => document.querySelectorAll("#openExternal").forEach((elem) =>
elem.addEventListener("click", function (event) { elem.addEventListener("click", function (event) {
openExternal(event.target.getAttribute("data-url")); openExternal(event.target.getAttribute("data-url"));
}) })
@@ -119,10 +115,8 @@ window.addEventListener("DOMContentLoaded", () => {
mpris = get("mprisCheckbox"); mpris = get("mprisCheckbox");
enableCustomHotkeys = get("enableCustomHotkeys"); enableCustomHotkeys = get("enableCustomHotkeys");
enableDiscord = get("enableDiscord"); enableDiscord = get("enableDiscord");
skipArtists = get("skipArtists"); muteArtists = get("muteArtists");
skippedArtists = get("skippedArtists"); mutedArtists = get("mutedArtists");
adBlock = get("adBlock");
disableBackgroundThrottle = get("disableBackgroundThrottle");
singleInstance = get("singleInstance"); singleInstance = get("singleInstance");
disableHardwareMediaKeys = get("disableHardwareMediaKeys"); disableHardwareMediaKeys = get("disableHardwareMediaKeys");
gpuRasterization = get("gpuRasterization"); gpuRasterization = get("gpuRasterization");
@@ -139,10 +133,8 @@ window.addEventListener("DOMContentLoaded", () => {
addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys); addInputListener(enableCustomHotkeys, settings.enableCustomHotkeys);
addInputListener(enableDiscord, settings.enableDiscord); addInputListener(enableDiscord, settings.enableDiscord);
addInputListener(minimizeOnClose, settings.minimizeOnClose); addInputListener(minimizeOnClose, settings.minimizeOnClose);
addInputListener(skipArtists, settings.skipArtists); addInputListener(muteArtists, settings.muteArtists);
addTextAreaListener(skippedArtists, settings.skippedArtists); addTextAreaListener(mutedArtists, settings.mutedArtists);
addInputListener(adBlock, settings.adBlock);
addInputListener(disableBackgroundThrottle, settings.disableBackgroundThrottle);
addInputListener(singleInstance, settings.singleInstance); addInputListener(singleInstance, settings.singleInstance);
addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys); addInputListener(disableHardwareMediaKeys, settings.flags.disableHardwareMediaKeys);
addInputListener(gpuRasterization, settings.flags.gpuRasterization); addInputListener(gpuRasterization, settings.flags.gpuRasterization);

View File

@@ -2,277 +2,557 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>Tidal Hi-Fi settings</title> <title>Tidal-hifi 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" />
</head> </head>
<body class="settings-window"> <body>
<div class="settings-window__wrapper"> <div class="header">
<div class="settings-window__drag-area"></div> <h1 class="title">Settings</h1>
<a id="close" class="settings-window__close-button" title="Close settings"> <a id="close" style="cursor: pointer;" class="exitWindow">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 348.333 348.334" class="settings-window__svg-icon">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 348.333 348.334">
<g>
<path fill="white" d="M336.559,68.611L231.016,174.165l105.543,105.549c15.699,15.705,15.699,41.145,0,56.85 <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>
<main class="settings"> </a>
<input type="radio" name="tab" id="general" checked /> </div>
<div class="body">
<div class="tabset">
<input type="radio" name="tabset" id="general" checked />
<label for="general">General</label> <label for="general">General</label>
<input type="radio" name="tab" id="api" /> <input type="radio" name="tabset" id="api" />
<label for="api">API</label> <label for="api">Api</label>
<input type="radio" name="tab" id="integrations" /> <!-- Integrations tab -->
<input type="radio" name="tabset" id="integrations" />
<label for="integrations">Integrations</label> <label for="integrations">Integrations</label>
<input type="radio" name="tab" id="advanced" /> <!-- advanced tab -->
<input type="radio" name="tabset" id="advanced" />
<label for="advanced">Advanced</label> <label for="advanced">Advanced</label>
<!-- about tab -->
<input type="radio" name="tab" id="about" /> <input type="radio" name="tabset" id="about" />
<label for="about">About</label> <label for="about">About</label>
<div class="tabs"> <div class="tab-panels">
<section id="general-section" class="tabs__section"> <section id="general" class="tab-panel">
<div class="group"> <div class="section">
<p class="group__title">Playback</p> <h3>Playback</h3>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Notifications</h4> <h4>Notifications</h4>
<p>Show a notification when a new song starts.</p>
</div>
<label class="switch">
<input id="notifications" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<h4>Skip Artists automatically</h4>
<p>The following list of artists (1 per line) will be skipped automatically.</p>
</div>
<label class="switch">
<input id="skipArtists" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<textarea id="skippedArtists" class="textarea" cols="40" rows="5" spellcheck="false"></textarea>
<div class="group__option">
<div class="group__description">
<h4>Block ads</h4>
<p> <p>
Disabled audio & visual ads, unlocked lyrics, suggested track, track info, Whether to show a notification when a new song starts.
unlimited skips
</p> </p>
</div>
<label class="switch"> <label class="switch">
<input id="adBlock" type="checkbox" /> <input id="notifications" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label>
</div>
<div class="option">
<h4>Mute Artists automatically</h4>
<p>
The following list of artists (1 per line) will be muted automatically.
</p>
<label class="switch" style="margin-bottom:10px">
<input id="muteArtists" type="checkbox">
<span class="slider round"></span>
</label>
<textarea id="mutedArtists" cols="40" rows="5"></textarea>
</div>
</div>
<div class="section">
<h3>UI</h3>
<div class="option">
<h4>Menubar</h4>
<p>
Show Tidal-hifi's menu bar
</p>
<label class="switch">
<input id="menuBar" type="checkbox">
<span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
<div class="group"> <div class="section">
<p class="group__title">UI</p> <h3>System</h3>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Fixed menubar</h4>
<p>Always show TIDAL Hi-Fi's menu bar.</p>
</div>
<label class="switch">
<input id="menuBar" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
</div>
<div class="group">
<p class="group__title">System</p>
<div class="group__option">
<div class="group__description">
<h4>Tray icon</h4> <h4>Tray icon</h4>
<p>Show TIDAL Hi-Fi's tray icon.</p> <p>
</div> Show Tidal-hifi's tray icon<br />
</p>
<label class="switch"> <label class="switch">
<input id="trayIcon" type="checkbox" /> <input id="trayIcon" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Minimize on Close</h4> <h4>Minimize on Close</h4>
<p>Minimize window on close instead.</p> <p>
</div> Minimize window on close instead <br />
</p>
<label class="switch"> <label class="switch">
<input id="minimizeOnClose" type="checkbox" /> <input id="minimizeOnClose" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Hotkeys</h4> <h4>Hotkeys</h4>
<p> <p>
Enable extra hotkeys to achieve feature parity with the Enables extra hotkeys to achieve feature parity with the <a id="openExternal"
<a class="external-link" data-url="https://defkey.com/tidal-desktop-shortcuts">desktop apps</a>. style="text-decoration: underline; cursor: pointer;"
data-url="https://defkey.com/tidal-desktop-shortcuts">desktop apps</a><br />
</p> </p>
</div>
<label class="switch"> <label class="switch">
<input id="enableCustomHotkeys" type="checkbox" /> <input id="enableCustomHotkeys" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Single instance</h4> <h4>Single instance</h4>
<p>Prevent opening multiple TIDAL Hi-Fi's instances.</p> <p>
</div> Prevent opening multiple tidal-hifi instances
</p>
<label class="switch"> <label class="switch">
<input id="singleInstance" type="checkbox" /> <input id="singleInstance" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
</section> </section>
<section id="api" class="tab-panel">
<section id="api-section" class="tabs__section"> <div class="section">
<div class="group"> <h3>Api</h3>
<p class="group__title">API</p> <p style="margin-bottom: 15px;">
<div class="group__description"> Tidal-hifi has a web api built in to allow users to get current song information. You can optionally
<p> enable playback control as well.
TIDAL Hi-Fi has a built-in web API to allow users to get current song information.
You can optionally enable playback control as well.
</p> </p>
</div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Web API</h4> <h4>Web API</h4>
<p>Enable the TIDAL Hi-Fi web API.</p> <p>
</div> Whether to enable the Tidal-hifi web api
</p>
<label class="switch"> <label class="switch">
<input id="apiCheckbox" type="checkbox" /> <input id="apiCheckbox" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description"> <h4 style="margin-bottom: 5px;">API port</h4>
<label for="port">API port</label> <input id="port" type="text" class="freeTextInput" name="port">
<input id="port" type="text" class="text-input" name="port" />
</div> </div>
</div> <div class="option">
<div class="group__option">
<div class="group__description">
<h4>Playback control</h4> <h4>Playback control</h4>
<p>Enable playback control from the web API.</p> <p>
</div> Whether to enable playback control from the api
</p>
<label class="switch"> <label class="switch">
<input id="playBackControl" type="checkbox" /> <input id="playBackControl" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
</section> </section>
<section id="integrations" class="tab-panel">
<section id="integrations-section" class="tabs__section"> <div class="section">
<div class="group"> <h3>integrations</h3>
<p class="group__title">Integrations</p> <p style="margin-bottom: 15px;">
<div class="group__description"> Tidal-hifi is extensible through the use of integrations. You can enable or disable integrations here
<p>
TIDAL Hi-Fi is extensible through the use of integrations. You can enable or
disable them here.
</p> </p>
</div> <div class="option">
<div class="group__option"> <h4>MPRIS-player</h4>
<div class="group__description">
<h4>MPRIS</h4>
<p> <p>
Enable MPRIS interface which provides a mechanism for discovery, querying and Whether to enable the MPRIS media player controls for Linux systems
basic playback control on Linux systems.
</p> </p>
</div>
<label class="switch"> <label class="switch">
<input id="mprisCheckbox" type="checkbox" /> <input id="mprisCheckbox" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Discord RPC</h4> <h4>Discord RPC</h4>
<p>Show what you're listening to on Discord.</p> <p>
</div> Show what you're listening to on Discord
</p>
<label class="switch"> <label class="switch">
<input id="enableDiscord" type="checkbox" /> <input id="enableDiscord" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
</section> </section>
<section id="advanced" class="tab-panel">
<section id="advanced-section" class="tabs__section"> <div class="section">
<div class="group"> <h3>Flags</h3>
<p class="group__title">Flags</p> <div class="option">
<div class="group__option"> <h4>Disable hardware media keys</h4>
<div class="group__description">
<h4>Disable hardware built-in media keys</h4>
<p> <p>
Also prevents certain desktop environments from recognizing the chrome MPRIS Disable built-in media keys. <br />
client separately from the custom MPRIS client. Also prevents certain desktop environments from recognizing the chrome MPRIS client separetely from the
custom MPRIS client.
</p> </p>
</div>
<label class="switch"> <label class="switch">
<input id="disableHardwareMediaKeys" type="checkbox" /> <input id="disableHardwareMediaKeys" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
<div class="group__option"> <div class="option">
<div class="group__description">
<h4>Enable GPU rasterization</h4> <h4>Enable GPU rasterization</h4>
<p>Move a part of the rendering to the GPU for increased performance.</p>
</div>
<label class="switch">
<input id="gpuRasterization" type="checkbox" />
<span class="switch__slider"></span>
</label>
</div>
<div class="group__option">
<div class="group__description">
<h4>Disable Background Throttling</h4>
<p> <p>
Makes app more responsive while in the background, at the cost of performance. Move a part of the rendering to the GPU for increased performance.
</p> </p>
</div>
<label class="switch"> <label class="switch">
<input id="disableBackgroundThrottle" type="checkbox" /> <input id="gpuRasterization" type="checkbox">
<span class="switch__slider"></span> <span class="slider round"></span>
</label> </label>
</div> </div>
</div> </div>
</section> </section>
<section id="about" class="tab-panel">
<section id="about-section" class="tabs__section about-section"> <div class="section">
<img alt="tidal icon" class="about-section__icon" src="./icon.png" /> <img alt="tidal icon"
<p class="about-section__text"> style="width: 100px; height: auto; display: block; margin: 0 auto; margin-bottom: 20px; margin-top: 20px;"
<a class="external-link" data-url="https://github.com/Mastermindzh/tidal-hifi">TIDAL Hi-Fi</a> src="./icon.png">
is made by <p style="max-width: 350px; display:block; margin: 0 auto; text-align: center;">
<a class="external-link" data-url="https://www.rickvanlieshout.com"> <a id="openExternal" style="text-decoration: underline; cursor: pointer;"
Rick van Lieshout</a>. <br />It uses data-url="https://github.com/Mastermindzh/tidal-hifi">Tidal-hifi</a> is made by <a id="openExternal"
<a class="external-link" data-url="https://castlabs.com/">Castlabs'</a> data-url="https://www.rickvanlieshout.com" style="text-decoration: underline; cursor: pointer;">Rick van
version of Electron for widevine support. Lieshout</a>.<br />
It uses <a style="text-decoration: underline; cursor: pointer;" id="openExternal"
data-url="https://castlabs.com/">Castlabs'</a> versions of Electron for widevine support.
</p> </p>
</div>
</section> </section>
<footer class="footer"> <small>Some settings require a restart of Tidal-hifi. To do so, click the button below:</small>
<p class="footer__note"> <button id="restart" style="width: 100%">Restart Tidal-hifi</button>
Some settings may require a restart of TIDAL Hi-Fi. To do so, click the button below: </div>
</p>
<button class="footer__button" id="restart">Restart TIDAL Hi-Fi</button>
</footer>
</div> </div>
</main>
</div> </div>
</body> </body>
<style>
.header {
-webkit-user-select: none;
-webkit-app-region: drag;
}
.header a {
-webkit-app-region: no-drag;
}
* {
margin: 0%;
padding: 0%;
color: #ffffff;
font-weight: 400;
font-stretch: normal;
-webkit-font-smoothing: antialiased;
font-family: nationale, nationale-regular, Helvetica, sans-serif;
}
html,
body {
height: 100%;
background-color: black;
display: flex;
flex-direction: column;
}
h2 {
font-size: 1.2rem;
}
small {
font-style: italic;
color: #72777f;
}
.header {
background-color: #242528;
border-bottom: 1px solid #5a5a5a;
height: 50px;
}
.title {
float: left;
line-height: 50px;
margin-left: 15px;
}
.accent {
color: #0ff;
}
.exitWindow {
border: none;
outline: none;
text-decoration: none;
font-size: 1.4rem;
float: right;
margin-right: 15px;
height: 50px;
line-height: 50px;
}
.exitWindow:focus {
border: none;
outline: none;
}
.exitWindow svg {
height: 50px;
color: white;
}
.section {
padding-top: 10px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(246, 245, 255, .1);
}
.section .option {
margin-bottom: 15px;
}
.section .option p {
max-width: 75%;
float: left
}
.section .option label {
float: right;
}
.section:after,
.section .option:after {
content: "";
display: table;
clear: both;
}
.section h3 {
margin-bottom: 15px;
}
.section h4 {
font-size: 0.9rem;
}
.section p {
color: #72777f;
}
.bottom-border {
border-bottom: 1px solid #0ff;
}
.body {
padding: 15px;
flex: 1 1 auto;
position: relative;
overflow-y: auto;
}
.body::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
border-radius: 5px;
background-color: 2a2a2a;
}
.body::-webkit-scrollbar {
width: 10px;
background-color: #2a2a2a;
}
.body::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
background-color: #5a5a5a;
}
/* Tabs */
.tabset>input[type="radio"] {
position: absolute;
left: -200vw;
}
.tabset .tab-panel {
display: none;
}
.tabset>input:first-child:checked~.tab-panels>.tab-panel:first-child,
.tabset>input:nth-child(3):checked~.tab-panels>.tab-panel:nth-child(2),
.tabset>input:nth-child(5):checked~.tab-panels>.tab-panel:nth-child(3),
.tabset>input:nth-child(7):checked~.tab-panels>.tab-panel:nth-child(4),
.tabset>input:nth-child(9):checked~.tab-panels>.tab-panel:nth-child(5) {
display: block;
}
.tabset>label {
position: relative;
display: inline-block;
padding: 15px 0px 10px;
border-bottom: 0;
cursor: pointer;
}
.tabset>input+label {
color: #e0e0e0;
margin-right: 30px;
}
.tabset>input:checked+label {
color: #0ff;
border-bottom: 2px solid #0ff;
}
.tab-panel {
padding: 10px 0;
}
/* switches */
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 50px;
height: 28px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(246, 245, 255, .1);
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 24px;
width: 24px;
left: 2px;
bottom: 2px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #0ff;
}
input:focus+.slider {
box-shadow: 0 0 1px #0ff;
}
input:checked+.slider:before {
-webkit-transform: translateX(22px);
-ms-transform: translateX(22px);
transform: translateX(22px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
/* input field */
input {
background: transparent;
border: 0;
border-bottom: 1px solid rgba(246, 245, 255, .1);
color: rgba(229, 238, 255, .6);
width: 100%;
display: block;
padding: 0 0 12px;
}
.freeTextInput:focus {
outline: none;
border-bottom: 1px solid #0ff;
}
/* buttons */
button {
border: none;
background: none;
align-items: center;
background-color: rgba(229, 238, 255, .2);
display: inline-flex;
justify-content: center;
border-radius: 12px;
height: 48px;
line-height: 49px;
padding: 0 24px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: background .35s ease;
min-height: 0;
min-width: 0;
font-size: 1.14286rem;
font-family: nationale, nationale-regular, Helvetica, sans-serif;
margin-top: 10px;
cursor: pointer;
}
button:hover {
background-color: rgba(229, 238, 255, .3);
}
textarea {
color: #72777f;
background: #242528;
border: 0;
width: 100%;
color: rgba(229, 238, 255, .6);
padding: 0 0 12px;
display: block;
}
textarea:focus {
outline: none;
border: 0;
border-bottom: 1px solid #0ff;
}
</style>
</html> </html>

View File

@@ -1,363 +0,0 @@
// --- Variables ---
$black: #17171a;
$grey-333: #333;
$white: #f9f9f9;
$tidal-blue: #0ff;
$tidal-grey: #72777f;
$tidal-grey-darker: #404248;
$tidal-grey-darker-focus: #55585f;
$tidal-grey-darkest: #242528;
// --- Fonts ---
@font-face {
font-family: "Noto Sans";
font-weight: 300;
src: url("fonts/NotoSans-Light.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-weight: normal;
src: url("fonts/NotoSans-Regular.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-weight: 600;
src: url("fonts/NotoSans-SemiBold.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-weight: bold;
src: url("fonts/NotoSans-Bold.ttf") format("truetype");
}
$font1: "Noto Sans", Helvetica, sans-serif;
// --- Mixins ---
@mixin drag($enabled: true) {
@if $enabled {
-webkit-app-region: drag;
}
@else {
-webkit-app-region: no-drag;
}
}
button {
cursor: pointer;
}
// --- Settings window ---
html {
height: 100%;
}
.external-link {
@extend button;
text-decoration: underline;
}
.settings-window {
height: 100%;
margin: 0;
color: $white;
font-family: $font1;
&__wrapper {
height: 100%;
background: $black;
box-shadow: inset 0 0 2px 0 $tidal-grey;
overflow: hidden;
}
&__drag-area {
@include drag;
position: absolute;
width: 100%;
height: 50px;
z-index: 0;
user-select: none;
}
&__close-button {
@extend button;
@include drag(false);
position: absolute;
top: 12px;
right: 10px;
padding: 10px;
border-radius: 100%;
z-index: 1;
&:hover {
background: $grey-333;
}
}
&__svg-icon {
display: block;
width: 18px;
height: 18px;
opacity: .7;
}
// --- Settings tabs ---
}
.settings {
height: 100%;
margin: 20px 0;
padding-left: 15px;
font-size: 0;
input {
&[type="radio"] {
margin-right: -18px;
transform: scale(0);
outline: none;
}
&+label {
@include drag(false);
display: inline-block;
position: relative;
margin-right: 35px;
padding-bottom: 8px;
border-bottom: 0;
font-size: 16px;
cursor: pointer;
z-index: 1;
user-select: none;
}
&:checked+label {
border-bottom: 2px solid $tidal-blue;
color: $tidal-blue;
}
}
}
.tabs {
height: calc(100% - 70px);
padding-right: 15px;
font-size: 16px;
overflow: auto;
&__section {
display: none;
}
@for $i from 1 to 6 {
.settings>input:nth-child(#{$i*2-1}):checked~&>.tabs__section:nth-child(#{$i}) {
display: block;
}
}
&::-webkit-scrollbar {
width: 10px;
&-thumb {
border-radius: 10px;
background-color: $tidal-grey-darker;
box-shadow: inset 0 0 10px 2px $tidal-grey-darkest;
}
// --- Settings group ---
}
}
.group {
padding: 10px 0;
border-bottom: 1px solid $grey-333;
&:last-child {
border: 0;
}
&__title {
margin-bottom: 10px;
font-size: 16px;
font-weight: bold;
}
&__option {
display: flex;
align-items: center;
}
&__description {
flex-grow: 1;
h4,
label {
display: block;
margin-top: 10px;
margin-bottom: 0;
font-size: 14px;
font-weight: 600;
}
p {
margin-top: 5px;
margin-bottom: 8px;
color: $tidal-grey;
font-size: 14px;
}
.text-input {
display: block;
width: 100%;
margin-bottom: 10px;
padding: 5px 0;
transition: .2s;
border: 0;
border-bottom: solid 1px $grey-333;
outline: none;
background: transparent;
color: $tidal-grey;
font-size: 14px;
&:focus {
border-color: $tidal-blue;
color: $white;
}
// --- Switch slider component ---
}
}
}
.switch {
$this: &;
position: relative;
min-width: 50px;
height: 28px;
margin-left: 10px;
input {
transform: scale(0);
outline: none;
&:checked+#{$this}__slider {
background-color: $tidal-blue;
&::before {
transform: translateX(22px);
background-color: white;
}
}
&:focus+#{$this}__slider {
box-shadow: inset 0 0 0 1px $tidal-blue;
}
}
&__slider {
@extend button;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: .4s;
border-radius: 40px;
background-color: $tidal-grey-darkest;
&::before {
position: absolute;
bottom: 2px;
left: 2px;
width: 24px;
height: 24px;
transition: .4s;
border-radius: 50%;
background-color: $white;
content: "";
}
// --- Textarea component
}
}
.textarea {
min-width: 100%;
max-width: 100%;
min-height: 50px;
max-height: 100px;
padding: 8px;
transition: .2s;
border: 0;
border-bottom: 1px solid transparent;
background: $tidal-grey-darkest;
color: $tidal-grey;
font-size: 13px;
box-sizing: border-box;
&:focus {
border-color: $tidal-blue;
outline: none;
color: $white;
}
// --- About section ---
}
.about-section {
padding-top: 120px;
text-align: center;
&__icon {
display: inline-block;
width: 100px;
}
&__text {
display: block;
max-width: 350px;
margin: 20px auto 0;
}
// --- Footer ---
}
.footer {
position: sticky;
top: calc(100% - 120px);
height: 100px;
padding-top: 20px;
text-align: center;
&__note {
max-width: 300px;
margin: 0 auto 15px;
color: $tidal-grey;
font-size: 12px;
}
&__button {
@extend button;
display: block;
height: 48px;
margin: auto;
padding: 0 24px;
transition: .2s;
border: 0;
border-radius: 12px;
background: $tidal-grey-darker;
color: $white;
font-size: 16px;
&:hover {
background: $tidal-grey-darker-focus;
}
}
}

View File

@@ -7,12 +7,12 @@ const { downloadFile } = require("./scripts/download");
const statuses = require("./constants/statuses"); const statuses = require("./constants/statuses");
const hotkeys = require("./scripts/hotkeys"); const hotkeys = require("./scripts/hotkeys");
const globalEvents = require("./constants/globalEvents"); const globalEvents = require("./constants/globalEvents");
const { skipArtists } = require("./constants/settings");
const notificationPath = `${app.getPath("userData")}/notification.jpg`; const notificationPath = `${app.getPath("userData")}/notification.jpg`;
const appName = "Tidal Hifi"; const appName = "Tidal Hifi";
let currentSong = ""; let currentSong = "";
let player; let player;
let currentPlayStatus = statuses.paused; let currentPlayStatus = statuses.paused;
let isMutedArtist = true;
const elements = { const elements = {
play: '*[data-test="play"]', play: '*[data-test="play"]',
@@ -300,7 +300,6 @@ function updateMediaInfo(options, notify) {
"xesam:album": options.album, "xesam:album": options.album,
"mpris:artUrl": options.image, "mpris:artUrl": options.image,
"mpris:length": convertDuration(options.duration) * 1000 * 1000, "mpris:length": convertDuration(options.duration) * 1000 * 1000,
"mpris:trackid": "/org/mpris/MediaPlayer2/track/" + getTrackID(),
}, },
}; };
player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing"; player.playbackStatus = options.status == statuses.paused ? "Paused" : "Playing";
@@ -313,15 +312,10 @@ function updateMediaInfo(options, notify) {
* If it's a song it returns the track URL, if not it will return undefined * If it's a song it returns the track URL, if not it will return undefined
*/ */
function getTrackURL() { function getTrackURL() {
const id = getTrackID();
return `https://tidal.com/browse/track/${id}`;
}
function getTrackID() {
const URLelement = elements.get("title").querySelector("a"); const URLelement = elements.get("title").querySelector("a");
if (URLelement !== null) { if (URLelement !== null) {
const id = URLelement.href.replace(/\D/g, ""); const id = URLelement.href.replace(/[^0-9]/g, "");
return id; return `https://tidal.com/browse/track/${id}`;
} }
return window.location; return window.location;
@@ -333,7 +327,7 @@ function getTrackID() {
setInterval(function () { setInterval(function () {
const title = elements.getText("title"); const title = elements.getText("title");
const artists = elements.getArtists(); const artists = elements.getArtists();
skipArtistsIfFoundInSkippedArtistsList(artists); muteArtistIfFoundInMutedArtistsList(); // doing this here so that nothing can possibly fail before we call this function
const album = elements.getAlbumName(); const album = elements.getAlbumName();
const current = elements.getText("current"); const current = elements.getText("current");
@@ -351,8 +345,11 @@ setInterval(function () {
"app-name": appName, "app-name": appName,
}; };
const titleOrArtistChanged = currentSong !== songDashArtistTitle; const titleOrArtistChanged = currentSong !== songDashArtistTitle;
// update title, url and play info with new info // update title, url and play info with new info
setTitle(songDashArtistTitle); setTitle(songDashArtistTitle);
getTrackURL(); getTrackURL();
@@ -386,18 +383,23 @@ setInterval(function () {
); );
/** /**
* automatically skip a song if the artists are found in the list of artists to skip * Checks whether the current artist is included in the "muted artists" list and if so it will automatically mute the player
* @param {*} artists list of artists to skip
*/ */
function skipArtistsIfFoundInSkippedArtistsList(artists) { function muteArtistIfFoundInMutedArtistsList() {
if (store.get(skipArtists)) { if (store.get(settings.muteArtists)) {
const skippedArtists = store.get(settings.skippedArtists); const mutedArtists = store.get(settings.mutedArtists);
if (skippedArtists.find((artist) => artist === artists) !== undefined) { if (mutedArtists.find((artist) => artist === artists) !== undefined) {
elements.click("next"); if (!elements.isMuted()) {
isMutedArtist = true;
elements.click("volume");
}
} else if (isMutedArtist && elements.isMuted()) {
elements.click("volume");
isMutedArtist = false;
} }
} }
} }
}, 100); }, 1000);
if (process.platform === "linux" && store.get(settings.mpris)) { if (process.platform === "linux" && store.get(settings.mpris)) {
try { try {

View File

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

View File

@@ -10,10 +10,8 @@ const store = new Store({
notifications: true, notifications: true,
api: true, api: true,
playBackControl: true, playBackControl: true,
skipArtists: false, muteArtists: false,
skippedArtists: [""], mutedArtists: ["TIDAL"],
adBlock: false,
disableBackgroundThrottle: true,
menuBar: true, menuBar: true,
apiSettings: { apiSettings: {
port: 47836, port: 47836,
@@ -50,13 +48,11 @@ const settingsModule = {
settingsModule.createSettingsWindow = function () { settingsModule.createSettingsWindow = function () {
settingsWindow = new BrowserWindow({ settingsWindow = new BrowserWindow({
width: 700, width: 500,
height: 600, height: 600,
resizable: false,
show: false, show: false,
transparent: true,
frame: false, frame: false,
title: "TIDAL Hi-Fi settings", title: "Tidal-hifi - settings",
webPreferences: { webPreferences: {
preload: path.join(__dirname, "../pages/settings/preload.js"), preload: path.join(__dirname, "../pages/settings/preload.js"),
plugins: true, plugins: true,

View File

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