aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/_locales/en/messages.json2
-rw-r--r--app/scripts/controllers/app-state.js73
-rw-r--r--app/scripts/metamask-controller.js12
-rw-r--r--ui/app/pages/routes/index.js17
-rw-r--r--ui/app/store/actions.js14
5 files changed, 105 insertions, 13 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 254bfdfb9..bef278f79 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -161,7 +161,7 @@
"message": "Auto-Logout Timer (minutes)"
},
"autoLogoutTimeLimitDescription": {
- "message": "Set the number of idle time in minutes before Metamask automatically log out"
+ "message": "Set the idle time in minutes before MetaMask will automatically log out"
},
"available": {
"message": "Available"
diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js
new file mode 100644
index 000000000..9533fd458
--- /dev/null
+++ b/app/scripts/controllers/app-state.js
@@ -0,0 +1,73 @@
+const ObservableStore = require('obs-store')
+const extend = require('xtend')
+
+class AppStateController {
+ /**
+ * @constructor
+ * @param opts
+ */
+ constructor (opts = {}) {
+ const {initState, onInactiveTimeout, preferencesStore} = opts
+ const {preferences} = preferencesStore.getState()
+
+ this.onInactiveTimeout = onInactiveTimeout || (() => {})
+ this.store = new ObservableStore(extend({
+ timeoutMinutes: 0,
+ }, initState))
+ this.timer = null
+
+ preferencesStore.subscribe(state => {
+ this._setInactiveTimeout(state.preferences.autoLogoutTimeLimit)
+ })
+
+ this._setInactiveTimeout(preferences.autoLogoutTimeLimit)
+ }
+
+ /**
+ * Sets the last active time to the current time
+ * @return {void}
+ */
+ setLastActiveTime () {
+ this._resetTimer()
+ }
+
+ /**
+ * Sets the inactive timeout for the app
+ * @param {number} timeoutMinutes the inactive timeout in minutes
+ * @return {void}
+ * @private
+ */
+ _setInactiveTimeout (timeoutMinutes) {
+ this.store.putState({
+ timeoutMinutes,
+ })
+
+ this._resetTimer()
+ }
+
+ /**
+ * Resets the internal inactive timer
+ *
+ * If the {@code timeoutMinutes} state is falsy (i.e., zero) then a new
+ * timer will not be created.
+ *
+ * @return {void}
+ * @private
+ */
+ _resetTimer () {
+ const {timeoutMinutes} = this.store.getState()
+
+ if (this.timer) {
+ clearTimeout(this.timer)
+ }
+
+ if (!timeoutMinutes) {
+ return
+ }
+
+ this.timer = setTimeout(() => this.onInactiveTimeout(), timeoutMinutes * 60 * 1000)
+ }
+}
+
+module.exports = AppStateController
+
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index bdfff9827..07054f84b 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -25,6 +25,7 @@ const {setupMultiplex} = require('./lib/stream-utils.js')
const KeyringController = require('eth-keyring-controller')
const NetworkController = require('./controllers/network')
const PreferencesController = require('./controllers/preferences')
+const AppStateController = require('./controllers/app-state')
const CurrencyController = require('./controllers/currency')
const ShapeShiftController = require('./controllers/shapeshift')
const InfuraController = require('./controllers/infura')
@@ -101,6 +102,12 @@ module.exports = class MetamaskController extends EventEmitter {
network: this.networkController,
})
+ // app-state controller
+ this.appStateController = new AppStateController({
+ preferencesStore: this.preferencesController.store,
+ onInactiveTimeout: () => this.setLocked(),
+ })
+
// currency controller
this.currencyController = new CurrencyController({
initState: initState.CurrencyController,
@@ -252,6 +259,7 @@ module.exports = class MetamaskController extends EventEmitter {
})
this.store.updateStructure({
+ AppStateController: this.appStateController.store,
TransactionController: this.txController.store,
KeyringController: this.keyringController.store,
PreferencesController: this.preferencesController.store,
@@ -264,6 +272,7 @@ module.exports = class MetamaskController extends EventEmitter {
})
this.memStore = new ComposableObservableStore(null, {
+ AppStateController: this.appStateController.store,
NetworkController: this.networkController.store,
AccountTracker: this.accountTracker.store,
TxController: this.txController.memStore,
@@ -462,6 +471,9 @@ module.exports = class MetamaskController extends EventEmitter {
// AddressController
setAddressBook: this.addressBookController.set.bind(this.addressBookController),
+ // AppStateController
+ setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController),
+
// KeyringController
setLocked: nodeify(this.setLocked, this),
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
diff --git a/ui/app/pages/routes/index.js b/ui/app/pages/routes/index.js
index 9c30da086..9eeac2da2 100644
--- a/ui/app/pages/routes/index.js
+++ b/ui/app/pages/routes/index.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Route, Switch, withRouter, matchPath } from 'react-router-dom'
import { compose } from 'recompose'
-import actions, {hideSidebar, hideWarning, lockMetamask} from '../../store/actions'
+import actions from '../../store/actions'
import log from 'loglevel'
import IdleTimer from 'react-idle-timer'
import {getMetaMaskAccounts, getNetworkIdentifier, preferencesSelector} from '../../selectors/selectors'
@@ -99,7 +99,7 @@ class Routes extends Component {
}
renderRoutes () {
- const { autoLogoutTimeLimit, lockMetamask } = this.props
+ const { autoLogoutTimeLimit, setLastActiveTime } = this.props
const routes = (
<Switch>
@@ -122,10 +122,7 @@ class Routes extends Component {
if (autoLogoutTimeLimit > 0) {
return (
- <IdleTimer
- onIdle={lockMetamask}
- timeout={autoLogoutTimeLimit * 1000 * 60}
- >
+ <IdleTimer onAction={setLastActiveTime} throttle={1000}>
{routes}
</IdleTimer>
)
@@ -338,7 +335,7 @@ Routes.propTypes = {
networkDropdownOpen: PropTypes.bool,
showNetworkDropdown: PropTypes.func,
hideNetworkDropdown: PropTypes.func,
- lockMetamask: PropTypes.func,
+ setLastActiveTime: PropTypes.func,
history: PropTypes.object,
location: PropTypes.object,
dispatch: PropTypes.func,
@@ -447,11 +444,7 @@ function mapDispatchToProps (dispatch) {
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)),
- lockMetamask: () => {
- dispatch(lockMetamask())
- dispatch(hideWarning())
- dispatch(hideSidebar())
- },
+ setLastActiveTime: () => dispatch(actions.setLastActiveTime()),
}
}
diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js
index 7d45f0932..7f6cbea1f 100644
--- a/ui/app/store/actions.js
+++ b/ui/app/store/actions.js
@@ -356,6 +356,10 @@ var actions = {
setSelectedSettingsRpcUrl,
SET_NETWORKS_TAB_ADD_MODE: 'SET_NETWORKS_TAB_ADD_MODE',
setNetworksTabAddMode,
+
+ // AppStateController-related actions
+ SET_LAST_ACTIVE_TIME: 'SET_LAST_ACTIVE_TIME',
+ setLastActiveTime,
}
module.exports = actions
@@ -2760,3 +2764,13 @@ function setNetworksTabAddMode (isInAddMode) {
value: isInAddMode,
}
}
+
+function setLastActiveTime () {
+ return (dispatch) => {
+ background.setLastActiveTime((err) => {
+ if (err) {
+ return dispatch(actions.displayWarning(err.message))
+ }
+ })
+ }
+}