1
0
mirror of https://github.com/trezor/trezor-wallet synced 2025-02-11 15:42:42 +00:00

Separate notifications and loader

This commit is contained in:
Vladimir Volek 2018-11-21 15:24:07 +01:00 committed by Szymon Lesisz
parent c3bb0899c9
commit 827e5f14fa
7 changed files with 79 additions and 49 deletions

View File

@ -38,36 +38,27 @@ export const dispose = (): Action => ({
type: ACCOUNT.DISPOSE, type: ACCOUNT.DISPOSE,
}); });
const getAccountStatus = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => { const getAccountLoader = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => {
const device = state.wallet.selectedDevice; const device = state.wallet.selectedDevice;
if (!device || !device.state) {
return {
type: 'loader-progress',
title: 'Loading device...',
shouldRender: false,
};
}
const { const {
account, account,
discovery, discovery,
network, network,
} = selectedAccount; } = selectedAccount;
// corner case: accountState didn't finish loading state after LOCATION_CHANGE action if (!device || !device.state) {
if (!network) {
return { return {
type: 'loader-progress', type: 'progress',
title: 'Loading account state...', title: 'Loading device...',
shouldRender: false, shouldRender: false,
}; };
} }
const blockchain = state.blockchain.find(b => b.shortcut === network.shortcut); // corner case: accountState didn't finish loading state after LOCATION_CHANGE action
if (blockchain && !blockchain.connected) { if (!network) {
return { return {
type: 'backend', type: 'progress',
title: `${network.name} backend is not connected`, title: 'Loading account state...',
shouldRender: false, shouldRender: false,
}; };
} }
@ -79,14 +70,14 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
// case 1: device is connected but discovery not started yet (probably waiting for auth) // case 1: device is connected but discovery not started yet (probably waiting for auth)
if (device.available) { if (device.available) {
return { return {
type: 'loader-progress', type: 'progress',
title: 'Authenticating device...', title: 'Authenticating device...',
shouldRender: false, shouldRender: false,
}; };
} }
// case 2: device is unavailable (created with different passphrase settings) account cannot be accessed // case 2: device is unavailable (created with different passphrase settings) account cannot be accessed
return { return {
type: 'loader-info', type: 'info',
title: `Device ${device.instanceLabel} is unavailable`, title: `Device ${device.instanceLabel} is unavailable`,
message: 'Change passphrase settings to use this device', message: 'Change passphrase settings to use this device',
shouldRender: false, shouldRender: false,
@ -95,7 +86,7 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
// case 3: device is disconnected // case 3: device is disconnected
return { return {
type: 'loader-info', type: 'info',
title: `Device ${device.instanceLabel} is disconnected`, title: `Device ${device.instanceLabel} is disconnected`,
message: 'Connect device to load accounts', message: 'Connect device to load accounts',
shouldRender: false, shouldRender: false,
@ -105,13 +96,30 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
if (discovery.completed) { if (discovery.completed) {
// case 4: account not found and discovery is completed // case 4: account not found and discovery is completed
return { return {
type: 'loader-info', type: 'info',
title: 'Account does not exist', title: 'Account does not exist',
shouldRender: false, shouldRender: false,
}; };
} }
} }
return null;
};
const getAccountNotification = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => {
const device = state.wallet.selectedDevice;
const { network } = selectedAccount;
if (device && network) {
const blockchain = state.blockchain.find(b => b.shortcut === network.shortcut);
if (blockchain && !blockchain.connected) {
return {
type: 'backend',
title: `${network.name} backend is not connected`,
shouldRender: false,
};
}
// Additional status: account does exists and it's visible but shouldn't be active // Additional status: account does exists and it's visible but shouldn't be active
if (!device.connected) { if (!device.connected) {
return { return {
@ -128,6 +136,7 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
shouldRender: true, shouldRender: true,
}; };
} }
}
return null; return null;
}; };
@ -152,13 +161,18 @@ const actions = [
export const observe = (prevState: State, action: Action): PayloadAction<boolean> => (dispatch: Dispatch, getState: GetState): boolean => { export const observe = (prevState: State, action: Action): PayloadAction<boolean> => (dispatch: Dispatch, getState: GetState): boolean => {
// ignore not listed actions // ignore not listed actions
if (actions.indexOf(action.type) < 0) return false; if (actions.indexOf(action.type) < 0) return false;
const state: State = getState(); const state: State = getState();
const notification = { const notification = {
type: null, type: null,
message: null, message: null,
title: null, title: null,
}; };
const loader = {
type: null,
message: null,
title: null,
};
const { location } = state.router; const { location } = state.router;
// displayed route is not an account route // displayed route is not an account route
if (!location.state.account) return false; if (!location.state.account) return false;
@ -179,13 +193,18 @@ export const observe = (prevState: State, action: Action): PayloadAction<boolean
tokens, tokens,
pending, pending,
notification, notification,
loader,
shouldRender: false, shouldRender: false,
}; };
// get "selectedAccount" status from newState // get "selectedAccount" status from newState
const status = getAccountStatus(state, newState); const statusNotification = getAccountNotification(state, newState);
newState.notification = status || notification; const statusLoader = getAccountLoader(state, newState);
newState.shouldRender = status ? status.shouldRender : true; const shouldRender = (statusNotification && statusLoader) ? (statusNotification.shouldRender || statusLoader.shouldRender) : true;
newState.notification = statusNotification || notification;
newState.shouldRender = shouldRender;
newState.loader = statusLoader || loader;
// check if newState is different than previous state // check if newState is different than previous state
const stateChanged = reducerUtils.observeChanges(prevState.selectedAccount, newState, { const stateChanged = reducerUtils.observeChanges(prevState.selectedAccount, newState, {
account: ['balance', 'nonce'], account: ['balance', 'nonce'],

View File

@ -7,7 +7,7 @@ import type { Props } from '../../index';
// There could be only one account notification // There could be only one account notification
export default (props: Props) => { export default (props: Props) => {
const { network, notification } = props.selectedAccount; const { network, notification } = props.selectedAccount;
if (network && notification.type && notification.title && notification.type !== 'loader-progress' && notification.type !== 'loader-info') { if (network && notification.type && notification.title) {
if (notification.type === 'backend') { if (notification.type === 'backend') {
// special case: backend is down // special case: backend is down
// TODO: this is a different component with "auto resolve" button // TODO: this is a different component with "auto resolve" button

View File

@ -22,6 +22,11 @@ export type State = {
title: ?string, title: ?string,
message: ?string, message: ?string,
}, },
loader: {
type: ?string,
title: ?string,
message: ?string,
},
shouldRender: boolean, shouldRender: boolean,
}; };
@ -37,6 +42,11 @@ export const initialState: State = {
title: null, title: null,
message: null, message: null,
}, },
loader: {
type: null,
title: null,
message: null,
},
shouldRender: false, shouldRender: false,
}; };

View File

@ -45,10 +45,10 @@ const Content = ({
}) => ( }) => (
<Wrapper> <Wrapper>
{(!isLoading) && children} {(!isLoading) && children}
{isLoading && (type === 'loader-progress' || type === 'loader-info') && ( {isLoading && (type === 'progress' || type === 'info') && (
<Loading> <Loading>
<Row> <Row>
{type === 'loader-progress' && <Loader size={30} />} {type === 'progress' && <Loader size={30} />}
<Text>{title || 'Initializing accounts'}</Text> <Text>{title || 'Initializing accounts'}</Text>
</Row> </Row>
{message && <Message>{message}</Message>} {message && <Message>{message}</Message>}

View File

@ -93,9 +93,9 @@ const AccountReceive = (props: Props) => {
account, account,
discovery, discovery,
shouldRender, shouldRender,
notification, loader,
} = props.selectedAccount; } = props.selectedAccount;
const { type, title, message } = notification; const { type, title, message } = loader;
if (!device || !account || !discovery || !shouldRender) return <Content type={type} title={title} message={message} isLoading />; if (!device || !account || !discovery || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
const { const {

View File

@ -185,7 +185,7 @@ const AccountSend = (props: Props) => {
discovery, discovery,
tokens, tokens,
shouldRender, shouldRender,
notification, loader,
} = props.selectedAccount; } = props.selectedAccount;
const { const {
address, address,
@ -214,7 +214,7 @@ const AccountSend = (props: Props) => {
updateFeeLevels, updateFeeLevels,
onSend, onSend,
} = props.sendFormActions; } = props.sendFormActions;
const { type, title, message } = notification; const { type, title, message } = loader;
if (!device || !account || !discovery || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />; if (!device || !account || !discovery || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
const isCurrentCurrencyToken = networkSymbol !== currency; const isCurrentCurrencyToken = networkSymbol !== currency;

View File

@ -74,11 +74,12 @@ const AccountSummary = (props: Props) => {
network, network,
tokens, tokens,
pending, pending,
notification, loader,
shouldRender, shouldRender,
} = props.selectedAccount; } = props.selectedAccount;
const { type, title, message } = notification; const { type, title, message } = loader;
if (!device || !account || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />; if (!device || !account || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
const explorerLink: string = `${network.explorer.address}${account.address}`; const explorerLink: string = `${network.explorer.address}${account.address}`;