fix(sync-status):Use weighted percentage avg for sync status progress bar

Summary: Also move calculation to sync store, rename stuff a little bit

Test Plan: Manual :(

Reviewers: evan, jackie, halla

Reviewed By: jackie

Differential Revision: https://phab.nylas.com/D3547
This commit is contained in:
Juan Tejada 2016-12-21 07:28:21 -05:00
parent b5970e1e46
commit a0050a22d5
3 changed files with 70 additions and 38 deletions

View file

@ -8,7 +8,11 @@ export default class InitialSyncActivity extends React.Component {
constructor(props) {
super(props);
this.state = this.getStateFromStores();
this.state = {
isExpanded: false,
syncState: NylasSyncStatusStore.getSyncState(),
syncProgress: NylasSyncStatusStore.getSyncProgress(),
}
}
componentDidMount() {
@ -22,35 +26,15 @@ export default class InitialSyncActivity extends React.Component {
}
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;
const syncState = NylasSyncStatusStore.getSyncState()
const syncProgress = NylasSyncStatusStore.getSyncProgress()
this.setState({syncState, syncProgress});
}
hideExpandedState = (event) => {
event.stopPropagation(); // So it doesn't reach the parent's onClick
event.preventDefault();
this.setState({expandedSync: false});
this.setState({isExpanded: false});
}
renderExpandedSyncState() {
@ -60,7 +44,8 @@ export default class InitialSyncActivity extends React.Component {
return false;
}
const folderStates = _.map(accountSyncState.folderSyncProgress, (progress, name) => {
const {folderSyncProgress} = accountSyncState
const folderStates = _.map(folderSyncProgress, ({progress}, name) => {
return this.renderFolderProgress(name, progress)
})
@ -104,7 +89,7 @@ export default class InitialSyncActivity extends React.Component {
}
render() {
const progress = this.calculateProgress();
const {syncProgress: {progress}} = this.state
if (progress === 1) {
return false;
}
@ -124,14 +109,14 @@ export default class InitialSyncActivity extends React.Component {
const classSet = classNames({
'item': true,
'expanded-sync': this.state.expandedSync,
'expanded-sync': this.state.isExpanded,
});
return (
<div
className={classSet}
key="initial-sync"
onClick={() => (progress ? this.setState({expandedSync: !this.state.expandedSync}) : null)}
onClick={() => (progress ? this.setState({isExpanded: !this.state.isExpanded}) : null)}
>
{this.renderProgressBar(progress)}
{innerContent}

View file

@ -91,7 +91,7 @@ class DeveloperBarStore extends NylasStore
_onSyncStatusChanged: ->
@_longPollStates = {}
_.forEach NylasSyncStatusStore.state(), (state, accountId) =>
_.forEach NylasSyncStatusStore.getSyncState(), (state, accountId) =>
@_longPollStates[accountId] = state.deltaStatus
@trigger()

View file

@ -22,8 +22,14 @@ import CategoryStore from './category-store'
* n1Cloud,
* },
* folderSyncProgress: {
* inbox: 0.5,
* archive: 0.2,
* inbox: {
* progress: 0.5,
* total: 100,
* }
* archive: {
* progress: 0.2,
* total: 600,
* },
* ...
* }
* }
@ -85,11 +91,11 @@ class NylasSyncStatusStore extends NylasStore {
const {uidnext, fetchedmin, fetchedmax} = folder.syncState || {}
if (uidnext) {
const progress = (+fetchedmax - +fetchedmin + 1) / uidnext
updates[name] = progress
updates[name] = {progress, total: uidnext}
} else {
// We don't have a uidnext if the sync hasn't started at all,
// but we've found the folder.
updates[name] = 0
updates[name] = {progress: 0, total: null}
}
}
this._updateState(accountId, {folderSyncProgress: updates})
@ -107,10 +113,51 @@ class NylasSyncStatusStore extends NylasStore {
this._triggerDebounced()
}
state() {
getSyncState() {
return this._statesByAccount
}
/**
* Returns the weighted sync progress for all accounts as a percentage, and
* the total number of messages to sync for a given account
*/
getSyncProgressForAccount(accountId) {
const {folderSyncProgress} = this._statesByAccount[accountId]
const folderNames = Object.keys(folderSyncProgress)
const progressPerFolder = folderNames.map(fname => folderSyncProgress[fname])
const weightedProgress = progressPerFolder.reduce(
(accum, {progress, total}) => accum + progress * total, 0
)
const totalMessageCount = progressPerFolder.reduce(
(accum, {total}) => accum + total, 0
)
return {
progress: weightedProgress / totalMessageCount,
total: totalMessageCount,
}
}
/**
* Returns the weighted sync progress for all accounts as a percentage, and
* the total number of messages to sync
*/
getSyncProgress() {
const accountIds = AccountStore.accountIds()
const progressPerAccount = (
accountIds.map(accId => this.getSyncProgressForAccount(accId))
)
const weightedProgress = progressPerAccount.reduce(
(accum, {progress, total}) => accum + progress * total, 0
)
const totalMessageCount = progressPerAccount.reduce(
(accum, {total}) => accum + total, 0
)
return {
progress: weightedProgress / totalMessageCount,
total: totalMessageCount,
}
}
/**
* Returns true if N1's local cache contains the entire list of available
* folders and labels.
@ -123,7 +170,7 @@ class NylasSyncStatusStore extends NylasStore {
if (!state) { return false }
const folderNames = Object.keys(state.folderSyncProgress || {})
if (folderNames.length === 0) { return false }
return folderNames.some((name) => state.folderSyncProgress[name] !== 0)
return folderNames.some((fname) => state.folderSyncProgress[fname].progress !== 0)
}
whenCategoryListSynced(accountId) {
@ -149,11 +196,11 @@ class NylasSyncStatusStore extends NylasStore {
}
if (folderName) {
return state.folderSyncProgress[folderName] >= 1
return state.folderSyncProgress[folderName].progress >= 1
}
const folderNames = Object.keys(state.folderSyncProgress)
for (const fname of folderNames) {
const syncProgress = state.folderSyncProgress[fname]
const syncProgress = state.folderSyncProgress[fname].progress
if (syncProgress < 1) {
return false
}