feat(mail-rules): Per-account mail rules filter incoming, existing mail
Summary:
Originally, this was going to be a totally independent package, but
I wasn't able to isolate the functionality and get it tied in to
the delta-stream consumption. Here's how it currently works:
- The preferences package has a new tab which allows you to edit
mail filters. Filters are saved in a new core store, and a new
stock component (ScenarioEditor) renders the editor. The editor
takes a set of templates that define a value space, and outputs
a valid set of values.
- A new MailFilterProcessor takes messages and creates tasks to
apply the actions from the MailFiltersStore.
- The worker-sync package now uses the MailFilterProcessor to
apply filters /before/ it calls didPassivelyReceiveNewModels,
so filtrs are applied before any notifications are created.
- A new task, ReprocessMailFiltersTask allows you to run filters
on all of your existing mail. It leverages the existing TaskQueue
architecture to: a) resume where it left off if you quit midway,
b) be queryable (for status) from all windows and c) cancelable.
The TaskQueue is a bit strange because it runs performLocal and
performRemote very differently, and I had to use `performRemote`.
(todo refactor soon.)
This diff also changes the EditableList a bit to behave like a
controlled component and render focused / unfocused states.
Test Plan: Run tests, only for actual filter processing atm.
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2379
2015-12-23 15:19:32 +08:00
|
|
|
_ = require 'underscore'
|
|
|
|
NylasObservables = require 'nylas-observables'
|
|
|
|
{Template} = require './components/scenario-editor-models'
|
|
|
|
|
|
|
|
ConditionTemplates = [
|
|
|
|
new Template('from', Template.Type.String, {
|
|
|
|
name: 'From',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
_.pluck(message.from, 'email')
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('to', Template.Type.String, {
|
|
|
|
name: 'To',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
_.pluck(message.to, 'email')
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('cc', Template.Type.String, {
|
|
|
|
name: 'Cc',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
_.pluck(message.cc, 'email')
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('bcc', Template.Type.String, {
|
|
|
|
name: 'Bcc',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
_.pluck(message.bcc, 'email')
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('anyRecipient', Template.Type.String, {
|
|
|
|
name: 'Any Recipient',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
recipients = [].concat(message.to, message.cc, message.bcc, message.from)
|
|
|
|
_.pluck(recipients, 'email')
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('anyAttachmentName', Template.Type.String, {
|
|
|
|
name: 'Any attachment name',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
_.pluck(message.files, 'filename')
|
|
|
|
})
|
|
|
|
|
2016-02-02 05:18:01 +08:00
|
|
|
new Template('starred', Template.Type.Enum, {
|
|
|
|
name: 'Starred',
|
|
|
|
values: [{name: 'True', value: 'true'}, {name: 'False', value: 'false'}]
|
|
|
|
valueLabel: 'is:'
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
if message.starred then return 'true' else return 'false'
|
|
|
|
})
|
|
|
|
|
feat(mail-rules): Per-account mail rules filter incoming, existing mail
Summary:
Originally, this was going to be a totally independent package, but
I wasn't able to isolate the functionality and get it tied in to
the delta-stream consumption. Here's how it currently works:
- The preferences package has a new tab which allows you to edit
mail filters. Filters are saved in a new core store, and a new
stock component (ScenarioEditor) renders the editor. The editor
takes a set of templates that define a value space, and outputs
a valid set of values.
- A new MailFilterProcessor takes messages and creates tasks to
apply the actions from the MailFiltersStore.
- The worker-sync package now uses the MailFilterProcessor to
apply filters /before/ it calls didPassivelyReceiveNewModels,
so filtrs are applied before any notifications are created.
- A new task, ReprocessMailFiltersTask allows you to run filters
on all of your existing mail. It leverages the existing TaskQueue
architecture to: a) resume where it left off if you quit midway,
b) be queryable (for status) from all windows and c) cancelable.
The TaskQueue is a bit strange because it runs performLocal and
performRemote very differently, and I had to use `performRemote`.
(todo refactor soon.)
This diff also changes the EditableList a bit to behave like a
controlled component and render focused / unfocused states.
Test Plan: Run tests, only for actual filter processing atm.
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2379
2015-12-23 15:19:32 +08:00
|
|
|
new Template('subject', Template.Type.String, {
|
|
|
|
name: 'Subject',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
message.subject
|
|
|
|
})
|
|
|
|
|
|
|
|
new Template('body', Template.Type.String, {
|
|
|
|
name: 'Body',
|
|
|
|
valueForMessage: (message) ->
|
|
|
|
message.body
|
|
|
|
})
|
|
|
|
]
|
|
|
|
|
|
|
|
ActionTemplates = [
|
|
|
|
new Template('markAsRead', Template.Type.None, {name: 'Mark as Read'})
|
|
|
|
new Template('moveToTrash', Template.Type.None, {name: 'Move to Trash'})
|
|
|
|
new Template('star', Template.Type.None, {name: 'Star'})
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
module.exports =
|
|
|
|
ConditionMode:
|
|
|
|
Any: 'any'
|
|
|
|
All: 'all'
|
|
|
|
|
|
|
|
ConditionTemplates: ConditionTemplates
|
|
|
|
|
|
|
|
ConditionTemplatesForAccount: (account) ->
|
|
|
|
return [] unless account
|
|
|
|
return ConditionTemplates
|
|
|
|
|
|
|
|
ActionTemplates: ActionTemplates
|
|
|
|
|
|
|
|
ActionTemplatesForAccount: (account) ->
|
|
|
|
return [] unless account
|
|
|
|
|
|
|
|
templates = [].concat(ActionTemplates)
|
|
|
|
|
|
|
|
CategoryNamesObservable = NylasObservables.Categories
|
|
|
|
.forAccount(account)
|
|
|
|
.sort()
|
|
|
|
.map (cats) ->
|
|
|
|
cats.map (cat) ->
|
|
|
|
name: cat.displayName || cat.name
|
|
|
|
value: cat.id
|
|
|
|
|
|
|
|
if account.usesLabels()
|
|
|
|
templates.unshift new Template('markAsImportant', Template.Type.None, {
|
|
|
|
name: 'Mark as Important'
|
|
|
|
})
|
|
|
|
templates.unshift new Template('applyLabelArchive', Template.Type.None, {
|
|
|
|
name: 'Archive'
|
|
|
|
})
|
|
|
|
templates.unshift new Template('applyLabel', Template.Type.Enum, {
|
|
|
|
name: 'Apply Label'
|
|
|
|
values: CategoryNamesObservable
|
|
|
|
})
|
|
|
|
|
|
|
|
else
|
|
|
|
templates.push new Template('changeFolder', Template.Type.Enum, {
|
|
|
|
name: 'Move Message'
|
|
|
|
valueLabel: 'to folder:'
|
|
|
|
values: CategoryNamesObservable
|
|
|
|
})
|
|
|
|
|
|
|
|
templates
|