Mailspring/internal_packages/thread-list/lib/thread-list-store.coffee
Juan Tejada 281e458d39 feat(account-prefs): Adds new page for Account in preferences
Summary:
Adds the new Account preferences page. This consists of two major React components,
PreferencesAccountList and PreferencesAccountDetails, both of which use EditableList.

I added a bunch of fixes and updated the API for EditableList, plus a bit of
refactoring for PreferencesAccount component, and a bunch of CSS so its a big diff.

The detailed changelog:

Updates to EditableList:
  - Fix bug updating selection state when arrows pressed to move selection
  - Add new props:
    - allowEmptySelection to allow the list to have no selection
    - createInputProps to pass aditional props to the createInput
  - Add scroll region for list items
  - Update styles and refactor render methods

Other Updates:
- Updates Account model to hold aliases and a label
  - Adds getter for label to default to email
- Update accountswitcher to display label, update styles and spec

- Refactor PreferencesAccounts component:
  - Splits it into smaller components,
  - Removes unused code
- Splits preferences styelsheets into smaller separate stylesheet for
  account page. Adds some updates and fixes (scroll-region padding)
- Update AccountStore to be able to perform updates on an account.
- Adds new Action to update account, and an action to remove account to
  be consistent with Action usage
- Adds components for Account list and Aliases list using EditableList

Test Plan: - All specs pass, but need to write new tests!

Reviewers: bengotow, evan

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2332
2015-12-10 15:27:29 -08:00

155 lines
4.8 KiB
CoffeeScript

_ = require 'underscore'
NylasStore = require 'nylas-store'
{Thread,
Message,
Actions,
SearchView,
DatabaseView,
DatabaseStore,
AccountStore,
WorkspaceStore,
FocusedContentStore,
TaskQueueStatusStore,
FocusedMailViewStore} = require 'nylas-exports'
# Public: A mutable text container with undo/redo support and the ability
# to annotate logical regions in the text.
class ThreadListStore extends NylasStore
constructor: ->
@_resetInstanceVars()
@listenTo DatabaseStore, @_onDataChanged
@listenTo AccountStore, @_onAccountChanged
@listenTo FocusedMailViewStore, @_onMailViewChanged
NylasEnv.commands.add "body",
'thread-list:select-read' : @_onSelectRead
'thread-list:select-unread' : @_onSelectUnread
'thread-list:select-starred' : @_onSelectStarred
'thread-list:select-unstarred': @_onSelectUnstarred
# We can't create a @view on construction because the CategoryStore
# has hot yet been populated from the database with the list of
# categories and their corresponding ids. Once that is ready, the
# CategoryStore will trigger, which will update the
# FocusedMailViewStore, which will cause us to create a new
# @view.
_resetInstanceVars: ->
@_lastQuery = null
view: ->
@_view
setView: (view) ->
@_viewUnlisten() if @_viewUnlisten
@_view = view
@_viewUnlisten = view.listen ->
@trigger(@)
,@
# Set up a one-time listener to focus an item in the new view
if WorkspaceStore.layoutMode() is 'split'
unlisten = view.listen ->
if view.loaded()
Actions.setFocus(collection: 'thread', item: view.get(0))
unlisten()
@trigger(@)
createView: ->
mailViewFilter = FocusedMailViewStore.mailView()
account = AccountStore.current()
return unless account and mailViewFilter
if mailViewFilter.searchQuery
@setView(new SearchView(mailViewFilter.searchQuery, account.id))
else
matchers = []
matchers.push Thread.attributes.accountId.equal(account.id)
matchers = matchers.concat(mailViewFilter.matchers())
view = new DatabaseView Thread, {matchers}, (ids) =>
DatabaseStore.findAll(Message)
.where(Message.attributes.threadId.in(ids))
.where(Message.attributes.accountId.equal(account.id))
.then (messages) ->
messagesByThread = {}
for id in ids
messagesByThread[id] = []
for message in messages
messagesByThread[message.threadId].push message
messagesByThread
@setView(view)
Actions.setFocus(collection: 'thread', item: null)
_onSelectRead: =>
items = @_view.itemsCurrentlyInViewMatching (item) -> not item.unread
@_view.selection.set(items)
_onSelectUnread: =>
items = @_view.itemsCurrentlyInViewMatching (item) -> item.unread
@_view.selection.set(items)
_onSelectStarred: =>
items = @_view.itemsCurrentlyInViewMatching (item) -> item.starred
@_view.selection.set(items)
_onSelectUnstarred: =>
items = @_view.itemsCurrentlyInViewMatching (item) -> not item.starred
@_view.selection.set(items)
# Inbound Events
_onMailViewChanged: ->
@createView()
_onAccountChanged: ->
accountId = AccountStore.current()?.id
accountMatcher = (m) ->
m.attribute() is Thread.attributes.accountId and m.value() is accountId
return if @_view and _.find(@_view.matchers(), accountMatcher)
@createView()
_onDataChanged: (change) ->
return unless @_view
if change.objectClass is Thread.name
focusedId = FocusedContentStore.focusedId('thread')
keyboardId = FocusedContentStore.keyboardCursorId('thread')
viewModeAutofocuses = WorkspaceStore.layoutMode() is 'split' or WorkspaceStore.topSheet().root is true
focusedIndex = @_view.indexOfId(focusedId)
keyboardIndex = @_view.indexOfId(keyboardId)
shiftIndex = (i) =>
if i > 0 and (@_view.get(i - 1)?.unread or i >= @_view.count())
return i - 1
else
return i
@_view.invalidate({change: change, shallow: true})
focusedLost = focusedIndex >= 0 and @_view.indexOfId(focusedId) is -1
keyboardLost = keyboardIndex >= 0 and @_view.indexOfId(keyboardId) is -1
if viewModeAutofocuses and focusedLost
Actions.setFocus(collection: 'thread', item: @_view.get(shiftIndex(focusedIndex)))
if keyboardLost
Actions.setCursorPosition(collection: 'thread', item: @_view.get(shiftIndex(keyboardIndex)))
if change.objectClass is Message.name
# Important: Until we optimize this so that it detects the set change
# and avoids a query, this should be defered since it's very unimportant
_.defer =>
threadIds = _.uniq _.map change.objects, (m) -> m.threadId
@_view.invalidateMetadataFor(threadIds)
module.exports = new ThreadListStore()