mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-24 01:06:07 +08:00
b29f46fdae
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
142 lines
3.8 KiB
JavaScript
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…</div>);
|
|
} else {
|
|
innerContent.push(<div className="inner" key="0">Syncing your mailbox…</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>
|
|
)
|
|
}
|
|
}
|