Convert project backend to typescript
This commit is contained in:
parent
31f2b3a133
commit
8683140003
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,7 +1,8 @@
|
|||||||
/.idea
|
.idea
|
||||||
node_modules/
|
node_modules
|
||||||
/config
|
config
|
||||||
/dist
|
dist
|
||||||
|
build
|
||||||
GH_TOKEN
|
GH_TOKEN
|
||||||
|
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
22
package.json
22
package.json
@ -8,14 +8,14 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/ArisuOngaku/tabs",
|
"homepage": "https://gitlab.com/ArisuOngaku/tabs",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"main": "tabs.js",
|
"main": "build/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron .",
|
"clean": "! test -d build || rm -r build",
|
||||||
"dev": "electron . --dev",
|
"compile": "yarn clean && tsc",
|
||||||
"build": "electron-builder",
|
"start": "yarn compile && electron .",
|
||||||
"build-arch": "electron-builder --linux dir",
|
"dev": "yarn compile && electron . --dev",
|
||||||
"release": "GH_TOKEN=$(cat GH_TOKEN) electron-builder -wlp always",
|
"build": "yarn compile && electron-builder -wl",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"release": "yarn compile && GH_TOKEN=$(cat GH_TOKEN) electron-builder -wlp always"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"appdata-path": "^1.0.0",
|
"appdata-path": "^1.0.0",
|
||||||
@ -25,11 +25,17 @@
|
|||||||
"single-instance": "^0.0.1"
|
"single-instance": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/node": "^12.12.41",
|
||||||
"electron": "^9.0.0",
|
"electron": "^9.0.0",
|
||||||
"electron-builder": "^22.4.0"
|
"electron-builder": "^22.4.0",
|
||||||
|
"typescript": "^3.9.3"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "tabs-app",
|
"appId": "tabs-app",
|
||||||
|
"files": [
|
||||||
|
"resources/**/*",
|
||||||
|
"build/**/*"
|
||||||
|
],
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": "AppImage",
|
"target": "AppImage",
|
||||||
"icon": "resources/logo.png",
|
"icon": "resources/logo.png",
|
||||||
|
@ -9,18 +9,19 @@ const configDir = Meta.isDevMode() ? getAppDataPath('tabs-app-dev') : getAppData
|
|||||||
const configFile = path.resolve(configDir, 'config.json');
|
const configFile = path.resolve(configDir, 'config.json');
|
||||||
|
|
||||||
export default class Config {
|
export default class Config {
|
||||||
updateCheckSkip = undefined;
|
public services: Service[] = [];
|
||||||
securityButton = true;
|
public updateCheckSkip?: string;
|
||||||
homeButton = false;
|
public securityButton: boolean = true;
|
||||||
backButton = true;
|
public homeButton: boolean = false;
|
||||||
forwardButton = false;
|
public backButton: boolean = true;
|
||||||
refreshButton = false;
|
public forwardButton: boolean = false;
|
||||||
|
public refreshButton: boolean = false;
|
||||||
|
|
||||||
properties = [];
|
private properties: string[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Load data from config file
|
// Load data from config file
|
||||||
let data = {};
|
let data: any = {};
|
||||||
if (fs.existsSync(configDir) && fs.statSync(configDir).isDirectory()) {
|
if (fs.existsSync(configDir) && fs.statSync(configDir).isDirectory()) {
|
||||||
if (fs.existsSync(configFile) && fs.statSync(configFile).isFile())
|
if (fs.existsSync(configFile) && fs.statSync(configFile).isFile())
|
||||||
data = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
data = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
||||||
@ -29,7 +30,6 @@ export default class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse services
|
// Parse services
|
||||||
this.services = [];
|
|
||||||
if (typeof data.services === 'object') {
|
if (typeof data.services === 'object') {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const service of data.services) {
|
for (const service of data.services) {
|
||||||
@ -60,18 +60,18 @@ export default class Config {
|
|||||||
console.log('> Config saved to', configFile.toString());
|
console.log('> Config saved to', configFile.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProperty(name, data) {
|
defineProperty(name: string, data: any) {
|
||||||
if (data[name] !== undefined) {
|
if (data[name] !== undefined) {
|
||||||
this[name] = data[name];
|
(<any>this)[name] = data[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.properties.push(name);
|
this.properties.push(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data) {
|
update(data: any) {
|
||||||
for (const prop of this.properties) {
|
for (const prop of this.properties) {
|
||||||
if (data[prop] !== undefined) {
|
if (data[prop] !== undefined) {
|
||||||
this[prop] = data[prop];
|
(<any>this)[prop] = data[prop];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
29
src/Meta.js
29
src/Meta.js
@ -1,29 +0,0 @@
|
|||||||
export default class Meta {
|
|
||||||
static #title = 'Tabs';
|
|
||||||
static #devMode = null;
|
|
||||||
|
|
||||||
static get title() {
|
|
||||||
return this.#title;
|
|
||||||
}
|
|
||||||
|
|
||||||
static isDevMode() {
|
|
||||||
if (this.#devMode === null) {
|
|
||||||
this.#devMode = process.argv.length > 2 && process.argv[2] === '--dev';
|
|
||||||
console.debug('Dev mode:', this.#devMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.#devMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param service {Service}
|
|
||||||
* @param viewTitle {string}
|
|
||||||
*/
|
|
||||||
static getTitleForService(service, viewTitle) {
|
|
||||||
let suffix = '';
|
|
||||||
if (typeof viewTitle === 'string' && viewTitle.length > 0) {
|
|
||||||
suffix = ' - ' + viewTitle;
|
|
||||||
}
|
|
||||||
return this.title + ' - ' + service.name + suffix;
|
|
||||||
}
|
|
||||||
}
|
|
23
src/Meta.ts
Normal file
23
src/Meta.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import Service from "./Service";
|
||||||
|
|
||||||
|
export default class Meta {
|
||||||
|
public static readonly title = 'Tabs';
|
||||||
|
private static devMode?: boolean;
|
||||||
|
|
||||||
|
public static isDevMode() {
|
||||||
|
if (this.devMode === undefined) {
|
||||||
|
this.devMode = process.argv.length > 2 && process.argv[2] === '--dev';
|
||||||
|
console.debug('Dev mode:', this.devMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.devMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getTitleForService(service: Service, viewTitle: string) {
|
||||||
|
let suffix = '';
|
||||||
|
if (viewTitle.length > 0) {
|
||||||
|
suffix = ' - ' + viewTitle;
|
||||||
|
}
|
||||||
|
return this.title + ' - ' + service.name + suffix;
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
class Service {
|
|
||||||
constructor(partition, name, icon, isImage, url, useFavicon) {
|
|
||||||
if (arguments.length === 1) {
|
|
||||||
let data = arguments[0];
|
|
||||||
for (let k in data) {
|
|
||||||
if (data.hasOwnProperty(k)) {
|
|
||||||
this[k] = data[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.partition = partition;
|
|
||||||
this.name = name;
|
|
||||||
this.icon = icon;
|
|
||||||
this.isImage = isImage;
|
|
||||||
this.url = url;
|
|
||||||
this.useFavicon = useFavicon;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let k in Service.requiredProperties) {
|
|
||||||
if (Service.requiredProperties.hasOwnProperty(k)) {
|
|
||||||
if (!this.hasOwnProperty(k) || this[k] === undefined) {
|
|
||||||
this[k] = Service.requiredProperties[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Service.requiredProperties = {
|
|
||||||
'partition': null,
|
|
||||||
'name': null,
|
|
||||||
'icon': null,
|
|
||||||
'isImage': null,
|
|
||||||
'url': null,
|
|
||||||
'useFavicon': true,
|
|
||||||
'autoLoad': false,
|
|
||||||
'customCSS': null,
|
|
||||||
'customUserAgent': null,
|
|
||||||
'permissions': {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Service;
|
|
31
src/Service.ts
Normal file
31
src/Service.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
export default class Service {
|
||||||
|
public partition?: string;
|
||||||
|
public name?: string;
|
||||||
|
public icon?: string;
|
||||||
|
public isImage?: boolean = false;
|
||||||
|
public url?: string;
|
||||||
|
public useFavicon?: boolean = true;
|
||||||
|
public favicon?: string;
|
||||||
|
public autoLoad?: boolean = false;
|
||||||
|
public customCSS?: string;
|
||||||
|
public customUserAgent?: string;
|
||||||
|
public permissions?: {} = {};
|
||||||
|
|
||||||
|
constructor(partition: string, name?: string, icon?: string, isImage?: boolean, url?: string, useFavicon?: boolean) {
|
||||||
|
if (arguments.length === 1) {
|
||||||
|
const data = arguments[0];
|
||||||
|
for (const k in data) {
|
||||||
|
if (data.hasOwnProperty(k)) {
|
||||||
|
(<any>this)[k] = data[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.partition = partition;
|
||||||
|
this.name = name;
|
||||||
|
this.icon = icon;
|
||||||
|
this.isImage = isImage;
|
||||||
|
this.url = url;
|
||||||
|
this.useFavicon = useFavicon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,32 +1,32 @@
|
|||||||
import {autoUpdater} from "electron-updater";
|
import {autoUpdater, UpdateInfo} from "electron-updater";
|
||||||
|
|
||||||
export default class Updater {
|
export default class Updater {
|
||||||
#updateInfo;
|
private updateInfo?: UpdateInfo;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
autoUpdater.autoDownload = false;
|
autoUpdater.autoDownload = false;
|
||||||
autoUpdater.on('error', err => {
|
autoUpdater.on('error', err => {
|
||||||
this.notifyUpdate(false, err);
|
console.log('Error while checking for updates', err);
|
||||||
});
|
});
|
||||||
autoUpdater.on('update-available', v => {
|
autoUpdater.on('update-available', v => {
|
||||||
this.notifyUpdate(true, v);
|
console.log('Update available', v);
|
||||||
});
|
});
|
||||||
autoUpdater.on('update-not-available', () => {
|
autoUpdater.on('update-not-available', () => {
|
||||||
this.notifyUpdate(false);
|
console.log('No update available.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
checkForUpdates(callback) {
|
checkForUpdates(callback: UpdateCheckCallback) {
|
||||||
if (this.#updateInfo) {
|
if (this.updateInfo) {
|
||||||
callback(this.#updateInfo.version !== this.getCurrentVersion().raw, this.#updateInfo);
|
callback(this.updateInfo.version !== this.getCurrentVersion().raw, this.updateInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
autoUpdater.checkForUpdates().then(r => {
|
autoUpdater.checkForUpdates().then(r => {
|
||||||
this.#updateInfo = r.updateInfo;
|
this.updateInfo = r.updateInfo;
|
||||||
callback(r.updateInfo.version !== this.getCurrentVersion().raw, r.updateInfo);
|
callback(r.updateInfo.version !== this.getCurrentVersion().raw, r.updateInfo);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
callback(false, err);
|
callback(false, err);
|
||||||
@ -36,8 +36,6 @@ export default class Updater {
|
|||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return autoUpdater.currentVersion;
|
return autoUpdater.currentVersion;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notifyUpdate(available, data) {
|
export type UpdateCheckCallback = (available: boolean, data: UpdateInfo) => void;
|
||||||
console.log('Update:', available, data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,13 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import SingleInstance from "single-instance";
|
||||||
import {app, BrowserWindow, dialog, ipcMain, Menu, shell, Tray} from "electron";
|
import {app, BrowserWindow, dialog, ipcMain, Menu, shell, Tray} from "electron";
|
||||||
|
|
||||||
import Meta from "./Meta";
|
import Meta from "./Meta";
|
||||||
import Config from "./Config";
|
import Config from "./Config";
|
||||||
import Service from "./Service";
|
import Service from "./Service";
|
||||||
import Updater from "./Updater";
|
import Updater from "./Updater";
|
||||||
|
import Event = Electron.Event;
|
||||||
|
|
||||||
const resourcesDir = path.resolve(__dirname, '../resources');
|
const resourcesDir = path.resolve(__dirname, '../resources');
|
||||||
const iconPath = path.resolve(resourcesDir, 'logo.png');
|
const iconPath = path.resolve(resourcesDir, 'logo.png');
|
||||||
@ -21,9 +23,9 @@ const solidIcons = listIcons('solid');
|
|||||||
|
|
||||||
let selectedService = 0;
|
let selectedService = 0;
|
||||||
|
|
||||||
let tray;
|
let tray: Tray;
|
||||||
let window;
|
let window: BrowserWindow | null;
|
||||||
let serviceSettingsWindow, settingsWindow;
|
let serviceSettingsWindow: BrowserWindow | null, settingsWindow: BrowserWindow | null;
|
||||||
|
|
||||||
function toggleMainWindow() {
|
function toggleMainWindow() {
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
@ -41,7 +43,7 @@ async function createWindow() {
|
|||||||
// Check for updates
|
// Check for updates
|
||||||
updater.checkForUpdates((available, updateInfo) => {
|
updater.checkForUpdates((available, updateInfo) => {
|
||||||
if (available && updateInfo.version !== config.updateCheckSkip) {
|
if (available && updateInfo.version !== config.updateCheckSkip) {
|
||||||
dialog.showMessageBox(window, {
|
dialog.showMessageBox(window!, {
|
||||||
message: `Version ${updateInfo.version} of tabs is available. Do you wish to download this update?`,
|
message: `Version ${updateInfo.version} of tabs is available. Do you wish to download this update?`,
|
||||||
buttons: [
|
buttons: [
|
||||||
'Cancel',
|
'Cancel',
|
||||||
@ -71,7 +73,7 @@ async function createWindow() {
|
|||||||
tray.setToolTip('Tabs');
|
tray.setToolTip('Tabs');
|
||||||
tray.setContextMenu(Menu.buildFromTemplate([
|
tray.setContextMenu(Menu.buildFromTemplate([
|
||||||
{label: 'Tabs', enabled: false},
|
{label: 'Tabs', enabled: false},
|
||||||
{label: 'Open Tabs', click: () => window.show()},
|
{label: 'Open Tabs', click: () => window!.show()},
|
||||||
{type: 'separator'},
|
{type: 'separator'},
|
||||||
{label: 'Quit', role: 'quit'}
|
{label: 'Quit', role: 'quit'}
|
||||||
]));
|
]));
|
||||||
@ -142,7 +144,7 @@ async function createWindow() {
|
|||||||
enableRemoteModule: true,
|
enableRemoteModule: true,
|
||||||
webviewTag: true,
|
webviewTag: true,
|
||||||
},
|
},
|
||||||
parent: window,
|
parent: window!,
|
||||||
modal: true,
|
modal: true,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
height: 850,
|
height: 850,
|
||||||
@ -155,10 +157,10 @@ async function createWindow() {
|
|||||||
mode: 'right'
|
mode: 'right'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let syncListener;
|
let syncListener: () => void;
|
||||||
ipcMain.on('sync-settings', syncListener = () => {
|
ipcMain.on('sync-settings', syncListener = () => {
|
||||||
serviceSettingsWindow.webContents.send('syncIcons', brandIcons, solidIcons);
|
serviceSettingsWindow!.webContents.send('syncIcons', brandIcons, solidIcons);
|
||||||
serviceSettingsWindow.webContents.send('loadService', serviceId, config.services[serviceId]);
|
serviceSettingsWindow!.webContents.send('loadService', serviceId, config.services[serviceId]);
|
||||||
});
|
});
|
||||||
serviceSettingsWindow.on('close', () => {
|
serviceSettingsWindow.on('close', () => {
|
||||||
ipcMain.removeListener('sync-settings', syncListener);
|
ipcMain.removeListener('sync-settings', syncListener);
|
||||||
@ -179,7 +181,7 @@ async function createWindow() {
|
|||||||
}
|
}
|
||||||
config.save();
|
config.save();
|
||||||
|
|
||||||
window.webContents.send('updateService', id, newService);
|
window!.webContents.send('updateService', id, newService);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('deleteService', (e, id) => {
|
ipcMain.on('deleteService', (e, id) => {
|
||||||
@ -187,7 +189,7 @@ async function createWindow() {
|
|||||||
delete config.services[id];
|
delete config.services[id];
|
||||||
config.save();
|
config.save();
|
||||||
|
|
||||||
window.webContents.send('deleteService', id);
|
window!.webContents.send('deleteService', id);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('reorderService', (e, serviceId, targetId) => {
|
ipcMain.on('reorderService', (e, serviceId, targetId) => {
|
||||||
@ -219,10 +221,10 @@ async function createWindow() {
|
|||||||
|
|
||||||
ipcMain.on('updateWindowTitle', (event, serviceId, viewTitle) => {
|
ipcMain.on('updateWindowTitle', (event, serviceId, viewTitle) => {
|
||||||
if (serviceId === null) {
|
if (serviceId === null) {
|
||||||
window.setTitle(Meta.title);
|
window!.setTitle(Meta.title);
|
||||||
} else {
|
} else {
|
||||||
const service = config.services[serviceId];
|
const service = config.services[serviceId];
|
||||||
window.setTitle(Meta.getTitleForService(service, viewTitle));
|
window!.setTitle(Meta.getTitleForService(service, viewTitle));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -236,7 +238,7 @@ async function createWindow() {
|
|||||||
enableRemoteModule: true,
|
enableRemoteModule: true,
|
||||||
webviewTag: true,
|
webviewTag: true,
|
||||||
},
|
},
|
||||||
parent: window,
|
parent: window!,
|
||||||
modal: true,
|
modal: true,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
height: 850,
|
height: 850,
|
||||||
@ -249,21 +251,21 @@ async function createWindow() {
|
|||||||
mode: 'right'
|
mode: 'right'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let syncListener;
|
let syncListener: () => void;
|
||||||
ipcMain.on('syncSettings', syncListener = () => {
|
ipcMain.on('syncSettings', syncListener = () => {
|
||||||
settingsWindow.webContents.send('current-version', updater.getCurrentVersion());
|
settingsWindow!.webContents.send('current-version', updater.getCurrentVersion());
|
||||||
settingsWindow.webContents.send('config', config);
|
settingsWindow!.webContents.send('config', config);
|
||||||
});
|
});
|
||||||
|
|
||||||
let checkForUpdatesListener;
|
let checkForUpdatesListener: () => void;
|
||||||
ipcMain.on('checkForUpdates', checkForUpdatesListener = (e) => {
|
ipcMain.on('checkForUpdates', checkForUpdatesListener = () => {
|
||||||
updater.checkForUpdates((available, version) => {
|
updater.checkForUpdates((available, version) => {
|
||||||
settingsWindow.webContents.send('updateStatus', available, version);
|
settingsWindow!.webContents.send('updateStatus', available, version);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let saveConfigListener;
|
let saveConfigListener: (e: Event, data: any) => void;
|
||||||
ipcMain.on('save-config', saveConfigListener = (e, data) => {
|
ipcMain.on('save-config', saveConfigListener = (e: Event, data: any) => {
|
||||||
config.update(data);
|
config.update(data);
|
||||||
config.save();
|
config.save();
|
||||||
sendData();
|
sendData();
|
||||||
@ -284,18 +286,18 @@ async function createWindow() {
|
|||||||
|
|
||||||
function sendData() {
|
function sendData() {
|
||||||
console.log('Syncing data');
|
console.log('Syncing data');
|
||||||
window.webContents.send('data', Meta.title, brandIcons, solidIcons, selectedService, path.resolve(resourcesDir, 'empty.html'), config);
|
window!.webContents.send('data', Meta.title, brandIcons, solidIcons, selectedService, path.resolve(resourcesDir, 'empty.html'), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveService(index) {
|
function setActiveService(index: number) {
|
||||||
console.log('Selected service is now', index);
|
console.log('Selected service is now', index);
|
||||||
selectedService = index;
|
selectedService = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listIcons(set) {
|
function listIcons(set: string) {
|
||||||
console.log('Loading icon set', set);
|
console.log('Loading icon set', set);
|
||||||
const directory = path.resolve(resourcesDir, 'icons/' + set);
|
const directory = path.resolve(resourcesDir, 'icons/' + set);
|
||||||
const icons = [];
|
const icons: { name: string; faIcon: string }[] = [];
|
||||||
const dir = set === 'brands' ? 'fab' : 'fas';
|
const dir = set === 'brands' ? 'fab' : 'fas';
|
||||||
fs.readdirSync(directory).forEach(i => icons.push({
|
fs.readdirSync(directory).forEach(i => icons.push({
|
||||||
name: i.split('.svg')[0],
|
name: i.split('.svg')[0],
|
||||||
@ -304,7 +306,15 @@ function listIcons(set) {
|
|||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Starting app');
|
|
||||||
app.on('ready', () => {
|
// Check if application is already running
|
||||||
createWindow().catch(console.error);
|
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);
|
||||||
});
|
});
|
7
src/types/single-instance.d.ts
vendored
Normal file
7
src/types/single-instance.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
declare module "single-instance" {
|
||||||
|
export default class SingleInstance {
|
||||||
|
constructor(lockName: string);
|
||||||
|
|
||||||
|
public lock(): Promise<void>;
|
||||||
|
}
|
||||||
|
}
|
10
tabs.js
10
tabs.js
@ -1,10 +0,0 @@
|
|||||||
#!/bin/electron
|
|
||||||
const SingleInstance = require('single-instance');
|
|
||||||
const lock = new SingleInstance('tabs-app');
|
|
||||||
lock.lock().then(() => {
|
|
||||||
require = require("esm")(module);
|
|
||||||
module.exports = require("./src/main.js");
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "CommonJS",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"outDir": "build",
|
||||||
|
"target": "ES6",
|
||||||
|
"strict": true,
|
||||||
|
"lib": [
|
||||||
|
"es2020",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types",
|
||||||
|
"src/types"
|
||||||
|
],
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"*": [
|
||||||
|
"node_modules/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
10
yarn.lock
10
yarn.lock
@ -70,6 +70,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.12.39.tgz#532d25c1e639d89dd6f3aa1d7b3962e3e7fa943d"
|
resolved "https://registry.npmjs.org/@types/node/-/node-12.12.39.tgz#532d25c1e639d89dd6f3aa1d7b3962e3e7fa943d"
|
||||||
integrity sha512-pADGfwnDkr6zagDwEiCVE4yQrv7XDkoeVa4OfA9Ju/zRTk6YNDLGtQbkdL4/56mCQQCs4AhNrBIag6jrp7ZuOg==
|
integrity sha512-pADGfwnDkr6zagDwEiCVE4yQrv7XDkoeVa4OfA9Ju/zRTk6YNDLGtQbkdL4/56mCQQCs4AhNrBIag6jrp7ZuOg==
|
||||||
|
|
||||||
|
"@types/node@^12.12.41":
|
||||||
|
version "12.12.41"
|
||||||
|
resolved "https://registry.npmjs.org/@types/node/-/node-12.12.41.tgz#cf48562b53ab6cf85d28dde95f1d06815af275c8"
|
||||||
|
integrity sha512-Q+eSkdYQJ2XK1AJnr4Ji8Gvk3sRDybEwfTvtL9CA25FFUSD2EgZQewN6VCyWYZCXg5MWZdwogdTNBhlWRcWS1w==
|
||||||
|
|
||||||
"@types/semver@^7.1.0":
|
"@types/semver@^7.1.0":
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b"
|
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b"
|
||||||
@ -1505,6 +1510,11 @@ typedarray@^0.0.6:
|
|||||||
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
|
typescript@^3.9.3:
|
||||||
|
version "3.9.3"
|
||||||
|
resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a"
|
||||||
|
integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==
|
||||||
|
|
||||||
unique-string@^2.0.0:
|
unique-string@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
||||||
|
Loading…
Reference in New Issue
Block a user