diff --git a/electron.js b/electron.js index 48c4000..c943087 100644 --- a/electron.js +++ b/electron.js @@ -275,7 +275,8 @@ ipcMain.on('extract_release', (event, data) => { helpers.mkDirByPathSync(destination); const stream = fs.createReadStream(data.Source); - stream.pipe(unzip.Extract({ path: destination })) + stream + .pipe(unzip.Extract({ path: destination })) .on('error', (e) => { try { helpers.removeDirectoryRecursively(destination); @@ -301,6 +302,59 @@ ipcMain.on('extract_release', (event, data) => { }); }); +ipcMain.on('get_config', (event, data) => { + const dataDirectory = helpers.resolvePath(data.Directory); + helpers + .getConfig(dataDirectory, data.Version, data.StorageType) + .then((data) => { + if (data.Code === 0) { + event.sender.send('get_config_reply', { + data: { + Success: true, + Config: data.Data, + } + }); + } else { + event.sender.send('get_config_reply', { + data: { + Error: data.Code, + Success: false, + } + }); + } + }) + .catch((e)=> { + event.sender.send('get_config_reply', { + data: { + Error: e, + Success: false, + } + }); + }); +}); + +ipcMain.on('get_config_template', (event, data) => { + const dataDirectory = helpers.resolvePath(data.Directory); + helpers + .getConfigTemplate(dataDirectory, data.Version, data.StorageType) + .then((data) => { + event.sender.send('get_config_template_reply', { + data: { + Success: true, + Template: data, + } + }); + }) + .catch((e)=> { + event.sender.send('get_config_template_reply', { + data: { + Error: e, + Success: false, + } + }); + }); +}); + ipcMain.on('get_platform', (event) => { event.sender.send('get_platform_reply', { data: os.platform() @@ -408,14 +462,34 @@ ipcMain.on('save_state', (event, data) => { fs.writeFileSync(configFile, JSON.stringify(data.State), 'utf8'); }); -ipcMain.on('unmount_drive', (event, data) => { - helpers.stopProcessByPID(data.PID) - .then((pid)=> { - if (mountedPIDs.indexOf(pid) === -1) { - event.sender.send('unmount_drive_reply'); +ipcMain.on('set_config_values', (event, data) => { + const dataDirectory = helpers.resolvePath(data.Directory); + const setConfigValue = (i) => { + if (i < data.Items.length) { + helpers + .setConfigValue(data.Items[i].Name, data.Items[i].Value, dataDirectory, data.StorageType, data.Version) + .then(() => { + setConfigValue(++i); + }) + .catch(() => { + setConfigValue(++i); + }); + } else { + event.sender.send('set_config_values_reply', {}); } - }) - .catch((e) => { - console.log(e); - }); + }; + setConfigValue(0); +}); + +ipcMain.on('unmount_drive', (event, data) => { + helpers + .stopProcessByPID(data.PID) + .then((pid)=> { + if (mountedPIDs.indexOf(pid) === -1) { + event.sender.send('unmount_drive_reply'); + } + }) + .catch((e) => { + console.log(e); + }); }); diff --git a/helpers.js b/helpers.js index 69ac777..7564a12 100644 --- a/helpers.js +++ b/helpers.js @@ -195,6 +195,85 @@ module.exports.executeMount = (directory, version, storageType, location, exitCa }); }; +module.exports.getConfig = (directory, version, storageType) => { + return new Promise((resolve, reject) => { + const processOptions = { + detached: true, + shell: false, + windowsHide: true, + }; + + const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); + const args = []; + args.push('-dc'); + if (storageType.toLowerCase() === 'hyperspace') { + args.push('-hs'); + } + + const process = new spawn(command, args, processOptions); + let result = ''; + + process.on('error', (err) => { + reject(err); + }); + + process.stdout.on('data', (d)=> { + result += d; + }); + + process.on('exit', () => { + const lines = result + .replace(/\r\n/g, '\n') + .split('\n'); + + const code = parseInt(lines[0], 10); + if (code === 0) { + lines.shift(); + resolve({ + Code: code, + Data: JSON.parse(lines.join('\n')), + }); + } else { + resolve(code); + } + }); + process.unref(); + }); +}; + +module.exports.getConfigTemplate = (directory, version, storageType) => { + return new Promise((resolve, reject) => { + const processOptions = { + detached: true, + shell: false, + windowsHide: true, + }; + + const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); + const args = []; + args.push('-gt'); + if (storageType.toLowerCase() === 'hyperspace') { + args.push('-hs'); + } + + const process = new spawn(command, args, processOptions); + let result = ''; + + process.on('error', (err) => { + reject(err); + }); + + process.stdout.on('data', (d)=> { + result += d; + }); + + process.on('exit', () => { + resolve(JSON.parse(result)); + }); + process.unref(); + }); +}; + module.exports.getMissingDependencies = dependencies => { return new Promise((resolve, reject) => { if (!dependencies || (dependencies.length === 0)) { @@ -323,6 +402,37 @@ module.exports.resolvePath = str => { } }; +module.exports.setConfigValue = (name, value, directory, storageType, version) => { + return new Promise((resolve, reject) => { + const processOptions = { + detached: true, + shell: false, + windowsHide: true, + }; + + const command = path.join(directory, version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); + const args = []; + args.push('-set'); + args.push(name); + args.push(value); + if (storageType.toLowerCase() === 'hyperspace') { + args.push('-hs'); + } + + const process = new spawn(command, args, processOptions); + + process.on('error', (err) => { + reject(err); + }); + + process.on('exit', () => { + resolve(); + }); + + process.unref(); + }); +}; + module.exports.stopProcessByPID = pid => { return new Promise((resolve, reject) => { const processOptions = { diff --git a/src/App.js b/src/App.js index 73be628..2635a6f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,18 +1,20 @@ import React, {Component} from 'react'; -import CSSModules from 'react-css-modules'; -import styles from './App.css'; -import Box from './components/UI/Box/Box'; -import DropDown from './components/UI/DropDown/DropDown'; import * as Constants from './constants'; import axios from 'axios'; -import MountItems from './containers/MountItems/MountItems'; -import DependencyList from './components/DependencyList/DependencyList'; +import styles from './App.css'; +import Box from './components/UI/Box/Box'; import Button from './components/UI/Button/Button'; -import Modal from './components/UI/Modal/Modal'; +import Configuration from './containers/Configuration/Configuration'; +import CSSModules from 'react-css-modules'; +import DependencyList from './components/DependencyList/DependencyList'; import DownloadProgress from './components/DownloadProgress/DownloadProgress'; -import UpgradeUI from './components/UpgradeUI/UpgradeUI'; -import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; +import DropDown from './components/UI/DropDown/DropDown'; import Loading from './components/UI/Loading/Loading'; +import Modal from './components/UI/Modal/Modal'; +import MountItems from './containers/MountItems/MountItems'; +import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; +import UpgradeUI from './components/UpgradeUI/UpgradeUI'; + const Scheduler = require('node-schedule'); let ipcRenderer = null; @@ -208,6 +210,7 @@ class App extends Component { AllowOptions: false, AllowDownload: false, AutoMountChecked: false, + ConfigStorageType: null, DownloadActive: false, DownloadProgress: 0.0, DownloadingDependency: false, @@ -313,6 +316,18 @@ class App extends Component { this.saveState(this.state.Release, this.state.Version, sia, hyperspace); }; + handleConfigClicked = (storageType) => { + this.setState({ + ConfigStorageType: storageType, + }) + }; + + handleConfigClosed = () => { + this.setState({ + ConfigStorageType: null, + }); + }; + handleDependencyDownload = (url) => { if (ipcRenderer) { const items = url.split('/'); @@ -440,30 +455,62 @@ class App extends Component { const selectedVersion = (this.state.Version === -1) ? 'unavailable' : this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]][this.state.Version]; + const downloadEnabled = this.state.AllowDownload && !this.state.MountsBusy && !this.state.DownloadActive && - (((selectedVersion !== 'unavailable') && (selectedVersion !== this.state.RepertoryVersion))); + (selectedVersion !== 'unavailable') && + (selectedVersion !== this.state.RepertoryVersion); + const allowMount = this.state.RepertoryVersion !== 'none'; const missingDependencies = (this.state.MissingDependencies.length > 0); + const allowConfig = this.state.LocationsLookup[selectedVersion] && + !this.state.LocationsLookup[selectedVersion].config_allowed; + + const showDependencies = missingDependencies && + !this.state.DownloadActive; + + const showConfig = !missingDependencies && + this.state.ConfigStorageType && + allowConfig; + + const showUpgrade = !showConfig && + !missingDependencies && + !this.state.DownloadActive && + this.state.UpgradeAvailable && + !this.state.UpgradeDismissed; + + let configDisplay = null; + if (showConfig) { + configDisplay = ( + + + + ); + } let mountDisplay = null; if (allowMount) { - mountDisplay = ; + disabled={!allowMount} + hyperspace={this.state.Hyperspace} + mountsBusy={this.notifyMountsBusy} + platform={this.state.Platform} + processAutoMount={!this.state.AutoMountChecked} + sia={this.state.Sia} + version={this.state.RepertoryVersion}/>; } let dependencyDisplay = null; - if (missingDependencies && !this.state.DownloadActive) { + if (showDependencies) { dependencyDisplay = ( - + ); } @@ -487,19 +534,16 @@ class App extends Component { if (this.state.ExtractActive) { releaseDisplay =

{'Activating <' + selectedVersion + '>'}

} else { - releaseDisplay = ; + releaseDisplay = ; } let upgradeDisplay = null; - if (!missingDependencies && - !this.state.DownloadActive && - this.state.UpgradeAvailable && - !this.state.UpgradeDismissed) { + if (showUpgrade) { upgradeDisplay = ( - this.setState({UpgradeDismissed: true})}/> + this.setState({UpgradeDismissed: true})} + upgrade={this.handleUIDownload}/> ); } @@ -510,28 +554,30 @@ class App extends Component { - - -
+

Release

-

Version

+
+

Version

+

Installed

- + selected={this.state.Release}/> - + selected={this.state.Version}/> {this.state.RepertoryVersion} @@ -558,15 +604,24 @@ class App extends Component { {dependencyDisplay} {upgradeDisplay} {downloadDisplay} - - + {configDisplay} + +
- -
- + +

{'Repertory UI v' + this.props.version}

+ this.setState({UpgradeDismissed: false})}/> diff --git a/src/assets/images/configure.png b/src/assets/images/configure.png new file mode 100644 index 0000000..e6ed2e0 Binary files /dev/null and b/src/assets/images/configure.png differ diff --git a/src/components/ConfigurationItem/ConfigurationItem.css b/src/components/ConfigurationItem/ConfigurationItem.css new file mode 100644 index 0000000..c880836 --- /dev/null +++ b/src/components/ConfigurationItem/ConfigurationItem.css @@ -0,0 +1,36 @@ +.ConfigurationItem { + margin: 0; + padding: 0; +} + +input.Input { + display: block; + margin: 0; + padding: 2px; + border-radius: var(--border_radius); + background: rgba(160, 160, 160, 0.1); + border: none; + box-shadow: none; + outline: none; + color: var(--text_color); + box-sizing: border-box; +} + +.Select { + display: block; + margin: 0; + padding: 2px; + border-radius: var(--border_radius); + background: rgba(160, 160, 160, 0.1); + border: none; + box-shadow: none; + outline: none; + color: var(--text_color); + box-sizing: border-box; +} + +.Option { + background: rgba(10, 10, 15, 0.8); + border-color: rgba(10, 10, 20, 0.9); + color: var(--text_color); +} \ No newline at end of file diff --git a/src/components/ConfigurationItem/ConfigurationItem.js b/src/components/ConfigurationItem/ConfigurationItem.js new file mode 100644 index 0000000..0f76ce2 --- /dev/null +++ b/src/components/ConfigurationItem/ConfigurationItem.js @@ -0,0 +1,107 @@ +import React from 'react'; +import CSSModules from 'react-css-modules'; +import styles from './ConfigurationItem.css'; + +export default CSSModules((props) => { + const handleChanged = (e) => { + const target = e.target; + if (target.type === 'checkbox') { + target.value = e.target.checked ? "true" : "false"; + } + props.changed(target); + }; + + let data; + switch (props.template.type) { + case "bool": + data = handleChanged(e)} + type={'checkbox'}/>; + break; + + case "double": + data = handleChanged(e)} + step={"0.01"} + styleName='Input' + type={'number'} + value={parseFloat(props.value).toFixed(2)}/>; + break; + + case "list": + const options = props.items.map((s, i) => { + return ( + + ); + }); + + data = ( + + ); + break; + + case "string": + data = handleChanged(e)} + styleName='Input' + type={'text'} + value={props.value}/>; + break; + + case "uint8": + data = handleChanged(e)} + styleName='Input' + type={'number'} + value={props.value}/>; + break; + + case "uint16": + data = handleChanged(e)} + styleName='Input' + type={'number'} + value={props.value}/>; + break; + + case "uint32": + data = handleChanged(e)} + styleName='Input' + type={'number'} + value={props.value}/>; + break; + + case "uint64": + data = handleChanged(e)} + styleName='Input' + type={'number'} + value={props.value}/>; + break; + + default: + data =
{props.value}
; + } + + return ( +
+ + + + + + + +
{props.label}{data}
+
+ ); +}, styles, {allowMultiple: true}); \ No newline at end of file diff --git a/src/components/DependencyList/DependencyList.js b/src/components/DependencyList/DependencyList.js index 4a5b155..1d387a4 100644 --- a/src/components/DependencyList/DependencyList.js +++ b/src/components/DependencyList/DependencyList.js @@ -8,15 +8,15 @@ export default CSSModules((props) => { const items = props.dependencies.map((k, i)=> { return ( ); }); return ( - +

Missing Dependencies

diff --git a/src/components/DownloadProgress/DownloadProgress.js b/src/components/DownloadProgress/DownloadProgress.js index 7263e8e..60adaf9 100644 --- a/src/components/DownloadProgress/DownloadProgress.js +++ b/src/components/DownloadProgress/DownloadProgress.js @@ -6,7 +6,7 @@ import styles from './DownloadProgress.css'; export default CSSModules((props) => { return ( - +

{'Downloading ' + props.display}

diff --git a/src/components/MountItem/MountItem.js b/src/components/MountItem/MountItem.js index eb0c45c..cb516dc 100644 --- a/src/components/MountItem/MountItem.js +++ b/src/components/MountItem/MountItem.js @@ -4,21 +4,34 @@ import styles from './MountItem.css'; import DropDown from '../UI/DropDown/DropDown'; import Button from '../UI/Button/Button'; import Loader from 'react-loader-spinner'; +import configureImage from '../../assets/images/configure.png'; export default CSSModules((props) => { + let configButton = null; + if (props.allowConfig) { + configButton = ( + + ); + } + let inputControl = null; let mountWidth = '70%'; if (props.platform === 'win32') { - inputControl = ; + selected={props.items.indexOf(props.location)}/>; mountWidth = '18%'; } else { inputControl = ; + value={props.location}/>; } let actionDisplay = null; @@ -28,21 +41,29 @@ export default CSSModules((props) => { } else { actionDisplay = ; + type='Circles' + width='24px'/>; } + return (
-

{props.title}

- +
{configButton}

{props.title}

+ - - + diff --git a/src/components/UI/DropDown/DropDown.js b/src/components/UI/DropDown/DropDown.js index 5ec0ec4..cc16361 100644 --- a/src/components/UI/DropDown/DropDown.js +++ b/src/components/UI/DropDown/DropDown.js @@ -1,6 +1,6 @@ import React from 'react'; -import CSSModules from 'react-css-modules'; import styles from './DropDown.css'; +import CSSModules from 'react-css-modules'; export default CSSModules((props) => { const options = props.items.map((s, i) => { diff --git a/src/components/UpgradeIcon/UpgradeIcon.css b/src/components/UpgradeIcon/UpgradeIcon.css index 4225165..c70cc50 100644 --- a/src/components/UpgradeIcon/UpgradeIcon.css +++ b/src/components/UpgradeIcon/UpgradeIcon.css @@ -1,6 +1,6 @@ .UpgradeIcon { display: block; - margin: 0; + margin-right: 2px; padding: 0; width: 20px; height: 20px; diff --git a/src/components/UpgradeIcon/UpgradeIcon.js b/src/components/UpgradeIcon/UpgradeIcon.js index 11d5ee2..a6ef861 100644 --- a/src/components/UpgradeIcon/UpgradeIcon.js +++ b/src/components/UpgradeIcon/UpgradeIcon.js @@ -10,6 +10,10 @@ export default CSSModules((props) => { } return props.available ? - : + : null; }, styles, {allowMultiple: true}); \ No newline at end of file diff --git a/src/components/UpgradeUI/UpgradeUI.js b/src/components/UpgradeUI/UpgradeUI.js index 7e795d6..3702c65 100644 --- a/src/components/UpgradeUI/UpgradeUI.js +++ b/src/components/UpgradeUI/UpgradeUI.js @@ -6,22 +6,22 @@ import styles from './UpgradeUI.css'; export default CSSModules((props) => { return ( - +

UI Upgrade Available

{inputControl} + {inputControl} + {actionDisplay} - Auto-mount + Auto-mount
- - - - + + + +
- - - -
+ + + +
); diff --git a/src/containers/Configuration/Configuration.css b/src/containers/Configuration/Configuration.css new file mode 100644 index 0000000..675f8c8 --- /dev/null +++ b/src/containers/Configuration/Configuration.css @@ -0,0 +1,6 @@ +.Configuration { + width: 90vw; + height: 90vh; + padding: 4px; + margin: 0; +} \ No newline at end of file diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js new file mode 100644 index 0000000..f94e257 --- /dev/null +++ b/src/containers/Configuration/Configuration.js @@ -0,0 +1,287 @@ +import React, {Component} from 'react'; +import styles from './Configuration.css'; +import Box from '../../components/UI/Box/Box'; +import Button from '../../components/UI/Button/Button'; +import ConfigurationItem from '../../components/ConfigurationItem/ConfigurationItem'; +import CSSModules from 'react-css-modules'; +import Modal from '../../components/UI/Modal/Modal'; + +let ipcRenderer = null; +if (!process.versions.hasOwnProperty('electron')) { + ipcRenderer = ((window && window.require) ? window.require('electron').ipcRenderer : null); +} + +class Configuration extends Component { + constructor(props) { + super(props); + if (ipcRenderer) { + ipcRenderer.on('get_config_template_reply', this.onGetConfigTemplateReply); + ipcRenderer.on('get_config_reply', this.onGetConfigReply); + ipcRenderer.on('set_config_values_reply', this.onSetConfigValuesReply); + + ipcRenderer.send('get_config_template', { + Directory: this.props.directory, + StorageType: this.props.storageType, + Version: this.props.version, + }); + } + } + + state = { + ChangedItems: [], + ChangedObjectLookup: null, + ObjectLookup: {}, + OriginalItemList: [], + OriginalObjectLookup: {}, + ItemList: [], + Saving: false, + ShowAdvanced: false, + Template: {} + }; + + checkSaveRequired = () => { + const changedItems = []; + let i = 0; + for (const item of this.state.ItemList) { + if (this.state.OriginalItemList[i++].value !== item.value) { + changedItems.push(item); + } + } + + let changedObjectLookup = null; + for (const key of Object.keys(this.state.ObjectLookup)) { + const changedObjectItems = []; + let j = 0; + for (const item of this.state.ObjectLookup[key]) { + if (this.state.OriginalObjectLookup[key][j++].value !== item.value) { + changedObjectItems.push(item); + } + } + + if (changedObjectItems.length > 0) { + if (changedObjectLookup === null) { + changedObjectLookup = {}; + } + changedObjectLookup[key] = changedObjectItems; + } + } + + if ((changedItems.length > 0) || changedObjectLookup) { + this.setState({ + ChangedItems: changedItems, + ChangedObjectLookup: changedObjectLookup, + }); + } else { + this.props.closed(); + } + }; + + componentWillUnmount = () => { + if (ipcRenderer) { + ipcRenderer.removeListener('get_config_reply', this.onGetConfigReply); + ipcRenderer.removeListener('get_config_template_reply', this.onGetConfigTemplateReply); + ipcRenderer.removeListener('set_config_values', this.onSetConfigValuesReply); + } + }; + + createItemList = (config, template) => { + const objectList = []; + const itemList = Object + .keys(config) + .map(key => { + return { + advanced: template[key] ? template[key].advanced : false, + label: key, + value: config[key], + }; + }) + .filter(i=> { + let ret = template[i.label]; + if (ret && (template[i.label].type === 'object')) { + objectList.push(i); + ret = false; + } + return ret; + }); + + return { + ObjectList: objectList, + ItemList: itemList, + } + }; + + handleItemChanged = (target, idx) => { + const itemList = [ + ...this.state.ItemList + ]; + itemList[idx].value = target.value.toString(); + this.setState({ + ItemList: itemList + }); + }; + + handleObjectItemChanged = (target, name, idx) => { + const itemList = [ + ...this.state.ObjectLookup[name] + ]; + const objectLookup = { + ...this.state.ObjectLookup, + }; + + itemList[idx].value = target.value.toString(); + objectLookup[name] = itemList; + this.setState({ + ObjectLookup: objectLookup, + }); + }; + + onGetConfigReply = (event, arg) => { + if (arg.data.Success) { + const list = this.createItemList(arg.data.Config, this.state.Template); + const itemListCopy = JSON.parse(JSON.stringify(list.ItemList)); + + let objectLookup = {}; + for (const obj of list.ObjectList) { + const list2 = this.createItemList(obj.value, this.state.Template[obj.label].template); + objectLookup[obj.label] = list2.ItemList; + } + const objectLookupCopy = JSON.parse(JSON.stringify(objectLookup)); + + this.setState({ + ItemList: list.ItemList, + ObjectLookup: objectLookup, + OriginalItemList: itemListCopy, + OriginalObjectLookup: objectLookupCopy, + }); + } + }; + + onGetConfigTemplateReply = (event, arg) => { + if (arg.data.Success) { + this.setState({ + Template: arg.data.Template, + }); + ipcRenderer.send('get_config', { + Directory: this.props.directory, + StorageType: this.props.storageType, + Version: this.props.version, + }); + } + }; + + onSetConfigValuesReply = () => { + this.props.closed(); + }; + + saveAndClose = () => { + if (ipcRenderer) { + this.setState({ + Saving: true, + }); + + const changedItems = []; + for (const item of this.state.ChangedItems) { + changedItems.push({ + Name: item.label, + Value: item.value, + }); + } + + if (this.state.ChangedObjectLookup) { + for (const key of Object.keys(this.state.ChangedObjectLookup)) { + for (const item of this.state.ChangedObjectLookup[key]) { + changedItems.push({ + Name: key + '.' + item.label, + Value: item.value, + }); + } + } + } + + ipcRenderer.send('set_config_values', { + Directory: this.props.directory, + Items: changedItems, + StorageType: this.props.storageType, + Version: this.props.version, + }); + } + }; + + render() { + let confirmSave = null; + if ((this.state.ChangedItems.length > 0) || this.state.ChangedObjectLookup) { + confirmSave = ( + + +

Save Changes?

+ + + + + +
+
+
+ ); + } + + let configurationItems = this.state.ItemList + .map((k, i) => { + return ( + ((this.state.ShowAdvanced && k.advanced) || !k.advanced) ? + this.handleItemChanged(e, i)} + items={this.state.Template[k.label].items} + key={i} + label={k.label} + template={this.state.Template[k.label]} + value={k.value}/> : + null) + }); + + let objectItems = []; + for (const key of Object.keys(this.state.ObjectLookup)) { + objectItems.push(( +
+

{key}

+
+ { + this.state.ObjectLookup[key].map((k, i) => { + return ( + ((this.state.ShowAdvanced && k.advanced) || !k.advanced) ? + this.handleObjectItemChanged(e, key, i)} + items={this.state.Template[key].template[k.label].items} + key={i} + label={k.label} + template={this.state.Template[key].template[k.label]} + value={k.value}/> : + null) + }) + } +
+
+ )); + } + + return ( +
+ {confirmSave} + +
+ X +
+

{this.props.storageType + ' Configuration'}

+
+ {objectItems} +

Settings

+ {configurationItems} +
+
+
+ ); + } +} + +export default CSSModules(Configuration, styles, {allowMultiple: true}); \ No newline at end of file diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js index d0ce06d..a3268a9 100644 --- a/src/containers/MountItems/MountItems.js +++ b/src/containers/MountItems/MountItems.js @@ -13,66 +13,9 @@ class MountItems extends Component { constructor(props) { super(props); if (ipcRenderer) { - ipcRenderer.on('detect_mounts_reply', (event, arg) => { - if (arg.data.Success) { - const sia = { - ...this.state.Sia, - AllowMount: true, - DriveLetters: (arg.data.DriveLetters.Sia), - Mounted: (arg.data.Locations.Sia.length > 0), - PID: arg.data.PIDS.Sia, - }; - const hs = { - ...this.state.Hyperspace, - AllowMount: true, - DriveLetters: (arg.data.DriveLetters.Hyperspace), - Mounted: (arg.data.Locations.Hyperspace.length > 0), - PID: arg.data.PIDS.Hyperspace, - }; - - this.setState({ - Hyperspace: hs, - Sia: sia, - }); - - this.props.mountsBusy(hs.Mounted || sia.Mounted); - - let hsLocation = arg.data.Locations.Hyperspace; - if ((hsLocation.length === 0) && (this.props.platform === 'win32')) { - hsLocation = this.props.hyperspace.MountLocation || arg.data.DriveLetters.Hyperspace[0]; - } - if (hsLocation !== this.props.hyperspace.MountLocation) { - this.props.changed('Hyperspace', hsLocation); - } - - let siaLocation = arg.data.Locations.Sia; - if ((siaLocation.length === 0) && (this.props.platform === 'win32')) { - siaLocation = this.props.sia.MountLocation || arg.data.DriveLetters.Sia[0]; - } - if (siaLocation !== this.props.sia.MountLocation) { - this.props.changed('Sia', siaLocation); - } - - this.performAutoMount(); - } - }); - - ipcRenderer.on('mount_drive_reply', (event, arg) => { - const state = { - ...this.state[arg.data.StorageType], - PID: arg.data.PID, - Mounted: arg.data.Success, - }; - this.setState({ - [arg.data.StorageType]: state, - }); - - this.detectMounts(); - }); - - ipcRenderer.on('unmount_drive_reply', (event, arg) => { - this.detectMounts(); - }); + ipcRenderer.on('detect_mounts_reply', this.onDetectMountsReply); + ipcRenderer.on('mount_drive_reply', this.onMountDriveReply); + ipcRenderer.on('unmount_drive_reply', this.onUnmountDriveReply); this.detectMounts(); } @@ -93,6 +36,14 @@ class MountItems extends Component { }, }; + componentWillUnmount = () => { + if (ipcRenderer) { + ipcRenderer.removeListener('detect_mounts_reply', this.onDetectMountsReply); + ipcRenderer.removeListener('mount_drive_reply', this.onMountDriveReply); + ipcRenderer.removeListener('unmount_drive_reply', this.onUnmountDriveReply); + } + }; + detectMounts = ()=> { this.props.mountsBusy(true); ipcRenderer.send('detect_mounts', { @@ -141,6 +92,67 @@ class MountItems extends Component { } }; + onDetectMountsReply = (event, arg) => { + if (arg.data.Success) { + const sia = { + ...this.state.Sia, + AllowMount: true, + DriveLetters: (arg.data.DriveLetters.Sia), + Mounted: (arg.data.Locations.Sia.length > 0), + PID: arg.data.PIDS.Sia, + }; + const hs = { + ...this.state.Hyperspace, + AllowMount: true, + DriveLetters: (arg.data.DriveLetters.Hyperspace), + Mounted: (arg.data.Locations.Hyperspace.length > 0), + PID: arg.data.PIDS.Hyperspace, + }; + + this.setState({ + Hyperspace: hs, + Sia: sia, + }); + + this.props.mountsBusy(hs.Mounted || sia.Mounted); + + let hsLocation = arg.data.Locations.Hyperspace; + if ((hsLocation.length === 0) && (this.props.platform === 'win32')) { + hsLocation = this.props.hyperspace.MountLocation || arg.data.DriveLetters.Hyperspace[0]; + } + if (hsLocation !== this.props.hyperspace.MountLocation) { + this.props.changed('Hyperspace', hsLocation); + } + + let siaLocation = arg.data.Locations.Sia; + if ((siaLocation.length === 0) && (this.props.platform === 'win32')) { + siaLocation = this.props.sia.MountLocation || arg.data.DriveLetters.Sia[0]; + } + if (siaLocation !== this.props.sia.MountLocation) { + this.props.changed('Sia', siaLocation); + } + + this.performAutoMount(); + } + }; + + onMountDriveReply = (event, arg) => { + const state = { + ...this.state[arg.data.StorageType], + PID: arg.data.PID, + Mounted: arg.data.Success, + }; + this.setState({ + [arg.data.StorageType]: state, + }); + + this.detectMounts(); + }; + + onUnmountDriveReply = (event, arg) => { + this.detectMounts(); + }; + performAutoMount = ()=> { if (this.props.processAutoMount) { this.props.autoMountProcessed(); @@ -160,28 +172,32 @@ class MountItems extends Component { render() { return (
- this.props.autoMountChanged('Hyperspace', e)} - mounted={this.state.Hyperspace.Mounted} - items={this.state.Hyperspace.DriveLetters} - platform={this.props.platform} - title={'Hyperspace'} - location={this.props.hyperspace.MountLocation} changed={(e) => this.handleMountLocationChanged('Hyperspace', e.target.value)} clicked={this.handleMountUnMount} - pid={this.state.Hyperspace.PID}/> - this.props.configClicked('Hyperspace')} + items={this.state.Hyperspace.DriveLetters} + location={this.props.hyperspace.MountLocation} + mounted={this.state.Hyperspace.Mounted} + pid={this.state.Hyperspace.PID} + platform={this.props.platform} + title={'Hyperspace'}/> + this.props.autoMountChanged('Sia', e)} - mounted={this.state.Sia.Mounted} - items={this.state.Sia.DriveLetters} - platform={this.props.platform} - title={'Sia'} - location={this.props.sia.MountLocation} changed={(e) => this.handleMountLocationChanged('Sia', e.target.value)} clicked={this.handleMountUnMount} - pid={this.state.Sia.PID}/> + configClicked={()=>this.props.configClicked('Sia')} + items={this.state.Sia.DriveLetters} + location={this.props.sia.MountLocation} + mounted={this.state.Sia.Mounted} + pid={this.state.Sia.PID} + platform={this.props.platform} + title={'Sia'}/>
); } } diff --git a/src/index.css b/src/index.css index fe9fcd3..a2b349f 100644 --- a/src/index.css +++ b/src/index.css @@ -6,18 +6,18 @@ --control_border: 1px solid rgba(70, 70, 70, 0.9); --control_box_shadow: 1px 1px 1px black; --control_transparent_background: rgba(60, 60, 70, 0.4); - --control_dark_transparent_background: rgba(60, 60, 70, 0.4); + --control_dark_transparent_background: rgba(15, 15, 15, 0.8); - --text_color: rgba(200, 205, 220, 0.7); - --text_color_hover: rgba(200, 205, 220, 0.7); - --heading_text_color: rgba(194, 217, 255, 0.6); - --heading_other_text_color: rgba(200, 205, 220, 0.7); + --text_color: rgba(200, 205, 220, 0.75); + --text_color_hover: rgba(200, 205, 220, 0.75); + --heading_text_color: rgba(140, 169, 203, 0.75); + --heading_other_text_color: rgba(200, 205, 220, 0.75); --text_color_transition: color 0.3s; } * { font-family: 'Nunito', sans-serif; - font-size: 15px; + font-size: 14px; } *::-moz-focus-inner {