Partial export processing
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
||||
"@fortawesome/react-fontawesome": "^0.1.11",
|
||||
"@reduxjs/toolkit": "^1.3.4",
|
||||
"auto-launch": "^5.0.5",
|
||||
"axios": "^0.19.2",
|
||||
@@ -19,6 +19,7 @@
|
||||
"node-schedule": "^1.3.2",
|
||||
"randomstring": "^1.1.5",
|
||||
"react": "^16.13.1",
|
||||
"react-checkbox-tree": "^1.6.0",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-loader-spinner": "^3.1.5",
|
||||
"react-redux": "^7.2.0",
|
||||
|
||||
23
src/App.js
23
src/App.js
@@ -36,6 +36,7 @@ import {createModalConditionally} from './utils';
|
||||
import SkynetImport from './containers/SkynetImport/SkynetImport';
|
||||
import {displaySkynetImport} from './redux/actions/skynet_actions';
|
||||
import ApplicationBusy from './components/ApplicationBusy/ApplicationBusy';
|
||||
import SkynetExport from './containers/SkynetExport/SkynetExport';
|
||||
|
||||
const Constants = require('./constants');
|
||||
const Scheduler = require('node-schedule');
|
||||
@@ -162,12 +163,23 @@ class App extends IPCContainer {
|
||||
!showUpgrade &&
|
||||
this.props.DisplayImport;
|
||||
|
||||
const configDisplay = createModalConditionally(showConfig, <Configuration version={selectedVersion}
|
||||
const showSkynetExport = !showConfig &&
|
||||
!showDependencies &&
|
||||
!this.props.DownloadActive &&
|
||||
!showNewReleases &&
|
||||
!this.props.RebootRequired &&
|
||||
!this.props.DisplaySelectAppPlatform &&
|
||||
!showUpgrade &&
|
||||
this.props.DisplayExport;
|
||||
|
||||
const configDisplay = createModalConditionally(showConfig, <Configuration
|
||||
version={selectedVersion}
|
||||
remoteSupported={remoteSupported}/>);
|
||||
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
|
||||
const dependencyDisplay = createModalConditionally(showDependencies,
|
||||
<DependencyList/>, false, this.props.InstallActive);
|
||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress/>, false, true);
|
||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive,
|
||||
<DownloadProgress/>, false, true);
|
||||
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
|
||||
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
|
||||
const newReleasesDisplay = createModalConditionally(showNewReleases, <NewReleases/>);
|
||||
@@ -175,7 +187,10 @@ class App extends IPCContainer {
|
||||
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform,
|
||||
<SelectAppPlatform/>);
|
||||
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
|
||||
const importDisplay = createModalConditionally(showSkynetImport, <SkynetImport version={selectedVersion}/>);
|
||||
const importDisplay = createModalConditionally(showSkynetImport, <SkynetImport
|
||||
version={selectedVersion}/>);
|
||||
const exportDisplay = createModalConditionally(showSkynetExport, <SkynetExport
|
||||
version={selectedVersion}/>)
|
||||
const appBusyDisplay = createModalConditionally(this.props.AppBusy,
|
||||
<ApplicationBusy/>, false, true, this.props.AppBusyTransparent);
|
||||
|
||||
@@ -246,6 +261,7 @@ class App extends IPCContainer {
|
||||
</div>
|
||||
</div>
|
||||
{importDisplay}
|
||||
{exportDisplay}
|
||||
{newReleasesDisplay}
|
||||
{selectAppPlatformDisplay}
|
||||
{dependencyDisplay}
|
||||
@@ -274,6 +290,7 @@ const mapStateToProps = state => {
|
||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
||||
DisplayError: state.error.DisplayError,
|
||||
DisplayExport: state.skynet.DisplayExport,
|
||||
DisplayImport: state.skynet.DisplayImport,
|
||||
DisplayInfo: state.error.DisplayInfo,
|
||||
DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform,
|
||||
|
||||
@@ -99,6 +99,9 @@ exports.IPC_Download_File = 'download_file';
|
||||
exports.IPC_Download_File_Complete = 'download_file_complete';
|
||||
exports.IPC_Download_File_Progress = 'download_file_progress';
|
||||
|
||||
exports.IPC_Export_Skylinks = 'export_skylinks';
|
||||
exports.IPC_Export_Skylinks_Reply = 'export_skylinks_reply';
|
||||
|
||||
exports.IPC_Extract_Release = 'extract_release';
|
||||
exports.IPC_Extract_Release_Complete = 'extract_release_complete';
|
||||
|
||||
@@ -114,6 +117,9 @@ exports.IPC_Get_Platform_Reply = 'get_platform_reply';
|
||||
exports.IPC_Get_State = 'get_state';
|
||||
exports.IPC_Get_State_Reply = 'get_state_reply';
|
||||
|
||||
exports.IPC_Grab_Skynet_Tree = 'grab_skynet_tree';
|
||||
exports.IPC_Grab_Skynet_Tree_Reply = 'grab_skynet_tree_reply';
|
||||
|
||||
exports.IPC_Import_Skylinks = 'import_skylinks';
|
||||
exports.IPC_Import_Skylinks_Reply = 'import_skylinks_reply';
|
||||
|
||||
|
||||
4
src/containers/SkynetExport/SkynetExport.css
Normal file
4
src/containers/SkynetExport/SkynetExport.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.SkynetExportHeading {
|
||||
text-align: center;
|
||||
padding-bottom: var(--default_spacing);
|
||||
}
|
||||
144
src/containers/SkynetExport/SkynetExport.js
Normal file
144
src/containers/SkynetExport/SkynetExport.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import React from 'react';
|
||||
import './SkynetExport.css';
|
||||
import CheckboxTree from 'react-checkbox-tree';
|
||||
import {connect} from 'react-redux';
|
||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
||||
import {notifyError} from '../../redux/actions/error_actions';
|
||||
import Box from '../../components/UI/Box/Box';
|
||||
import {displaySkynetExport} from '../../redux/actions/skynet_actions';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faCheckSquare, faChevronDown,
|
||||
faChevronRight, faFile, faFolder, faFolderOpen,
|
||||
faHSquare, faMinusSquare, faPlusSquare,
|
||||
faSquare, faSquareFull, faSquareRootAlt
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const Constants = require('../../constants');
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
AppBusy: state.common.AppBusy,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||
notifyError: msg => dispatch(notifyError(msg)),
|
||||
}
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||
state = {
|
||||
checked: [],
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setRequestHandler(Constants.IPC_Grab_Skynet_Tree_Reply, this.onGrabSkynetTreeReply);
|
||||
this.setRequestHandler(Constants.IPC_Export_Skylinks_Reply, this.onExportSkylinksReply);
|
||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
createNodes = items => {
|
||||
/*
|
||||
{
|
||||
name: '',
|
||||
path: '',
|
||||
directory: true/false,
|
||||
children: [],
|
||||
}
|
||||
*/
|
||||
const ret = [];
|
||||
for (const item of items) {
|
||||
const treeItem = {
|
||||
label: item.name,
|
||||
path: item.path,
|
||||
value: item.name === '/' ? 0 : JSON.stringify(item),
|
||||
};
|
||||
|
||||
if (item.directory) {
|
||||
treeItem.children = this.createNodes(item.children);
|
||||
}
|
||||
|
||||
ret.push(treeItem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
onGrabSkynetTreeReply = (_, arg) => {
|
||||
if (arg.data.Success) {
|
||||
this.setState({
|
||||
checked: [],
|
||||
expanded: [0],
|
||||
nodes: this.createNodes(arg.data.Result),
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
checked: [],
|
||||
expanded: [],
|
||||
nodes: [],
|
||||
}, () => {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onExportSkylinksReply = (_, arg) => {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log(this.state.expanded);
|
||||
return this.props.AppBusy ? (<div/>) : (
|
||||
<Box dxDark dxStyle={{
|
||||
height: '90vh',
|
||||
padding: 'var(--default_spacing)',
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block'
|
||||
}}>
|
||||
<a href={'#'}
|
||||
onClick={() => this.props.displaySkynetExport(false)}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
</div>
|
||||
<h1 className={'SkynetExportHeading'}>{'Export Files'}</h1>
|
||||
<CheckboxTree checked={this.state.checked}
|
||||
expanded={this.state.expanded}
|
||||
icons={{
|
||||
check: <FontAwesomeIcon icon={faCheckSquare}/>,
|
||||
uncheck: <FontAwesomeIcon icon={faSquare}/>,
|
||||
halfCheck: <FontAwesomeIcon icon={faHSquare}/>,
|
||||
expandClose: <FontAwesomeIcon icon={faChevronRight}/>,
|
||||
expandOpen: <FontAwesomeIcon icon={faChevronDown}/>,
|
||||
expandAll: <FontAwesomeIcon icon={faPlusSquare}/>,
|
||||
collapseAll: <FontAwesomeIcon icon={faMinusSquare}/>,
|
||||
parentClose: <FontAwesomeIcon icon={faFolder}
|
||||
color={'var(--heading_text_color)'}/>,
|
||||
parentOpen: <FontAwesomeIcon icon={faFolderOpen}
|
||||
color={'var(--heading_text_color)'}/>,
|
||||
leaf: <FontAwesomeIcon icon={faFile} color={'var(--heading_text_color)'}/>
|
||||
}}
|
||||
nodes={this.state.nodes}
|
||||
onCheck={checked => this.setState({checked})}
|
||||
onExpand={expanded => this.setState({expanded})}/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -166,12 +166,20 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||
}}>
|
||||
<div
|
||||
style={{float: 'right', margin: 0, padding: 0, marginTop: '-4px', boxSizing: 'border-box', display: 'block'}}>
|
||||
style={{
|
||||
float: 'right',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
marginTop: '-4px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'block'
|
||||
}}>
|
||||
<a href={'#'}
|
||||
onClick={() => this.props.displaySkynetImport(false)}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
</div>
|
||||
<h1 className={'SkynetImportHeading'}>{this.state.second_stage ? 'Verify Imports' : 'Import List'}</h1>
|
||||
<h1
|
||||
className={'SkynetImportHeading'}>{this.state.second_stage ? 'Verify Imports' : 'Import List'}</h1>
|
||||
{
|
||||
this.state.second_stage ? (
|
||||
<ImportList imports_array={this.state.imports_array}/>
|
||||
@@ -186,7 +194,8 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
||||
)
|
||||
}
|
||||
<div className={'SkynetImportButtons'}>
|
||||
<Button buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
|
||||
<Button
|
||||
buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
|
||||
clicked={this.displaySyntax}>Import Syntax...</Button>
|
||||
<div className={'SkynetActionButtons'}>
|
||||
{
|
||||
@@ -206,7 +215,8 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
||||
marginLeft: 'var(--default_spacing)',
|
||||
marginTop: 'var(--default_spacing)',
|
||||
width: 'auto'
|
||||
}} clicked={this.handleNavigation}>{this.state.second_stage ? 'Import' : 'Next'}</Button>
|
||||
}}
|
||||
clicked={this.handleNavigation}>{this.state.second_stage ? 'Import' : 'Next'}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
133
src/helpers.js
133
src/helpers.js
@@ -9,7 +9,6 @@ const Constants = require('./constants');
|
||||
const RandomString = require('randomstring');
|
||||
|
||||
let vcRuntimeExists;
|
||||
|
||||
const _vcRuntimeExists = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (os.platform() !== 'win32') {
|
||||
@@ -19,7 +18,7 @@ const _vcRuntimeExists = () => {
|
||||
resolve(true);
|
||||
} else {
|
||||
const cmd = path.join(process.env.windir, 'system32', 'reg.exe');
|
||||
const args = ["QUERY", "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"];
|
||||
const args = ['QUERY', 'HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'];
|
||||
_execProcessGetOutput(cmd, null, args)
|
||||
.then(lines => {
|
||||
const parseLine = index => {
|
||||
@@ -62,7 +61,93 @@ const _vcRuntimeExists = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const _executeProcess = (command, working, args=[]) => {
|
||||
// https://stackoverflow.com/questions/19531453/transform-file-directory-structure-into-tree-in-javascript
|
||||
const _createTreeNodes = fileList => {
|
||||
let tree = {}
|
||||
|
||||
const directorySort = (a, b) => {
|
||||
return !!a.directory === !!b.directory ? a.name.localeCompare(b.name) : a.directory ? -1 : 1;
|
||||
};
|
||||
|
||||
const addNode = obj => {
|
||||
const fullPath = path.join(obj.directory, obj.filename).replace(/\\/g, '/');
|
||||
const pathParts = fullPath.replace(/^\/|\/$/g, '').split('/');
|
||||
let ptr = tree;
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const node = {
|
||||
directory: true,
|
||||
name: pathParts[i],
|
||||
};
|
||||
if (i === pathParts.length - 1) {
|
||||
node.directory = false;
|
||||
node.path = fullPath;
|
||||
}
|
||||
ptr[pathParts[i]] = ptr[pathParts[i]] || node;
|
||||
ptr[pathParts[i]].children = ptr[pathParts[i]].children || {};
|
||||
ptr = ptr[pathParts[i]].children;
|
||||
}
|
||||
}
|
||||
|
||||
const objectToArray = node => {
|
||||
Object.keys(node || {}).map((k) => {
|
||||
if (node[k].children) {
|
||||
objectToArray(node[k])
|
||||
}
|
||||
})
|
||||
if (node.children) {
|
||||
node.children = Object.values(node.children);
|
||||
node.children.forEach(objectToArray)
|
||||
node.children = node.children.sort(directorySort);
|
||||
}
|
||||
}
|
||||
|
||||
fileList.map(addNode);
|
||||
objectToArray(tree);
|
||||
return Object.values(tree).sort(directorySort);
|
||||
};
|
||||
|
||||
const _exportAllSkylinks = version => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const repertoryExec = _getRepertoryExec(version);
|
||||
const processOptions = {
|
||||
cwd: repertoryExec.working,
|
||||
detached: true,
|
||||
shell: false,
|
||||
windowsHide: true,
|
||||
};
|
||||
|
||||
const args = _getDefaultRepertoryArgs('Skynet');
|
||||
args.push('-ea');
|
||||
|
||||
let result = '';
|
||||
const process = new spawn(repertoryExec.cmd, args, processOptions);
|
||||
|
||||
process.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
process.stderr.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
process.on('exit', code => {
|
||||
if (code === 0) {
|
||||
result = result.substr(result.indexOf('{'));
|
||||
resolve(JSON.parse(result));
|
||||
} else {
|
||||
reject(new Error('Failed to import: ' + code + ':' + result));
|
||||
}
|
||||
});
|
||||
|
||||
process.unref();
|
||||
});
|
||||
};
|
||||
|
||||
const _executeProcess = (command, working, args = []) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let processOptions = {
|
||||
detached: true,
|
||||
@@ -392,7 +477,7 @@ module.exports.executeAndWait = (command, ignoreResult) => {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.executeAsync = (command, args=[]) => {
|
||||
module.exports.executeAsync = (command, args = []) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const launchProcess = (count, timeout) => {
|
||||
let cmd = path.basename(command);
|
||||
@@ -416,7 +501,7 @@ module.exports.executeAsync = (command, args=[]) => {
|
||||
reject(err, pid);
|
||||
} else {
|
||||
clearTimeout(timeout);
|
||||
setTimeout(()=> launchProcess(count, setTimeout(() => resolve(), 3000)), 1000);
|
||||
setTimeout(() => launchProcess(count, setTimeout(() => resolve(), 3000)), 1000);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -458,7 +543,7 @@ module.exports.executeScript = script => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on('data', (d)=> {
|
||||
process.stdout.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
@@ -510,6 +595,8 @@ module.exports.executeMount = (version, provider, remote, location, exitCallback
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.exportAllSkylinks = _exportAllSkylinks;
|
||||
|
||||
module.exports.getConfig = (version, provider, remote) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const repertoryExec = _getRepertoryExec(version);
|
||||
@@ -530,7 +617,7 @@ module.exports.getConfig = (version, provider, remote) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on('data', (d)=> {
|
||||
process.stdout.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
@@ -574,7 +661,7 @@ module.exports.getConfigTemplate = (version, provider, remote) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on('data', (d)=> {
|
||||
process.stdout.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
@@ -666,7 +753,7 @@ module.exports.getMissingDependencies = dependencies => {
|
||||
};
|
||||
|
||||
for (const dependency of dependencies) {
|
||||
checkRegistry(dependency,0);
|
||||
checkRegistry(dependency, 0);
|
||||
}
|
||||
} else {
|
||||
for (const dep of dependencies) {
|
||||
@@ -683,6 +770,22 @@ module.exports.getMissingDependencies = dependencies => {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.grabSkynetFileTree = version => {
|
||||
return new Promise((resolve, reject) => {
|
||||
_exportAllSkylinks(version)
|
||||
.then(results => {
|
||||
resolve([{
|
||||
name: '/',
|
||||
directory: true,
|
||||
children: _createTreeNodes(results.success),
|
||||
}]);
|
||||
})
|
||||
.catch(e => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.importSkylinks = (version, jsonArray) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const repertoryExec = _getRepertoryExec(version);
|
||||
@@ -704,11 +807,11 @@ module.exports.importSkylinks = (version, jsonArray) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
process.stdout.on('data', (d)=> {
|
||||
process.stdout.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
process.stderr.on('data', (d)=> {
|
||||
process.stderr.on('data', (d) => {
|
||||
result += d;
|
||||
});
|
||||
|
||||
@@ -726,7 +829,7 @@ module.exports.importSkylinks = (version, jsonArray) => {
|
||||
};
|
||||
|
||||
//https://stackoverflow.com/questions/31645738/how-to-create-full-path-with-nodes-fs-mkdirsync
|
||||
module.exports.mkDirByPathSync = (targetDir, { isRelativeToScript = false } = {}) => {
|
||||
module.exports.mkDirByPathSync = (targetDir, {isRelativeToScript = false} = {}) => {
|
||||
const sep = path.sep;
|
||||
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
||||
const baseDir = isRelativeToScript ? __dirname : '.';
|
||||
@@ -761,7 +864,7 @@ module.exports.performWindowsUninstall = names => {
|
||||
reject('Windows OS is not being used');
|
||||
} else {
|
||||
const cmd = path.join(process.env.windir, 'system32', 'reg.exe');
|
||||
const args = ["QUERY", "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"];
|
||||
const args = ['QUERY', 'HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'];
|
||||
_execProcessGetOutput(cmd, null, args)
|
||||
.then(lines => {
|
||||
const parseLine = index => {
|
||||
@@ -780,7 +883,7 @@ module.exports.performWindowsUninstall = names => {
|
||||
if (names.includes(value)) {
|
||||
const items = line.split('\\');
|
||||
const productCode = items[items.length - 1];
|
||||
_executeProcess('msiexec.exe', null,['/x', productCode, '/norestart'])
|
||||
_executeProcess('msiexec.exe', null, ['/x', productCode, '/norestart'])
|
||||
.then(code => {
|
||||
if ((code === 0) || (code === 3010) || (code === 1641)) {
|
||||
resolve(true);
|
||||
@@ -807,7 +910,7 @@ module.exports.performWindowsUninstall = names => {
|
||||
};
|
||||
parseLine(0);
|
||||
})
|
||||
.catch( err => {
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {Provider} from 'react-redux';
|
||||
import {setActiveRelease} from './redux/actions/release_version_actions';
|
||||
import {setProviderState} from './redux/actions/mount_actions';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import 'react-checkbox-tree/lib/react-checkbox-tree.css';
|
||||
|
||||
const Constants = require('./constants');
|
||||
|
||||
|
||||
@@ -14,6 +14,19 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {}, error);
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on(Constants.IPC_Grab_Skynet_Tree, (event, data) => {
|
||||
helpers
|
||||
.grabSkynetFileTree(data.Version)
|
||||
.then(result => {
|
||||
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {
|
||||
Result: result,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {}, error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
Reference in New Issue
Block a user