2016-02-26 02:37:03 +08:00
|
|
|
import moment from 'moment';
|
2016-02-19 02:00:11 +08:00
|
|
|
import _ from 'underscore';
|
|
|
|
import {
|
|
|
|
Actions,
|
|
|
|
Thread,
|
2017-06-28 02:31:22 +08:00
|
|
|
Label,
|
fix(sync-status): Change old per model status, in favor of per folder
Summary:
Addresses T7275
Previously, we kept track of the sync status of each API model, and the progress
we'd made syncing all available models (e.g. all threads, messages, events, etc)
Given K2's set up, we are now keeping track of sync status per folder, i.e. what
percent of the folder's messages we've synced. This status is now reported from K2
to N1 via folder object deltas, and this commit rewrites the
NylasSyncStatusStore (in ES6) to reflect that.
The new Store keeps the sync state per account, which is the merged state of
per folder sync state, and delta connections state.
We also got rid of `CategoryStore.whenCategoriesReady` in favor of
`whenCategoryListSynced`, which is derived from the fact hat as long as we've
started syncing one folder, we've already synced the entire list of of folders/labels.
There are a couple of TODOs to be addressed in upcoming diffs:
- T7329 Restore the sidebar component to show sync progress, which was previously removed
- T7330 Figure out how to report sync progress per label, specifically, we are interested in knowing how much of the inbox we've synced, which is a label in Gmail. (This might be a non-issue if we sync the inbox very fast, first)
Depends on D3514
Test Plan: Manual
Reviewers: mark, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D3515
2016-12-16 03:07:11 +08:00
|
|
|
DateUtils,
|
|
|
|
TaskFactory,
|
|
|
|
AccountStore,
|
2016-02-19 02:00:11 +08:00
|
|
|
CategoryStore,
|
|
|
|
DatabaseStore,
|
|
|
|
SyncbackCategoryTask,
|
2017-06-28 02:31:22 +08:00
|
|
|
ChangeLabelsTask,
|
|
|
|
ChangeFolderTask,
|
2017-06-23 06:07:04 +08:00
|
|
|
TaskQueue,
|
2017-03-09 04:24:59 +08:00
|
|
|
FolderSyncProgressStore,
|
2016-02-19 02:00:11 +08:00
|
|
|
} from 'nylas-exports';
|
2016-03-07 08:55:28 +08:00
|
|
|
import {SNOOZE_CATEGORY_NAME} from './snooze-constants'
|
|
|
|
|
|
|
|
const {DATE_FORMAT_SHORT} = DateUtils
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2016-02-26 05:06:01 +08:00
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
const SnoozeUtils = {
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
snoozedUntilMessage(snoozeDate, now = moment()) {
|
|
|
|
let message = 'Snoozed'
|
|
|
|
if (snoozeDate) {
|
|
|
|
let dateFormat = DATE_FORMAT_SHORT
|
|
|
|
const date = moment(snoozeDate)
|
|
|
|
const hourDifference = moment.duration(date.diff(now)).asHours()
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
if (hourDifference < 24) {
|
|
|
|
dateFormat = dateFormat.replace('MMM D, ', '');
|
|
|
|
}
|
|
|
|
if (date.minutes() === 0) {
|
|
|
|
dateFormat = dateFormat.replace(':mm', '');
|
2016-02-19 02:00:11 +08:00
|
|
|
}
|
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
message += ` until ${DateUtils.format(date, dateFormat)}`;
|
|
|
|
}
|
|
|
|
return message;
|
|
|
|
},
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
createSnoozeCategory(accountId, name = SNOOZE_CATEGORY_NAME) {
|
2017-06-29 15:41:07 +08:00
|
|
|
const task = new SyncbackCategoryTask({
|
|
|
|
path: name,
|
2016-03-04 04:37:20 +08:00
|
|
|
accountId: accountId,
|
|
|
|
})
|
|
|
|
|
|
|
|
Actions.queueTask(task)
|
2017-06-29 15:41:07 +08:00
|
|
|
return TaskQueue.waitForPerformRemote(task).then((finishedTask) => {
|
|
|
|
return finishedTask.created;
|
|
|
|
});
|
2016-03-04 04:37:20 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
getSnoozeCategory(accountId, categoryName = SNOOZE_CATEGORY_NAME) {
|
2017-03-09 04:24:59 +08:00
|
|
|
return FolderSyncProgressStore.whenCategoryListSynced(accountId)
|
2016-05-06 13:30:34 +08:00
|
|
|
.then(() => {
|
2016-03-04 04:37:20 +08:00
|
|
|
const allCategories = CategoryStore.categories(accountId)
|
|
|
|
const category = _.findWhere(allCategories, {displayName: categoryName})
|
|
|
|
if (category) {
|
|
|
|
return Promise.resolve(category);
|
2016-02-23 07:48:07 +08:00
|
|
|
}
|
2016-03-04 04:37:20 +08:00
|
|
|
return SnoozeUtils.createSnoozeCategory(accountId, categoryName)
|
2016-02-23 07:48:07 +08:00
|
|
|
})
|
2016-03-04 04:37:20 +08:00
|
|
|
},
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
getSnoozeCategoriesByAccount(accounts = AccountStore.accounts()) {
|
|
|
|
const snoozeCategoriesByAccountId = {}
|
2016-05-06 13:30:34 +08:00
|
|
|
accounts.forEach(({id}) => {
|
2016-03-04 04:37:20 +08:00
|
|
|
if (snoozeCategoriesByAccountId[id] != null) return;
|
|
|
|
snoozeCategoriesByAccountId[id] = SnoozeUtils.getSnoozeCategory(id)
|
|
|
|
})
|
|
|
|
return Promise.props(snoozeCategoriesByAccountId)
|
|
|
|
},
|
|
|
|
|
|
|
|
moveThreads(threads, {snooze, getSnoozeCategory, getInboxCategory, description} = {}) {
|
2017-06-28 02:31:22 +08:00
|
|
|
const tasks = TaskFactory.tasksForThreadsByAccountId(threads, (accountThreads, accountId) => {
|
|
|
|
const snoozeCat = getSnoozeCategory(accountId);
|
|
|
|
const inboxCat = getInboxCategory(accountId);
|
|
|
|
if (snoozeCat instanceof Label) {
|
|
|
|
return ChangeLabelsTask({
|
|
|
|
source: "Snooze Move",
|
|
|
|
threads: accountThreads,
|
|
|
|
taskDescription: description,
|
|
|
|
labelsToAdd: snooze ? [snoozeCat] : [inboxCat],
|
|
|
|
labelsToRemove: snooze ? [inboxCat] : [snoozeCat],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return ChangeFolderTask({
|
|
|
|
source: "Snooze Move",
|
|
|
|
threads: accountThreads,
|
|
|
|
taskDescription: description,
|
|
|
|
folder: snooze ? snoozeCat : inboxCat,
|
|
|
|
});
|
|
|
|
});
|
2016-02-19 02:00:11 +08:00
|
|
|
|
2017-06-28 02:31:22 +08:00
|
|
|
Actions.queueTasks(tasks);
|
2017-06-23 06:07:04 +08:00
|
|
|
const promises = tasks.map(task => TaskQueue.waitForPerformRemote(task))
|
2016-03-04 04:37:20 +08:00
|
|
|
// Resolve with the updated threads
|
|
|
|
return (
|
2016-05-06 13:30:34 +08:00
|
|
|
Promise.all(promises).then(() => {
|
2017-06-22 04:12:49 +08:00
|
|
|
return DatabaseStore.modelify(Thread, _.pluck(threads, 'id'))
|
2016-03-04 04:37:20 +08:00
|
|
|
})
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
moveThreadsToSnooze(threads, snoozeCategoriesByAccountPromise, snoozeDate) {
|
|
|
|
return snoozeCategoriesByAccountPromise
|
2016-05-06 13:30:34 +08:00
|
|
|
.then((snoozeCategoriesByAccountId) => {
|
2016-03-08 10:13:53 +08:00
|
|
|
const getSnoozeCategory = (accId) => [snoozeCategoriesByAccountId[accId]]
|
2016-03-11 09:45:50 +08:00
|
|
|
const getInboxCategory = (accId) => [CategoryStore.getInboxCategory(accId)]
|
2016-03-04 04:37:20 +08:00
|
|
|
const description = SnoozeUtils.snoozedUntilMessage(snoozeDate)
|
|
|
|
return SnoozeUtils.moveThreads(
|
|
|
|
threads,
|
|
|
|
{snooze: true, getSnoozeCategory, getInboxCategory, description}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
moveThreadsFromSnooze(threads, snoozeCategoriesByAccountPromise) {
|
|
|
|
return snoozeCategoriesByAccountPromise
|
2016-05-06 13:30:34 +08:00
|
|
|
.then((snoozeCategoriesByAccountId) => {
|
2016-03-08 10:13:53 +08:00
|
|
|
const getSnoozeCategory = (accId) => [snoozeCategoriesByAccountId[accId]]
|
2016-03-11 09:45:50 +08:00
|
|
|
const getInboxCategory = (accId) => [CategoryStore.getInboxCategory(accId)]
|
2016-03-04 04:37:20 +08:00
|
|
|
const description = 'Unsnoozed';
|
|
|
|
return SnoozeUtils.moveThreads(
|
|
|
|
threads,
|
|
|
|
{snooze: false, getSnoozeCategory, getInboxCategory, description}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
},
|
2016-02-19 02:00:11 +08:00
|
|
|
}
|
|
|
|
|
2016-03-04 04:37:20 +08:00
|
|
|
export default SnoozeUtils
|