import * as Constants from '../../constants'; import {createAction} from '@reduxjs/toolkit'; import { getIPCRenderer, getSelectedVersionFromState } from '../../utils'; import {notifyError} from './error_actions'; import {downloadItem, setAllowDownload} from './download_actions'; import { loadReleases, setActiveRelease, setInstalledVersion, setReleaseUpgradeAvailable } from './release_version_actions'; import { confirmYesNo, displaySelectAppPlatform, setAllowMount, setApplicationReady, setLinuxAppPlatform, setRebootRequired, showWindow, shutdownApplication } from './common_actions'; import {unmountAll} from './mount_actions'; const ipcRenderer = getIPCRenderer(); export const checkInstalled = (dependencies, version) => { return (dispatch, getState) => { const checkInstalledComplete = (event, arg) => { const result = arg.data; const updateState = () => { const installedVersion = result.Success && result.Exists ? result.Version : 'none'; const state = getState(); const release = state.relver.Release; let version = state.relver.Version; let upgradeAvailable = false; if (installedVersion !== 'none') { const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1; if (version === -1) { version = latestVersion; dispatch(setActiveRelease(release, version)); } else { upgradeAvailable = version !== latestVersion; } } dispatch(setInstalledVersion(installedVersion)); dispatch(setReleaseUpgradeAvailable(upgradeAvailable)); dispatch(setMissingDependencies(result.Dependencies)); dispatch(setAllowDownload(true)); dispatch(setAllowMount(true)); const autoInstallRelease = getState().install.AutoInstallRelease; dispatch(setAutoInstallRelease(false)); if (result.Dependencies && (result.Dependencies.length > 0)) { dispatch(showWindow()); } else if ((installedVersion === 'none') && autoInstallRelease) { dispatch(setAllowMount(false)); const versionString = getState().relver.VersionLookup[Constants.RELEASE_TYPES[release]][version]; const urls = getState().relver.LocationsLookup[versionString].urls; const fileName = versionString + '.zip'; dispatch(downloadItem(fileName, Constants.INSTALL_TYPES.Release, urls)); } }; if (result.Success) { updateState(); } else { dispatch(notifyError(result.Error, false, updateState)); } }; ipcRenderer.once(Constants.IPC_Check_Installed_Reply, checkInstalledComplete); ipcRenderer.send(Constants.IPC_Check_Installed, { Dependencies: dependencies, Version: version, }); }; }; export const checkVersionInstalled = () => { return (dispatch, getState) => { const state = getState(); dispatch(setAllowDownload(false)); const selectedVersion = getSelectedVersionFromState(state); if (selectedVersion && (selectedVersion !== 'unavailable')) { let dependencies = []; if (state.relver.LocationsLookup[selectedVersion] && state.relver.LocationsLookup[selectedVersion].dependencies) { dependencies = state.relver.LocationsLookup[selectedVersion].dependencies; } dispatch(checkInstalled(dependencies, selectedVersion)); } else { dispatch(setInstalledVersion('none')); dispatch(setAllowDownload(true)); } }; }; export const installDependency = (source, url, isWinFSP) => { return (dispatch, getState) => { if (ipcRenderer && !getState().install.InstallActive) { dispatch(setInstallActive(Constants.INSTALL_TYPES.Dependency)); const installDependencyComplete = (event, arg) => { const result = arg.data; const handleCompleted = ()=> { if (result.RebootRequired) { dispatch(setRebootRequired()); } else { ipcRenderer.send(Constants.IPC_Delete_File, { FilePath: source, }); dispatch(setInstallComplete(result)); dispatch(checkVersionInstalled()); } }; if (result.Success && source.toLowerCase().endsWith('.dmg')) { const dep = getState().install.MissingDependencies.find(d => { return d.download === url; }); const i = setInterval(()=> { const ret = ipcRenderer.sendSync(Constants.IPC_Check_Dependency_Installed + '_sync', { File: dep.file, }); if (ret.data.Exists) { clearInterval(i); setTimeout(() => { handleCompleted(); }, 5000); } }, 3000); } else { handleCompleted(); } }; ipcRenderer.once(Constants.IPC_Install_Dependency_Reply, installDependencyComplete); ipcRenderer.send(Constants.IPC_Install_Dependency, { Source: source, URL: url, IsWinFSP: isWinFSP, }); } }; }; export const installAndTestRelease = (source, version, appPlatform) => { return (dispatch, getState) => { if (ipcRenderer && getState().install.InstallTestActive) { const extractReleaseComplete = (event, arg) => { ipcRenderer.send(Constants.IPC_Delete_File, { FilePath: source, }); ipcRenderer.once(Constants.IPC_Test_Release_Reply, (event, arg) => { if (arg.data.Success) { ipcRenderer.sendSync(Constants.IPC_Set_Linux_AppPlatform, { AppPlatform: appPlatform, }); dispatch(setLinuxAppPlatform(appPlatform)); dispatch(setInstallTestActive(false)); dispatch(displaySelectAppPlatform(false)); dispatch(setAllowDownload(false)); dispatch(loadReleases()); } else { dispatch(notifyError(arg.data.Error)); dispatch(setInstallTestActive(false)); } }); ipcRenderer.send(Constants.IPC_Test_Release, { Version: version, }) }; ipcRenderer.once(Constants.IPC_Extract_Release_Complete, extractReleaseComplete); ipcRenderer.send(Constants.IPC_Extract_Release, { Source: source, Version: version, }); } }; }; export const installReleaseByVersion = (release, version) => { return (dispatch, getState) => { const install = () => { if (getState().download.AllowDownload && !getState().download.DownloadActive) { dispatch(setAutoInstallRelease(true)); dispatch(setActiveRelease(release, version)); } else { notifyError('Download is active. Unable to install release.'); } }; if (getState().mounts.MountsBusy) { dispatch(confirmYesNo('Unmount all drives?')) .then(confirmed => { if (confirmed) { dispatch(unmountAll(install)); } }) .catch(error => notifyError(error)); } else { install(); } }; }; export const installRelease = source => { return (dispatch, getState) => { if (ipcRenderer && !getState().install.InstallActive) { dispatch(setInstallActive(Constants.INSTALL_TYPES.Release)); const version = getSelectedVersionFromState(getState()); const extractReleaseComplete = (event, arg) => { ipcRenderer.send(Constants.IPC_Delete_File, { FilePath: source, }); dispatch(setInstallComplete(arg.data)); dispatch(checkVersionInstalled()); }; ipcRenderer.once(Constants.IPC_Extract_Release_Complete, extractReleaseComplete); ipcRenderer.send(Constants.IPC_Extract_Release, { Source: source, Version: version, }); } }; }; export const installUpgrade = (source, sha256, signature, skipVerification) => { return (dispatch, getState) => { if (ipcRenderer && !getState().install.InstallActive) { dispatch(setInstallActive(Constants.INSTALL_TYPES.Upgrade)); dispatch(setApplicationReady(false)); const installUpgradeComplete = (event, arg) => { const result = arg.data; if (result.Success) { dispatch(shutdownApplication()); } else { dispatch(setApplicationReady(true)); dispatch(setInstallComplete(result)); dispatch(notifyError(result.Error, false, () => { // TODO Prompt to verify if (result.AllowSkipVerification) { dispatch(installUpgrade(source, sha256, signature, true)); } }, false)); } }; ipcRenderer.once(Constants.IPC_Install_Upgrade_Reply, installUpgradeComplete); ipcRenderer.send(Constants.IPC_Install_Upgrade, { Sha256: sha256, Signature: signature, SkipVerification: skipVerification, Source: source, }); } }; }; export const setAutoInstallRelease = createAction('install/setAutoInstallRelease'); export const setDismissDependencies = createAction('install/setDismissDependencies'); export const setInstallActive = createAction('install/setInstallActive'); export const setInstallTestActive = createAction('install/setInstallTestActive'); export const setInstallComplete = createAction('install/setInstallComplete'); export const setMissingDependencies = createAction('install/setMissingDependencies');