Skip to content

Commit

Permalink
Setting for idle timeout (#372)
Browse files Browse the repository at this point in the history
Co-authored-by: Chi Kei Chan <chikeichan@gmail.com>
  • Loading branch information
rithvikvibhu and chikeichan authored Jul 9, 2021
1 parent f8c2cbd commit d6a0347
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 9 deletions.
26 changes: 18 additions & 8 deletions app/components/IdleModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import Modal from '../Modal';
import * as walletAction from '../../ducks/walletActions';
import './idle-modal.scss';

const MAX_IDLE = 5;

class IdleModal extends Component {
static propTypes = {
idle: PropTypes.number.isRequired,
maxIdle: PropTypes.number.isRequired,
resetIdle: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
};
Expand All @@ -25,7 +24,15 @@ class IdleModal extends Component {
return;
}

if (!nextProps.isLocked && nextProps.idle >= MAX_IDLE && !this.state.isShowing) {
if (this.props.maxIdle === 0) {
return;
}

if (
!nextProps.isLocked &&
nextProps.idle >= this.props.maxIdle &&
!this.state.isShowing
) {
if (!this.interval) {
this.interval = setInterval(this.countDown, 1000);
}
Expand Down Expand Up @@ -59,7 +66,7 @@ class IdleModal extends Component {
};

countDown = async () => {
const {timeRemaining} = this.state;
const { timeRemaining } = this.state;

if (timeRemaining < 1) {
await this.logout();
Expand All @@ -80,7 +87,9 @@ class IdleModal extends Component {
return (
<Modal className="idle-modal__wrapper" onClose={() => ({})}>
<div className="idle-modal">
<div className="idle-modal__title">You will be automatically logged out in:</div>
<div className="idle-modal__title">
You will be automatically logged out in:
</div>
<div className="idle-modal__time">{this.state.timeRemaining}s</div>
<div className="idle-modal__actions">
<button
Expand All @@ -103,12 +112,13 @@ class IdleModal extends Component {
}

export default connect(
state => ({
(state) => ({
idle: state.wallet.idle,
maxIdle: state.wallet.maxIdle,
isLocked: state.wallet.isLocked,
}),
dispatch => ({
(dispatch) => ({
resetIdle: () => dispatch(walletAction.resetIdle()),
logout: () => dispatch(walletAction.lockWallet()),
}),
})
)(IdleModal);
12 changes: 12 additions & 0 deletions app/db/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ export async function setInitializationState(network, state) {
return dbClient.put(initializationStateKey(network), state ? '1' : '0');
}

export async function getMaxIdleMinutes() {
const maxIdle = await dbClient.get('max-idle');
if (maxIdle === null) {
return null;
}
return (maxIdle >>> 0);
}

export async function setMaxIdleMinutes(maxIdle) {
return dbClient.put('max-idle', maxIdle >>> 0);
}

function initializationStateKey(network) {
return `initialization-state:${network || 'main'}`;
}
Expand Down
17 changes: 16 additions & 1 deletion app/ducks/walletActions.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import walletClient from '../utils/walletClient';
import nodeClient from '../utils/nodeClient';
import throttle from 'lodash.throttle';
import { getInitializationState, setInitializationState } from '../db/system';
import { getInitializationState, setInitializationState, getMaxIdleMinutes, setMaxIdleMinutes } from '../db/system';
import {
GET_PASSPHRASE,
getInitialState,
INCREMENT_IDLE,
LOCK_WALLET,
NONE,
RESET_IDLE,
SET_MAX_IDLE,
SET_PENDING_TRANSACTIONS,
SET_TRANSACTIONS,
SET_WALLET,
Expand Down Expand Up @@ -76,6 +77,12 @@ export const fetchWalletAPIKey = () => async (dispatch) => {
export const fetchWallet = () => async (dispatch, getState) => {
const network = getState().node.network;

const maxIdle = await getMaxIdleMinutes();
dispatch({
type: SET_MAX_IDLE,
payload: maxIdle ?? 5,
})

const isInitialized = await getInitializationState(network);

if (!isInitialized) {
Expand Down Expand Up @@ -317,6 +324,14 @@ export const resetIdle = () => ({
type: RESET_IDLE,
});

export const setMaxIdle = (maxIdle) => async (dispatch) => {
await setMaxIdleMinutes(maxIdle);
dispatch({
type: SET_MAX_IDLE,
payload: maxIdle,
})
};

export const getPassphrase = (resolve, reject) => async (dispatch, getState) => {
if (getState().wallet.watchOnly === true) {
resolve();
Expand Down
7 changes: 7 additions & 0 deletions app/ducks/walletReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const LOCK_WALLET = 'app/wallet/lockWallet';
export const SET_TRANSACTIONS = 'app/wallet/setTransactions';
export const INCREMENT_IDLE = 'app/wallet/incrementIdle';
export const RESET_IDLE = 'app/wallet/resetIdle';
export const SET_MAX_IDLE = 'app/wallet/setMaxIdle';
export const SET_PENDING_TRANSACTIONS = 'app/wallet/setPendingTransactions';
export const START_SYNC_WALLET = 'app/wallet/startSyncWallet';
export const STOP_SYNC_WALLET = 'app/wallet/stopSyncWallet';
Expand Down Expand Up @@ -40,6 +41,7 @@ export function getInitialState() {
receiveDepth: 0,
transactions: new Map(),
idle: 0,
maxIdle: 5,
walletSync: false,
walletHeight: 0,
getPassphrase: {get: false},
Expand Down Expand Up @@ -115,6 +117,11 @@ export default function walletReducer(state = getInitialState(), {type, payload}
...state,
idle: 0,
};
case SET_MAX_IDLE:
return {
...state,
maxIdle: payload,
};
case START_SYNC_WALLET:
return {
...state,
Expand Down
70 changes: 70 additions & 0 deletions app/pages/Settings/MaxIdleModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import MiniModal from "../../components/Modal/MiniModal";
import { setMaxIdle } from "../../ducks/walletActions";
import "./max-idle-modal.scss";

@withRouter
@connect(
(state) => ({
maxIdle: state.wallet.maxIdle,
}),
(dispatch) => ({
setMaxIdle: (maxIdle) => dispatch(setMaxIdle(maxIdle)),
})
)
export default class MaxIdleModal extends Component {
static propTypes = {
maxIdle: PropTypes.number.isRequired,
setMaxIdle: PropTypes.func.isRequired,
history: PropTypes.shape({
push: PropTypes.func.isRequired,
}).isRequired,
};

constructor(props) {
super(props);
this.state = {
maxIdle: props.maxIdle,
};
}

onUpdateMaxIdle = async () => {
try {
await this.props.setMaxIdle(this.state.maxIdle);
this.props.history.push("/settings");
} catch (e) {
console.error(e);
}
};

render() {
return (
<MiniModal title="Change idle timeout" closeRoute="/settings" centered>
<div className="max-idle-modal__instructions">
Enter the time of inactivity after which the wallet should
automatically lock (0 to disable auto-lock).
</div>
<div className="max-idle-modal__input">
<input
type="number"
value={this.state.maxIdle}
onChange={(e) => this.setState({ maxIdle: e.target.value >>> 0 })}
placeholder="5"
min="0"
autoFocus
/>{" "}
minutes
</div>
<button
className="max-idle-modal__submit"
onClick={this.onUpdateMaxIdle}
>
Change timeout
</button>
</MiniModal>
);
}
}
10 changes: 10 additions & 0 deletions app/pages/Settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ContentArea } from '../ContentArea';
import { connect } from 'react-redux';
import './index.scss';
import AccountIndexModal from './AccountIndexModal';
import MaxIdleModal from './MaxIdleModal';
import RevealSeedModal from './RevealSeedModal';
import ZapTXsModal from './ZapTXsModal';
import * as logger from '../../utils/logClient';
Expand Down Expand Up @@ -398,6 +399,14 @@ export default class Settings extends Component {
<ExplorerPicker />,
false,
)}
{this.renderSection(
'Idle Timeout',
<span>
Automatically lock the wallet after a set period of inactivity
</span>,
'Change',
() => history.push('/settings/general/max-idle'),
)}
</>
</Route>
<Route path="/settings/connection">
Expand Down Expand Up @@ -488,6 +497,7 @@ export default class Settings extends Component {
{ this.renderNav() }
{ this.renderContent() }
<Switch>
<Route path="/settings/general/max-idle" component={MaxIdleModal} />
<Route path="/settings/wallet/account-index" component={AccountIndexModal} />
<Route
path="/settings/wallet/remove-wallet"
Expand Down
27 changes: 27 additions & 0 deletions app/pages/Settings/max-idle-modal.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@import "../../variables";

.max-idle-modal {
&__instructions {
margin-bottom: 27px;
}

&__input {
font-size: 20px;
font-weight: 500;
margin-bottom: 27px;

input {
padding: 8px;
border-radius: 3px;
border: 1px solid $grey;
margin-left: 3px;
font-size: 16px;
width: 40px;
text-align: center;
}
}

&__submit {
@extend %btn-primary;
}
}

0 comments on commit d6a0347

Please sign in to comment.