Mailspring/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx
Juan Tejada b29f46fdae fix(auth): Fix authentication notifications
Summary:
Depends on D3544 (K2 diff)

This commit ensures that auth notifications are showed when the
underlying sync worker fails and are cleared when an account is
successfully reconnected

To achieve this, we manually keep track and update syncStates where
appropriate via `Actions.updateAccount`, given that we have access to
N1's version of the account directly from local-sync.
Initially I was considering account delta stream to the cloud-api and the local-api, but that
just complicated things more than it helped.

This commit also fixes a bug with refreshing the gmail token in which we
we were only attempting a token refresh upon restarting the app

This addresses: T7346, T7305, T7335

Test Plan: Manual

Reviewers: halla, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3545
2016-12-21 07:23:09 -05:00

142 lines
3.8 KiB
JavaScript

import _ from 'underscore';
import _str from 'underscore.string';
import classNames from 'classnames';
import {AccountStore, NylasSyncStatusStore, React} from 'nylas-exports';
export default class InitialSyncActivity extends React.Component {
static displayName = 'InitialSyncActivity';
constructor(props) {
super(props);
this.state = this.getStateFromStores();
}
componentDidMount() {
this.unsubscribe = NylasSyncStatusStore.listen(this.onDataChanged);
}
componentWillUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
}
onDataChanged = () => {
this.setState(this.getStateFromStores());
}
getStateFromStores() {
return {
syncState: NylasSyncStatusStore.state(),
};
}
/*
Iterate through the sync progress of each folder of each account and get a
normalized progress value (0: not started, 1: sync complete) for all syncs.
*/
calculateProgress() {
let count = 0;
const total = _.values(this.state.syncState).reduce((outerSum, accountSyncState) => {
return outerSum + _.values(accountSyncState.folderSyncProgress).reduce((innerSum, progress) => {
count++;
return innerSum + progress;
}, 0)
}, 0);
return count ? (total / count) : 0;
}
expandedSyncState() {
const accounts = _.map(this.state.syncState, (accountSyncState, accountId) => {
const account = _.findWhere(AccountStore.accounts(), {id: accountId});
if (!account) {
return false;
}
const folderStates = _.map(accountSyncState.folderSyncProgress, (progress, name) => {
return this.renderFolderProgress(name, progress)
})
return (
<div className="account inner" key={accountId}>
<h2>{account.emailAddress}</h2>
{folderStates}
</div>
)
});
return (
<div className="account-detail-area" key="expanded-sync-state">
{accounts}
<a className="close-expanded" onClick={this.hideExpandedState}>Hide</a>
</div>
)
}
hideExpandedState = (event) => {
event.stopPropagation(); // So it doesn't reach the parent's onClick
event.preventDefault();
this.setState({expandedSync: false});
}
renderFolderProgress(name, progress) {
let status = 'busy';
if (progress === 1) {
status = 'complete';
}
return (
<div className={`model-progress ${status}`} key={name}>
<h3>{_str.titleize(name)}:</h3>
{this.renderProgressBar(progress)}
<div className="amount">{`${_str.numberFormat(progress * 100, 2) || '0.00'}%`}</div>
</div>
)
}
renderProgressBar(progress) {
return (
<div className="progress-track">
<div className="progress" style={{width: `${(progress || 0) * 100}%`}} />
</div>
)
}
render() {
const progress = this.calculateProgress();
if (progress === 1) {
return false;
}
const innerContent = []
if (AccountStore.accountsAreSyncing()) {
if (progress === 0) {
// On application start, the NylasSyncStatusStore takes awhile to populate
// the folderSyncProgress fields. Don't let the user expand the details,
// because they'll be empty.
innerContent.push(<div className="inner" key="0">Preparing to sync your mailbox&hellip;</div>);
} else {
innerContent.push(<div className="inner" key="0">Syncing your mailbox&hellip;</div>);
innerContent.push(this.renderExpandedSyncState());
}
}
const classSet = classNames({
'item': true,
'expanded-sync': this.state.expandedSync,
});
return (
<div
className={classSet}
key="initial-sync"
onClick={() => (progress ? this.setState({expandedSync: !this.state.expandedSync}) : null)}
>
{this.renderProgressBar(progress)}
{innerContent}
</div>
)
}
}