2020-01-03 15:01:15 +01:00
|
|
|
import fs from "fs";
|
|
|
|
import path from "path";
|
2020-05-21 07:38:44 +02:00
|
|
|
import SingleInstance from "single-instance";
|
2020-05-19 11:46:34 +02:00
|
|
|
import {app, BrowserWindow, dialog, ipcMain, Menu, shell, Tray} from "electron";
|
2020-01-03 15:01:15 +01:00
|
|
|
|
2020-01-10 15:02:21 +01:00
|
|
|
import Meta from "./Meta";
|
2020-01-03 15:01:15 +01:00
|
|
|
import Config from "./Config";
|
2020-01-04 15:20:02 +01:00
|
|
|
import Service from "./Service";
|
2020-05-19 10:54:00 +02:00
|
|
|
import Updater from "./Updater";
|
2020-05-21 07:38:44 +02:00
|
|
|
import Event = Electron.Event;
|
2019-10-13 22:59:28 +02:00
|
|
|
|
|
|
|
const resourcesDir = path.resolve(__dirname, '../resources');
|
2020-01-03 15:01:15 +01:00
|
|
|
const iconPath = path.resolve(resourcesDir, 'logo.png');
|
2019-10-13 22:59:28 +02:00
|
|
|
|
|
|
|
const config = new Config();
|
2020-05-19 10:54:00 +02:00
|
|
|
const updater = new Updater();
|
2019-10-13 22:59:28 +02:00
|
|
|
|
2020-01-10 15:02:21 +01:00
|
|
|
const devMode = Meta.isDevMode();
|
2020-01-03 13:01:50 +01:00
|
|
|
|
2020-01-04 15:20:02 +01:00
|
|
|
// Load icons
|
|
|
|
const brandIcons = listIcons('brands');
|
|
|
|
const solidIcons = listIcons('solid');
|
|
|
|
|
2019-10-13 22:59:28 +02:00
|
|
|
let selectedService = 0;
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
let tray: Tray;
|
|
|
|
let window: BrowserWindow | null;
|
|
|
|
let serviceSettingsWindow: BrowserWindow | null, settingsWindow: BrowserWindow | null;
|
2019-10-13 22:59:28 +02:00
|
|
|
|
2020-01-03 13:01:50 +01:00
|
|
|
function toggleMainWindow() {
|
|
|
|
if (window != null) {
|
|
|
|
if (!window.isFocused()) {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Showing main window');
|
2020-01-03 13:01:50 +01:00
|
|
|
window.show();
|
|
|
|
} else {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Hiding main window');
|
2020-01-03 13:01:50 +01:00
|
|
|
window.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-18 15:14:13 +02:00
|
|
|
async function createWindow() {
|
|
|
|
// Check for updates
|
2020-05-19 11:46:34 +02:00
|
|
|
updater.checkForUpdates((available, updateInfo) => {
|
|
|
|
if (available && updateInfo.version !== config.updateCheckSkip) {
|
2020-05-21 07:38:44 +02:00
|
|
|
dialog.showMessageBox(window!, {
|
2020-05-19 11:46:34 +02:00
|
|
|
message: `Version ${updateInfo.version} of tabs is available. Do you wish to download this update?`,
|
|
|
|
buttons: [
|
|
|
|
'Cancel',
|
|
|
|
'Download',
|
|
|
|
],
|
|
|
|
checkboxChecked: false,
|
|
|
|
checkboxLabel: `Don't remind me for this version`,
|
|
|
|
cancelId: 0,
|
|
|
|
defaultId: 1,
|
|
|
|
type: 'question'
|
|
|
|
}).then(e => {
|
|
|
|
if (e.checkboxChecked) {
|
|
|
|
console.log('Skipping update check for version', updateInfo.version);
|
|
|
|
config.updateCheckSkip = updateInfo.version;
|
|
|
|
config.save();
|
|
|
|
}
|
|
|
|
if (e.response === 1) {
|
|
|
|
return shell.openExternal(`https://github.com/ArisuOngaku/tabs/releases/download/v${updateInfo.version}/${updateInfo.path}`);
|
|
|
|
}
|
|
|
|
}).catch(console.error);
|
|
|
|
}
|
|
|
|
});
|
2020-04-18 14:54:32 +02:00
|
|
|
|
2020-01-03 13:01:50 +01:00
|
|
|
// System tray
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Loading system Tray');
|
2020-01-03 15:01:15 +01:00
|
|
|
tray = new Tray(iconPath);
|
2020-01-03 13:01:50 +01:00
|
|
|
tray.setToolTip('Tabs');
|
|
|
|
tray.setContextMenu(Menu.buildFromTemplate([
|
|
|
|
{label: 'Tabs', enabled: false},
|
2020-05-21 07:38:44 +02:00
|
|
|
{label: 'Open Tabs', click: () => window!.show()},
|
2020-01-03 13:01:50 +01:00
|
|
|
{type: 'separator'},
|
|
|
|
{label: 'Quit', role: 'quit'}
|
|
|
|
]));
|
|
|
|
tray.on('click', () => toggleMainWindow());
|
|
|
|
|
2019-10-13 22:59:28 +02:00
|
|
|
// Create the browser window.
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Creating main window');
|
2019-10-13 22:59:28 +02:00
|
|
|
window = new BrowserWindow({
|
|
|
|
webPreferences: {
|
|
|
|
nodeIntegration: true,
|
|
|
|
enableRemoteModule: true,
|
|
|
|
webviewTag: true,
|
|
|
|
},
|
|
|
|
autoHideMenuBar: true,
|
2020-01-03 15:01:15 +01:00
|
|
|
icon: iconPath,
|
2020-01-12 13:29:24 +01:00
|
|
|
title: Meta.title,
|
2019-10-13 22:59:28 +02:00
|
|
|
});
|
|
|
|
window.maximize();
|
|
|
|
window.on('closed', () => {
|
|
|
|
window = null;
|
|
|
|
});
|
|
|
|
|
2020-01-03 13:01:50 +01:00
|
|
|
if (devMode) {
|
2019-10-13 22:59:28 +02:00
|
|
|
window.webContents.openDevTools({
|
|
|
|
mode: 'right'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-01-03 22:47:10 +01:00
|
|
|
// Open external links in default OS browser
|
|
|
|
app.on('web-contents-created', (e, contents) => {
|
|
|
|
if (contents.getType() === 'webview') {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Setting external links to open in default OS browser');
|
2020-01-03 22:47:10 +01:00
|
|
|
contents.on('new-window', (e, url) => {
|
|
|
|
e.preventDefault();
|
2020-04-01 09:24:44 +02:00
|
|
|
if (url.startsWith('https://')) {
|
|
|
|
shell.openExternal(url);
|
|
|
|
}
|
2020-01-03 22:47:10 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2019-10-13 22:59:28 +02:00
|
|
|
|
2020-01-04 15:56:37 +01:00
|
|
|
// Sync data
|
2020-01-04 15:20:02 +01:00
|
|
|
window.webContents.on('dom-ready', sendData);
|
2019-10-13 22:59:28 +02:00
|
|
|
|
|
|
|
// Load navigation view
|
|
|
|
window.loadFile(path.resolve(resourcesDir, 'index.html'))
|
|
|
|
.catch(console.error);
|
|
|
|
|
|
|
|
// Load active service
|
|
|
|
ipcMain.on('setActiveService', (event, index) => {
|
|
|
|
setActiveService(index);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Set a service's favicon
|
|
|
|
ipcMain.on('setServiceFavicon', (event, index, favicon) => {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Setting service', index, 'favicon', favicon);
|
2019-10-13 22:59:28 +02:00
|
|
|
config.services[index].favicon = favicon;
|
|
|
|
config.save();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Open add service window
|
2020-01-04 15:20:02 +01:00
|
|
|
ipcMain.on('openServiceSettings', (e, serviceId) => {
|
|
|
|
if (!serviceSettingsWindow) {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Opening service settings', serviceId);
|
2020-01-04 15:20:02 +01:00
|
|
|
serviceSettingsWindow = new BrowserWindow({
|
2020-01-03 13:01:50 +01:00
|
|
|
webPreferences: {
|
|
|
|
nodeIntegration: true,
|
|
|
|
enableRemoteModule: true,
|
|
|
|
webviewTag: true,
|
|
|
|
},
|
2020-05-21 07:38:44 +02:00
|
|
|
parent: window!,
|
2019-10-13 22:59:28 +02:00
|
|
|
modal: true,
|
|
|
|
autoHideMenuBar: true,
|
2020-01-04 15:20:02 +01:00
|
|
|
height: 850,
|
2019-10-13 22:59:28 +02:00
|
|
|
});
|
2020-01-04 15:20:02 +01:00
|
|
|
serviceSettingsWindow.on('close', () => {
|
|
|
|
serviceSettingsWindow = null;
|
2019-10-13 22:59:28 +02:00
|
|
|
});
|
2020-01-03 13:01:50 +01:00
|
|
|
if (devMode) {
|
2020-01-04 15:20:02 +01:00
|
|
|
serviceSettingsWindow.webContents.openDevTools({
|
2020-01-03 13:01:50 +01:00
|
|
|
mode: 'right'
|
|
|
|
});
|
|
|
|
}
|
2020-05-21 07:38:44 +02:00
|
|
|
let syncListener: () => void;
|
2020-01-07 12:52:41 +01:00
|
|
|
ipcMain.on('sync-settings', syncListener = () => {
|
2020-05-21 07:38:44 +02:00
|
|
|
serviceSettingsWindow!.webContents.send('syncIcons', brandIcons, solidIcons);
|
|
|
|
serviceSettingsWindow!.webContents.send('loadService', serviceId, config.services[serviceId]);
|
2020-01-03 15:01:15 +01:00
|
|
|
});
|
2020-01-07 12:52:41 +01:00
|
|
|
serviceSettingsWindow.on('close', () => {
|
|
|
|
ipcMain.removeListener('sync-settings', syncListener);
|
|
|
|
});
|
2020-01-04 15:20:02 +01:00
|
|
|
serviceSettingsWindow.loadFile(path.resolve(resourcesDir, 'service-settings.html'))
|
2019-10-13 22:59:28 +02:00
|
|
|
.catch(console.error);
|
|
|
|
}
|
|
|
|
});
|
2020-01-04 15:20:02 +01:00
|
|
|
|
|
|
|
ipcMain.on('saveService', (e, id, data) => {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Saving service', id, data);
|
2020-01-04 15:20:02 +01:00
|
|
|
const newService = new Service(data);
|
|
|
|
if (typeof id === 'number') {
|
|
|
|
config.services[id] = newService;
|
|
|
|
} else {
|
|
|
|
config.services.push(newService);
|
2020-03-06 14:32:14 +01:00
|
|
|
id = config.services.indexOf(newService);
|
2020-01-04 15:20:02 +01:00
|
|
|
}
|
|
|
|
config.save();
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
window!.webContents.send('updateService', id, newService);
|
2020-01-04 15:20:02 +01:00
|
|
|
});
|
2020-01-04 15:49:23 +01:00
|
|
|
|
|
|
|
ipcMain.on('deleteService', (e, id) => {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Deleting service', id);
|
2020-01-04 15:49:23 +01:00
|
|
|
delete config.services[id];
|
|
|
|
config.save();
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
window!.webContents.send('deleteService', id);
|
2020-01-04 15:49:23 +01:00
|
|
|
});
|
2020-01-04 15:56:37 +01:00
|
|
|
|
2020-01-21 13:03:32 +01:00
|
|
|
ipcMain.on('reorderService', (e, serviceId, targetId) => {
|
|
|
|
console.log('Reordering services', serviceId, targetId);
|
|
|
|
|
|
|
|
const oldServices = config.services;
|
|
|
|
config.services = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < targetId; i++) {
|
|
|
|
if (i !== serviceId) {
|
|
|
|
config.services.push(oldServices[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
config.services.push(oldServices[serviceId]);
|
|
|
|
for (let i = targetId; i < oldServices.length; i++) {
|
|
|
|
if (i !== serviceId) {
|
|
|
|
config.services.push(oldServices[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
e.reply('reorderService', serviceId, targetId);
|
2020-01-21 13:06:59 +01:00
|
|
|
config.save();
|
2020-01-21 13:03:32 +01:00
|
|
|
});
|
|
|
|
|
2020-04-01 13:39:20 +02:00
|
|
|
ipcMain.on('updateServicePermissions', (e, serviceId, permissions) => {
|
|
|
|
config.services[serviceId].permissions = permissions;
|
|
|
|
config.save();
|
|
|
|
});
|
|
|
|
|
2020-01-12 13:29:24 +01:00
|
|
|
ipcMain.on('updateWindowTitle', (event, serviceId, viewTitle) => {
|
|
|
|
if (serviceId === null) {
|
2020-05-21 07:38:44 +02:00
|
|
|
window!.setTitle(Meta.title);
|
2020-01-12 13:29:24 +01:00
|
|
|
} else {
|
|
|
|
const service = config.services[serviceId];
|
2020-05-21 07:38:44 +02:00
|
|
|
window!.setTitle(Meta.getTitleForService(service, viewTitle));
|
2020-01-12 13:29:24 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-05-19 10:54:00 +02:00
|
|
|
// Open add service window
|
|
|
|
ipcMain.on('openSettings', (e) => {
|
|
|
|
if (!settingsWindow) {
|
|
|
|
console.log('Opening settings');
|
|
|
|
settingsWindow = new BrowserWindow({
|
|
|
|
webPreferences: {
|
|
|
|
nodeIntegration: true,
|
|
|
|
enableRemoteModule: true,
|
|
|
|
webviewTag: true,
|
|
|
|
},
|
2020-05-21 07:38:44 +02:00
|
|
|
parent: window!,
|
2020-05-19 10:54:00 +02:00
|
|
|
modal: true,
|
|
|
|
autoHideMenuBar: true,
|
|
|
|
height: 850,
|
|
|
|
});
|
|
|
|
settingsWindow.on('close', () => {
|
|
|
|
settingsWindow = null;
|
|
|
|
});
|
|
|
|
if (devMode) {
|
|
|
|
settingsWindow.webContents.openDevTools({
|
|
|
|
mode: 'right'
|
|
|
|
});
|
|
|
|
}
|
2020-05-21 07:38:44 +02:00
|
|
|
let syncListener: () => void;
|
2020-05-19 10:54:00 +02:00
|
|
|
ipcMain.on('syncSettings', syncListener = () => {
|
2020-05-21 07:38:44 +02:00
|
|
|
settingsWindow!.webContents.send('current-version', updater.getCurrentVersion());
|
|
|
|
settingsWindow!.webContents.send('config', config);
|
2020-05-19 10:54:00 +02:00
|
|
|
});
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
let checkForUpdatesListener: () => void;
|
|
|
|
ipcMain.on('checkForUpdates', checkForUpdatesListener = () => {
|
2020-05-19 10:54:00 +02:00
|
|
|
updater.checkForUpdates((available, version) => {
|
2020-05-21 07:38:44 +02:00
|
|
|
settingsWindow!.webContents.send('updateStatus', available, version);
|
2020-05-19 10:54:00 +02:00
|
|
|
});
|
|
|
|
});
|
2020-05-20 17:13:33 +02:00
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
let saveConfigListener: (e: Event, data: any) => void;
|
|
|
|
ipcMain.on('save-config', saveConfigListener = (e: Event, data: any) => {
|
2020-05-20 17:13:33 +02:00
|
|
|
config.update(data);
|
|
|
|
config.save();
|
|
|
|
sendData();
|
|
|
|
});
|
|
|
|
|
2020-05-19 10:54:00 +02:00
|
|
|
settingsWindow.on('close', () => {
|
2020-05-20 17:13:33 +02:00
|
|
|
ipcMain.removeListener('syncSettings', syncListener);
|
2020-05-19 10:54:00 +02:00
|
|
|
ipcMain.removeListener('checkForUpdates', checkForUpdatesListener);
|
2020-05-20 17:13:33 +02:00
|
|
|
ipcMain.removeListener('save-config', saveConfigListener);
|
2020-05-19 10:54:00 +02:00
|
|
|
});
|
|
|
|
settingsWindow.loadFile(path.resolve(resourcesDir, 'settings.html'))
|
|
|
|
.catch(console.error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('> App started');
|
2019-10-13 22:59:28 +02:00
|
|
|
}
|
|
|
|
|
2020-01-04 15:20:02 +01:00
|
|
|
function sendData() {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Syncing data');
|
2020-05-21 07:38:44 +02:00
|
|
|
window!.webContents.send('data', Meta.title, brandIcons, solidIcons, selectedService, path.resolve(resourcesDir, 'empty.html'), config);
|
2019-10-13 22:59:28 +02:00
|
|
|
}
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
function setActiveService(index: number) {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Selected service is now', index);
|
2019-10-13 22:59:28 +02:00
|
|
|
selectedService = index;
|
|
|
|
}
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
function listIcons(set: string) {
|
2020-01-04 15:56:37 +01:00
|
|
|
console.log('Loading icon set', set);
|
2020-01-03 15:01:15 +01:00
|
|
|
const directory = path.resolve(resourcesDir, 'icons/' + set);
|
2020-05-21 07:38:44 +02:00
|
|
|
const icons: { name: string; faIcon: string }[] = [];
|
2020-01-04 15:20:02 +01:00
|
|
|
const dir = set === 'brands' ? 'fab' : 'fas';
|
|
|
|
fs.readdirSync(directory).forEach(i => icons.push({
|
|
|
|
name: i.split('.svg')[0],
|
|
|
|
faIcon: dir + ' fa-' + i.split('.svg')[0],
|
|
|
|
}));
|
2020-01-03 15:01:15 +01:00
|
|
|
return icons;
|
|
|
|
}
|
|
|
|
|
2020-05-21 07:38:44 +02:00
|
|
|
|
|
|
|
// Check if application is already running
|
|
|
|
const lock = new SingleInstance('tabs-app');
|
|
|
|
lock.lock().then(() => {
|
|
|
|
console.log('Starting app');
|
|
|
|
app.on('ready', () => {
|
|
|
|
createWindow().catch(console.error);
|
|
|
|
});
|
|
|
|
}).catch(err => {
|
|
|
|
console.error(err);
|
|
|
|
process.exit(0);
|
2020-04-18 15:14:13 +02:00
|
|
|
});
|