added media keys + notifications

This commit is contained in:
Rick van Lieshout 2019-10-22 21:25:57 +02:00
parent 9c3ac88d12
commit a56d18e414
7 changed files with 575 additions and 146 deletions

View File

@ -1,4 +1,6 @@
appId: com.rickvanlieshout.tidal-hifi
electronDownload:
mirror: https://github.com/castlabs/electron-releases/releases/download/v
snap:
plugs:
- default

566
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,9 @@
"main": "src/main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder -c ./build/electron-builder.yml"
"build": "electron-builder -c ./build/electron-builder.yml",
"build-wl": "electron-builder -c ./build/electron-builder.yml -wl",
"build-mac": "electron-builder -c ./build/electron-builder.yml -m"
},
"keywords": [
"electron",
@ -16,11 +18,13 @@
"author": "Rick van Lieshout <info@rickvanlieshout.com> (http://rickvanlieshout.com)",
"license": "MIT",
"dependencies": {
"hotkeys-js": "^3.7.1"
"hotkeys-js": "^3.7.1",
"node-notifier": "^6.0.0",
"request": "^2.88.0"
},
"devDependencies": {
"@mastermindzh/prettier-config": "^1.0.0",
"electron": "https://github.com/castlabs/electron-releases#v6.0.12-wvvmp",
"electron": "https://github.com/castlabs/electron-releases#v6.1.0-wvvmp",
"electron-builder": "^21.2.0",
"electron-reload": "^1.5.0",
"prettier": "^1.18.2"

View File

@ -1,6 +1,7 @@
const { app, BrowserWindow } = require("electron");
const { app, BrowserWindow, globalShortcut } = require("electron");
const path = require("path");
const tidalUrl = "https://listen.tidal.com";
const mediaKeys = require("./scripts/media-keys");
let mainWindow;
/**
@ -19,6 +20,8 @@ function createWindow(options = {}) {
y: options.y,
width: 1024,
height: 800,
icon: "./../build/icon.png",
tray: true,
backgroundColor: options.backgroundColor,
webPreferences: {
affinity: "window",
@ -42,10 +45,11 @@ function createWindow(options = {}) {
}
function addGlobalShortcuts() {
// globalShortcut.register("Control+A", () => {
// dialog.showErrorBox("test", "test");
// // mainWindow.webContents.send("getPlayInfo");
// });
Object.values(mediaKeys).forEach((key) => {
globalShortcut.register(key, () => {
mainWindow.webContents.send("globalKey", key);
});
});
}
// This method will be called when Electron has finished

View File

@ -1,6 +1,12 @@
const { setTitle, getTitle } = require("./scripts/window-functions");
const { dialog } = require("electron").remote;
const hotkeys = require("./scripts/hotkeys");
const mediaKeys = require("./scripts/media-keys");
const notifier = require("node-notifier");
const { ipcRenderer } = require("electron");
const { app } = require("electron").remote;
const { downloadFile } = require("./scripts/download");
const notificationPath = `${app.getPath("userData")}/notification.jpg`;
const elements = {
play: '*[data-test="play"]',
@ -18,19 +24,55 @@ const elements = {
block: '[class="blockButton"]',
account: '*[data-test^="profile-image-button"]',
settings: '*[data-test^="open-settings"]',
media: '*[data-test="current-media-imagery"]',
image: '*[class^="image--"]',
/**
* Get an element from the dom
* @param {*} key key in elements object to fetch
*/
get: function(key) {
return window.document.querySelector(this[key.toLowerCase()]);
},
getText: function(key) {
return this.get(key).textContent;
/**
* Get the icon of the current song
*/
getSongIcon: function() {
const figure = this.get("media");
if (figure) {
const mediaElement = figure.querySelector(this["image"]);
if (mediaElement) {
return mediaElement.src;
}
}
return "";
},
/**
* Shorthand function to get the text of a dom element
* @param {*} key key in elements object to fetch
*/
getText: function(key) {
const element = this.get(key);
return element ? element.textContent : "";
},
/**
* Shorthand function to click a dom element
* @param {*} key key in elements object to fetch
*/
click: function(key) {
this.get(key).click();
return this;
},
/**
* Shorthand function to focus a dom element
* @param {*} key key in elements object to fetch
*/
focus: function(key) {
return this.get(key).focus();
},
@ -141,25 +183,65 @@ function handleLogout() {
*/
function addIPCEventListeners() {
window.addEventListener("DOMContentLoaded", () => {
const { ipcRenderer } = require("electron");
ipcRenderer.on("getPlayInfo", (event, col) => {
ipcRenderer.on("getPlayInfo", () => {
alert(`${elements.getText("title")} - ${elements.getText("artists")}`);
});
ipcRenderer.on("globalEvent", (event, args) => {
switch (args) {
case mediaKeys.playPause:
playPause();
break;
case mediaKeys.next:
elements.click("next");
break;
case mediaKeys.previous:
elements.click("previous");
break;
}
});
});
}
/**
* Update window title
* Watch for song changes and update title + notify
*/
setInterval(function() {
const title = elements.getText("title");
const artists = elements.getText("artists");
const songDashArtistTitle = `${title} - ${artists}`;
if (getTitle() !== songDashArtistTitle) {
setTitle(songDashArtistTitle);
const image = elements.getSongIcon();
const options = {
title,
message: artists,
};
new Promise((resolve, reject) => {
if (image.startsWith("http")) {
downloadFile(image, notificationPath).then(
() => {
options.icon = notificationPath;
resolve();
},
() => {
reject();
}
);
} else {
reject();
}
}).then(
() => {
notifier.notify(options);
},
() => {}
);
}
}, 1000);
}, 200);
addHotKeys();
addIPCEventListeners();

26
src/scripts/download.js Normal file
View File

@ -0,0 +1,26 @@
const download = {};
const request = require("request");
const fs = require("fs");
/**
* download and save a file
* @param {*} fileUrl url to download
* @param {*} targetPath path to save it at
*/
download.downloadFile = function(fileUrl, targetPath) {
return new Promise((resolve, reject) => {
var req = request({
method: "GET",
uri: fileUrl,
});
var out = fs.createWriteStream(targetPath);
req.pipe(out);
req.on("end", resolve);
req.on("error", reject);
});
};
module.exports = download;

View File

@ -0,0 +1,7 @@
const mediaKeys = {
play: "MediaPlayPause",
next: "MediaNextTrack",
previous: "MediaPreviousTrack",
};
module.exports = mediaKeys;