Mailspring/internal_packages/account-sidebar/lib/sidebar-item.coffee
Ben Gotow 91240f8979 feat(outbox): Sending status now appears beside drafts
Summary:
This diff adds an "OutboxStore" which reflects the TaskQueue and
adds a progress bar / cancel button to drafts which are currently sending.

- Sending state is different from things like Send later because drafts
  which are sending shouldn't be editable. You should have to stop them
  from sending before editing. I think we can implement "Send Later"
  indicators, etc. with a simple InjectedComponentSet on the draft list
  rows, but the OutboxStore is woven into the DraftList query subscription
  so every draft has a `uploadTaskId`.

- The TaskQueue now saves periodically (every one second) when there are
  "Processing" tasks. This is not really necessary, but makes it super
  easy for tasks to expose "progress", because they're essentially
  serialized and propagated to all windows every one second with the
  current progress value. Kind of questionable, but super convenient.

- I also cleaned up ListTabular and MultiselectList a bit because they
  applied the className prop to an inner element and not the top one.

- If a DestroyDraft task is created for a draft without a server id, it
  ends with Task.Status.Continue and not Failed.

- The SendDraftTask doesn't delete uploads until the send actually goes
  through, in case the app crashes and it forgets the file IDs it created.

Test Plan: Tests coming soon

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2524
2016-02-04 14:14:24 -08:00

117 lines
3.9 KiB
CoffeeScript

_ = require 'underscore'
{WorkspaceStore,
MailboxPerspective,
FocusedPerspectiveStore,
SyncbackCategoryTask,
DestroyCategoryTask,
Actions,
Utils} = require 'nylas-exports'
{OutlineViewItem} = require 'nylas-component-kit'
idForCategories = (categories) ->
_.pluck(categories, 'id').join('-')
countForItem = (perspective) ->
unreadCountEnabled = NylasEnv.config.get('core.workspace.showUnreadForAllCategories')
if perspective.isInbox() or unreadCountEnabled
return perspective.unreadCount()
return 0
isItemSelected = (perspective) ->
(WorkspaceStore.rootSheet() in [WorkspaceStore.Sheet.Threads, WorkspaceStore.Sheet.Drafts] and
FocusedPerspectiveStore.current().isEqual(perspective))
isItemDeleted = (perspective) ->
_.any perspective.categories(), (c) -> c.isDeleted
isItemCollapsed = (id) ->
key = "core.accountSidebarCollapsed.#{id}"
NylasEnv.config.get(key)
toggleItemCollapsed = (item) ->
return unless item.children.length > 0
key = "core.accountSidebarCollapsed.#{item.id}"
NylasEnv.config.set(key, not item.collapsed)
onDeleteItem = (item) ->
# TODO Delete multiple categories at once
return if item.deleted is true
category = item.perspective.category()
return unless category
Actions.queueTask(new DestroyCategoryTask({category}))
onEditItem = (item, value) ->
return unless value
return if item.deleted is true
category = item.perspective.category()
return unless category
Actions.queueTask(new SyncbackCategoryTask({category, displayName: value}))
class SidebarItem
@forPerspective: (id, perspective, opts = {}) ->
counterStyle = OutlineViewItem.CounterStyles.Alt if perspective.isInbox()
return _.extend({
id: id
name: perspective.name
count: countForItem(perspective)
iconName: perspective.iconName
children: []
perspective: perspective
className: if isItemDeleted(perspective) then 'deleted' else ''
selected: isItemSelected(perspective)
collapsed: isItemCollapsed(id) ? true
counterStyle: counterStyle
dataTransferType: 'nylas-threads-data'
onDelete: if opts.deletable then onDeleteItem else undefined
onEdited: if opts.editable then onEditItem else undefined
onCollapseToggled: toggleItemCollapsed
onDrop: (item, event) ->
jsonString = event.dataTransfer.getData(item.dataTransferType)
data = Utils.jsonParse(jsonString)
return unless data
item.perspective.receiveThreads(data.threadIds)
shouldAcceptDrop: (item, event) ->
target = item.perspective
current = FocusedPerspectiveStore.current()
jsonString = event.dataTransfer.getData(item.dataTransferType)
data = Utils.jsonParse(jsonString)
return false unless data
return false unless target
return false if target.isEqual(current)
return false unless target.canReceiveThreads(data.accountIds)
return item.dataTransferType in event.dataTransfer.types
onSelect: (item) ->
Actions.selectRootSheet(WorkspaceStore.Sheet.Threads)
Actions.focusMailboxPerspective(item.perspective)
}, opts)
@forCategories: (categories = [], opts = {}) ->
id = idForCategories(categories)
perspective = MailboxPerspective.forCategories(categories)
opts.deletable ?= true
opts.editable ?= true
@forPerspective(id, perspective, opts)
@forStarred: (accountIds, opts = {}) ->
perspective = MailboxPerspective.forStarred(accountIds)
id = 'Starred'
id += "-#{opts.name}" if opts.name
@forPerspective(id, perspective, opts)
@forDrafts: (accountIds, opts = {}) ->
perspective = MailboxPerspective.forDrafts(accountIds)
id = "Drafts-#{opts.name}"
opts.onSelect = ->
Actions.focusMailboxPerspective(perspective)
Actions.selectRootSheet(WorkspaceStore.Sheet.Drafts)
@forPerspective(id, perspective, opts)
module.exports = SidebarItem