mirror of
				https://github.com/Mastermindzh/tidal-hifi.git
				synced 2025-11-04 02:39:13 +01:00 
			
		
		
		
	chore: more typescript
This commit is contained in:
		
							
								
								
									
										7
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -20,6 +20,7 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "devDependencies": {
 | 
					      "devDependencies": {
 | 
				
			||||||
        "@mastermindzh/prettier-config": "^1.0.0",
 | 
					        "@mastermindzh/prettier-config": "^1.0.0",
 | 
				
			||||||
 | 
					        "@types/discord-rpc": "^4.0.4",
 | 
				
			||||||
        "@types/express": "^4.17.17",
 | 
					        "@types/express": "^4.17.17",
 | 
				
			||||||
        "@types/request": "^2.48.8",
 | 
					        "@types/request": "^2.48.8",
 | 
				
			||||||
        "@typescript-eslint/eslint-plugin": "^5.59.1",
 | 
					        "@typescript-eslint/eslint-plugin": "^5.59.1",
 | 
				
			||||||
@@ -953,6 +954,12 @@
 | 
				
			|||||||
        "@types/node": "*"
 | 
					        "@types/node": "*"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/discord-rpc": {
 | 
				
			||||||
 | 
					      "version": "4.0.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/discord-rpc/-/discord-rpc-4.0.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Afr+3GqUqZnQ6bA/WzNp388heVAmfKuNxy6giAde2ZZP7sNr6mnl+ELpcecD/z2sndfKSauLB89ABNqjWWCZlg==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/express": {
 | 
					    "node_modules/@types/express": {
 | 
				
			||||||
      "version": "4.17.17",
 | 
					      "version": "4.17.17",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@mastermindzh/prettier-config": "^1.0.0",
 | 
					    "@mastermindzh/prettier-config": "^1.0.0",
 | 
				
			||||||
 | 
					    "@types/discord-rpc": "^4.0.4",
 | 
				
			||||||
    "@types/express": "^4.17.17",
 | 
					    "@types/express": "^4.17.17",
 | 
				
			||||||
    "@types/request": "^2.48.8",
 | 
					    "@types/request": "^2.48.8",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "^5.59.1",
 | 
					    "@typescript-eslint/eslint-plugin": "^5.59.1",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *    },
 | 
					 *    },
 | 
				
			||||||
 *    windowBounds: { width: 800, height: 600 },
 | 
					 *    windowBounds: { width: 800, height: 600 },
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const settings = {
 | 
					export const settings = {
 | 
				
			||||||
  adBlock: "adBlock",
 | 
					  adBlock: "adBlock",
 | 
				
			||||||
  api: "api",
 | 
					  api: "api",
 | 
				
			||||||
  apiSettings: {
 | 
					  apiSettings: {
 | 
				
			||||||
@@ -41,5 +41,3 @@ const settings = {
 | 
				
			|||||||
    height: "windowBounds.height",
 | 
					    height: "windowBounds.height",
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = settings;
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								src/declarations.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/declarations.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					declare module "mpris-service";
 | 
				
			||||||
							
								
								
									
										57
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/main.ts
									
									
									
									
									
								
							@@ -12,19 +12,20 @@ import path from "path";
 | 
				
			|||||||
import flagValues from "./constants/flags";
 | 
					import flagValues from "./constants/flags";
 | 
				
			||||||
import globalEvents from "./constants/globalEvents";
 | 
					import globalEvents from "./constants/globalEvents";
 | 
				
			||||||
import mediaKeys from "./constants/mediaKeys";
 | 
					import mediaKeys from "./constants/mediaKeys";
 | 
				
			||||||
import discordModule from "./scripts/discord";
 | 
					import { initRPC, rpc, unRPC } from "./scripts/discord";
 | 
				
			||||||
import { startExpress } from "./scripts/express";
 | 
					import { startExpress } from "./scripts/express";
 | 
				
			||||||
import mediaInfoModule from "./scripts/mediaInfo";
 | 
					import { updateMediaInfo } from "./scripts/mediaInfo";
 | 
				
			||||||
import { addMenu } from "./scripts/menu";
 | 
					import { addMenu } from "./scripts/menu";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  closeSettingsWindow,
 | 
					  closeSettingsWindow,
 | 
				
			||||||
  createSettingsWindow,
 | 
					  createSettingsWindow,
 | 
				
			||||||
  hideSettingsWindow,
 | 
					  hideSettingsWindow,
 | 
				
			||||||
  settings,
 | 
					 | 
				
			||||||
  showSettingsWindow,
 | 
					  showSettingsWindow,
 | 
				
			||||||
  store,
 | 
					  settingsStore,
 | 
				
			||||||
} from "./scripts/settings";
 | 
					} from "./scripts/settings";
 | 
				
			||||||
 | 
					import { settings } from "./constants/settings";
 | 
				
			||||||
import { addTray, refreshTray } from "./scripts/tray";
 | 
					import { addTray, refreshTray } from "./scripts/tray";
 | 
				
			||||||
 | 
					import { MediaInfo } from "./models/mediaInfo";
 | 
				
			||||||
const tidalUrl = "https://listen.tidal.com";
 | 
					const tidalUrl = "https://listen.tidal.com";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
initialize();
 | 
					initialize();
 | 
				
			||||||
@@ -36,7 +37,7 @@ const PROTOCOL_PREFIX = "tidal";
 | 
				
			|||||||
setFlags();
 | 
					setFlags();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setFlags() {
 | 
					function setFlags() {
 | 
				
			||||||
  const flags = store.get(settings.flags.root);
 | 
					  const flags = settingsStore.get(settings.flags.root);
 | 
				
			||||||
  if (flags) {
 | 
					  if (flags) {
 | 
				
			||||||
    for (const [key, value] of Object.entries(flags)) {
 | 
					    for (const [key, value] of Object.entries(flags)) {
 | 
				
			||||||
      if (value) {
 | 
					      if (value) {
 | 
				
			||||||
@@ -59,7 +60,7 @@ function setFlags() {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function syncMenuBarWithStore() {
 | 
					function syncMenuBarWithStore() {
 | 
				
			||||||
  const fixedMenuBar = !!store.get(settings.menuBar);
 | 
					  const fixedMenuBar = !!settingsStore.get(settings.menuBar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mainWindow.autoHideMenuBar = !fixedMenuBar;
 | 
					  mainWindow.autoHideMenuBar = !fixedMenuBar;
 | 
				
			||||||
  mainWindow.setMenuBarVisibility(fixedMenuBar);
 | 
					  mainWindow.setMenuBarVisibility(fixedMenuBar);
 | 
				
			||||||
@@ -72,7 +73,7 @@ function syncMenuBarWithStore() {
 | 
				
			|||||||
 * @returns true if singInstance is not requested, otherwise true/false based on whether the current window is the main window
 | 
					 * @returns true if singInstance is not requested, otherwise true/false based on whether the current window is the main window
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function isMainInstanceOrMultipleInstancesAllowed() {
 | 
					function isMainInstanceOrMultipleInstancesAllowed() {
 | 
				
			||||||
  if (store.get(settings.singleInstance)) {
 | 
					  if (settingsStore.get(settings.singleInstance)) {
 | 
				
			||||||
    const gotTheLock = app.requestSingleInstanceLock();
 | 
					    const gotTheLock = app.requestSingleInstanceLock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!gotTheLock) {
 | 
					    if (!gotTheLock) {
 | 
				
			||||||
@@ -87,8 +88,8 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
 | 
				
			|||||||
  mainWindow = new BrowserWindow({
 | 
					  mainWindow = new BrowserWindow({
 | 
				
			||||||
    x: options.x,
 | 
					    x: options.x,
 | 
				
			||||||
    y: options.y,
 | 
					    y: options.y,
 | 
				
			||||||
    width: store && store.get(settings.windowBounds.width),
 | 
					    width: settingsStore && settingsStore.get(settings.windowBounds.width),
 | 
				
			||||||
    height: store && store.get(settings.windowBounds.height),
 | 
					    height: settingsStore && settingsStore.get(settings.windowBounds.height),
 | 
				
			||||||
    icon,
 | 
					    icon,
 | 
				
			||||||
    backgroundColor: options.backgroundColor,
 | 
					    backgroundColor: options.backgroundColor,
 | 
				
			||||||
    autoHideMenuBar: true,
 | 
					    autoHideMenuBar: true,
 | 
				
			||||||
@@ -106,13 +107,13 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
 | 
				
			|||||||
  // load the Tidal website
 | 
					  // load the Tidal website
 | 
				
			||||||
  mainWindow.loadURL(tidalUrl);
 | 
					  mainWindow.loadURL(tidalUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (store.get(settings.disableBackgroundThrottle)) {
 | 
					  if (settingsStore.get(settings.disableBackgroundThrottle)) {
 | 
				
			||||||
    // prevent setInterval lag
 | 
					    // prevent setInterval lag
 | 
				
			||||||
    mainWindow.webContents.setBackgroundThrottling(false);
 | 
					    mainWindow.webContents.setBackgroundThrottling(false);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mainWindow.on("close", function (event: CloseEvent) {
 | 
					  mainWindow.on("close", function (event: CloseEvent) {
 | 
				
			||||||
    if (store.get(settings.minimizeOnClose)) {
 | 
					    if (settingsStore.get(settings.minimizeOnClose)) {
 | 
				
			||||||
      event.preventDefault();
 | 
					      event.preventDefault();
 | 
				
			||||||
      mainWindow.hide();
 | 
					      mainWindow.hide();
 | 
				
			||||||
      refreshTray(mainWindow);
 | 
					      refreshTray(mainWindow);
 | 
				
			||||||
@@ -126,12 +127,12 @@ function createWindow(options = { x: 0, y: 0, backgroundColor: "white" }) {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
  mainWindow.on("resize", () => {
 | 
					  mainWindow.on("resize", () => {
 | 
				
			||||||
    const { width, height } = mainWindow.getBounds();
 | 
					    const { width, height } = mainWindow.getBounds();
 | 
				
			||||||
    store.set(settings.windowBounds.root, { width, height });
 | 
					    settingsStore.set(settings.windowBounds.root, { width, height });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function registerHttpProtocols() {
 | 
					function registerHttpProtocols() {
 | 
				
			||||||
  protocol.registerHttpProtocol(PROTOCOL_PREFIX, (request, _callback) => {
 | 
					  protocol.registerHttpProtocol(PROTOCOL_PREFIX, (request) => {
 | 
				
			||||||
    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)) {
 | 
					  if (!app.isDefaultProtocolClient(PROTOCOL_PREFIX)) {
 | 
				
			||||||
@@ -155,7 +156,7 @@ app.on("ready", async () => {
 | 
				
			|||||||
    await components.whenReady();
 | 
					    await components.whenReady();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Adblock
 | 
					    // Adblock
 | 
				
			||||||
    if (store.get(settings.adBlock)) {
 | 
					    if (settingsStore.get(settings.adBlock)) {
 | 
				
			||||||
      const filter = { urls: ["https://listen.tidal.com/*"] };
 | 
					      const filter = { urls: ["https://listen.tidal.com/*"] };
 | 
				
			||||||
      session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
 | 
					      session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
 | 
				
			||||||
        if (details.url.match(/\/users\/.*\d\?country/)) callback({ cancel: true });
 | 
					        if (details.url.match(/\/users\/.*\d\?country/)) callback({ cancel: true });
 | 
				
			||||||
@@ -167,12 +168,12 @@ app.on("ready", async () => {
 | 
				
			|||||||
    addMenu(mainWindow);
 | 
					    addMenu(mainWindow);
 | 
				
			||||||
    createSettingsWindow();
 | 
					    createSettingsWindow();
 | 
				
			||||||
    addGlobalShortcuts();
 | 
					    addGlobalShortcuts();
 | 
				
			||||||
    if (store.get(settings.trayIcon)) {
 | 
					    if (settingsStore.get(settings.trayIcon)) {
 | 
				
			||||||
      addTray(mainWindow, { icon });
 | 
					      addTray(mainWindow, { icon });
 | 
				
			||||||
      refreshTray(mainWindow);
 | 
					      refreshTray(mainWindow);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    store.get(settings.api) && startExpress(mainWindow);
 | 
					    settingsStore.get(settings.api) && startExpress(mainWindow);
 | 
				
			||||||
    store.get(settings.enableDiscord) && discordModule.initRPC();
 | 
					    settingsStore.get(settings.enableDiscord) && initRPC();
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    app.quit();
 | 
					    app.quit();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -191,31 +192,31 @@ app.on("browser-window-created", (_, window) => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IPC
 | 
					// IPC
 | 
				
			||||||
ipcMain.on(globalEvents.updateInfo, (_event, arg) => {
 | 
					ipcMain.on(globalEvents.updateInfo, (_event, arg: MediaInfo) => {
 | 
				
			||||||
  mediaInfoModule.update(arg);
 | 
					  updateMediaInfo(arg);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ipcMain.on(globalEvents.hideSettings, (_event, _arg) => {
 | 
					ipcMain.on(globalEvents.hideSettings, () => {
 | 
				
			||||||
  hideSettingsWindow();
 | 
					  hideSettingsWindow();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
ipcMain.on(globalEvents.showSettings, (_event, _arg) => {
 | 
					ipcMain.on(globalEvents.showSettings, () => {
 | 
				
			||||||
  showSettingsWindow();
 | 
					  showSettingsWindow();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ipcMain.on(globalEvents.refreshMenuBar, (_event, _arg) => {
 | 
					ipcMain.on(globalEvents.refreshMenuBar, () => {
 | 
				
			||||||
  syncMenuBarWithStore();
 | 
					  syncMenuBarWithStore();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ipcMain.on(globalEvents.storeChanged, (_event, _arg) => {
 | 
					ipcMain.on(globalEvents.storeChanged, () => {
 | 
				
			||||||
  syncMenuBarWithStore();
 | 
					  syncMenuBarWithStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (store.get(settings.enableDiscord) && !discordModule.rpc) {
 | 
					  if (settingsStore.get(settings.enableDiscord) && !rpc) {
 | 
				
			||||||
    discordModule.initRPC();
 | 
					    initRPC();
 | 
				
			||||||
  } else if (!store.get(settings.enableDiscord) && discordModule.rpc) {
 | 
					  } else if (!settingsStore.get(settings.enableDiscord) && rpc) {
 | 
				
			||||||
    discordModule.unRPC();
 | 
					    unRPC();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ipcMain.on(globalEvents.error, (event, _arg) => {
 | 
					ipcMain.on(globalEvents.error, (event) => {
 | 
				
			||||||
  console.log(event);
 | 
					  console.log(event);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								src/models/mediaInfo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/models/mediaInfo.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import { MediaStatus } from "./mediaStatus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface MediaInfo {
 | 
				
			||||||
 | 
					  title: string;
 | 
				
			||||||
 | 
					  artists: string;
 | 
				
			||||||
 | 
					  album: string;
 | 
				
			||||||
 | 
					  icon: string;
 | 
				
			||||||
 | 
					  status: MediaStatus;
 | 
				
			||||||
 | 
					  url: string;
 | 
				
			||||||
 | 
					  current: string;
 | 
				
			||||||
 | 
					  duration: string;
 | 
				
			||||||
 | 
					  image: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								src/models/mediaStatus.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/models/mediaStatus.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					export enum MediaStatus {
 | 
				
			||||||
 | 
					  playing = "playing",
 | 
				
			||||||
 | 
					  paused = "paused",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,9 @@
 | 
				
			|||||||
 | 
					import remote from "@electron/remote";
 | 
				
			||||||
 | 
					import { ipcRenderer, shell } from "electron";
 | 
				
			||||||
 | 
					import globalEvents from "../../constants/globalEvents";
 | 
				
			||||||
 | 
					import { settings } from "../../constants/settings";
 | 
				
			||||||
 | 
					import { settingsStore } from "./../../scripts/settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let adBlock: HTMLInputElement,
 | 
					let adBlock: HTMLInputElement,
 | 
				
			||||||
  api: HTMLInputElement,
 | 
					  api: HTMLInputElement,
 | 
				
			||||||
  customCSS: HTMLInputElement,
 | 
					  customCSS: HTMLInputElement,
 | 
				
			||||||
@@ -18,42 +24,35 @@ let adBlock: HTMLInputElement,
 | 
				
			|||||||
  trayIcon: HTMLInputElement,
 | 
					  trayIcon: HTMLInputElement,
 | 
				
			||||||
  updateFrequency: HTMLInputElement;
 | 
					  updateFrequency: HTMLInputElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { store, settings } = require("../../scripts/settings");
 | 
					 | 
				
			||||||
const { ipcRenderer } = require("electron");
 | 
					 | 
				
			||||||
const globalEvents = require("../../constants/globalEvents");
 | 
					 | 
				
			||||||
const remote = require("@electron/remote");
 | 
					 | 
				
			||||||
const { app } = remote;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Sync the UI forms with the current settings
 | 
					 * Sync the UI forms with the current settings
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function refreshSettings() {
 | 
					function refreshSettings() {
 | 
				
			||||||
  adBlock.checked = store.get(settings.adBlock);
 | 
					  adBlock.checked = settingsStore.get(settings.adBlock);
 | 
				
			||||||
  api.checked = store.get(settings.api);
 | 
					  api.checked = settingsStore.get(settings.api);
 | 
				
			||||||
  customCSS.value = store.get(settings.customCSS);
 | 
					  customCSS.value = settingsStore.get(settings.customCSS);
 | 
				
			||||||
  disableBackgroundThrottle.checked = store.get(settings.disableBackgroundThrottle);
 | 
					  disableBackgroundThrottle.checked = settingsStore.get(settings.disableBackgroundThrottle);
 | 
				
			||||||
  disableHardwareMediaKeys.checked = store.get(settings.flags.disableHardwareMediaKeys);
 | 
					  disableHardwareMediaKeys.checked = settingsStore.get(settings.flags.disableHardwareMediaKeys);
 | 
				
			||||||
  enableCustomHotkeys.checked = store.get(settings.enableCustomHotkeys);
 | 
					  enableCustomHotkeys.checked = settingsStore.get(settings.enableCustomHotkeys);
 | 
				
			||||||
  enableDiscord.checked = store.get(settings.enableDiscord);
 | 
					  enableDiscord.checked = settingsStore.get(settings.enableDiscord);
 | 
				
			||||||
  gpuRasterization.checked = store.get(settings.flags.gpuRasterization);
 | 
					  gpuRasterization.checked = settingsStore.get(settings.flags.gpuRasterization);
 | 
				
			||||||
  menuBar.checked = store.get(settings.menuBar);
 | 
					  menuBar.checked = settingsStore.get(settings.menuBar);
 | 
				
			||||||
  minimizeOnClose.checked = store.get(settings.minimizeOnClose);
 | 
					  minimizeOnClose.checked = settingsStore.get(settings.minimizeOnClose);
 | 
				
			||||||
  mpris.checked = store.get(settings.mpris);
 | 
					  mpris.checked = settingsStore.get(settings.mpris);
 | 
				
			||||||
  notifications.checked = store.get(settings.notifications);
 | 
					  notifications.checked = settingsStore.get(settings.notifications);
 | 
				
			||||||
  playBackControl.checked = store.get(settings.playBackControl);
 | 
					  playBackControl.checked = settingsStore.get(settings.playBackControl);
 | 
				
			||||||
  port.value = store.get(settings.apiSettings.port);
 | 
					  port.value = settingsStore.get(settings.apiSettings.port);
 | 
				
			||||||
  singleInstance.checked = store.get(settings.singleInstance);
 | 
					  singleInstance.checked = settingsStore.get(settings.singleInstance);
 | 
				
			||||||
  skipArtists.checked = store.get(settings.skipArtists);
 | 
					  skipArtists.checked = settingsStore.get(settings.skipArtists);
 | 
				
			||||||
  skippedArtists.value = (store.get(settings.skippedArtists) as string[]).join("\n");
 | 
					  skippedArtists.value = settingsStore.get<string, string[]>(settings.skippedArtists).join("\n");
 | 
				
			||||||
  trayIcon.checked = store.get(settings.trayIcon);
 | 
					  trayIcon.checked = settingsStore.get(settings.trayIcon);
 | 
				
			||||||
  updateFrequency.value = store.get(settings.updateFrequency);
 | 
					  updateFrequency.value = settingsStore.get(settings.updateFrequency);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Open an url in the default browsers
 | 
					 * Open an url in the default browsers
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function openExternal(url: string) {
 | 
					function openExternal(url: string) {
 | 
				
			||||||
  const { shell } = require("electron");
 | 
					 | 
				
			||||||
  shell.openExternal(url);
 | 
					  shell.openExternal(url);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,8 +67,8 @@ function hide() {
 | 
				
			|||||||
 * Restart tidal-hifi after changes
 | 
					 * Restart tidal-hifi after changes
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function restart() {
 | 
					function restart() {
 | 
				
			||||||
  app.relaunch();
 | 
					  remote.app.relaunch();
 | 
				
			||||||
  app.exit();
 | 
					  remote.app.exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -91,9 +90,9 @@ window.addEventListener("DOMContentLoaded", () => {
 | 
				
			|||||||
  function addInputListener(source: HTMLInputElement, key: string) {
 | 
					  function addInputListener(source: HTMLInputElement, key: string) {
 | 
				
			||||||
    source.addEventListener("input", () => {
 | 
					    source.addEventListener("input", () => {
 | 
				
			||||||
      if (source.value === "on") {
 | 
					      if (source.value === "on") {
 | 
				
			||||||
        store.set(key, source.checked);
 | 
					        settingsStore.set(key, source.checked);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        store.set(key, source.value);
 | 
					        settingsStore.set(key, source.value);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      ipcRenderer.send(globalEvents.storeChanged);
 | 
					      ipcRenderer.send(globalEvents.storeChanged);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -101,7 +100,7 @@ window.addEventListener("DOMContentLoaded", () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  function addTextAreaListener(source: HTMLInputElement, key: string) {
 | 
					  function addTextAreaListener(source: HTMLInputElement, key: string) {
 | 
				
			||||||
    source.addEventListener("input", () => {
 | 
					    source.addEventListener("input", () => {
 | 
				
			||||||
      store.set(key, source.value.split("\n"));
 | 
					      settingsStore.set(key, source.value.split("\n"));
 | 
				
			||||||
      ipcRenderer.send(globalEvents.storeChanged);
 | 
					      ipcRenderer.send(globalEvents.storeChanged);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,15 @@
 | 
				
			|||||||
import { Notification, app, dialog } from "@electron/remote";
 | 
					import { Notification, app, dialog } from "@electron/remote";
 | 
				
			||||||
import { ipcRenderer } from "electron";
 | 
					import { ipcRenderer } from "electron";
 | 
				
			||||||
 | 
					import Player from "mpris-service";
 | 
				
			||||||
import globalEvents from "./constants/globalEvents";
 | 
					import globalEvents from "./constants/globalEvents";
 | 
				
			||||||
import { customCSS, skipArtists, updateFrequency } from "./constants/settings";
 | 
					import { settings } from "./constants/settings";
 | 
				
			||||||
import statuses from "./constants/statuses";
 | 
					import statuses from "./constants/statuses";
 | 
				
			||||||
import { Options } from "./models/options";
 | 
					import { Options } from "./models/options";
 | 
				
			||||||
import { downloadFile } from "./scripts/download";
 | 
					import { downloadFile } from "./scripts/download";
 | 
				
			||||||
import { addHotkey } from "./scripts/hotkeys";
 | 
					import { addHotkey } from "./scripts/hotkeys";
 | 
				
			||||||
import { settings, store } from "./scripts/settings";
 | 
					
 | 
				
			||||||
import { setTitle } from "./scripts/window-functions";
 | 
					import { setTitle } from "./scripts/window-functions";
 | 
				
			||||||
 | 
					import { settingsStore } from "./scripts/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 = "";
 | 
				
			||||||
@@ -146,7 +148,7 @@ const elements = {
 | 
				
			|||||||
function addCustomCss() {
 | 
					function addCustomCss() {
 | 
				
			||||||
  window.addEventListener("DOMContentLoaded", () => {
 | 
					  window.addEventListener("DOMContentLoaded", () => {
 | 
				
			||||||
    const style = document.createElement("style");
 | 
					    const style = document.createElement("style");
 | 
				
			||||||
    style.innerHTML = store.get(customCSS);
 | 
					    style.innerHTML = settingsStore.get(settings.customCSS);
 | 
				
			||||||
    document.head.appendChild(style);
 | 
					    document.head.appendChild(style);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -156,7 +158,7 @@ function addCustomCss() {
 | 
				
			|||||||
 * make sure it returns a number, if not use the default
 | 
					 * make sure it returns a number, if not use the default
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function getUpdateFrequency() {
 | 
					function getUpdateFrequency() {
 | 
				
			||||||
  const storeValue = store.get(updateFrequency) as number;
 | 
					  const storeValue = settingsStore.get(settings.updateFrequency) as number;
 | 
				
			||||||
  const defaultValue = 500;
 | 
					  const defaultValue = 500;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!isNaN(storeValue)) {
 | 
					  if (!isNaN(storeValue)) {
 | 
				
			||||||
@@ -185,7 +187,7 @@ function playPause() {
 | 
				
			|||||||
 * https://defkey.com/tidal-desktop-shortcuts
 | 
					 * https://defkey.com/tidal-desktop-shortcuts
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function addHotKeys() {
 | 
					function addHotKeys() {
 | 
				
			||||||
  if (store.get(settings.enableCustomHotkeys)) {
 | 
					  if (settingsStore.get(settings.enableCustomHotkeys)) {
 | 
				
			||||||
    addHotkey("Control+p", function () {
 | 
					    addHotkey("Control+p", function () {
 | 
				
			||||||
      elements.click("account").click("settings");
 | 
					      elements.click("account").click("settings");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -291,7 +293,7 @@ function addIPCEventListeners() {
 | 
				
			|||||||
 * Update the current status of tidal (e.g playing or paused)
 | 
					 * Update the current status of tidal (e.g playing or paused)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function getCurrentlyPlayingStatus() {
 | 
					function getCurrentlyPlayingStatus() {
 | 
				
			||||||
  let pause = elements.get("pause");
 | 
					  const pause = elements.get("pause");
 | 
				
			||||||
  let status = undefined;
 | 
					  let status = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // if pause button is visible tidal is playing
 | 
					  // if pause button is visible tidal is playing
 | 
				
			||||||
@@ -320,7 +322,7 @@ function convertDuration(duration: string) {
 | 
				
			|||||||
function updateMediaInfo(options: Options, notify: boolean) {
 | 
					function updateMediaInfo(options: Options, notify: boolean) {
 | 
				
			||||||
  if (options) {
 | 
					  if (options) {
 | 
				
			||||||
    ipcRenderer.send(globalEvents.updateInfo, options);
 | 
					    ipcRenderer.send(globalEvents.updateInfo, options);
 | 
				
			||||||
    if (store.get(settings.notifications) && notify) {
 | 
					    if (settingsStore.get(settings.notifications) && notify) {
 | 
				
			||||||
      new Notification({ title: options.title, body: options.artists, icon: options.icon }).show();
 | 
					      new Notification({ title: options.title, body: options.artists, icon: options.icon }).show();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (player) {
 | 
					    if (player) {
 | 
				
			||||||
@@ -430,23 +432,20 @@ setInterval(function () {
 | 
				
			|||||||
      // if the image can't be found on the page continue without it
 | 
					      // if the image can't be found on the page continue without it
 | 
				
			||||||
      resolve();
 | 
					      resolve();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }).then(
 | 
					  }).then(() => {
 | 
				
			||||||
    () => {
 | 
					    updateMediaInfo(options, titleOrArtistsChanged);
 | 
				
			||||||
      updateMediaInfo(options, titleOrArtistsChanged);
 | 
					    if (titleOrArtistsChanged) {
 | 
				
			||||||
      if (titleOrArtistsChanged) {
 | 
					      updateMediaSession(options);
 | 
				
			||||||
        updateMediaSession(options);
 | 
					    }
 | 
				
			||||||
      }
 | 
					  });
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    () => {}
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * automatically skip a song if the artists are found in the list of artists to skip
 | 
					   * automatically skip a song if the artists are found in the list of artists to skip
 | 
				
			||||||
   * @param {*} artists array of artists
 | 
					   * @param {*} artists array of artists
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  function skipArtistsIfFoundInSkippedArtistsList(artists: string[]) {
 | 
					  function skipArtistsIfFoundInSkippedArtistsList(artists: string[]) {
 | 
				
			||||||
    if (store.get(skipArtists)) {
 | 
					    if (settingsStore.get(settings.skipArtists)) {
 | 
				
			||||||
      const skippedArtists = store.get(settings.skippedArtists) as string[];
 | 
					      const skippedArtists = settingsStore.get<string, string[]>(settings.skippedArtists);
 | 
				
			||||||
      if (skippedArtists.length > 0) {
 | 
					      if (skippedArtists.length > 0) {
 | 
				
			||||||
        const artistsToSkip = skippedArtists.map((artist) => artist);
 | 
					        const artistsToSkip = skippedArtists.map((artist) => artist);
 | 
				
			||||||
        const artistNames = Object.values(artists).map((artist) => artist);
 | 
					        const artistNames = Object.values(artists).map((artist) => artist);
 | 
				
			||||||
@@ -459,9 +458,8 @@ setInterval(function () {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}, getUpdateFrequency());
 | 
					}, getUpdateFrequency());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (process.platform === "linux" && store.get(settings.mpris)) {
 | 
					if (process.platform === "linux" && settingsStore.get(settings.mpris)) {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    const Player = require("mpris-service");
 | 
					 | 
				
			||||||
    player = Player({
 | 
					    player = Player({
 | 
				
			||||||
      name: "tidal-hifi",
 | 
					      name: "tidal-hifi",
 | 
				
			||||||
      identity: "tidal-hifi",
 | 
					      identity: "tidal-hifi",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,103 +0,0 @@
 | 
				
			|||||||
const discordrpc = require("discord-rpc");
 | 
					 | 
				
			||||||
const { app, ipcMain } = require("electron");
 | 
					 | 
				
			||||||
const globalEvents = require("../constants/globalEvents");
 | 
					 | 
				
			||||||
const clientId = "833617820704440341";
 | 
					 | 
				
			||||||
const mediaInfoModule = require("./mediaInfo");
 | 
					 | 
				
			||||||
const discordModule = {
 | 
					 | 
				
			||||||
  rpc: {},
 | 
					 | 
				
			||||||
  unRPC: function () {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  initRPC: function () {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function timeToSeconds(timeArray) {
 | 
					 | 
				
			||||||
  let minutes = timeArray[0] * 1;
 | 
					 | 
				
			||||||
  let seconds = minutes * 60 + timeArray[1] * 1;
 | 
					 | 
				
			||||||
  return seconds;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let rpc;
 | 
					 | 
				
			||||||
const observer = (event, arg) => {
 | 
					 | 
				
			||||||
  if (mediaInfoModule.mediaInfo.status == "paused" && rpc) {
 | 
					 | 
				
			||||||
    rpc.setActivity(idleStatus);
 | 
					 | 
				
			||||||
  } else if (rpc) {
 | 
					 | 
				
			||||||
    const currentSeconds = timeToSeconds(mediaInfoModule.mediaInfo.current.split(":"));
 | 
					 | 
				
			||||||
    const durationSeconds = timeToSeconds(mediaInfoModule.mediaInfo.duration.split(":"));
 | 
					 | 
				
			||||||
    const date = new Date();
 | 
					 | 
				
			||||||
    const now = (date.getTime() / 1000) | 0;
 | 
					 | 
				
			||||||
    const remaining = date.setSeconds(date.getSeconds() + (durationSeconds - currentSeconds));
 | 
					 | 
				
			||||||
    if (mediaInfoModule.mediaInfo.url) {
 | 
					 | 
				
			||||||
      rpc.setActivity({
 | 
					 | 
				
			||||||
        ...idleStatus,
 | 
					 | 
				
			||||||
        ...{
 | 
					 | 
				
			||||||
          details: `Listening to ${mediaInfoModule.mediaInfo.title}`,
 | 
					 | 
				
			||||||
          state: mediaInfoModule.mediaInfo.artists
 | 
					 | 
				
			||||||
            ? mediaInfoModule.mediaInfo.artists
 | 
					 | 
				
			||||||
            : "unknown artist(s)",
 | 
					 | 
				
			||||||
          startTimestamp: parseInt(now),
 | 
					 | 
				
			||||||
          endTimestamp: parseInt(remaining),
 | 
					 | 
				
			||||||
          largeImageKey: mediaInfoModule.mediaInfo.image,
 | 
					 | 
				
			||||||
          largeImageText: mediaInfoModule.mediaInfo.album
 | 
					 | 
				
			||||||
            ? mediaInfoModule.mediaInfo.album
 | 
					 | 
				
			||||||
            : `${idleStatus.largeImageText}`,
 | 
					 | 
				
			||||||
          buttons: [{ label: "Play on Tidal", url: mediaInfoModule.mediaInfo.url }],
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      rpc.setActivity({
 | 
					 | 
				
			||||||
        ...idleStatus,
 | 
					 | 
				
			||||||
        ...{
 | 
					 | 
				
			||||||
          details: `Watching ${mediaInfoModule.mediaInfo.title}`,
 | 
					 | 
				
			||||||
          state: mediaInfoModule.mediaInfo.artists,
 | 
					 | 
				
			||||||
          startTimestamp: parseInt(now),
 | 
					 | 
				
			||||||
          endTimestamp: parseInt(remaining),
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const idleStatus = {
 | 
					 | 
				
			||||||
  details: `Browsing Tidal`,
 | 
					 | 
				
			||||||
  largeImageKey: "tidal-hifi-icon",
 | 
					 | 
				
			||||||
  largeImageText: `Tidal HiFi ${app.getVersion()}`,
 | 
					 | 
				
			||||||
  instance: false,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Set up the discord rpc and listen on globalEvents.updateInfo
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
discordModule.initRPC = function () {
 | 
					 | 
				
			||||||
  rpc = new discordrpc.Client({ transport: "ipc" });
 | 
					 | 
				
			||||||
  rpc.login({ clientId }).then(
 | 
					 | 
				
			||||||
    () => {
 | 
					 | 
				
			||||||
      discordModule.rpc = rpc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      rpc.on("ready", () => {
 | 
					 | 
				
			||||||
        rpc.setActivity(idleStatus);
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      ipcMain.on(globalEvents.updateInfo, observer);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    () => {
 | 
					 | 
				
			||||||
      console.error("Can't connect to Discord, is it running?");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Remove any RPC connection with discord and remove the event listener on globalEvents.updateInfo
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
discordModule.unRPC = function () {
 | 
					 | 
				
			||||||
  if (rpc) {
 | 
					 | 
				
			||||||
    rpc.clearActivity();
 | 
					 | 
				
			||||||
    rpc.destroy();
 | 
					 | 
				
			||||||
    rpc = false;
 | 
					 | 
				
			||||||
    discordModule.rpc = undefined;
 | 
					 | 
				
			||||||
    ipcMain.removeListener(globalEvents.updateInfo, observer);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = discordModule;
 | 
					 | 
				
			||||||
							
								
								
									
										88
									
								
								src/scripts/discord.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/scripts/discord.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					import { Client } from "discord-rpc";
 | 
				
			||||||
 | 
					import { app, ipcMain } from "electron";
 | 
				
			||||||
 | 
					import globalEvents from "../constants/globalEvents";
 | 
				
			||||||
 | 
					import { MediaStatus } from "../models/mediaStatus";
 | 
				
			||||||
 | 
					import { mediaInfo } from "./mediaInfo";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const clientId = "833617820704440341";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function timeToSeconds(timeArray: string[]) {
 | 
				
			||||||
 | 
					  const minutes = parseInt(timeArray[0]) * 1;
 | 
				
			||||||
 | 
					  const seconds = minutes * 60 + parseInt(timeArray[1]) * 1;
 | 
				
			||||||
 | 
					  return seconds;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export let rpc: Client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const observer = () => {
 | 
				
			||||||
 | 
					  if (mediaInfo.status == MediaStatus.paused && rpc) {
 | 
				
			||||||
 | 
					    rpc.setActivity(idleStatus);
 | 
				
			||||||
 | 
					  } else if (rpc) {
 | 
				
			||||||
 | 
					    const currentSeconds = timeToSeconds(mediaInfo.current.split(":"));
 | 
				
			||||||
 | 
					    const durationSeconds = timeToSeconds(mediaInfo.duration.split(":"));
 | 
				
			||||||
 | 
					    const date = new Date();
 | 
				
			||||||
 | 
					    const now = (date.getTime() / 1000) | 0;
 | 
				
			||||||
 | 
					    const remaining = date.setSeconds(date.getSeconds() + (durationSeconds - currentSeconds));
 | 
				
			||||||
 | 
					    if (mediaInfo.url) {
 | 
				
			||||||
 | 
					      rpc.setActivity({
 | 
				
			||||||
 | 
					        ...idleStatus,
 | 
				
			||||||
 | 
					        ...{
 | 
				
			||||||
 | 
					          details: `Listening to ${mediaInfo.title}`,
 | 
				
			||||||
 | 
					          state: mediaInfo.artists ? mediaInfo.artists : "unknown artist(s)",
 | 
				
			||||||
 | 
					          startTimestamp: now,
 | 
				
			||||||
 | 
					          endTimestamp: remaining,
 | 
				
			||||||
 | 
					          largeImageKey: mediaInfo.image,
 | 
				
			||||||
 | 
					          largeImageText: mediaInfo.album ? mediaInfo.album : `${idleStatus.largeImageText}`,
 | 
				
			||||||
 | 
					          buttons: [{ label: "Play on Tidal", url: mediaInfo.url }],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      rpc.setActivity({
 | 
				
			||||||
 | 
					        ...idleStatus,
 | 
				
			||||||
 | 
					        ...{
 | 
				
			||||||
 | 
					          details: `Watching ${mediaInfo.title}`,
 | 
				
			||||||
 | 
					          state: mediaInfo.artists,
 | 
				
			||||||
 | 
					          startTimestamp: now,
 | 
				
			||||||
 | 
					          endTimestamp: remaining,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const idleStatus = {
 | 
				
			||||||
 | 
					  details: `Browsing Tidal`,
 | 
				
			||||||
 | 
					  largeImageKey: "tidal-hifi-icon",
 | 
				
			||||||
 | 
					  largeImageText: `Tidal HiFi ${app.getVersion()}`,
 | 
				
			||||||
 | 
					  instance: false,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Set up the discord rpc and listen on globalEvents.updateInfo
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const initRPC = () => {
 | 
				
			||||||
 | 
					  rpc = new Client({ transport: "ipc" });
 | 
				
			||||||
 | 
					  rpc.login({ clientId }).then(
 | 
				
			||||||
 | 
					    () => {
 | 
				
			||||||
 | 
					      rpc.on("ready", () => {
 | 
				
			||||||
 | 
					        rpc.setActivity(idleStatus);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      ipcMain.on(globalEvents.updateInfo, observer);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    () => {
 | 
				
			||||||
 | 
					      console.error("Can't connect to Discord, is it running?");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Remove any RPC connection with discord and remove the event listener on globalEvents.updateInfo
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const unRPC = () => {
 | 
				
			||||||
 | 
					  if (rpc) {
 | 
				
			||||||
 | 
					    rpc.clearActivity();
 | 
				
			||||||
 | 
					    rpc.destroy();
 | 
				
			||||||
 | 
					    rpc = null;
 | 
				
			||||||
 | 
					    ipcMain.removeListener(globalEvents.updateInfo, observer);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
import { BrowserWindow } from "electron";
 | 
					import { BrowserWindow, dialog } from "electron";
 | 
				
			||||||
import express, { Response } from "express";
 | 
					import express, { Response } from "express";
 | 
				
			||||||
import fs from "fs";
 | 
					import fs from "fs";
 | 
				
			||||||
const { mediaInfo } = require("./mediaInfo");
 | 
					import globalEvents from "./../constants/globalEvents";
 | 
				
			||||||
const { store, settings } = require("./settings");
 | 
					import statuses from "./../constants/statuses";
 | 
				
			||||||
const globalEvents = require("./../constants/globalEvents");
 | 
					import { mediaInfo } from "./mediaInfo";
 | 
				
			||||||
const statuses = require("./../constants/statuses");
 | 
					import { settingsStore } from "./settings";
 | 
				
			||||||
 | 
					import { settings } from "../constants/settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Function to enable tidal-hifi's express api
 | 
					 * Function to enable tidal-hifi's express api
 | 
				
			||||||
@@ -37,7 +38,7 @@ export const startExpress = (mainWindow: BrowserWindow) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (store.get(settings.playBackControl)) {
 | 
					  if (settingsStore.get(settings.playBackControl)) {
 | 
				
			||||||
    expressApp.get("/play", (req, res) => handleGlobalEvent(res, globalEvents.play));
 | 
					    expressApp.get("/play", (req, res) => handleGlobalEvent(res, globalEvents.play));
 | 
				
			||||||
    expressApp.get("/pause", (req, res) => handleGlobalEvent(res, globalEvents.pause));
 | 
					    expressApp.get("/pause", (req, res) => handleGlobalEvent(res, globalEvents.pause));
 | 
				
			||||||
    expressApp.get("/next", (req, res) => handleGlobalEvent(res, globalEvents.next));
 | 
					    expressApp.get("/next", (req, res) => handleGlobalEvent(res, globalEvents.next));
 | 
				
			||||||
@@ -51,15 +52,15 @@ export const startExpress = (mainWindow: BrowserWindow) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let port = store.get(settings.apiSettings.port);
 | 
					  const port = settingsStore.get<string, number>(settings.apiSettings.port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const expressInstance = expressApp.listen(port, "127.0.0.1", () => {});
 | 
					  const expressInstance = expressApp.listen(port, "127.0.0.1");
 | 
				
			||||||
  expressInstance.on("error", function (e: { code: string }) {
 | 
					  expressInstance.on("error", function (e: { code: string }) {
 | 
				
			||||||
    let message = e.code;
 | 
					    let message = e.code;
 | 
				
			||||||
    if (e.code === "EADDRINUSE") {
 | 
					    if (e.code === "EADDRINUSE") {
 | 
				
			||||||
      message = `Port ${port} in use.`;
 | 
					      message = `Port ${port} in use.`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const { dialog } = require("electron");
 | 
					
 | 
				
			||||||
    dialog.showErrorBox("Api failed to start.", message);
 | 
					    dialog.showErrorBox("Api failed to start.", message);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,38 +0,0 @@
 | 
				
			|||||||
const statuses = require("./../constants/statuses");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const mediaInfo = {
 | 
					 | 
				
			||||||
  title: "",
 | 
					 | 
				
			||||||
  artists: "",
 | 
					 | 
				
			||||||
  album: "",
 | 
					 | 
				
			||||||
  icon: "",
 | 
					 | 
				
			||||||
  status: statuses.paused,
 | 
					 | 
				
			||||||
  url: "",
 | 
					 | 
				
			||||||
  current: "",
 | 
					 | 
				
			||||||
  duration: "",
 | 
					 | 
				
			||||||
  image: "tidal-hifi-icon",
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
const mediaInfoModule = {
 | 
					 | 
				
			||||||
  mediaInfo,
 | 
					 | 
				
			||||||
  update: function (arg) {
 | 
					 | 
				
			||||||
    mediaInfo.title = propOrDefault(arg.title);
 | 
					 | 
				
			||||||
    mediaInfo.artists = propOrDefault(arg.artists);
 | 
					 | 
				
			||||||
    mediaInfo.album = propOrDefault(arg.album);
 | 
					 | 
				
			||||||
    mediaInfo.icon = propOrDefault(arg.icon);
 | 
					 | 
				
			||||||
    mediaInfo.url = propOrDefault(arg.url);
 | 
					 | 
				
			||||||
    mediaInfo.status = propOrDefault(arg.status);
 | 
					 | 
				
			||||||
    mediaInfo.current = propOrDefault(arg.current);
 | 
					 | 
				
			||||||
    mediaInfo.duration = propOrDefault(arg.duration);
 | 
					 | 
				
			||||||
    mediaInfo.image = propOrDefault(arg.image);
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return the property or a default value
 | 
					 | 
				
			||||||
 * @param {*} prop property to check
 | 
					 | 
				
			||||||
 * @param {*} defaultValue defaults to ""
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function propOrDefault(prop, defaultValue = "") {
 | 
					 | 
				
			||||||
  return prop ? prop : defaultValue;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = mediaInfoModule;
 | 
					 | 
				
			||||||
							
								
								
									
										35
									
								
								src/scripts/mediaInfo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/scripts/mediaInfo.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					import { MediaInfo } from "../models/mediaInfo";
 | 
				
			||||||
 | 
					import statuses from "./../constants/statuses";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const mediaInfo = {
 | 
				
			||||||
 | 
					  title: "",
 | 
				
			||||||
 | 
					  artists: "",
 | 
				
			||||||
 | 
					  album: "",
 | 
				
			||||||
 | 
					  icon: "",
 | 
				
			||||||
 | 
					  status: statuses.paused,
 | 
				
			||||||
 | 
					  url: "",
 | 
				
			||||||
 | 
					  current: "",
 | 
				
			||||||
 | 
					  duration: "",
 | 
				
			||||||
 | 
					  image: "tidal-hifi-icon",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const updateMediaInfo = (arg: MediaInfo) => {
 | 
				
			||||||
 | 
					  mediaInfo.title = propOrDefault(arg.title);
 | 
				
			||||||
 | 
					  mediaInfo.artists = propOrDefault(arg.artists);
 | 
				
			||||||
 | 
					  mediaInfo.album = propOrDefault(arg.album);
 | 
				
			||||||
 | 
					  mediaInfo.icon = propOrDefault(arg.icon);
 | 
				
			||||||
 | 
					  mediaInfo.url = propOrDefault(arg.url);
 | 
				
			||||||
 | 
					  mediaInfo.status = propOrDefault(arg.status);
 | 
				
			||||||
 | 
					  mediaInfo.current = propOrDefault(arg.current);
 | 
				
			||||||
 | 
					  mediaInfo.duration = propOrDefault(arg.duration);
 | 
				
			||||||
 | 
					  mediaInfo.image = propOrDefault(arg.image);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the property or a default value
 | 
				
			||||||
 | 
					 * @param {*} prop property to check
 | 
				
			||||||
 | 
					 * @param {*} defaultValue defaults to ""
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function propOrDefault(prop: string, defaultValue = "") {
 | 
				
			||||||
 | 
					  return prop ? prop : defaultValue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
const Store = require("electron-store");
 | 
					import Store from "electron-store";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const settings = require("../constants/settings");
 | 
					import { settings } from "../constants/settings";
 | 
				
			||||||
const path = require("path");
 | 
					import path from "path";
 | 
				
			||||||
const { BrowserWindow } = require("electron");
 | 
					import { BrowserWindow } from "electron";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let settingsWindow;
 | 
					let settingsWindow: BrowserWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const store = new Store({
 | 
					export const settingsStore = new Store({
 | 
				
			||||||
  defaults: {
 | 
					  defaults: {
 | 
				
			||||||
    adBlock: false,
 | 
					    adBlock: false,
 | 
				
			||||||
    api: true,
 | 
					    api: true,
 | 
				
			||||||
@@ -46,12 +46,11 @@ const store = new Store({
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const settingsModule = {
 | 
					const settingsModule = {
 | 
				
			||||||
  store,
 | 
					  // settings,
 | 
				
			||||||
  settings,
 | 
					 | 
				
			||||||
  settingsWindow,
 | 
					  settingsWindow,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
settingsModule.createSettingsWindow = function () {
 | 
					export const createSettingsWindow = function () {
 | 
				
			||||||
  settingsWindow = new BrowserWindow({
 | 
					  settingsWindow = new BrowserWindow({
 | 
				
			||||||
    width: 700,
 | 
					    width: 700,
 | 
				
			||||||
    height: 600,
 | 
					    height: 600,
 | 
				
			||||||
@@ -67,7 +66,7 @@ settingsModule.createSettingsWindow = function () {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  settingsWindow.on("close", (event) => {
 | 
					  settingsWindow.on("close", (event: any) => {
 | 
				
			||||||
    if (settingsWindow != null) {
 | 
					    if (settingsWindow != null) {
 | 
				
			||||||
      event.preventDefault();
 | 
					      event.preventDefault();
 | 
				
			||||||
      settingsWindow.hide();
 | 
					      settingsWindow.hide();
 | 
				
			||||||
@@ -79,19 +78,17 @@ settingsModule.createSettingsWindow = function () {
 | 
				
			|||||||
  settingsModule.settingsWindow = settingsWindow;
 | 
					  settingsModule.settingsWindow = settingsWindow;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
settingsModule.showSettingsWindow = function (tab = "general") {
 | 
					export const showSettingsWindow = function (tab = "general") {
 | 
				
			||||||
  settingsWindow.webContents.send("goToTab", tab);
 | 
					  settingsWindow.webContents.send("goToTab", tab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // refresh data just before showing the window
 | 
					  // refresh data just before showing the window
 | 
				
			||||||
  settingsWindow.webContents.send("refreshData");
 | 
					  settingsWindow.webContents.send("refreshData");
 | 
				
			||||||
  settingsWindow.show();
 | 
					  settingsWindow.show();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
settingsModule.hideSettingsWindow = function () {
 | 
					export const hideSettingsWindow = function () {
 | 
				
			||||||
  settingsWindow.hide();
 | 
					  settingsWindow.hide();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
settingsModule.closeSettingsWindow = function () {
 | 
					export const closeSettingsWindow = function () {
 | 
				
			||||||
  settingsWindow = null;
 | 
					  settingsWindow = null;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = settingsModule;
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user