import React from 'react'; import AddMount from '../AddMount/AddMount'; import Box from '../../components/UI/Box/Box'; import Button from '../../components/UI/Button/Button'; import {connect} from 'react-redux'; import './MountItems.css'; import Modal from '../../components/UI/Modal/Modal'; import MountItem from './MountItem/MountItem'; import IPCContainer from '../IPCContainer/IPCContainer'; import { resetMountsState, setAllowMount, setAutoMountProcessed, setBusy, setMounted, setMountState, setProviderState } from '../../redux/actions/mount_actions'; import {notifyError} from '../../redux/actions/error_actions'; const Constants = require('../../constants'); class MountItems extends IPCContainer { retryIntervals = {}; activeDetections = []; state = { DisplayRetry: false, RetryItems: {}, }; addMountsBusy = provider => { this.props.setMountsBusy(true); this.activeDetections.push(provider); }; cancelRetryMount = (provider, stateCallback) => { clearInterval(this.retryIntervals[provider]); delete this.retryIntervals[provider]; if (stateCallback) { let retryItems = { ...this.state.RetryItems, }; delete retryItems[provider]; this.setState({ DisplayRetry: Object.keys(retryItems).length > 0, RetryItems: retryItems, }, () => { if (this.state.DisplayRetry) { this.sendRequest(Constants.IPC_Show_Window); } stateCallback(); }); } }; componentDidMount() { this.setRequestHandler(Constants.IPC_Detect_Mount_Reply, this.onDetectMountReply); this.setRequestHandler(Constants.IPC_Mount_Drive_Reply, this.onMountDriveReply); this.setRequestHandler(Constants.IPC_Unmount_Drive_Reply, this.onUnmountDriveReply); this.props.resetMountsState(); this.detectMounts(); } componentWillUnmount() { for (const provider in this.state.RetryItems) { if (this.state.RetryItems.hasOwnProperty(provider)) { this.cancelRetryMount(provider); } } this.props.resetMountsState(); this.activeDetections = []; super.componentWillUnmount(); }; detectMount = provider => { this.addMountsBusy(provider); this.sendRequest(Constants.IPC_Detect_Mount, { RemoteMounts: this.props.RemoteMounts, Provider: provider, Version: this.props.InstalledVersion, }); }; detectMounts = ()=> { if (!this.state.DisplayRetry) { const providerList = this.getProviderList(); providerList.forEach(provider => { this.detectMount(provider); }); } }; displayRetryMount = (provider, remote, s3, mountLocation, msg) => { if (!this.state.RetryItems[provider]) { let retryItems = { ...this.state.RetryItems }; retryItems[provider] = { RetrySeconds: 10, RetryMessage: msg ? msg.toString() : null, }; const mountState = { AllowMount: false, Mounted: false, }; this.props.setMountState(provider, mountState); this.setState({ DisplayRetry: true, RetryItems: retryItems, }, () => { this.sendRequest(Constants.IPC_Show_Window); this.retryIntervals[provider] = setInterval(() => { let retryItems = { ...this.state.RetryItems, }; const retrySeconds = retryItems[provider].RetrySeconds - 1; if (retrySeconds === 0) { this.cancelRetryMount(provider, () => { this.handleMountUnMount(provider, remote, s3, true, mountLocation); }); } else { retryItems[provider].RetrySeconds = retrySeconds; this.setState({ RetryItems: retryItems, }); } }, 1000); }); } }; handleBrowseLocation = (provider, location) => { location = this.sendSyncRequest(Constants.IPC_Browse_Directory, { Title: provider + ' Mount Location', Location: location, }); if (location && (location.length > 0)) { this.handleMountLocationChanged(provider, location); } }; handleMountLocationChanged = (provider, mountLocation) => { const state = { ...this.props.ProviderState[provider], MountLocation: mountLocation, }; this.props.setProviderState(provider, state); }; handleMountUnMount = (provider, remote, s3, mount, location) => { if (!location || (location.trim().length === 0)) { this.props.notifyError('Mount location is not set'); } else { let allowAction = true; if (mount) { let result = remote || s3 || provider === 'Skynet' ? {Valid: true, Success: true} : this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, { Provider: provider, Remote: remote, S3: s3, Version: this.props.InstalledVersion }).data; if (result.Success) { if (result.Valid) { if (this.props.Platform !== 'win32') { result = this.sendSyncRequest(Constants.IPC_Check_Mount_Location, { Location: location, }); if (!result.Success) { allowAction = false; this.props.notifyError(result.Error.toString()); } } } else { allowAction = false; if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) { this.displayRetryMount(provider, remote, s3, location, 'Failed to connect to ' + provider + ' daemon'); } else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) { this.displayRetryMount(provider, remote, s3, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.'); } else { this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error); } } } else { allowAction = false; if (this.props.Platform === 'win32') { this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.'); } else { this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error); } } } if (allowAction) { this.addMountsBusy(provider); this.props.setAllowMount(provider, false); if (mount) { this.sendRequest(Constants.IPC_Mount_Drive, { Location: location, Provider: provider, Remote: remote, S3: s3, Version: this.props.InstalledVersion, }); } else { this.sendRequest(Constants.IPC_Unmount_Drive, { Location: location, Provider: provider, Remote: remote, S3: s3, Version: this.props.InstalledVersion, }); } } } }; getProviderList = providersOnly => { const providerList = Constants.PROVIDER_LIST.filter(i => { return ((i === 'Skynet') && this.props.skynetSupported) || ((i === 'ScPrime') && this.props.scPrimeSupported) || ((i === 'Sia') && this.props.siaSupported); }); let remoteList = []; if (this.props.remoteSupported && !providersOnly) { remoteList = [...this.props.RemoteMounts]; } let s3List = []; if (this.props.s3Supported && !providersOnly) { s3List = [...this.props.S3Mounts]; } return [ ...providerList, ...remoteList, ...s3List, ]; }; hasActiveMount = () => { for (const provider of Object.keys(this.props.MountState)) { if (this.props.MountState[provider].Mounted) return true; } return false; }; onDetectMountReply = (event, arg) => { const provider = arg.data.Provider; if (!this.state.RetryItems[provider]) { if (arg.data.Success && (!arg.data.Active || (arg.data.Location && (arg.data.Location.length > 0)))) { const mountState = { AllowMount: true, DriveLetters: arg.data.DriveLetters, Mounted: arg.data.Active, }; this.props.setMountState(provider, mountState); this.updateMountLocation(provider, arg.data.Location, mountState.Mounted, arg.data.DriveLetters); this.props.setAutoMountProcessed(provider, true); this.removeMountsBusy(provider); } else { this.detectMount(provider); this.removeMountsBusy(provider); } } }; onMountDriveReply = (event, arg) => { this.props.setMounted(arg.data.Provider, arg.data.Success); this.detectMount(arg.data.Provider); this.removeMountsBusy(arg.data.Provider); }; onUnmountDriveReply = (event, arg) => { if (arg && arg.data && !arg.data.Expected && arg.data.Location && this.props.ProviderState[arg.data.Provider].AutoRestart) { this.displayRetryMount(arg.data.Provider, arg.data.Remote, arg.data.Location); } else { this.detectMount(arg.data.Provider); } this.removeMountsBusy(arg.data.Provider); }; removeMountsBusy = provider => { const idx = this.activeDetections.indexOf(provider); if (idx > -1) { this.activeDetections.splice(idx, 1); } this.props.setMountsBusy((this.activeDetections.length > 0) || this.hasActiveMount()); }; updateMountLocation = (provider, location, mounted, driveLetters) => { const providerState = this.props.ProviderState[provider]; if (location.length === 0) { location = (this.props.Platform === 'win32') ? providerState.MountLocation || driveLetters[0] : providerState.MountLocation; } if (location !== providerState.MountLocation) { const value = (this.props.Platform === 'win32') ? driveLetters.indexOf(location) : location; this.handleMountLocationChanged(provider, value); } if (!this.props.AutoMountProcessed[provider] && this.props.ProviderState[provider].AutoMount && !mounted && (location.length > 0)) { this.handleMountUnMount(provider, this.props.RemoteMounts.includes(provider),true, location); } }; render() { let retryDisplay; if (this.state.DisplayRetry) { let retryList = []; let retryCount = 0; for (const provider in this.state.RetryItems) { if (this.state.RetryItems.hasOwnProperty(provider)) { if (this.state.RetryItems[provider].RetryMessage) { retryList.push(
{this.state.RetryItems[provider].RetryMessage}
); } retryList.push(); if (++retryCount < Object.keys(this.state.RetryItems).length) { retryList.push(); } } } retryDisplay = (