diff --git a/.gitignore b/.gitignore index f2b4e6d..749a40d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build/ chrome_data/ dist/ /.cache +/temp.json diff --git a/public/electron.js b/public/electron.js index c65de22..e01a3cb 100644 --- a/public/electron.js +++ b/public/electron.js @@ -308,16 +308,29 @@ if (!instanceLock) { configurePrimaryApp(); } +const AppFunctions = { + closeApplication, + detectScript, + dialog, + getCleanupReleases: () => cleanupReleases, + getMainWindow, + saveUiSettings, + setIsInstalling, + setTrayImage, + setWindowVisibility, + standardIPCReply, + unmountAllDrives: MountsIPC.unmountAllDrives, +}; -AppIPC.addListeners(ipcMain, closeApplication, setWindowVisibility); -ConfigIPC.addListeners(ipcMain, standardIPCReply); -DaemonIPC.addListeners(ipcMain, standardIPCReply); -DependencyIPC.addListeners(ipcMain, standardIPCReply); -DownloadIPC.addListeners(ipcMain, standardIPCReply); -FilesystemIPC.addListeners(ipcMain, getMainWindow, dialog); -MountsIPC.addListeners(ipcMain, setTrayImage, standardIPCReply); -PlatformIPC.addListeners(ipcMain, detectScript, saveUiSettings); -ReleaseIPC.addListeners(ipcMain, () => cleanupReleases, standardIPCReply); -StateIPC.addListeners(ipcMain); -SystemIPC.addListeners(ipcMain, closeApplication); -UpgradeIPC.addListeners(ipcMain, setIsInstalling, MountsIPC.unmountAllDrives, standardIPCReply); +AppIPC.addListeners(ipcMain, AppFunctions); +ConfigIPC.addListeners(ipcMain, AppFunctions); +DaemonIPC.addListeners(ipcMain, AppFunctions); +DependencyIPC.addListeners(ipcMain, AppFunctions); +DownloadIPC.addListeners(ipcMain, AppFunctions); +FilesystemIPC.addListeners(ipcMain, AppFunctions); +MountsIPC.addListeners(ipcMain, AppFunctions); +PlatformIPC.addListeners(ipcMain, AppFunctions); +ReleaseIPC.addListeners(ipcMain, AppFunctions); +StateIPC.addListeners(ipcMain, AppFunctions); +SystemIPC.addListeners(ipcMain, AppFunctions); +UpgradeIPC.addListeners(ipcMain, AppFunctions); diff --git a/src/App.js b/src/App.js index c34ca6e..5f570a8 100644 --- a/src/App.js +++ b/src/App.js @@ -14,6 +14,10 @@ import MountItems from './containers/MountItems/MountItems'; import NewReleases from './components/NewReleases/NewReleases'; import {notifyError} from './redux/actions/error_actions'; import Reboot from './components/Reboot/Reboot'; +import { + setDismissNewReleasesAvailable, + setNewReleasesAvailable +} from './redux/actions/release_version_actions'; import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay'; import { displaySelectAppPlatform, @@ -73,6 +77,15 @@ class App extends IPCContainer { this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion]; }; + handleUpgradeIconClicked = () => { + if (this.props.UpgradeAvailable) { + this.props.setDismissUIUpgrade(false) + } else if (this.props.NewReleasesAvailable2.length > 0) { + this.props.setNewReleasesAvailable(this.props.NewReleasesAvailable2); + this.props.setDismissNewReleasesAvailable(false); + } + }; + render() { const selectedVersion = this.getSelectedVersion(); @@ -177,8 +190,9 @@ class App extends IPCContainer { textAlign={'center'} type={'Heading1'}/> this.props.setDismissUIUpgrade(false)} + available={this.props.UpgradeAvailable || (this.props.NewReleasesAvailable2.length > 0)} + newReleases={!this.props.UpgradeAvailable && (this.props.NewReleasesAvailable2.length > 0)} + clicked={this.handleUpgradeIconClicked} col={dimensions => dimensions.columns - 6} colSpan={5} row={1} @@ -225,6 +239,7 @@ const mapStateToProps = state => { MissingDependencies: state.install.MissingDependencies, MountsBusy: state.mounts.MountsBusy, NewReleasesAvailable: state.relver.NewReleasesAvailable, + NewReleasesAvailable2: state.relver.NewReleasesAvailable2, Platform: state.common.Platform, ProviderState: state.mounts.ProviderState, RebootRequired: state.common.RebootRequired, @@ -243,6 +258,8 @@ const mapDispatchToProps = dispatch => { loadReleases: ()=> dispatch(loadReleases()), notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)), saveState: () => dispatch(saveState()), + setDismissNewReleasesAvailable: dismiss => dispatch(setDismissNewReleasesAvailable), + setNewReleasesAvailable: items => dispatch(setNewReleasesAvailable(items)), setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)), }; }; diff --git a/src/assets/images/release_available.png b/src/assets/images/release_available.png deleted file mode 100644 index 4dbba4c..0000000 Binary files a/src/assets/images/release_available.png and /dev/null differ diff --git a/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js b/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js index 71dadfe..d9e8149 100644 --- a/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js +++ b/src/components/ReleaseVersionDisplay/ReleaseVersionDisplay.js @@ -143,4 +143,4 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { {optionsDisplay} ); -}); \ No newline at end of file +}); diff --git a/src/components/UpgradeIcon/UpgradeIcon.css b/src/components/UpgradeIcon/UpgradeIcon.css index fcc9e3c..0dce756 100644 --- a/src/components/UpgradeIcon/UpgradeIcon.css +++ b/src/components/UpgradeIcon/UpgradeIcon.css @@ -17,5 +17,9 @@ max-width: 100%; max-height: 100%; box-sizing: border-box; - opacity: 0.65; - } \ No newline at end of file + color: var(--heading_text_color); +} + +.UpgradeIcon.Release { + color: var(--heading_other_text_color); +} diff --git a/src/components/UpgradeIcon/UpgradeIcon.js b/src/components/UpgradeIcon/UpgradeIcon.js index 5b3af36..3828eef 100644 --- a/src/components/UpgradeIcon/UpgradeIcon.js +++ b/src/components/UpgradeIcon/UpgradeIcon.js @@ -1,13 +1,19 @@ import React from 'react'; import './UpgradeIcon.css'; -import availableImage from '../../assets/images/release_available.png'; import ReactTooltip from 'react-tooltip'; +import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; export default props => { + const styles = ['UpgradeIcon']; let placement = 'left'; let toolTipText = 'UI Upgrade Available'; if (props.release) { placement='bottom'; + styles.push('Release'); + } + + if (props.release || props.newReleases) { toolTipText = 'New Release Available'; } @@ -16,13 +22,14 @@ export default props => { (

- + + +

{toolTipText}
) : null; -}; \ No newline at end of file +}; diff --git a/src/containers/MountItems/MountItem/MountItem.js b/src/containers/MountItems/MountItem/MountItem.js index 21af275..0d86886 100644 --- a/src/containers/MountItems/MountItem/MountItem.js +++ b/src/containers/MountItems/MountItem/MountItem.js @@ -152,13 +152,14 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => { } }; removeControl = ( - dimensions.columns - 6} - onClick={handleRemoveMount} - row={secondRow + 3} - style={removeStyle}> - - ); + dimensions.columns - 6} + row={secondRow + 3}> + + + + ); } return ( diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js index 48700c9..68fb3df 100644 --- a/src/redux/actions/install_actions.js +++ b/src/redux/actions/install_actions.js @@ -10,7 +10,8 @@ import { loadReleases, setActiveRelease, setInstalledVersion, - setReleaseUpgradeAvailable + setReleaseUpgradeAvailable, + setNewReleasesAvailable2, } from './release_version_actions'; import { confirmYesNo, @@ -224,6 +225,11 @@ export const installRelease = source => { FilePath: source, }); + if (arg.data.Success) { + localStorage.setItem('previous_releases', localStorage.getItem('releases')); + dispatch(setNewReleasesAvailable2([])); + } + dispatch(setInstallComplete(arg.data)); dispatch(checkVersionInstalled()); }; diff --git a/src/redux/actions/release_version_actions.js b/src/redux/actions/release_version_actions.js index e570313..595826a 100644 --- a/src/redux/actions/release_version_actions.js +++ b/src/redux/actions/release_version_actions.js @@ -14,6 +14,7 @@ import { } from './install_actions'; import {unmountAll} from './mount_actions'; import { + checkNewReleases, getIPCRenderer, getNewReleases } from '../../utils'; @@ -140,8 +141,11 @@ export const loadReleases = () => { dispatch(setNewReleasesAvailable(newReleases)); if (getState().relver.NewReleasesAvailable.length > 0) { + dispatch(setNewReleasesAvailable2(newReleases)); localStorage.setItem('previous_releases', storedReleases); dispatch(showWindow()); + } else if ((newReleases = checkNewReleases()).length > 0) { + dispatch(setNewReleasesAvailable2(newReleases)); } }).catch(error => { const releases = localStorage.getItem('releases'); @@ -193,6 +197,7 @@ export const setDismissNewReleasesAvailable = createAction('relver/setDismissNew export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade'); export const setInstalledVersion = createAction('relver/setInstalledVersion'); export const setNewReleasesAvailable = createAction('relver/setNewReleasesAvailable'); +export const setNewReleasesAvailable2 = createAction('relver/setNewReleasesAvailable2'); export const SET_RELEASE_DATA = 'relver/setReleaseData'; export const setReleaseData = (locationsLookup, versionLookup)=> { diff --git a/src/redux/reducers/release_version_reducer.js b/src/redux/reducers/release_version_reducer.js index 52066ec..5946b7e 100644 --- a/src/redux/reducers/release_version_reducer.js +++ b/src/redux/reducers/release_version_reducer.js @@ -19,6 +19,7 @@ export const releaseVersionReducer = createReducer({ InstalledVersion: 'none', LocationsLookup: {}, NewReleasesAvailable: [], + NewReleasesAvailable2: [], Release: 0, ReleaseDefault: 0, ReleaseUpgradeAvailable: false, @@ -76,6 +77,12 @@ export const releaseVersionReducer = createReducer({ NewReleasesAvailable: action.payload, }; }, + [Actions.setNewReleasesAvailable2]: (state, action) => { + return { + ...state, + NewReleasesAvailable2: action.payload, + }; + }, [Actions.SET_RELEASE_DATA]: (state, action) => { return { ...state, diff --git a/src/renderer/ipc/AppIPC.js b/src/renderer/ipc/AppIPC.js index 4fdd3da..9473440 100644 --- a/src/renderer/ipc/AppIPC.js +++ b/src/renderer/ipc/AppIPC.js @@ -1,6 +1,6 @@ const Constants = require('../../constants'); -const addListeners = (ipcMain, closeApplication, setWindowVisibility) => { +const addListeners = (ipcMain, {closeApplication, setWindowVisibility}) => { ipcMain.on(Constants.IPC_Shutdown, () => { closeApplication(); }); @@ -17,4 +17,4 @@ const addListeners = (ipcMain, closeApplication, setWindowVisibility) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/ConfigIPC.js b/src/renderer/ipc/ConfigIPC.js index 76bba25..a609eda 100644 --- a/src/renderer/ipc/ConfigIPC.js +++ b/src/renderer/ipc/ConfigIPC.js @@ -1,7 +1,7 @@ const Constants = require('../../constants'); const helpers = require('../../helpers'); -const addListeners = (ipcMain, standardIPCReply) => { +const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Get_Config, (event, data) => { helpers .getConfig(data.Version, data.Provider, data.Remote) @@ -53,4 +53,4 @@ const addListeners = (ipcMain, standardIPCReply) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/DaemonIPC.js b/src/renderer/ipc/DaemonIPC.js index c563c1c..6e4ec62 100644 --- a/src/renderer/ipc/DaemonIPC.js +++ b/src/renderer/ipc/DaemonIPC.js @@ -1,7 +1,7 @@ const Constants = require('../../constants'); const helpers = require('../../helpers'); -const addListeners = (ipcMain, standardIPCReply) => { +const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => { helpers .checkDaemonVersion(data.Version, data.Provider) @@ -44,4 +44,4 @@ const addListeners = (ipcMain, standardIPCReply) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/DependencyIPC.js b/src/renderer/ipc/DependencyIPC.js index ffb9907..f6945e0 100644 --- a/src/renderer/ipc/DependencyIPC.js +++ b/src/renderer/ipc/DependencyIPC.js @@ -2,7 +2,7 @@ const Constants = require('../../constants'); const fs = require('fs'); const helpers = require('../../helpers'); -const addListeners = (ipcMain, standardIPCReply) => { +const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { try { const exists = fs.lstatSync(data.File).isFile(); diff --git a/src/renderer/ipc/DownloadIPC.js b/src/renderer/ipc/DownloadIPC.js index 1492ea9..366d72e 100644 --- a/src/renderer/ipc/DownloadIPC.js +++ b/src/renderer/ipc/DownloadIPC.js @@ -2,7 +2,7 @@ const Constants = require('../../constants'); const helpers = require('../../helpers'); const path = require('path'); -const addListeners = (ipcMain, standardIPCReply) => { +const addListeners = (ipcMain, {standardIPCReply}) => { ipcMain.on(Constants.IPC_Download_File, (event, data) => { const destination = path.join(helpers.getDataDirectory(), data.Filename); helpers.downloadFile(data.URL, destination, (progress) => { @@ -22,4 +22,4 @@ const addListeners = (ipcMain, standardIPCReply) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/FilesystemIPC.js b/src/renderer/ipc/FilesystemIPC.js index 1294e76..cb71d62 100644 --- a/src/renderer/ipc/FilesystemIPC.js +++ b/src/renderer/ipc/FilesystemIPC.js @@ -1,7 +1,7 @@ const Constants = require('../../constants'); const fs = require('fs'); -const addListeners = (ipcMain, getMainWindow, dialog) => { +const addListeners = (ipcMain, {getMainWindow, dialog}) => { ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => { dialog.showOpenDialog(getMainWindow(), { defaultPath: data.Location, @@ -28,4 +28,4 @@ const addListeners = (ipcMain, getMainWindow, dialog) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/MountsIPC.js b/src/renderer/ipc/MountsIPC.js index 4b6cfe8..8cd5b37 100644 --- a/src/renderer/ipc/MountsIPC.js +++ b/src/renderer/ipc/MountsIPC.js @@ -62,7 +62,7 @@ const unmountAllDrives = () => { mountedData = {}; }; -const addListeners = (ipcMain, setTrayImage, standardIPCReply) => { +const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => { ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => { let response = { Success: true, diff --git a/src/renderer/ipc/PlatformIPC.js b/src/renderer/ipc/PlatformIPC.js index f55a35c..16ec438 100644 --- a/src/renderer/ipc/PlatformIPC.js +++ b/src/renderer/ipc/PlatformIPC.js @@ -14,7 +14,7 @@ const setPlatformOverride = platformOverride => { _platformOverride = platformOverride; }; -const addListeners = (ipcMain, detectScript, saveUiSettings) => { +const addListeners = (ipcMain, {detectScript, saveUiSettings}) => { ipcMain.on(Constants.IPC_Get_Platform, (event) => { const sendResponse = (appPlatform, platform) => { event.sender.send(Constants.IPC_Get_Platform_Reply, { @@ -76,4 +76,4 @@ module.exports = { getPlatformOverride, setPlatformOverride, addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/ReleaseIPC.js b/src/renderer/ipc/ReleaseIPC.js index f76fcf8..f2d7a77 100644 --- a/src/renderer/ipc/ReleaseIPC.js +++ b/src/renderer/ipc/ReleaseIPC.js @@ -5,7 +5,7 @@ const os = require('os'); const path = require('path'); const unzip = require('unzipper'); -const addListeners = (ipcMain, getCleanupReleases, standardIPCReply) => { +const addListeners = (ipcMain, {getCleanupReleases, standardIPCReply}) => { ipcMain.on(Constants.IPC_Check_Installed, (event, data) => { const destination = path.join(helpers.getDataDirectory(), data.Version); helpers diff --git a/src/renderer/ipc/SystemIPC.js b/src/renderer/ipc/SystemIPC.js index 52ebb2f..a6298c5 100644 --- a/src/renderer/ipc/SystemIPC.js +++ b/src/renderer/ipc/SystemIPC.js @@ -2,7 +2,7 @@ const Constants = require('../../constants'); const os = require('os'); const helpers = require('../../helpers'); -const addListeners = (ipcMain, closeApplication) => { +const addListeners = (ipcMain, {closeApplication}) => { ipcMain.on(Constants.IPC_Reboot_System, () => { if (os.platform() === 'win32') { helpers.executeAsync('shutdown.exe', ['/r', '/t', '30']); @@ -13,4 +13,4 @@ const addListeners = (ipcMain, closeApplication) => { module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/renderer/ipc/UpgradeIPC.js b/src/renderer/ipc/UpgradeIPC.js index 7bdc24c..b717ab8 100644 --- a/src/renderer/ipc/UpgradeIPC.js +++ b/src/renderer/ipc/UpgradeIPC.js @@ -3,7 +3,7 @@ const fs = require('fs'); const helpers = require('../../helpers'); const os = require('os'); -const addListeners = (ipcMain, setIsInstalling, unmountAllDrives, standardIPCReply) => { +const addListeners = (ipcMain, {setIsInstalling, unmountAllDrives, standardIPCReply}) => { ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => { let allowSkipVerification = true; @@ -113,4 +113,4 @@ const addListeners = (ipcMain, setIsInstalling, unmountAllDrives, standardIPCRep module.exports = { addListeners -}; \ No newline at end of file +}; diff --git a/src/utils.js b/src/utils.js index 2448039..ab8f565 100644 --- a/src/utils.js +++ b/src/utils.js @@ -7,6 +7,21 @@ const ipcRenderer = (!process.versions.hasOwnProperty('electron') && window && w window.require('electron').ipcRenderer : null; +export const checkNewReleases = () => { + let previousReleases = localStorage.getItem('previous_releases'); + if (previousReleases) { + previousReleases = JSON.parse(previousReleases).VersionLookup; + + let currentReleases = localStorage.getItem('releases'); + if (currentReleases) { + currentReleases = JSON.parse(currentReleases).VersionLookup; + return getNewReleases(previousReleases, currentReleases); + } + } + + return []; +}; + export const createModalConditionally = (condition, jsx, critical, disableFocusTrap) => { const modalProps = {critical: critical, disableFocusTrap: disableFocusTrap}; return condition ? ({jsx}) : null; @@ -62,7 +77,7 @@ export const getIPCRenderer = () => { return ipcRenderer; }; -export const getNewReleases = (existingReleases, newReleases) => { +export const getNewReleases = (existingLocations, newLocations) => { const ret = []; /*existingReleases = Constants.RELEASE_TYPES.reduce((map, release) => { @@ -70,15 +85,15 @@ export const getNewReleases = (existingReleases, newReleases) => { return map; }, {});*/ - if (existingReleases && newReleases) { + if (existingLocations && newLocations) { Constants.RELEASE_TYPES.forEach(release => { - newReleases[release] - .filter(version => !existingReleases[release].includes(version) && (version !== 'unavailable')) + newLocations[release] + .filter(version => !existingLocations[release].includes(version) && (version !== 'unavailable')) .forEach(version => { ret.splice(0, 0, { Display: version, Release: Constants.RELEASE_TYPES.indexOf(release), - Version: newReleases[release].indexOf(version), + Version: newLocations[release].indexOf(version), VersionString: version, }); });