Mailspring/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx
Halla Moore 78d1b85c7f re-feat(initial-sync-status): Bring the intiial sync progress bar back
Summary:
Adds a UI component to see the progress of initial sync.
(The behavior is sometimes a little strange, but I believe this is
just because of weird behavior in the NylasSyncStatusStore itself.
For instance, it sometimes never populates the `folderSyncProgress`
fields, or it never sets the progress to 1, so the bar stops at 99%)

Test Plan: tested locally

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3536
2016-12-19 12:40:36 -08:00

140 lines
3.7 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 (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.expandedSyncState());
}
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>
)
}
}