Merge branch 'develop'
This commit is contained in:
commit
999905b235
6
dev-app-update.yml
Normal file
6
dev-app-update.yml
Normal file
@ -0,0 +1,6 @@
|
||||
owner: ArisuOngaku
|
||||
repo: tabs
|
||||
provider: github
|
||||
updaterCacheDirName: tabs-updater
|
||||
publisherName:
|
||||
- Alice Gaudon
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tabs",
|
||||
"version": "0.7.2",
|
||||
"version": "0.8.0",
|
||||
"description": "Persistent and separate browser tabs in one window.",
|
||||
"author": {
|
||||
"name": "Alice Gaudon",
|
||||
@ -18,13 +18,14 @@
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"appdata-path": "^1.0.0",
|
||||
"ejs": "^3.0.1",
|
||||
"electron-updater": "^4.2.4",
|
||||
"esm": "^3.2.25",
|
||||
"single-instance": "^0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^8.2.0",
|
||||
"electron": "^9.0.0",
|
||||
"electron-builder": "^22.4.0"
|
||||
},
|
||||
"build": {
|
||||
@ -71,6 +72,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"electronVersion": "8.2.5"
|
||||
"electronVersion": "9.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,30 @@
|
||||
<body>
|
||||
<div id="navigation">
|
||||
<div id="history">
|
||||
<button id="back"><i class="fas fa-arrow-left"></i></button>
|
||||
<button id="status">
|
||||
<i class="fas fa-question unknown active">
|
||||
<span class="tip">Unknown protocol</span>
|
||||
</i>
|
||||
<i class="fas fa-lock https">
|
||||
<span class="tip">Secured via TLS (https)</span>
|
||||
</i>
|
||||
<i class="fas fa-lock-open http">
|
||||
<span class="tip">Vulnerable connection (http)</span>
|
||||
</i>
|
||||
<i class="fas fa-folder file">
|
||||
<span class="tip">Local file</span>
|
||||
</i>
|
||||
</button>
|
||||
<button id="home" class="disabled"><i class="fas fa-home"></i></button>
|
||||
<button id="back" class="disabled"><i class="fas fa-arrow-left"></i></button>
|
||||
<button id="forward" class="disabled"><i class="fas fa-arrow-right"></i></button>
|
||||
<button id="reload" class="disabled"><i class="fas fa-redo"></i></button>
|
||||
</div>
|
||||
|
||||
<ul id="service-selector"></ul>
|
||||
<div id="service-last-drag-position" class="hidden"></div>
|
||||
<div id="service-buttons">
|
||||
<ul id="service-selector"></ul>
|
||||
<div id="service-last-drag-position" class="hidden"></div>
|
||||
</div>
|
||||
|
||||
<button id="add-button"><i class="fa fa-plus"></i></button>
|
||||
|
||||
|
@ -16,12 +16,13 @@ const icons = [];
|
||||
|
||||
let services = [];
|
||||
let selectedService = null;
|
||||
let forwardButton;
|
||||
let backButton;
|
||||
let addButton;
|
||||
let statusButton, homeButton, forwardButton, backButton, reloadButton;
|
||||
let addButton, settingsButton;
|
||||
let emptyPage;
|
||||
let urlPreview;
|
||||
|
||||
// Service reordering
|
||||
let lastDragPosition, oldActiveService;
|
||||
|
||||
// Service context menu
|
||||
function openServiceContextMenu(event, serviceId) {
|
||||
@ -146,7 +147,7 @@ ipcRenderer.on('data', (event, appData, brandIcons, solidIcons, actualServices,
|
||||
}
|
||||
|
||||
// Init drag last position
|
||||
const lastDragPosition = document.getElementById('service-last-drag-position');
|
||||
lastDragPosition = document.getElementById('service-last-drag-position');
|
||||
lastDragPosition.addEventListener('dragover', () => {
|
||||
const index = services.length;
|
||||
if (draggedId !== index && draggedId !== index - 1) {
|
||||
@ -215,16 +216,19 @@ ipcRenderer.on('reorderService', (e, serviceId, targetId) => {
|
||||
const oldServices = services;
|
||||
services = [];
|
||||
|
||||
let newId = targetId;
|
||||
|
||||
for (let i = 0; i < targetId; i++) {
|
||||
if (i !== serviceId) {
|
||||
services.push(oldServices[i]);
|
||||
if (i === oldActiveService) newId = services.length - 1;
|
||||
}
|
||||
}
|
||||
services.push(oldServices[serviceId]);
|
||||
const newId = services.length - 1;
|
||||
for (let i = targetId; i < oldServices.length; i++) {
|
||||
if (i !== serviceId) {
|
||||
services.push(oldServices[i]);
|
||||
if (i === oldActiveService) newId = services.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,13 +315,25 @@ function initDrag(index, li) {
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
document.getElementById('service-last-drag-position').classList.remove('hidden');
|
||||
});
|
||||
li.addEventListener('dragover', () => {
|
||||
if (draggedId !== index && draggedId !== index - 1) {
|
||||
resetDrag();
|
||||
lastDragTarget = dragTargetId = index;
|
||||
document.getElementById('service-last-drag-position').classList.remove('hidden');
|
||||
li.classList.add('drag-target');
|
||||
li.addEventListener('dragover', (e) => {
|
||||
let realIndex = index;
|
||||
let rect = li.getBoundingClientRect();
|
||||
|
||||
if ((e.clientY - rect.y) / rect.height >= 0.5) {
|
||||
realIndex++;
|
||||
}
|
||||
|
||||
if (draggedId === realIndex - 1) {
|
||||
realIndex--;
|
||||
}
|
||||
|
||||
resetDrag();
|
||||
let el = realIndex === services.length ? lastDragPosition : services[realIndex].li;
|
||||
lastDragTarget = dragTargetId = realIndex;
|
||||
lastDragPosition.classList.remove('hidden');
|
||||
el.classList.add('drag-target');
|
||||
|
||||
if (draggedId === realIndex || draggedId === realIndex - 1) el.classList.add('drag-target-self');
|
||||
});
|
||||
li.addEventListener('dragend', () => {
|
||||
reorderService(draggedId, lastDragTarget);
|
||||
@ -331,6 +347,7 @@ function resetDrag() {
|
||||
dragTargetCount = 0;
|
||||
document.getElementById('service-selector').querySelectorAll('li').forEach(li => {
|
||||
li.classList.remove('drag-target');
|
||||
li.classList.remove('drag-target-self');
|
||||
});
|
||||
const lastDragPosition = document.getElementById('service-last-drag-position');
|
||||
lastDragPosition.classList.remove('drag-target');
|
||||
@ -340,20 +357,32 @@ function resetDrag() {
|
||||
function reorderService(serviceId, targetId) {
|
||||
console.log('Reordering service', serviceId, targetId);
|
||||
if (targetId >= 0) {
|
||||
oldActiveService = selectedService;
|
||||
setActiveService(null);
|
||||
ipcRenderer.send('reorderService', serviceId, targetId);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
forwardButton = document.querySelector('#forward');
|
||||
statusButton = document.getElementById('status');
|
||||
|
||||
homeButton = document.getElementById('home');
|
||||
homeButton.addEventListener('click', () => goHome());
|
||||
|
||||
forwardButton = document.getElementById('forward');
|
||||
forwardButton.addEventListener('click', () => goForward());
|
||||
|
||||
backButton = document.querySelector('#back');
|
||||
backButton = document.getElementById('back');
|
||||
backButton.addEventListener('click', () => goBack());
|
||||
|
||||
addButton = document.querySelector('#add-button');
|
||||
reloadButton = document.getElementById('reload');
|
||||
reloadButton.addEventListener('click', () => reload());
|
||||
|
||||
addButton = document.getElementById('add-button');
|
||||
addButton.addEventListener('click', () => ipcRenderer.send('openServiceSettings', null));
|
||||
|
||||
settingsButton = document.getElementById('settings-button');
|
||||
settingsButton.addEventListener('click', () => ipcRenderer.send('openSettings', null));
|
||||
});
|
||||
|
||||
function setActiveService(serviceId) {
|
||||
@ -485,7 +514,7 @@ function loadService(serviceId, service) {
|
||||
// Load favicon
|
||||
service.view.addEventListener('page-favicon-updated', event => {
|
||||
console.debug('Loaded favicons for', service.name, event.favicons);
|
||||
if (event.favicons.length > 0) {
|
||||
if (event.favicons.length > 0 && service.favicon !== event.favicons[0]) {
|
||||
ipcRenderer.send('setServiceFavicon', serviceId, event.favicons[0]);
|
||||
if (service.useFavicon) {
|
||||
const img = document.createElement('img');
|
||||
@ -555,11 +584,14 @@ function updateNavigation() {
|
||||
// Update active list element
|
||||
for (let i = 0; i < services.length; i++) {
|
||||
const service = services[i];
|
||||
if (parseInt(selectedService) === i) {
|
||||
service.li.classList.add('active');
|
||||
} else {
|
||||
service.li.classList.remove('active');
|
||||
}
|
||||
|
||||
// Active?
|
||||
if (parseInt(selectedService) === i) service.li.classList.add('active');
|
||||
else service.li.classList.remove('active');
|
||||
|
||||
// Loaded?
|
||||
if (service.viewReady) service.li.classList.add('loaded');
|
||||
else service.li.classList.remove('loaded');
|
||||
}
|
||||
|
||||
if (selectedService !== null && services[selectedService].viewReady) {
|
||||
@ -567,16 +599,31 @@ function updateNavigation() {
|
||||
// Update history navigation
|
||||
let view = services[selectedService].view;
|
||||
|
||||
homeButton.classList.remove('disabled');
|
||||
|
||||
if (view && view.canGoForward()) forwardButton.classList.remove('disabled');
|
||||
else forwardButton.classList.add('disabled');
|
||||
|
||||
if (view && view.canGoBack()) backButton.classList.remove('disabled');
|
||||
else backButton.classList.add('disabled');
|
||||
|
||||
reloadButton.classList.remove('disabled');
|
||||
|
||||
updateStatusButton();
|
||||
}
|
||||
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
function updateStatusButton() {
|
||||
let protocol = services[selectedService].view.getURL().split('://')[0];
|
||||
if (!protocol) protocol = 'unknown';
|
||||
for (const c of statusButton.children) {
|
||||
if (c.classList.contains(protocol)) c.classList.add('active');
|
||||
else c.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
function updateWindowTitle() {
|
||||
if (selectedService === null) {
|
||||
ipcRenderer.send('updateWindowTitle', null);
|
||||
@ -585,6 +632,12 @@ function updateWindowTitle() {
|
||||
}
|
||||
}
|
||||
|
||||
function goHome() {
|
||||
let service = services[selectedService];
|
||||
service.view.loadURL(service.url)
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
function goForward() {
|
||||
let view = services[selectedService].view;
|
||||
if (view) remote.webContents.fromId(view.getWebContentsId()).goForward();
|
||||
@ -595,6 +648,10 @@ function goBack() {
|
||||
if (view) remote.webContents.fromId(view.getWebContentsId()).goBack();
|
||||
}
|
||||
|
||||
function reload() {
|
||||
reloadService(selectedService);
|
||||
}
|
||||
|
||||
function setContextMenu(webContents) {
|
||||
webContents.on('context-menu', (event, props) => {
|
||||
const menu = new Menu();
|
||||
@ -616,7 +673,8 @@ function setContextMenu(webContents) {
|
||||
label: 'Open URL in default browser',
|
||||
click: () => {
|
||||
if (props.linkURL.startsWith('https://')) {
|
||||
shell.openExternal(props.linkURL);
|
||||
shell.openExternal(props.linkURL)
|
||||
.catch(console.error);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
39
resources/js/settings.js
Normal file
39
resources/js/settings.js
Normal file
@ -0,0 +1,39 @@
|
||||
const {ipcRenderer, remote, shell} = require('electron');
|
||||
|
||||
let currentVersion;
|
||||
let updateStatus;
|
||||
let updateInfo;
|
||||
let updateButton;
|
||||
|
||||
ipcRenderer.on('current-version', (e, version) => {
|
||||
currentVersion.innerText = `Version: ${version.version}`;
|
||||
});
|
||||
|
||||
ipcRenderer.on('updateStatus', (e, available, version) => {
|
||||
console.log(available, version);
|
||||
updateInfo = version;
|
||||
if (available) {
|
||||
updateStatus.innerHTML = 'A new update is available!';
|
||||
updateButton.classList.remove('hidden');
|
||||
} else {
|
||||
updateStatus.innerText = 'Tabs is up to date.';
|
||||
}
|
||||
});
|
||||
|
||||
function save() {
|
||||
const formData = new FormData(document.querySelector('form'));
|
||||
remote.getCurrentWindow().close();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
currentVersion = document.getElementById('current-version');
|
||||
updateStatus = document.getElementById('update-status');
|
||||
updateButton = document.getElementById('download-button');
|
||||
updateButton.addEventListener('click', () => {
|
||||
shell.openExternal(`https://github.com/ArisuOngaku/tabs/releases/download/v${updateInfo.version}/${updateInfo.path}`)
|
||||
.catch(console.error);
|
||||
});
|
||||
|
||||
ipcRenderer.send('syncSettings');
|
||||
ipcRenderer.send('checkForUpdates');
|
||||
});
|
41
resources/settings.html
Normal file
41
resources/settings.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Service settings</title>
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="style-src 'self' 'unsafe-inline' https://use.fontawesome.com; font-src 'self' https://use.fontawesome.com; script-src 'self' 'unsafe-inline'">
|
||||
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
||||
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
||||
|
||||
<link rel="stylesheet" href="style/layout.css">
|
||||
<link rel="stylesheet" href="style/service-settings.css">
|
||||
|
||||
<script src="js/settings.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="javascript: save();">
|
||||
<div class="form-header">
|
||||
<h1>Settings</h1>
|
||||
</div>
|
||||
|
||||
<div class="form-body">
|
||||
<div class="updates">
|
||||
<p id="current-version"></p>
|
||||
<p id="update-status">Loading...</p>
|
||||
<button id="download-button" type="button" class="hidden">Download</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-footer">
|
||||
<div class="form-group" id="buttons">
|
||||
<button id="cancel-button">Cancel</button>
|
||||
<button type="submit">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -10,13 +10,22 @@ body {
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
#service-selector {
|
||||
#navigation > :not(#service-buttons) {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#service-buttons {
|
||||
flex-grow: 1;
|
||||
|
||||
overflow: hidden auto;
|
||||
}
|
||||
|
||||
#service-selector {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
overflow: hidden auto;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#service-selector::-webkit-scrollbar {
|
||||
@ -33,19 +42,20 @@ body {
|
||||
user-drag: none;
|
||||
}
|
||||
|
||||
#service-selector .drag-target button {
|
||||
height: 56px;
|
||||
padding-top: 88px;
|
||||
}
|
||||
|
||||
#service-selector .drag-target button::after,
|
||||
#service-last-drag-position.drag-target {
|
||||
content: "";
|
||||
height: 56px;
|
||||
border: 1px dashed #fff;
|
||||
height: 4px;
|
||||
transform: translateY(-50%);
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
background: #fff9;
|
||||
}
|
||||
|
||||
background-color: rgb(43, 43, 43);
|
||||
#service-selector .drag-target-self button::after {
|
||||
height: 48px;
|
||||
border: 1px dashed #fff;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
#service-selector .drag-target button::after {
|
||||
@ -55,18 +65,6 @@ body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#service-last-drag-position:not(.hidden):not(.drag-target) {
|
||||
display: block;
|
||||
padding: 16px 4px;
|
||||
background-color: #fff5;
|
||||
}
|
||||
|
||||
#service-last-drag-position:not(.drag-target)::after {
|
||||
content: "";
|
||||
display: block;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
#service-selector .drag-target::after {
|
||||
top: 75% !important;
|
||||
}
|
||||
@ -91,7 +89,7 @@ body {
|
||||
}
|
||||
|
||||
#navigation button:focus {
|
||||
outline-color: transparent;
|
||||
outline: none;
|
||||
background: #fff3 !important;
|
||||
}
|
||||
|
||||
@ -145,13 +143,18 @@ body {
|
||||
}
|
||||
|
||||
#history {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#history button {
|
||||
#history button,
|
||||
#history .status {
|
||||
display: inline;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 2px;
|
||||
padding: initial;
|
||||
font-size: 12px;
|
||||
|
||||
@ -159,6 +162,8 @@ body {
|
||||
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#history button i {
|
||||
@ -187,6 +192,66 @@ body {
|
||||
background-color: #fff4;
|
||||
}
|
||||
|
||||
#history #status {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#history #status .unknown,
|
||||
#history #status .file {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#history #status .https {
|
||||
color: #009800;
|
||||
}
|
||||
|
||||
#history #status .http {
|
||||
color: #e20000;
|
||||
}
|
||||
|
||||
#history #status > :not(.active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#history #status > * .tip {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: none;
|
||||
margin-left: 8px;
|
||||
|
||||
background-color: #000;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
color: #fff;
|
||||
text-transform: none;
|
||||
font-family: sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
#history #status > * .tip::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(-100%, -50%);
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 0 solid transparent;
|
||||
border-top-width: 4px;
|
||||
border-bottom-width: 4px;
|
||||
border-right: 7px solid black;
|
||||
}
|
||||
|
||||
#history #status:focus > * .tip {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#navigation #add-button:not(:hover) {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {homedir} from "os";
|
||||
import getAppDataPath from "appdata-path";
|
||||
|
||||
import Service from "./Service";
|
||||
import Meta from "./Meta";
|
||||
|
||||
const configDir = Meta.isDevMode() ? path.resolve(homedir(), '.config/tabs-app-dev') : path.resolve(homedir(), '.config/tabs-app');
|
||||
const configDir = Meta.isDevMode() ? getAppDataPath('tabs-app-dev') : getAppDataPath('tabs-app');
|
||||
const configFile = path.resolve(configDir, 'config.json');
|
||||
|
||||
export default class Config {
|
||||
@ -33,6 +33,8 @@ export default class Config {
|
||||
this.services.push(new Service('welcome', 'Welcome', 'rocket', false, 'https://github.com/ArisuOngaku/tabs', false));
|
||||
}
|
||||
|
||||
this.updateCheckSkip = data.updateCheckSkip;
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
|
43
src/Updater.js
Normal file
43
src/Updater.js
Normal file
@ -0,0 +1,43 @@
|
||||
import {autoUpdater} from "electron-updater";
|
||||
|
||||
export default class Updater {
|
||||
#updateInfo;
|
||||
|
||||
constructor() {
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.on('error', err => {
|
||||
this.notifyUpdate(false, err);
|
||||
});
|
||||
autoUpdater.on('update-available', v => {
|
||||
this.notifyUpdate(true, v);
|
||||
});
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
this.notifyUpdate(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function} callback
|
||||
*/
|
||||
checkForUpdates(callback) {
|
||||
if (this.#updateInfo) {
|
||||
callback(this.#updateInfo.version !== this.getCurrentVersion().raw, this.#updateInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
autoUpdater.checkForUpdates().then(r => {
|
||||
this.#updateInfo = r.updateInfo;
|
||||
callback(r.updateInfo.version !== this.getCurrentVersion().raw, r.updateInfo);
|
||||
}).catch(err => {
|
||||
callback(false, err);
|
||||
});
|
||||
}
|
||||
|
||||
getCurrentVersion() {
|
||||
return autoUpdater.currentVersion;
|
||||
}
|
||||
|
||||
notifyUpdate(available, data) {
|
||||
console.log('Update:', available, data);
|
||||
}
|
||||
}
|
76
src/main.js
76
src/main.js
@ -1,16 +1,17 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {app, BrowserWindow, ipcMain, Menu, shell, Tray} from "electron";
|
||||
import {app, BrowserWindow, dialog, ipcMain, Menu, shell, Tray} from "electron";
|
||||
|
||||
import Meta from "./Meta";
|
||||
import Config from "./Config";
|
||||
import Service from "./Service";
|
||||
import {autoUpdater} from "electron-updater";
|
||||
import Updater from "./Updater";
|
||||
|
||||
const resourcesDir = path.resolve(__dirname, '../resources');
|
||||
const iconPath = path.resolve(resourcesDir, 'logo.png');
|
||||
|
||||
const config = new Config();
|
||||
const updater = new Updater();
|
||||
|
||||
const devMode = Meta.isDevMode();
|
||||
|
||||
@ -22,7 +23,7 @@ let selectedService = 0;
|
||||
|
||||
let tray;
|
||||
let window;
|
||||
let serviceSettingsWindow;
|
||||
let serviceSettingsWindow, settingsWindow;
|
||||
|
||||
function toggleMainWindow() {
|
||||
if (window != null) {
|
||||
@ -38,7 +39,31 @@ function toggleMainWindow() {
|
||||
|
||||
async function createWindow() {
|
||||
// Check for updates
|
||||
await autoUpdater.checkForUpdatesAndNotify();
|
||||
updater.checkForUpdates((available, updateInfo) => {
|
||||
if (available && updateInfo.version !== config.updateCheckSkip) {
|
||||
dialog.showMessageBox(window, {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
// System tray
|
||||
console.log('Loading system Tray');
|
||||
@ -201,6 +226,49 @@ async function createWindow() {
|
||||
}
|
||||
});
|
||||
|
||||
// Open add service window
|
||||
ipcMain.on('openSettings', (e) => {
|
||||
if (!settingsWindow) {
|
||||
console.log('Opening settings');
|
||||
settingsWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
enableRemoteModule: true,
|
||||
webviewTag: true,
|
||||
},
|
||||
parent: window,
|
||||
modal: true,
|
||||
autoHideMenuBar: true,
|
||||
height: 850,
|
||||
});
|
||||
settingsWindow.on('close', () => {
|
||||
settingsWindow = null;
|
||||
});
|
||||
if (devMode) {
|
||||
settingsWindow.webContents.openDevTools({
|
||||
mode: 'right'
|
||||
});
|
||||
}
|
||||
let syncListener;
|
||||
ipcMain.on('syncSettings', syncListener = () => {
|
||||
settingsWindow.webContents.send('current-version', updater.getCurrentVersion());
|
||||
});
|
||||
|
||||
let checkForUpdatesListener;
|
||||
ipcMain.on('checkForUpdates', checkForUpdatesListener = (e) => {
|
||||
updater.checkForUpdates((available, version) => {
|
||||
settingsWindow.webContents.send('updateStatus', available, version);
|
||||
});
|
||||
});
|
||||
settingsWindow.on('close', () => {
|
||||
ipcMain.removeListener('sync-settings', syncListener);
|
||||
ipcMain.removeListener('checkForUpdates', checkForUpdatesListener);
|
||||
});
|
||||
settingsWindow.loadFile(path.resolve(resourcesDir, 'settings.html'))
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('> App started');
|
||||
}
|
||||
|
||||
|
133
yarn.lock
133
yarn.lock
@ -16,9 +16,9 @@
|
||||
ajv-keywords "^3.4.1"
|
||||
|
||||
"@electron/get@^1.0.1":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.npmjs.org/@electron/get/-/get-1.10.0.tgz#258fdda22bbd5a247e0b663ba9c525dedc1bdfff"
|
||||
integrity sha512-hlueNXU51c3CwQjBw/i5fwt+VfQgSQVUTdicpCHkhEjNZaa4CXJ5W1GaxSwtLE2dvRmAHjpIjUMHTqJ53uojfg==
|
||||
version "1.12.2"
|
||||
resolved "https://registry.npmjs.org/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3"
|
||||
integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
env-paths "^2.2.0"
|
||||
@ -54,26 +54,26 @@
|
||||
integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==
|
||||
|
||||
"@types/fs-extra@^8.1.0":
|
||||
version "8.1.0"
|
||||
resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d"
|
||||
integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==
|
||||
version "8.1.1"
|
||||
resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068"
|
||||
integrity sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "13.13.5"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz#96ec3b0afafd64a4ccea9107b75bf8489f0e5765"
|
||||
integrity sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g==
|
||||
version "14.0.1"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.0.1.tgz#5d93e0a099cd0acd5ef3d5bde3c086e1f49ff68c"
|
||||
integrity sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==
|
||||
|
||||
"@types/node@^12.0.12":
|
||||
version "12.12.38"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz#58841a382f231ad005dbb935c36d44aa1118a26b"
|
||||
integrity sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==
|
||||
version "12.12.39"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.12.39.tgz#532d25c1e639d89dd6f3aa1d7b3962e3e7fa943d"
|
||||
integrity sha512-pADGfwnDkr6zagDwEiCVE4yQrv7XDkoeVa4OfA9Ju/zRTk6YNDLGtQbkdL4/56mCQQCs4AhNrBIag6jrp7ZuOg==
|
||||
|
||||
"@types/semver@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.1.0.tgz#c8c630d4c18cd326beff77404887596f96408408"
|
||||
integrity sha512-pOKLaubrAEMUItGNpgwl0HMFPrSAFic8oSVIvfu1UwcgGNmNyK9gyhBHKmBnUTwwVvpZfkzUC0GaMgnL6P86uA==
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b"
|
||||
integrity sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
@ -82,10 +82,10 @@
|
||||
resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
|
||||
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
|
||||
|
||||
"@types/yargs@^15.0.4":
|
||||
version "15.0.4"
|
||||
resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299"
|
||||
integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==
|
||||
"@types/yargs@^15.0.5":
|
||||
version "15.0.5"
|
||||
resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79"
|
||||
integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
@ -136,26 +136,26 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
"@types/color-name" "^1.1.1"
|
||||
color-convert "^2.0.1"
|
||||
|
||||
app-builder-bin@3.5.8:
|
||||
version "3.5.8"
|
||||
resolved "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.8.tgz#4b96cf7d114171b20f32138082dc7cf20f16b85d"
|
||||
integrity sha512-ni3q7QTfQNWHNWuyn5x3FZu6GnQZv+TFnfgk5++svqleKEhHGqS1mIaKsh7x5pBX6NFXU3/+ktk98wA/AW4EXw==
|
||||
app-builder-bin@3.5.9:
|
||||
version "3.5.9"
|
||||
resolved "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.9.tgz#a3ac0c25286bac68357321cb2eaf7128b0bc0a4f"
|
||||
integrity sha512-NSjtqZ3x2kYiDp3Qezsgukx/AUzKPr3Xgf9by4cYt05ILWGAptepeeu0Uv+7MO+41o6ujhLixTou8979JGg2Kg==
|
||||
|
||||
app-builder-lib@22.6.0:
|
||||
version "22.6.0"
|
||||
resolved "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.6.0.tgz#65782fa8fc96180a22c008eb78c1355349bb0b86"
|
||||
integrity sha512-ky2aLYy92U+Gh6dKq/e8/bNmCotp6/GMhnX8tDZPv9detLg9WuBnWWi1ktBPlpbl1DREusy+TIh+9rgvfduQoA==
|
||||
app-builder-lib@22.6.1:
|
||||
version "22.6.1"
|
||||
resolved "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.6.1.tgz#f17bfbde1bbb26ae438e450b66005bf6714feb30"
|
||||
integrity sha512-ENL7r+H7IBfDb4faeLASgndsXrAT7AV7m7yJjcpbFDXYma6an7ZWGFIvR0HJrsfiC5TIB8kdLJ/aMSImrrSi/Q==
|
||||
dependencies:
|
||||
"7zip-bin" "~5.0.3"
|
||||
"@develar/schema-utils" "~2.6.5"
|
||||
async-exit-hook "^2.0.1"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util "22.6.0"
|
||||
builder-util "22.6.1"
|
||||
builder-util-runtime "8.7.0"
|
||||
chromium-pickle-js "^0.2.0"
|
||||
debug "^4.1.1"
|
||||
ejs "^3.1.2"
|
||||
electron-publish "22.6.0"
|
||||
electron-publish "22.6.1"
|
||||
fs-extra "^9.0.0"
|
||||
hosted-git-info "^3.0.4"
|
||||
is-ci "^2.0.0"
|
||||
@ -169,6 +169,11 @@ app-builder-lib@22.6.0:
|
||||
semver "^7.3.2"
|
||||
temp-file "^3.3.7"
|
||||
|
||||
appdata-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/appdata-path/-/appdata-path-1.0.0.tgz#c4022d0b6727d1ddc1dd7ecec143d4352f3eefad"
|
||||
integrity sha512-ZbH3ezXfnT/YE3NdqduIt4lBV+H0ybvA2Qx3K76gIjQvh8gROpDFdDLpx6B1QJtW7zxisCbpTlCLhKqoR8cDBw==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
@ -253,15 +258,15 @@ builder-util-runtime@8.7.0:
|
||||
debug "^4.1.1"
|
||||
sax "^1.2.4"
|
||||
|
||||
builder-util@22.6.0:
|
||||
version "22.6.0"
|
||||
resolved "https://registry.npmjs.org/builder-util/-/builder-util-22.6.0.tgz#25a3aca05d2c44949f0600282264dace8d289ee7"
|
||||
integrity sha512-jgdES2ExJYkuXC3DEaGAjFctKNA81C4QDy8zdoc+rqdSqheTizuDNtZg02uMFklmUES4V4fggmqds+Y7wraqng==
|
||||
builder-util@22.6.1:
|
||||
version "22.6.1"
|
||||
resolved "https://registry.npmjs.org/builder-util/-/builder-util-22.6.1.tgz#78172c3634da460325277ef798994592e595eff3"
|
||||
integrity sha512-A9cF+bSHqRTSKIUHEyE92Tl0Uh12N7yZRH9bccIL3gRUwtp6ulF28LsjNIWTSQ1clZo2M895cT5PCrKzjPQFVg==
|
||||
dependencies:
|
||||
"7zip-bin" "~5.0.3"
|
||||
"@types/debug" "^4.1.5"
|
||||
"@types/fs-extra" "^8.1.0"
|
||||
app-builder-bin "3.5.8"
|
||||
app-builder-bin "3.5.9"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util-runtime "8.7.0"
|
||||
chalk "^4.0.0"
|
||||
@ -469,13 +474,13 @@ detect-node@^2.0.4:
|
||||
resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||
|
||||
dmg-builder@22.6.0:
|
||||
version "22.6.0"
|
||||
resolved "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.6.0.tgz#78c3dee24f5713f4844d458949041e31fe7eec30"
|
||||
integrity sha512-rJxuGhHIpcuDGBtWZMM8aLxkbZNgYO2MO5dUerDIBXebhX1K8DA23iz/uZ8ahcRNgWEv57b8GDqJbXKEfr5T0A==
|
||||
dmg-builder@22.6.1:
|
||||
version "22.6.1"
|
||||
resolved "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.6.1.tgz#5777a9eb6904db5bf1f4c69addbf462f5f9bf4e4"
|
||||
integrity sha512-jUTN0acP15puzevtQASj7QEPgUGpedWSuSnOwR/++JbeYRTwU2oro09h/KZnaeMcxgxjdmT3tYLJeY1XUfPbRg==
|
||||
dependencies:
|
||||
app-builder-lib "22.6.0"
|
||||
builder-util "22.6.0"
|
||||
app-builder-lib "22.6.1"
|
||||
builder-util "22.6.1"
|
||||
fs-extra "^9.0.0"
|
||||
iconv-lite "^0.5.1"
|
||||
js-yaml "^3.13.1"
|
||||
@ -504,24 +509,24 @@ duplexer3@^0.1.4:
|
||||
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
|
||||
|
||||
ejs@^3.0.1, ejs@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/ejs/-/ejs-3.1.2.tgz#a9986e6920a60f2a3229e87d4f0f3c073209874c"
|
||||
integrity sha512-zFuywxrAWtX5Mk2KAuoJNkXXbfezpNA0v7i+YC971QORguPekpjpAgeOv99YWSdKXwj7JxI2QAWDeDkE8fWtXw==
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz#514d967a8894084d18d3d47bd169a1c0560f093d"
|
||||
integrity sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==
|
||||
dependencies:
|
||||
jake "^10.6.1"
|
||||
|
||||
electron-builder@^22.4.0:
|
||||
version "22.6.0"
|
||||
resolved "https://registry.npmjs.org/electron-builder/-/electron-builder-22.6.0.tgz#3ac81634e27026892d66f3a52568e65a7d28d26a"
|
||||
integrity sha512-aLHlB6DTfjJ3MI4AUIFeWnwIozNgNlbOk2c2sTHxB10cAKp0dBVSPZ7xF5NK0uwDhElvRzJQubnHtJD6zKg42Q==
|
||||
version "22.6.1"
|
||||
resolved "https://registry.npmjs.org/electron-builder/-/electron-builder-22.6.1.tgz#9cc704356ecba1342ff1c94d610aad1f3c6a8b02"
|
||||
integrity sha512-3/VNg9GfXKHM53TilFtfF1+bsAR8THK1XHgeqCpsiequa02J9jTPc/DhpCUKQPkrs6/EIGxP7uboop7XYoew0Q==
|
||||
dependencies:
|
||||
"@types/yargs" "^15.0.4"
|
||||
app-builder-lib "22.6.0"
|
||||
"@types/yargs" "^15.0.5"
|
||||
app-builder-lib "22.6.1"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util "22.6.0"
|
||||
builder-util "22.6.1"
|
||||
builder-util-runtime "8.7.0"
|
||||
chalk "^4.0.0"
|
||||
dmg-builder "22.6.0"
|
||||
dmg-builder "22.6.1"
|
||||
fs-extra "^9.0.0"
|
||||
is-ci "^2.0.0"
|
||||
lazy-val "^1.0.4"
|
||||
@ -530,19 +535,19 @@ electron-builder@^22.4.0:
|
||||
update-notifier "^4.1.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
electron-publish@22.6.0:
|
||||
version "22.6.0"
|
||||
resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-22.6.0.tgz#11dca595cfe3c0fdbc364c28dbb8838a1c6ec799"
|
||||
integrity sha512-+v05SBf9qR7Os5au+fifloNHy5QxHQkUGudBj68YaTb43Pn37UkwRxSc49Lf13s4wW32ohM45g8BOVInPJEdnA==
|
||||
electron-publish@22.6.1:
|
||||
version "22.6.1"
|
||||
resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-22.6.1.tgz#d5381220d3e0f3bfa869c5a059fd253a561e0f8a"
|
||||
integrity sha512-/MkS47ospdSfAFW5Jp52OzYou14HhGJpZ51uAc3GJ5rCfACeqpimC/n1ajRLE3hcXxTWfd3t9MCuClq5jrUO5w==
|
||||
dependencies:
|
||||
"@types/fs-extra" "^8.1.0"
|
||||
bluebird-lst "^1.0.9"
|
||||
builder-util "22.6.0"
|
||||
builder-util "22.6.1"
|
||||
builder-util-runtime "8.7.0"
|
||||
chalk "^4.0.0"
|
||||
fs-extra "^9.0.0"
|
||||
lazy-val "^1.0.4"
|
||||
mime "^2.4.4"
|
||||
mime "^2.4.5"
|
||||
|
||||
electron-updater@^4.2.4:
|
||||
version "4.3.1"
|
||||
@ -557,10 +562,10 @@ electron-updater@^4.2.4:
|
||||
lodash.isequal "^4.5.0"
|
||||
semver "^7.1.3"
|
||||
|
||||
electron@^8.2.0:
|
||||
version "8.2.5"
|
||||
resolved "https://registry.npmjs.org/electron/-/electron-8.2.5.tgz#ae3cb23d5517b2189fd35298e487198d65d1a291"
|
||||
integrity sha512-LxSCUwmlfJtRwthd3ofpYaZ+1C2hQSW8Ep1DD9K3VbnDItO+kb3t1z35daJgAab78j54aOwo9gMxJtvU0Ftj6w==
|
||||
electron@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.npmjs.org/electron/-/electron-9.0.0.tgz#335cd426a8a542ad8d4c96c0c40a8668ab5527b8"
|
||||
integrity sha512-JsaSQNPh+XDYkLj8APtVKTtvpb86KIG57W5OOss4TNrn8L3isC9LsCITwfnVmGIXHhvX6oY/weCtN5hAAytjVg==
|
||||
dependencies:
|
||||
"@electron/get" "^1.0.1"
|
||||
"@types/node" "^12.0.12"
|
||||
@ -1004,7 +1009,7 @@ matcher@^2.1.0:
|
||||
dependencies:
|
||||
escape-string-regexp "^2.0.0"
|
||||
|
||||
mime@^2.4.4:
|
||||
mime@^2.4.5:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009"
|
||||
integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==
|
||||
@ -1361,9 +1366,9 @@ spdx-exceptions@^2.1.0:
|
||||
integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
|
||||
|
||||
spdx-expression-parse@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
|
||||
integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
|
||||
integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
|
||||
dependencies:
|
||||
spdx-exceptions "^2.1.0"
|
||||
spdx-license-ids "^3.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user