diff --git a/exports/nylas-exports.coffee b/exports/nylas-exports.coffee
index 89ee66108..518dd2f42 100644
--- a/exports/nylas-exports.coffee
+++ b/exports/nylas-exports.coffee
@@ -90,7 +90,6 @@ class NylasExports
@require "ChangeStarredTask", 'flux/tasks/change-starred-task'
@require "CreateMetadataTask", 'flux/tasks/create-metadata-task'
@require "MarkMessageReadTask", 'flux/tasks/mark-message-read'
- @require "ArchiveThreadHelper", 'flux/tasks/archive-thread-helper'
@require "DestroyMetadataTask", 'flux/tasks/destroy-metadata-task'
# Stores
@@ -134,6 +133,7 @@ class NylasExports
@load "UndoManager", 'flux/undo-manager'
@load "QuotedHTMLParser", 'services/quoted-html-parser'
@load "QuotedPlainTextParser", 'services/quoted-plain-text-parser'
+ @require "RemoveThreadHelper", 'services/remove-thread-helper'
# Errors
@get "APIError", -> require('../src/flux/errors').APIError
diff --git a/internal_packages/message-list/lib/main.cjsx b/internal_packages/message-list/lib/main.cjsx
index 64095aa97..f5e0f62ec 100644
--- a/internal_packages/message-list/lib/main.cjsx
+++ b/internal_packages/message-list/lib/main.cjsx
@@ -9,7 +9,7 @@ MessageToolbarItems = require "./message-toolbar-items"
SidebarContactList} = require "./sidebar-components"
ThreadStarButton = require './thread-star-button'
-ThreadArchiveButton = require './thread-archive-button'
+ThreadRemoveButton = require './thread-remove-button'
ThreadToggleUnreadButton = require './thread-toggle-unread-button'
AutolinkerExtension = require './plugins/autolinker-extension'
@@ -36,7 +36,7 @@ module.exports =
ComponentRegistry.register ThreadStarButton,
role: 'message:Toolbar'
- ComponentRegistry.register ThreadArchiveButton,
+ ComponentRegistry.register ThreadRemoveButton,
role: 'message:Toolbar'
ComponentRegistry.register ThreadToggleUnreadButton,
@@ -48,7 +48,7 @@ module.exports =
deactivate: ->
ComponentRegistry.unregister MessageList
ComponentRegistry.unregister ThreadStarButton
- ComponentRegistry.unregister ThreadArchiveButton
+ ComponentRegistry.unregister ThreadRemoveButton
ComponentRegistry.unregister ThreadToggleUnreadButton
ComponentRegistry.unregister MessageToolbarItems
ComponentRegistry.unregister SidebarContactCard
diff --git a/internal_packages/message-list/lib/thread-archive-button.cjsx b/internal_packages/message-list/lib/thread-archive-button.cjsx
deleted file mode 100644
index cc9dab8b8..000000000
--- a/internal_packages/message-list/lib/thread-archive-button.cjsx
+++ /dev/null
@@ -1,24 +0,0 @@
-_ = require 'underscore'
-React = require 'react'
-{Actions, DOMUtils} = require 'nylas-exports'
-{RetinaImg} = require 'nylas-component-kit'
-
-class ThreadArchiveButton extends React.Component
- @displayName: "ThreadArchiveButton"
- @containerRequired: false
-
- render: =>
-
-
- _onArchive: (e) =>
- return unless DOMUtils.nodeIsVisible(e.currentTarget)
- Actions.archive()
- e.stopPropagation()
-
-
-module.exports = ThreadArchiveButton
diff --git a/internal_packages/message-list/lib/thread-remove-button.cjsx b/internal_packages/message-list/lib/thread-remove-button.cjsx
new file mode 100644
index 000000000..d4b5d2807
--- /dev/null
+++ b/internal_packages/message-list/lib/thread-remove-button.cjsx
@@ -0,0 +1,37 @@
+_ = require 'underscore'
+React = require 'react'
+{Actions,
+ DOMUtils,
+ RemoveThreadHelper,
+ FocusedMailViewStore} = require 'nylas-exports'
+{RetinaImg} = require 'nylas-component-kit'
+
+class ThreadRemoveButton extends React.Component
+ @displayName: "ThreadRemoveButton"
+ @containerRequired: false
+
+ render: =>
+ focusedMailViewFilter = FocusedMailViewStore.mailView()
+ return false unless focusedMailViewFilter?.canRemoveThreads()
+
+ if RemoveThreadHelper.removeType() is RemoveThreadHelper.Type.Archive
+ tooltip = "Archive"
+ imgName = "toolbar-archive.png"
+ else if RemoveThreadHelper.removeType() is RemoveThreadHelper.Type.Trash
+ tooltip = "Trash"
+ imgName = "toolbar-trash.png"
+
+
+
+ _onRemove: (e) =>
+ return unless DOMUtils.nodeIsVisible(e.currentTarget)
+ Actions.removeCurrentlyFocusedThread()
+ e.stopPropagation()
+
+
+module.exports = ThreadRemoveButton
diff --git a/internal_packages/thread-list/lib/main.cjsx b/internal_packages/thread-list/lib/main.cjsx
index 4df4aa631..ecf82fc66 100644
--- a/internal_packages/thread-list/lib/main.cjsx
+++ b/internal_packages/thread-list/lib/main.cjsx
@@ -2,7 +2,7 @@ _ = require 'underscore'
React = require "react"
{ComponentRegistry, WorkspaceStore} = require "nylas-exports"
-{DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton} = require "./thread-buttons"
+{DownButton, UpButton, ThreadBulkRemoveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton} = require "./thread-buttons"
{DraftDeleteButton} = require "./draft-buttons"
ThreadSelectionBar = require './thread-selection-bar'
ThreadList = require './thread-list'
@@ -44,7 +44,7 @@ module.exports =
location: WorkspaceStore.Sheet.Thread.Toolbar.Right
modes: ['list']
- ComponentRegistry.register ThreadBulkArchiveButton,
+ ComponentRegistry.register ThreadBulkRemoveButton,
role: 'thread:BulkAction'
ComponentRegistry.register ThreadBulkStarButton,
@@ -61,7 +61,7 @@ module.exports =
ComponentRegistry.unregister DraftSelectionBar
ComponentRegistry.unregister ThreadList
ComponentRegistry.unregister ThreadSelectionBar
- ComponentRegistry.unregister ThreadBulkArchiveButton
+ ComponentRegistry.unregister ThreadBulkRemoveButton
ComponentRegistry.unregister ThreadBulkToggleUnreadButton
ComponentRegistry.unregister DownButton
ComponentRegistry.unregister UpButton
diff --git a/internal_packages/thread-list/lib/thread-buttons.cjsx b/internal_packages/thread-list/lib/thread-buttons.cjsx
index 426942268..c9da92f1f 100644
--- a/internal_packages/thread-list/lib/thread-buttons.cjsx
+++ b/internal_packages/thread-list/lib/thread-buttons.cjsx
@@ -2,25 +2,38 @@ React = require "react/addons"
classNames = require 'classnames'
ThreadListStore = require './thread-list-store'
{RetinaImg} = require 'nylas-component-kit'
-{Actions, FocusedContentStore} = require "nylas-exports"
+{Actions,
+ RemoveThreadHelper,
+ FocusedContentStore,
+ FocusedMailViewStore} = require "nylas-exports"
-class ThreadBulkArchiveButton extends React.Component
- @displayName: 'ThreadBulkArchiveButton'
+class ThreadBulkRemoveButton extends React.Component
+ @displayName: 'ThreadBulkRemoveButton'
@containerRequired: false
@propTypes:
selection: React.PropTypes.object.isRequired
render: ->
+ focusedMailViewFilter = FocusedMailViewStore.mailView()
+ return false unless focusedMailViewFilter?.canRemoveThreads()
+
+ if RemoveThreadHelper.removeType() is RemoveThreadHelper.Type.Archive
+ tooltip = "Archive"
+ imgName = "toolbar-archive.png"
+ else if RemoveThreadHelper.removeType() is RemoveThreadHelper.Type.Trash
+ tooltip = "Trash"
+ imgName = "toolbar-trash.png"
+
- _onArchive: =>
- Actions.archiveSelection()
+ _onRemove: =>
+ Actions.removeSelection()
class ThreadBulkStarButton extends React.Component
@@ -158,4 +171,4 @@ UpButton = React.createClass
UpButton.containerRequired = false
DownButton.containerRequired = false
-module.exports = {DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton}
+module.exports = {DownButton, UpButton, ThreadBulkRemoveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton}
diff --git a/internal_packages/thread-list/lib/thread-list-quick-actions.cjsx b/internal_packages/thread-list/lib/thread-list-quick-actions.cjsx
index 029ca2c3e..8f3ac4197 100644
--- a/internal_packages/thread-list/lib/thread-list-quick-actions.cjsx
+++ b/internal_packages/thread-list/lib/thread-list-quick-actions.cjsx
@@ -1,71 +1,30 @@
-_ = require 'underscore'
React = require 'react'
{Actions,
- Utils,
- Thread,
- ArchiveThreadHelper,
- CategoryStore,
- ChangeFolderTask,
- ChangeLabelsTask,
- AccountStore} = require 'nylas-exports'
+ RemoveThreadHelper,
+ FocusedMailViewStore} = require 'nylas-exports'
class ThreadListQuickActions extends React.Component
@displayName: 'ThreadListQuickActions'
@propTypes:
thread: React.PropTypes.object
- categoryId: React.PropTypes.string
render: =>
- actions = []
- if @_shouldDisplayArchiveButton()
- actions.push
- else if AccountStore.current().usesLabels() and @props.categoryId == CategoryStore.getStandardCategory('all').id
- actions.push
+ focusedMailViewFilter = FocusedMailViewStore.mailView()
+ return false unless focusedMailViewFilter?.canRemoveThreads()
- return false if actions.length is 0
+ classNames = "btn action action-#{RemoveThreadHelper.removeType()}"
shouldComponentUpdate: (newProps, newState) ->
newProps.thread.id isnt @props?.thread.id
- _shouldDisplayArchiveButton: =>
- if @props.categoryId not in [CategoryStore.getStandardCategory('archive')?.id, CategoryStore.getStandardCategory('trash')?.id, CategoryStore.getStandardCategory('sent')?.id]
- if AccountStore.current().usesLabels()
- if @props.thread.labels.length == 1 and (@props.thread.labels[0].name == "archive" or @props.thread.labels[0].name == "all")
- return false
- return true
- else if @props.thread.folders.length == 1 and @props.thread.folders[0].name == "archive"
- return false
- return true
-
- return false
-
- _onTrash: (event) =>
- params =
- thread: @props.thread,
- labelsToRemove: [CategoryStore.byId(@props.categoryId)],
- labelsToAdd: [CategoryStore.getStandardCategory("trash")]
- Actions.queueTask(new ChangeLabelsTask(params))
- # Don't trigger the thread row click
- event.stopPropagation()
-
-
- _onForward: (event) =>
- Actions.composeForward({thread: @props.thread, popout: true})
- # Don't trigger the thread row click
- event.stopPropagation()
-
- _onReply: (event) =>
- Actions.composeReply({thread: @props.thread, popout: true})
- # Don't trigger the thread row click
- event.stopPropagation()
-
- _onArchive: (event) =>
- archiveTask = ArchiveThreadHelper.getArchiveTask([@props.thread])
- Actions.queueTask(archiveTask)
+ _onRemove: (event) =>
+ focusedMailViewFilter = FocusedMailViewStore.mailView()
+ t = RemoveThreadHelper.getRemovalTask([@props.thread], focusedMailViewFilter)
+ Actions.queueTask(t)
# Don't trigger the thread row click
event.stopPropagation()
diff --git a/internal_packages/thread-list/lib/thread-list-store.coffee b/internal_packages/thread-list/lib/thread-list-store.coffee
index fc6ab0c4c..53d44a5be 100644
--- a/internal_packages/thread-list/lib/thread-list-store.coffee
+++ b/internal_packages/thread-list/lib/thread-list-store.coffee
@@ -12,7 +12,7 @@ NylasStore = require 'nylas-store'
ChangeUnreadTask,
ChangeStarredTask,
FocusedContentStore,
- ArchiveThreadHelper,
+ RemoveThreadHelper,
TaskQueueStatusStore,
FocusedMailViewStore} = require 'nylas-exports'
@@ -22,14 +22,14 @@ class ThreadListStore extends NylasStore
constructor: ->
@_resetInstanceVars()
- @listenTo Actions.archiveAndPrevious, @_onArchiveAndPrev
- @listenTo Actions.archiveAndNext, @_onArchiveAndNext
+ @listenTo Actions.removeSelection, @_onRemoveSelection
- @listenTo Actions.archiveSelection, @_onArchiveSelection
- @listenTo Actions.moveThreads, @_onMoveThreads
+ @listenTo Actions.removeCurrentlyFocusedThread, @_onRemoveAndAuto
+ @listenTo Actions.removeAndNext, @_onRemoveAndNext
+ @listenTo Actions.removeAndPrevious, @_onRemoveAndPrev
- @listenTo Actions.archive, @_onArchive
@listenTo Actions.moveThread, @_onMoveThread
+ @listenTo Actions.moveThreads, @_onMoveThreads
@listenTo Actions.toggleStarSelection, @_onToggleStarSelection
@listenTo Actions.toggleStarFocused, @_onToggleStarFocused
@@ -158,24 +158,29 @@ class ThreadListStore extends NylasStore
task = new ChangeUnreadTask {threads, unread}
Actions.queueTask task
- _onArchive: ->
- @_archiveAndShiftBy('auto')
+ _onRemoveAndAuto: ->
+ @_removeAndShiftBy('auto')
- _onArchiveAndPrev: ->
- @_archiveAndShiftBy(-1)
+ _onRemoveAndPrev: ->
+ @_removeAndShiftBy(-1)
- _onArchiveAndNext: ->
- @_archiveAndShiftBy(1)
+ _onRemoveAndNext: ->
+ @_removeAndShiftBy(1)
- _archiveAndShiftBy: (offset) ->
+ _removeAndShiftBy: (offset) ->
+ mailViewFilter = FocusedMailViewStore.mailView()
+ return unless mailViewFilter.canApplyToThreads()
focused = FocusedContentStore.focused('thread')
return unless focused
- task = ArchiveThreadHelper.getArchiveTask([focused])
+ task = RemoveThreadHelper.getRemovalTask([focused], mailViewFilter)
@_moveAndShiftBy(offset, task)
- _onArchiveSelection: ->
+ _onRemoveSelection: ->
+ mailViewFilter = FocusedMailViewStore.mailView()
+ return unless mailViewFilter.canApplyToThreads()
selectedThreads = @_view.selection.items()
- task = ArchiveThreadHelper.getArchiveTask(selectedThreads)
+ return unless selectedThreads.length > 0
+ task = RemoveThreadHelper.getRemovalTask(selectedThreads, mailViewFilter)
@_onMoveThreads(selectedThreads, task)
_onMoveThread: (thread, task) ->
@@ -233,13 +238,13 @@ class ThreadListStore extends NylasStore
# Remove the current thread from selection
@_view.selection.remove(focused)
- # If the user is in list mode and archived without specifically saying
- # "archive and next" or "archive and prev", return to the thread list
+ # If the user is in list mode and removed without specifically saying
+ # "remove and next" or "remove and prev", return to the thread list
# instead of focusing on the next message.
if layoutMode is 'list' and not explicitOffset
nextFocus = null
- # Archive the current thread
+ # Remove the current thread
TaskQueueStatusStore.waitForPerformLocal(task).then =>
Actions.setFocus(collection: 'thread', item: nextFocus)
Actions.setCursorPosition(collection: 'thread', item: nextKeyboard)
diff --git a/internal_packages/thread-list/lib/thread-list.cjsx b/internal_packages/thread-list/lib/thread-list.cjsx
index 4b73f8e4a..3b2802ede 100644
--- a/internal_packages/thread-list/lib/thread-list.cjsx
+++ b/internal_packages/thread-list/lib/thread-list.cjsx
@@ -133,8 +133,7 @@ class ThreadList extends React.Component
c5 = new ListTabular.Column
name: "HoverActions"
resolver: (thread) =>
- currentCategoryId = FocusedMailViewStore.mailView()?.categoryId()
-
+
@wideColumns = [c1, c2, c3, c4, c5]
@@ -167,10 +166,10 @@ class ThreadList extends React.Component
@narrowColumns = [cNarrow]
@commands =
- 'core:remove-item': @_onArchive
+ 'core:remove-item': @_onRemoveItem
'core:star-item': @_onStarItem
- 'core:remove-and-previous': -> Actions.archiveAndPrevious()
- 'core:remove-and-next': -> Actions.archiveAndNext()
+ 'core:remove-and-previous': -> Actions.removeAndPrevious()
+ 'core:remove-and-next': -> Actions.removeAndNext()
@itemPropsProvider = (item) ->
className: classNames
@@ -257,15 +256,15 @@ class ThreadList extends React.Component
else
Actions.toggleStarFocused()
- _onArchive: =>
+ _onRemoveItem: =>
return unless ThreadListStore.view()
if WorkspaceStore.layoutMode() is "list" and WorkspaceStore.topSheet() is WorkspaceStore.Sheet.Thread
- Actions.archive()
+ Actions.removeCurrentlyFocusedThread()
else if ThreadListStore.view().selection.count() > 0
- Actions.archiveSelection()
+ Actions.removeSelection()
else
- Actions.archive()
+ Actions.removeCurrentlyFocusedThread()
module.exports = ThreadList
diff --git a/internal_packages/thread-list/spec/thread-list-spec.cjsx b/internal_packages/thread-list/spec/thread-list-spec.cjsx
index 00f0bb498..c2b51a3a8 100644
--- a/internal_packages/thread-list/spec/thread-list-spec.cjsx
+++ b/internal_packages/thread-list/spec/thread-list-spec.cjsx
@@ -216,9 +216,9 @@ describe "ThreadList", ->
spyOn(ThreadStore, "_onAccountChanged")
spyOn(DatabaseStore, "findAll").andCallFake ->
new Promise (resolve, reject) -> resolve(test_threads())
- spyOn(Actions, "archive")
- spyOn(Actions, "archiveAndNext")
- spyOn(Actions, "archiveAndPrevious")
+ spyOn(Actions, "removeCurrentlyFocusedThread")
+ spyOn(Actions, "removeAndNext")
+ spyOn(Actions, "removeAndPrevious")
ReactTestUtils.spyOnClass(ThreadList, "_prepareColumns").andCallFake ->
@_columns = columns
diff --git a/spec-nylas/tasks/remove-thread-helper-spec.coffee b/spec-nylas/tasks/remove-thread-helper-spec.coffee
new file mode 100644
index 000000000..5c0dfb360
--- /dev/null
+++ b/spec-nylas/tasks/remove-thread-helper-spec.coffee
@@ -0,0 +1,88 @@
+Account = require '../../src/flux/models/account'
+CategoryStore = require '../../src/flux/stores/category-store'
+RemoveThreadHelper = require '../../src/services/remove-thread-helper'
+
+ChangeFolderTask = require '../../src/flux/tasks/change-folder-task'
+ChangeLabelsTask = require '../../src/flux/tasks/change-labels-task'
+
+describe "RemoveThreadHelper", ->
+ describe "removeType", ->
+ it "returns null if there's no current account", ->
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn null
+ expect(RemoveThreadHelper.removeType()).toBe null
+
+ it "returns the type if it's saved", ->
+ spyOn(atom.config, "get").andReturn "trash"
+ expect(RemoveThreadHelper.removeType()).toBe "trash"
+
+ it "returns the archive category if it exists", ->
+ spyOn(CategoryStore, "getStandardCategory").andReturn {name: "archive"}
+ expect(RemoveThreadHelper.removeType()).toBe "archive"
+
+ it "defaults to archive for Gmail", ->
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn provider: "gmail"
+ expect(RemoveThreadHelper.removeType()).toBe "archive"
+
+ it "defaults to trash for everything else", ->
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn provider: "eas"
+ expect(RemoveThreadHelper.removeType()).toBe "trash"
+
+ describe "getRemovalTask", ->
+ beforeEach ->
+ spyOn(CategoryStore, "byId").andReturn({id: "inbox-id", name: "inbox"})
+ @mailViewFilterStub = categoryId: -> "inbox-id"
+ @categories = []
+
+ spyOn(CategoryStore, "getStandardCategory").andCallFake (cat) =>
+ if cat in @categories
+ return {id: "cat-id", name: cat}
+ else return null
+
+ afterEach ->
+ atom.testOrganizationUnit = null
+
+ it "returns null if there's no current account", ->
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn null
+ expect(RemoveThreadHelper.getRemovalTask()).toBe null
+
+ it "creates the task when using labels and trashing", ->
+ atom.testOrganizationUnit = "label"
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn new Account
+ provider: "eas"
+ organizationUnit: "label"
+ @categories = ["all", "trash"]
+ t = RemoveThreadHelper.getRemovalTask([], @mailViewFilterStub)
+ expect(t instanceof ChangeLabelsTask).toBe true
+ expect(t.labelsToRemove[0].name).toBe "inbox"
+ expect(t.labelsToAdd[0].name).toBe "trash"
+
+ it "creates the task when using labels and archiving", ->
+ @categories = ["all", "archive", "trash"]
+ atom.testOrganizationUnit = "label"
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn new Account
+ provider: "gmail"
+ organizationUnit: "label"
+ t = RemoveThreadHelper.getRemovalTask([], @mailViewFilterStub)
+ expect(t instanceof ChangeLabelsTask).toBe true
+ expect(t.labelsToRemove[0].name).toBe "inbox"
+ expect(t.labelsToAdd[0].name).toBe "all"
+
+ it "creates the task when using folders and trashing", ->
+ @categories = ["all", "trash"]
+ atom.testOrganizationUnit = "folder"
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn new Account
+ provider: "eas"
+ organizationUnit: "folder"
+ t = RemoveThreadHelper.getRemovalTask([], @mailViewFilterStub)
+ expect(t instanceof ChangeFolderTask).toBe true
+ expect(t.folder.name).toBe "trash"
+
+ it "creates the task when using folders and archiving", ->
+ @categories = ["all", "archive", "trash"]
+ atom.testOrganizationUnit = "folder"
+ spyOn(RemoveThreadHelper, "_currentAccount").andReturn new Account
+ provider: "gmail"
+ organizationUnit: "folder"
+ t = RemoveThreadHelper.getRemovalTask([], @mailViewFilterStub)
+ expect(t instanceof ChangeFolderTask).toBe true
+ expect(t.folder.name).toBe "archive"
diff --git a/src/components/multiselect-action-bar.cjsx b/src/components/multiselect-action-bar.cjsx
index 9be8c4f67..b6e6acabe 100644
--- a/src/components/multiselect-action-bar.cjsx
+++ b/src/components/multiselect-action-bar.cjsx
@@ -31,7 +31,7 @@ The MultiselectActionBar uses the `ComponentRegistry` to find items to display f
collection name. To add an item to the bar created in the example above, register it like this:
```coffee
-ComponentRegistry.register ThreadBulkArchiveButton,
+ComponentRegistry.register ThreadBulkRemoveButton,
role: 'thread:BulkAction'
```
diff --git a/src/flux/actions.coffee b/src/flux/actions.coffee
index 877efa1e8..26c3acf37 100644
--- a/src/flux/actions.coffee
+++ b/src/flux/actions.coffee
@@ -32,7 +32,7 @@ how it propogates between windows.
## Firing Actions
```coffee
-Actions.postNotification({message: "Archived Thread", type: 'success'})
+Actions.postNotification({message: "Removed Thread", type: 'success'})
Actions.queueTask(new ChangeStarredTask(thread: @_thread, starred: true))
```
@@ -305,20 +305,20 @@ class Actions
@destroyDraft: ActionScopeWindow
###
- Public: Archive the currently focused {Thread}.
+ Public: Remove the currently focused {Thread}.
*Scope: Window*
###
- @archive: ActionScopeWindow
+ @removeCurrentlyFocusedThread: ActionScopeWindow
###
- Public: Archives the Thread objects currently selected in the app's main thread list.
+ Public: Removes the Thread objects currently selected in the app's main thread list.
*Scope: Window*
###
- @archiveSelection: ActionScopeWindow
- @archiveAndNext: ActionScopeWindow
- @archiveAndPrevious: ActionScopeWindow
+ @removeSelection: ActionScopeWindow
+ @removeAndNext: ActionScopeWindow
+ @removeAndPrevious: ActionScopeWindow
@toggleStarSelection: ActionScopeWindow
@toggleStarFocused: ActionScopeWindow
@toggleUnreadSelection: ActionScopeWindow
@@ -367,7 +367,7 @@ class Actions
```
# A simple notification
- Actions.postNotification({message: "Archived Thread", type: 'success'})
+ Actions.postNotification({message: "Removed Thread", type: 'success'})
# A sticky notification with actions
NOTIF_ACTION_YES = 'YES'
diff --git a/src/flux/tasks/archive-thread-helper.coffee b/src/flux/tasks/archive-thread-helper.coffee
deleted file mode 100644
index 2bd3be29d..000000000
--- a/src/flux/tasks/archive-thread-helper.coffee
+++ /dev/null
@@ -1,72 +0,0 @@
-CategoryStore = require '../stores/category-store'
-FocusedMailViewStore = require '../stores/focused-mail-view-store'
-
-ChangeLabelsTask = require './change-labels-task'
-ChangeFolderTask = require './change-folder-task'
-Actions = require '../actions'
-
-AccountStore = require '../stores/account-store'
-
-class ArchiveThreadHelper
-
- getArchiveTask: (threads) ->
- @_getTask(threads, "archive")
-
- getUnarchiveTask: (threads) ->
- @_getTask(threads, "unarchive")
-
- _getTask: (threads=[], direction) ->
- threads = [threads] unless threads instanceof Array
- account = AccountStore.current()
- return null unless account
-
- if account.usesFolders()
- if direction is "archive"
- archiveFolder = CategoryStore.getStandardCategory("archive")
- if archiveFolder
- return new ChangeFolderTask
- folder: archiveFolder
- threads: threads
- else
- # TODO: Implement some sort of UI for people to pick the folder
- # they want to use as the Archive. Or better yet, automatically
- # add an `Archive` folder first, then move it to there and maybe
- # throw up some sort of notifciation.
- #
- # In the meantime, just throw up a notification so people do it on
- # the backend.
- Actions.postNotification
- type: 'error'
- tag: 'noArchive'
- sticky: true
- message: "You have not created an Archive folder. Please create a folder called 'Archive' with your email provider, restart N1, then try again.",
- return null
- else if direction is "unarchive"
- inboxFolder = CategoryStore.getStandardCategory("inbox")
- return new ChangeFolderTask
- folder: inboxFolder
- threads: threads
-
- else if account.usesLabels()
- viewCategoryId = FocusedMailViewStore.mailView().categoryId()
- currentLabel = CategoryStore.byId(viewCategoryId)
- currentLabel ?= CategoryStore.getStandardCategory("inbox")
-
- params = {threads}
- if direction is "archive"
- params.labelsToRemove = [currentLabel]
- else if direction is "unarchive"
- params.labelsToAdd = [currentLabel]
-
- archiveLabel = CategoryStore.getStandardCategory("all")
- if archiveLabel
- if direction is "archive"
- params.labelsToAdd = [archiveLabel]
- else if direction is "unarchive"
- params.labelsToRemove = [archiveLabel]
-
- return new ChangeLabelsTask(params)
- else
- throw new Error("Invalid organizationUnit")
-
-module.exports = new ArchiveThreadHelper()
diff --git a/src/mail-view-filter.coffee b/src/mail-view-filter.coffee
index eb6acebcc..3d7174d90 100644
--- a/src/mail-view-filter.coffee
+++ b/src/mail-view-filter.coffee
@@ -48,10 +48,13 @@ class MailViewFilter
canApplyToThreads: ->
throw new Error("canApplyToThreads: Not implemented in base class.")
+ # Whether or not the current MailViewFilter can "archive" or "trash"
+ canRemoveThreads: ->
+ throw new Error("canRemoveThreads: Not implemented in base class.")
+
applyToThreads: (threadsOrIds) ->
throw new Error("applyToThreads: Not implemented in base class.")
-
class SearchMailViewFilter extends MailViewFilter
constructor: (@searchQuery) ->
@
@@ -65,6 +68,9 @@ class SearchMailViewFilter extends MailViewFilter
canApplyToThreads: ->
false
+ canRemoveThreads: ->
+ false
+
categoryId: ->
null
@@ -84,6 +90,9 @@ class StarredMailViewFilter extends MailViewFilter
canApplyToThreads: ->
true
+ canRemoveThreads: ->
+ true
+
applyToThreads: (threadsOrIds) ->
ChangeStarredTask = require './flux/tasks/change-starred-task'
task = new ChangeStarredTask({threads:threadsOrIds, starred: true})
@@ -119,6 +128,11 @@ class CategoryMailViewFilter extends MailViewFilter
canApplyToThreads: ->
not (@category.name in CategoryStore.LockedCategoryNames)
+ canRemoveThreads: ->
+ return false if @category.name in ["archive", "trash", "sent", "all"]
+ return false if @category.displayName is atom.config.get("core.archiveFolder")
+ return true
+
applyToThreads: (threadsOrIds) ->
if AccountStore.current().usesLabels()
FocusedMailViewStore = require './flux/stores/focused-mail-view-store'
diff --git a/src/services/remove-thread-helper.coffee b/src/services/remove-thread-helper.coffee
new file mode 100644
index 000000000..814a80239
--- /dev/null
+++ b/src/services/remove-thread-helper.coffee
@@ -0,0 +1,93 @@
+_ = require 'underscore'
+CategoryStore = require '../stores/category-store'
+
+ChangeLabelsTask = require './change-labels-task'
+ChangeFolderTask = require './change-folder-task'
+Actions = require '../actions'
+
+AccountStore = require '../stores/account-store'
+
+class RemoveThreadHelper
+
+ Type:
+ Trash: "trash"
+ Archive: "archive"
+
+ removeType: ->
+ currentAccount = @_currentAccount()
+ return null unless currentAccount
+ savedType = atom.config.get("core.#{currentAccount.id}.removeType")
+ return savedType if savedType
+
+ archiveCategory = CategoryStore.getStandardCategory("archive")
+ return @Type.Archive if archiveCategory
+
+ if currentAccount.provider is "gmail"
+ return @Type.Archive
+ else
+ return @Type.Trash
+
+ _currentAccount: -> AccountStore.current() # To stub in testing
+
+ # In the case of folders, "removing" means moving the message to a
+ # particular folder
+ removalFolder: ->
+ if @removeType() is @Type.Trash
+ CategoryStore.getStandardCategory("trash")
+ else if @removeType() is @Type.Archive
+ CategoryStore.getStandardCategory("archive")
+
+ # In the case of labels, "removing" means removing the current label and
+ # applying a new label indicating it's in the "removed" state.
+ removalLabelToAdd: ->
+ if @removeType() is @Type.Trash
+ CategoryStore.getStandardCategory("trash")
+ else if @removeType() is @Type.Archive
+ CategoryStore.getStandardCategory("all")
+
+ getRemovalTask: (threads=[], focusedMailViewFilter) ->
+ threads = [threads] unless threads instanceof Array
+ account = @_currentAccount()
+ return null unless account
+
+ if account.usesFolders()
+ removalFolder = @removalFolder()
+ if removalFolder
+ return new ChangeFolderTask
+ folder: removalFolder
+ threads: threads
+ else
+ @_notifyFolderRemovalError()
+ return null
+
+ else if account.usesLabels()
+ viewCategoryId = focusedMailViewFilter.categoryId()
+ currentLabel = CategoryStore.byId(viewCategoryId)
+ currentLabel ?= CategoryStore.getStandardCategory("inbox")
+
+ params = {threads}
+ params.labelsToRemove = [currentLabel]
+
+ removalLabelToAdd = @removalLabelToAdd()
+ if removalLabelToAdd
+ params.labelsToAdd = [removalLabelToAdd]
+
+ return new ChangeLabelsTask(params)
+ else
+ throw new Error("Invalid organizationUnit")
+
+ _notifyFolderRemovalError: ->
+ # In the onboarding flow, users should have already created their
+ # Removal folder. This should only happen for legacy users or if
+ # there's an error somewhere.
+ if @removeType() is @Type.Trash
+ msg = "There is no Trash folder. Please create a folder called 'Trash' and try again."
+ else if @removeType() is @Type.Archive
+ msg = "We can't archive your messages because you have no 'Archive' folder. Please create a folder called 'Archive' and try again"
+ Actions.postNotification
+ type: 'error'
+ tag: 'noRemovalFolder'
+ sticky: true
+ message: msg
+
+module.exports = new RemoveThreadHelper()
diff --git a/static/images/toolbar/toolbar-trash@2x.png b/static/images/toolbar/toolbar-trash@2x.png
index d1d998924..6506eae06 100644
Binary files a/static/images/toolbar/toolbar-trash@2x.png and b/static/images/toolbar/toolbar-trash@2x.png differ