Mailspring/internal_packages/account-sidebar/lib/sidebar-item.coffee
Juan Tejada 37af2ba42c fix(remove-from-view): Fix logic for delete/remove-from-view behavior:
Summary:
- Separate gmail's remove-from-view and delete behaviors and write logic
  for each of those
  - Remove MailboxPerspective::{canArchiveThreads, canTrashThreads,
    removeThreads} and some unecessary code in TaskFactory
  - Instead, add MailboxPerspective::tasksForRemovingFromPerspective (I
    know its a bit of a mouthful)
  - I initially tried to put all of the logic for each execution path
    inside the TaskFactory by checking perspective types, but it made
    more sense to use the polymorphism already in place for the different
    perspective types.
  - There is a default delete/remove-from-view behavior which is
    configurable via simple ruleset objects. The gmail behavior is
    configured in this way.
- Update swipe css classes based on destination of threads
- Fixes #1460:
  - Update logic to display archive/trash buttons and context menu options correctly
    when selected threads can be archived/trashed (not based on
    perspective)
  - Same for swiping
- Add a bunch of specs
- Convert some code to ES6
- TODO write some docs for new functions

Test Plan: Unit tests

Reviewers: drew, evan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2682
2016-03-07 18:16:37 -08:00

142 lines
4.8 KiB
CoffeeScript

_ = require 'underscore'
_str = require 'underscore.string'
{WorkspaceStore,
MailboxPerspective,
FocusedPerspectiveStore,
SyncbackCategoryTask,
DestroyCategoryTask,
CategoryStore,
Actions,
Utils} = require 'nylas-exports'
{OutlineViewItem} = require 'nylas-component-kit'
SidebarActions = require './sidebar-actions'
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) ->
if NylasEnv.savedState.sidebarKeysCollapsed[id] isnt undefined
NylasEnv.savedState.sidebarKeysCollapsed[id]
else
true
toggleItemCollapsed = (item) ->
return unless item.children.length > 0
SidebarActions.setKeyCollapsed(item.id, not isItemCollapsed(item.id))
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
contextMenuLabel: 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.canReceiveThreadsFromAccountIds(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)
contextMenuLabel = _str.capitalize(categories[0]?.displayType())
perspective = MailboxPerspective.forCategories(categories)
opts.deletable ?= true
opts.editable ?= true
opts.contextMenuLabel = contextMenuLabel
@forPerspective(id, perspective, opts)
@forSnoozed: (accountIds, opts = {}) ->
# TODO This constant should be available elsewhere
displayName = require('../../thread-snooze/lib/snooze-constants').SNOOZE_CATEGORY_NAME
id = displayName
id += "-#{opts.name}" if opts.name
opts.name = "Snoozed" unless opts.name
opts.iconName= 'snooze.png'
categories = accountIds.map (accId) =>
_.findWhere CategoryStore.categories(accId), {displayName}
categories = _.compact(categories)
perspective = MailboxPerspective.forCategories(categories)
perspective.name = id unless perspective.name
@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