diff --git a/react/change.log b/react/change.log index eef01f2..0fad6c0 100644 --- a/react/change.log +++ b/react/change.log @@ -19,6 +19,8 @@ front: - seed extra space(s) check - custom seed option - copy seed button +- native only mode +- app update back: - added cli route diff --git a/react/src/actions/actionCreators.js b/react/src/actions/actionCreators.js index c51d237..acbdd9e 100644 --- a/react/src/actions/actionCreators.js +++ b/react/src/actions/actionCreators.js @@ -66,6 +66,7 @@ export * from './actions/fullTxHistory'; export * from './actions/basiliskTxHistory'; export * from './actions/iguanaHelpers'; export * from './actions/cli'; +export * from './actions/update'; export let Config; diff --git a/react/src/actions/actions/update.js b/react/src/actions/actions/update.js new file mode 100644 index 0000000..457c22b --- /dev/null +++ b/react/src/actions/actions/update.js @@ -0,0 +1,54 @@ +import { + Config, + triggerToaster +} from '../actionCreators'; +import { + logGuiHttp, + guiLogState +} from './log'; + +export function checkForUpdateUIPromise() { + return new Promise((resolve, reject) => { + fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/update/patch/check`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .catch(function(error) { + console.log(error); + dispatch( + triggerToaster( + 'checkForUpdateUIPromise', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => resolve(json)) + }); +} + +export function updateUIPromise() { + return new Promise((resolve, reject) => { + fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/update/patch`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .catch(function(error) { + console.log(error); + dispatch( + triggerToaster( + 'updateUIPromise', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => resolve(json)) + }); +} \ No newline at end of file diff --git a/react/src/components/dashboard/settings/settings.js b/react/src/components/dashboard/settings/settings.js index 9e298ba..f1f370b 100644 --- a/react/src/components/dashboard/settings/settings.js +++ b/react/src/components/dashboard/settings/settings.js @@ -12,15 +12,26 @@ import { getAppConfig, saveAppConfig, getAppInfo, - shepherdCli + shepherdCli, + checkForUpdateUIPromise, + updateUIPromise } from '../../../actions/actionCreators'; import Store from '../../../store'; import { AppInfoTabRender, - SettingsRender + SettingsRender, + AppUpdateTabRender, } from './settings.render'; +import { SocketProvider } from 'socket.io-react'; +import io from 'socket.io-client'; + +const socket = io.connect('http://127.0.0.1:' + Config.agamaPort); +let updateProgressBar = { + patch: -1, +}; + /* TODO: 1) pre-select active coin in add node tab @@ -44,6 +55,10 @@ class Settings extends React.Component { exportWifKeysRaw: false, seedInputVisibility: false, nativeOnly: Config.iguanaLessMode, + updatePatch: null, + updateBins: null, + updateLog: [], + updateProgressPatch: null, }; this.exportWifKeys = this.exportWifKeys.bind(this); this.updateInput = this.updateInput.bind(this); @@ -57,6 +72,9 @@ class Settings extends React.Component { this._saveAppConfig = this._saveAppConfig.bind(this); this.exportWifKeysRaw = this.exportWifKeysRaw.bind(this); this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this); + this._checkForUpdateUIPromise = this._checkForUpdateUIPromise.bind(this); + this._updateUIPromise = this._updateUIPromise.bind(this); + socket.on('patch', msg => this.updateSocketsData(msg)); } componentDidMount() { @@ -77,6 +95,115 @@ class Settings extends React.Component { } } + updateSocketsData(data) { + if (data && + data.msg && + data.msg.type === 'ui') { + + if (data.msg.status === 'progress' && + data.msg.progress && + data.msg.progress < 100) { + this.setState(Object.assign({}, this.state, { + updateProgressPatch: data.msg.progress, + })); + updateProgressBar.patch = data.msg.progress; + } else { + if (data.msg.status === 'progress' && + data.msg.progress && + data.msg.progress === 100) { + let _updateLog = []; + _updateLog.push('UI update downloaded. Verifying...'); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + })); + updateProgressBar.patch = 100; + } + + if (data.msg.status === 'done') { + let _updateLog = []; + _updateLog.push('UI is updated!'); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + updatePatch: null, + })); + updateProgressBar.patch = -1; + } + + if (data.msg.status === 'error') { + let _updateLog = []; + _updateLog.push('Error while verifying update file! Please retry again.'); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + })); + updateProgressBar.patch = -1; + } + } + } else { + if (data && + data.msg) { + let _updateLog = this.state.updateLog; + _updateLog.push(data.msg); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + })); + } + } + } + + _checkForUpdateUIPromise() { + let _updateLog = []; + _updateLog.push('Checking for UI update...'); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + })); + + checkForUpdateUIPromise() + .then((res) => { + let _updateLog = this.state.updateLog; + _updateLog.push(res.result === 'update' ? ('New UI update available ' + res.version.remote) : 'You have the lastest UI version'); + this.setState(Object.assign({}, this.state, { + updatePatch: res.result, + updateLog: _updateLog, + })); + }); + } + + _updateUIPromise() { + updateProgressBar.patch = 0; + let _updateLog = []; + _updateLog.push('Downloading UI update...'); + this.setState(Object.assign({}, this.state, { + updateLog: _updateLog, + })); + + updateUIPromise(); + } + + renderUpdateStatus() { + let items = []; + let patchProgressBar = null; + + for (let i = 0; i < this.state.updateLog.length; i++) { + items.push( +