2020-11-06 16:49:52 +01:00
|
|
|
const {app, BrowserWindow, ipcMain, Tray, Menu, session, dialog, shell, nativeTheme} = require('electron');
|
2020-08-28 23:06:19 +02:00
|
|
|
const {createServer} = require('./src/server');
|
|
|
|
const path = require('path');
|
2020-11-08 18:01:02 +01:00
|
|
|
const arg = require('arg');
|
|
|
|
const { exit } = require('process');
|
|
|
|
const packageJson = require('./package.json');
|
|
|
|
const chalk = require('chalk');
|
|
|
|
const {Settings} = require('./src/settings');
|
|
|
|
const fs = require('fs');
|
2020-08-28 23:06:19 +02:00
|
|
|
|
|
|
|
let win;
|
|
|
|
let tray;
|
|
|
|
let settings;
|
|
|
|
|
|
|
|
let shouldExit = false;
|
2020-09-28 18:17:23 +02:00
|
|
|
let playing = false;
|
2020-08-28 23:06:19 +02:00
|
|
|
|
2020-11-08 18:01:02 +01:00
|
|
|
//Arguments
|
|
|
|
const args = arg({
|
|
|
|
'--server': Boolean,
|
|
|
|
'--host': String,
|
|
|
|
'--port': Number,
|
|
|
|
'--help': Boolean,
|
|
|
|
'--settings': Boolean,
|
|
|
|
'--reset-settings': Boolean,
|
|
|
|
'--reset-downloads': Boolean,
|
|
|
|
'--log': Boolean,
|
|
|
|
|
|
|
|
'-S': '--server',
|
|
|
|
'-H': '--host',
|
|
|
|
'-h': '--help',
|
|
|
|
'-p': '--port'
|
|
|
|
}, {argv: process.argv.slice(1)});
|
|
|
|
|
|
|
|
executeCli();
|
|
|
|
|
2020-08-28 23:06:19 +02:00
|
|
|
//Get path to asset
|
|
|
|
function assetPath(a) {
|
|
|
|
return path.join(__dirname, 'assets', a);
|
|
|
|
}
|
|
|
|
|
2020-11-08 18:01:02 +01:00
|
|
|
//Execute actions by parameters
|
|
|
|
function executeCli() {
|
|
|
|
if (args['--help']) {
|
|
|
|
console.log(`
|
|
|
|
${chalk.bold.blue('Freezer PC')} ${chalk.bold(`v${packageJson.version}`)} by exttex
|
|
|
|
|
|
|
|
${chalk.bold('USAGE:')}
|
|
|
|
--help, -h Prints this and exits
|
|
|
|
--server, -S Starts in server mode
|
|
|
|
--host, -H Override host (default: 127.0.0.1)
|
|
|
|
--port, -p Override port (default: 10069)
|
|
|
|
|
|
|
|
${chalk.bold('TOOLS:')}
|
|
|
|
--settings Prints current settings and exits
|
|
|
|
--log Prints server log and exits
|
|
|
|
--reset-settings Reset settings to default
|
|
|
|
--reset-downloads Delete downloads cache and database
|
|
|
|
`);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
//Print settings and exit
|
|
|
|
if (args["--settings"]) {
|
|
|
|
let settings = new Settings();
|
|
|
|
settings.load();
|
|
|
|
console.log(JSON.stringify(settings, null, 2));
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if (args["--reset-settings"]) {
|
|
|
|
fs.unlinkSync(Settings.getPath());
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
//Delete downloads db and temp
|
|
|
|
if (args['--reset-downloads']) {
|
|
|
|
fs.unlinkSync(Settings.getDownloadsDB());
|
|
|
|
fs.rmdirSync(Settings.getTempDownloads(), {recursive: true});
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
//Show log
|
|
|
|
if (args['--log']) {
|
|
|
|
let p = path.join(Settings.getDir(), "freezer-server.log");
|
|
|
|
console.log(fs.readFileSync(p, {encoding: 'utf-8'}).toString());
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-01 14:30:00 +02:00
|
|
|
async function startServer() {
|
2020-11-08 18:01:02 +01:00
|
|
|
|
|
|
|
//Override settings
|
|
|
|
let override = {};
|
|
|
|
if (args["--host"])
|
|
|
|
override['host'] = args["--host"];
|
|
|
|
if (args["--port"])
|
|
|
|
override['port'] = args["--port"];
|
|
|
|
|
2020-11-03 10:11:37 +01:00
|
|
|
settings = await createServer(true, () => {
|
2020-08-28 23:06:19 +02:00
|
|
|
//Server error
|
|
|
|
shouldExit = true;
|
|
|
|
if (win) win.close();
|
|
|
|
|
|
|
|
dialog.showMessageBoxSync({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Server error',
|
|
|
|
message: 'Server error occured, Freezer is probably already running!',
|
|
|
|
buttons: ['Close']
|
|
|
|
});
|
2020-11-08 18:01:02 +01:00
|
|
|
}, override);
|
2020-10-01 14:30:00 +02:00
|
|
|
}
|
2020-08-28 23:06:19 +02:00
|
|
|
|
2020-10-01 14:30:00 +02:00
|
|
|
async function createWindow() {
|
2020-08-28 23:06:19 +02:00
|
|
|
//Create window
|
|
|
|
win = new BrowserWindow({
|
|
|
|
width: settings.width,
|
|
|
|
darkTheme: true,
|
|
|
|
height: settings.height,
|
|
|
|
minWidth: 620,
|
|
|
|
minHeight: 600,
|
|
|
|
resizable: true,
|
|
|
|
autoHideMenuBar: true,
|
2020-11-06 16:49:52 +01:00
|
|
|
frame: false,
|
2020-08-28 23:06:19 +02:00
|
|
|
icon: assetPath("icon.png"),
|
|
|
|
title: 'Freezer',
|
|
|
|
webPreferences: {
|
|
|
|
enableRemoteModule: true,
|
|
|
|
nodeIntegration: true,
|
|
|
|
devTools: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
win.loadURL(`http://localhost:${settings.port}`);
|
|
|
|
|
|
|
|
//Minimize to tray
|
|
|
|
win.on('minimize', (event) => {
|
|
|
|
if (settings.minimizeToTray) {
|
|
|
|
event.preventDefault();
|
|
|
|
win.hide();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
//On close
|
|
|
|
win.on('close', async (event) => {
|
|
|
|
if (shouldExit) {
|
|
|
|
win = null;
|
|
|
|
tray = null;
|
2020-10-01 14:30:00 +02:00
|
|
|
app.quit();
|
2020-08-28 23:06:19 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Normal exit
|
|
|
|
if (!settings || !settings.arl || settings.arl == '' || settings.closeOnExit) {
|
|
|
|
win.webContents.send('onExit');
|
|
|
|
shouldExit = true;
|
|
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
win.hide();
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2020-09-28 18:17:23 +02:00
|
|
|
//Thumbnail Toolbars
|
|
|
|
setThumbarButtons();
|
2020-08-28 23:06:19 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:20:49 +01:00
|
|
|
//Single instance
|
|
|
|
const singleInstanceLock = app.requestSingleInstanceLock();
|
|
|
|
if (!singleInstanceLock) {
|
|
|
|
app.quit();
|
|
|
|
} else {
|
|
|
|
app.on('second-instance', () => {
|
|
|
|
if (win) {
|
|
|
|
if (!win.visible) win.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-08-28 23:06:19 +02:00
|
|
|
//Create window
|
|
|
|
app.on('ready', async () => {
|
2020-10-01 14:30:00 +02:00
|
|
|
await startServer();
|
2020-11-08 18:01:02 +01:00
|
|
|
//Server mode
|
|
|
|
if (args['--server']) return;
|
2020-08-28 23:06:19 +02:00
|
|
|
createWindow();
|
|
|
|
|
2020-09-28 18:17:23 +02:00
|
|
|
//Create Tray
|
2020-11-06 18:10:42 +01:00
|
|
|
if (settings.forceWhiteTrayIcon || nativeTheme.shouldUseDarkColors)
|
2020-11-06 16:49:52 +01:00
|
|
|
tray = new Tray(assetPath("icon-taskbar-white.png"));
|
|
|
|
else
|
|
|
|
tray = new Tray(assetPath("icon-taskbar-black.png"));
|
2020-10-01 14:30:00 +02:00
|
|
|
tray.on('double-click', () => restoreWindow());
|
|
|
|
tray.on('click', () => restoreWindow());
|
2020-08-28 23:06:19 +02:00
|
|
|
|
2020-09-28 18:17:23 +02:00
|
|
|
setTray();
|
|
|
|
});
|
|
|
|
|
2020-10-01 14:30:00 +02:00
|
|
|
//Restore or create new window
|
|
|
|
function restoreWindow() {
|
2020-11-03 10:11:37 +01:00
|
|
|
if (win) {
|
|
|
|
win.show();
|
|
|
|
setThumbarButtons();
|
|
|
|
return;
|
|
|
|
}
|
2020-10-01 14:30:00 +02:00
|
|
|
createWindow();
|
|
|
|
}
|
|
|
|
|
2020-09-28 18:17:23 +02:00
|
|
|
//Update tray context menu
|
|
|
|
function setTray() {
|
2020-08-28 23:06:19 +02:00
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
|
|
|
{
|
|
|
|
label: 'Restore',
|
|
|
|
type: 'normal',
|
2020-10-01 14:30:00 +02:00
|
|
|
click: () => restoreWindow()
|
2020-08-28 23:06:19 +02:00
|
|
|
},
|
2020-09-28 18:17:23 +02:00
|
|
|
playing ?
|
2020-08-28 23:06:19 +02:00
|
|
|
{
|
2020-09-28 18:17:23 +02:00
|
|
|
label: 'Pause',
|
|
|
|
type: 'normal',
|
|
|
|
click: () => win.webContents.send('togglePlayback')
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
label: 'Play',
|
2020-08-28 23:06:19 +02:00
|
|
|
type: 'normal',
|
|
|
|
click: () => win.webContents.send('togglePlayback')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Next',
|
|
|
|
type: 'normal',
|
|
|
|
click: () => win.webContents.send('skipNext')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Previous',
|
|
|
|
type: 'normal',
|
|
|
|
click: () => win.webContents.send('skipPrev')
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Exit',
|
|
|
|
type: 'normal',
|
|
|
|
click: () => {
|
|
|
|
shouldExit = true;
|
2020-10-01 14:30:00 +02:00
|
|
|
if (!win) return app.quit();
|
2020-08-28 23:06:19 +02:00
|
|
|
win.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
tray.setContextMenu(contextMenu);
|
2020-09-28 18:17:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Update Thumbnail Toolbars (Windows)
|
|
|
|
function setThumbarButtons() {
|
|
|
|
win.setThumbarButtons([
|
|
|
|
{
|
|
|
|
tooltip: 'Skip Previous',
|
|
|
|
icon: assetPath('skip-previous.png'),
|
|
|
|
click: () => win.webContents.send('skipPrev')
|
|
|
|
},
|
|
|
|
//Play/Pause
|
|
|
|
playing ?
|
|
|
|
{
|
|
|
|
tooltip: 'Pause',
|
|
|
|
icon: assetPath('pause.png'),
|
|
|
|
click: () => win.webContents.send('togglePlayback')
|
|
|
|
} :
|
|
|
|
{
|
|
|
|
tooltip: 'Play',
|
|
|
|
icon: assetPath('play.png'),
|
|
|
|
click: () => win.webContents.send('togglePlayback')
|
|
|
|
},
|
|
|
|
//Skip next
|
|
|
|
{
|
|
|
|
tooltip: 'Skip Next',
|
|
|
|
icon: assetPath('skip-next.png'),
|
|
|
|
click: () => win.webContents.send('skipNext')
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2020-11-08 18:01:02 +01:00
|
|
|
|
|
|
|
//[] button
|
|
|
|
ipcMain.on('maximize', () => {
|
|
|
|
win.isMaximized() ? win.unmaximize() : win.maximize();
|
|
|
|
});
|
|
|
|
|
2020-11-06 16:49:52 +01:00
|
|
|
//_ button in ui
|
|
|
|
ipcMain.on('minimize', () => {
|
|
|
|
win.minimize();
|
|
|
|
});
|
|
|
|
|
|
|
|
//X button in ui
|
|
|
|
ipcMain.on('close', () => {
|
|
|
|
win.close();
|
|
|
|
});
|
|
|
|
|
2020-11-03 10:11:37 +01:00
|
|
|
ipcMain.on('openUrl', (event, args) => {
|
|
|
|
shell.openExternal(args);
|
|
|
|
});
|
|
|
|
|
2020-09-28 18:17:23 +02:00
|
|
|
//Playing state change from UI
|
|
|
|
ipcMain.on('playing', (event, args) => {
|
|
|
|
playing = args;
|
|
|
|
setThumbarButtons();
|
|
|
|
setTray();
|
2020-08-28 23:06:19 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
//Update settings from ui
|
|
|
|
ipcMain.on('updateSettings', (event, args) => {
|
|
|
|
Object.assign(settings, args);
|
|
|
|
});
|
|
|
|
|
|
|
|
//onExit callback
|
2020-11-03 10:11:37 +01:00
|
|
|
ipcMain.on('onExit', () => {
|
2020-08-28 23:06:19 +02:00
|
|
|
shouldExit = true;
|
|
|
|
win.close();
|
|
|
|
});
|
|
|
|
|
|
|
|
//Open downloads directory
|
2020-11-03 10:11:37 +01:00
|
|
|
ipcMain.on('openDownloadsDir', async () => {
|
2020-08-28 23:06:19 +02:00
|
|
|
if ((await shell.openPath(settings.downloadsPath)) == "") return;
|
|
|
|
shell.showItemInFolder(settings.downloadsPath);
|
|
|
|
});
|
|
|
|
|
|
|
|
//Download path picker
|
|
|
|
ipcMain.on('selectDownloadPath', async (event) => {
|
|
|
|
let res = await dialog.showOpenDialog({
|
|
|
|
title: 'Downloads folder',
|
|
|
|
properties: ['openDirectory', 'promptToCreate'],
|
|
|
|
});
|
|
|
|
if (!res.canceled && res.filePaths.length > 0) {
|
|
|
|
event.reply('selectDownloadPath', res.filePaths[0]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
//Login using browser
|
|
|
|
ipcMain.on('browserLogin', async (event) => {
|
|
|
|
//Initial clean
|
|
|
|
session.defaultSession.clearStorageData();
|
|
|
|
|
|
|
|
let lwin = new BrowserWindow({
|
|
|
|
width: 800,
|
|
|
|
height: 600,
|
|
|
|
icon: assetPath('icon.png'),
|
|
|
|
title: "Deezer Login",
|
|
|
|
resizable: true,
|
|
|
|
autoHideMenuBar: true,
|
|
|
|
webPreferences: {
|
|
|
|
nodeIntegration: false
|
|
|
|
}
|
|
|
|
});
|
|
|
|
lwin.loadURL('https://deezer.com/login');
|
|
|
|
|
|
|
|
let arl = await new Promise((res) => {
|
|
|
|
lwin.webContents.on('did-navigate', async () => {
|
|
|
|
let arlCookie = await session.defaultSession.cookies.get({
|
|
|
|
name: "arl"
|
|
|
|
});
|
|
|
|
if (arlCookie.length > 0) {
|
|
|
|
res(arlCookie[0].value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
lwin.close();
|
|
|
|
lwin = null;
|
|
|
|
//Delete deezer junk
|
|
|
|
session.defaultSession.clearStorageData();
|
|
|
|
|
|
|
|
event.reply('browserLogin', arl);
|
|
|
|
});
|