Mailspring/internal_packages/composer-signature/lib/preferences-signatures.cjsx
Ben Gotow 606909e256 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 02:19:32 -05:00

118 lines
3.6 KiB
CoffeeScript

React = require 'react'
_ = require 'underscore'
{Contenteditable, RetinaImg, Flexbox} = require 'nylas-component-kit'
{AccountStore, Utils} = require 'nylas-exports'
class PreferencesSignatures extends React.Component
@displayName: 'PreferencesSignatures'
constructor: (@props) ->
@_signatureSaveQueue = {}
selectedAccountId = AccountStore.current()?.id
if selectedAccountId
key = @_configKey(selectedAccountId)
initialSig = @props.config.get(key)
else
initialSig = ""
@state =
editAsHTML: false
accounts: AccountStore.items()
currentSignature: initialSig
selectedAccountId: selectedAccountId
componentDidMount: ->
@usub = AccountStore.listen @_onChange
componentWillUnmount: ->
@usub()
@_saveSignatureNow(@state.selectedAccountId, @state.currentSignature)
_saveSignatureNow: (accountId, value) =>
key = @_configKey(accountId)
@props.config.set(key, value)
_saveSignatureSoon: (accountId, value) =>
@_signatureSaveQueue[accountId] = value
@_saveSignaturesFromCache()
__saveSignaturesFromCache: =>
for accountId, value of @_signatureSaveQueue
@_saveSignatureNow(accountId, value)
@_signatureSaveQueue = {}
_saveSignaturesFromCache: _.debounce(PreferencesSignatures::__saveSignaturesFromCache, 500)
_onChange: =>
@setState @_getStateFromStores()
_getStateFromStores: ->
accounts = AccountStore.items()
selectedAccountId = @state.selectedAccountId
currentSignature = @state.currentSignature
if not @state.selectedAccountId in _.pluck(accounts, "id")
selectedAccountId = null
currentSignature = ""
return {accounts, selectedAccountId, currentSignature}
_renderAccountPicker: ->
options = @state.accounts.map (account) ->
<option value={account.id} key={account.id}>{account.emailAddress}</option>
<select value={@state.selectedAccountId} onChange={@_onSelectAccount}>
{options}
</select>
_renderEditableSignature: ->
<Contenteditable
tabIndex={-1}
ref="signatureInput"
value={@state.currentSignature}
onChange={@_onEditSignature}
spellcheck={false} />
_renderHTMLSignature: ->
<textarea ref="signatureHTMLInput"
value={@state.currentSignature}
onChange={@_onEditSignature}/>
_onEditSignature: (event) =>
html = event.target.value
@setState currentSignature: html
@_saveSignatureSoon(@state.selectedAccountId, html)
_configKey: (accountId) ->
"nylas.account-#{accountId}.signature"
_onSelectAccount: (event) =>
@_saveSignatureNow(@state.selectedAccountId, @state.currentSignature)
selectedAccountId = event.target.value
key = @_configKey(selectedAccountId)
initialSig = @props.config.get(key) ? ""
@setState
currentSignature: initialSig
selectedAccountId: selectedAccountId
_renderModeToggle: ->
if @state.editAsHTML
return <a onClick={=> @setState(editAsHTML: false); return}>Edit live preview</a>
else
return <a onClick={=> @setState(editAsHTML: true); return}>Edit raw HTML</a>
render: =>
rawText = if @state.editAsHTML then "Raw HTML " else ""
<section className="container-signatures">
<h2>Signatures</h2>
<div className="section-title">
{rawText}Signature for: {@_renderAccountPicker()}
</div>
<div className="signature-wrap">
{if @state.editAsHTML then @_renderHTMLSignature() else @_renderEditableSignature()}
</div>
<div className="toggle-mode" style={marginTop: "1em"}>{@_renderModeToggle()}</div>
</section>
module.exports = PreferencesSignatures