mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-25 01:36:06 +08:00
f88b0f3708
Summary: Fixes T3570 Fixes T3737 Rename ArchiveThreadHelper to RemoveThreadHelper Rename of `getRemovalTask` Remove unarchive from `RemoveThreadHelper`. Pass in mailviewfilter Rename actions Rename archive action renmaing support trash and archive folders in RemoveThreadHelper Move everything over to trash add tests Hide trash and archive Test Plan: new tests Reviewers: dillon, bengotow Reviewed By: dillon, bengotow Maniphest Tasks: T3570, T3737 Differential Revision: https://phab.nylas.com/D2089
254 lines
7.9 KiB
CoffeeScript
254 lines
7.9 KiB
CoffeeScript
_ = require 'underscore'
|
|
NylasStore = require 'nylas-store'
|
|
|
|
{Thread,
|
|
Message,
|
|
Actions,
|
|
SearchView,
|
|
DatabaseView,
|
|
DatabaseStore,
|
|
AccountStore,
|
|
WorkspaceStore,
|
|
ChangeUnreadTask,
|
|
ChangeStarredTask,
|
|
FocusedContentStore,
|
|
RemoveThreadHelper,
|
|
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 Actions.removeSelection, @_onRemoveSelection
|
|
|
|
@listenTo Actions.removeCurrentlyFocusedThread, @_onRemoveAndAuto
|
|
@listenTo Actions.removeAndNext, @_onRemoveAndNext
|
|
@listenTo Actions.removeAndPrevious, @_onRemoveAndPrev
|
|
|
|
@listenTo Actions.moveThread, @_onMoveThread
|
|
@listenTo Actions.moveThreads, @_onMoveThreads
|
|
|
|
@listenTo Actions.toggleStarSelection, @_onToggleStarSelection
|
|
@listenTo Actions.toggleStarFocused, @_onToggleStarFocused
|
|
|
|
@listenTo Actions.toggleUnreadSelection, @_onToggleUnreadSelection
|
|
|
|
@listenTo DatabaseStore, @_onDataChanged
|
|
@listenTo AccountStore, @_onAccountChanged
|
|
@listenTo FocusedMailViewStore, @_onMailViewChanged
|
|
|
|
# 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(@)
|
|
,@
|
|
|
|
@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
|
|
|
|
if WorkspaceStore.layoutMode() is 'split'
|
|
# Set up a one-time listener to focus an item in the new view
|
|
unlisten = view.listen ->
|
|
if view.loaded()
|
|
Actions.setFocus(collection: 'thread', item: view.get(0))
|
|
unlisten()
|
|
|
|
@setView(view)
|
|
|
|
Actions.setFocus(collection: 'thread', item: null)
|
|
|
|
# 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
|
|
@_view.invalidate({change: change, shallow: true})
|
|
|
|
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 debounced since it's very unimportant
|
|
_.defer =>
|
|
threadIds = _.uniq _.map change.objects, (m) -> m.threadId
|
|
@_view.invalidateMetadataFor(threadIds)
|
|
|
|
_onToggleStarSelection: ->
|
|
threads = @_view.selection.items()
|
|
focusedId = FocusedContentStore.focusedId('thread')
|
|
keyboardId = FocusedContentStore.keyboardCursorId('thread')
|
|
|
|
oneAlreadyStarred = false
|
|
for thread in threads
|
|
if thread.starred
|
|
oneAlreadyStarred = true
|
|
|
|
starred = not oneAlreadyStarred
|
|
task = new ChangeStarredTask({threads, starred})
|
|
Actions.queueTask(task)
|
|
|
|
_onToggleStarFocused: ->
|
|
focused = FocusedContentStore.focused('thread')
|
|
cursor = FocusedContentStore.keyboardCursor('thread')
|
|
if focused
|
|
task = new ChangeStarredTask(thread: focused, starred: !focused.starred)
|
|
else if cursor
|
|
task = new ChangeStarredTask(thread: cursor, starred: !cursor.starred)
|
|
|
|
if task
|
|
Actions.queueTask(task)
|
|
|
|
_onToggleUnreadSelection: ->
|
|
threads = @_view.selection.items()
|
|
allUnread = threads.every (t) ->
|
|
t.unread is true
|
|
unread = not allUnread
|
|
|
|
task = new ChangeUnreadTask {threads, unread}
|
|
Actions.queueTask task
|
|
|
|
_onRemoveAndAuto: ->
|
|
@_removeAndShiftBy('auto')
|
|
|
|
_onRemoveAndPrev: ->
|
|
@_removeAndShiftBy(-1)
|
|
|
|
_onRemoveAndNext: ->
|
|
@_removeAndShiftBy(1)
|
|
|
|
_removeAndShiftBy: (offset) ->
|
|
mailViewFilter = FocusedMailViewStore.mailView()
|
|
return unless mailViewFilter.canApplyToThreads()
|
|
focused = FocusedContentStore.focused('thread')
|
|
return unless focused
|
|
task = RemoveThreadHelper.getRemovalTask([focused], mailViewFilter)
|
|
@_moveAndShiftBy(offset, task)
|
|
|
|
_onRemoveSelection: ->
|
|
mailViewFilter = FocusedMailViewStore.mailView()
|
|
return unless mailViewFilter.canApplyToThreads()
|
|
selectedThreads = @_view.selection.items()
|
|
return unless selectedThreads.length > 0
|
|
task = RemoveThreadHelper.getRemovalTask(selectedThreads, mailViewFilter)
|
|
@_onMoveThreads(selectedThreads, task)
|
|
|
|
_onMoveThread: (thread, task) ->
|
|
@_moveAndShiftBy('auto', task)
|
|
|
|
_onMoveThreads: (threads, task) ->
|
|
threadIds = threads.map (thread) -> thread.id
|
|
focusedId = FocusedContentStore.focusedId('thread')
|
|
keyboardId = FocusedContentStore.keyboardCursorId('thread')
|
|
|
|
if focusedId in threadIds
|
|
changeFocused = true
|
|
if keyboardId in threadIds
|
|
changeKeyboardCursor = true
|
|
|
|
if changeFocused or changeKeyboardCursor
|
|
newFocusIndex = Number.MAX_VALUE
|
|
for thread in threads
|
|
newFocusIndex = Math.min(newFocusIndex, @_view.indexOfId(thread.id))
|
|
|
|
TaskQueueStatusStore.waitForPerformLocal(task).then =>
|
|
layoutMode = WorkspaceStore.layoutMode()
|
|
if changeFocused
|
|
item = @_view.get(newFocusIndex)
|
|
Actions.setFocus(collection: 'thread', item: item)
|
|
if changeKeyboardCursor
|
|
item = @_view.get(newFocusIndex)
|
|
Actions.setCursorPosition(collection: 'thread', item: item)
|
|
Actions.setFocus(collection: 'thread', item: item) if layoutMode is 'split'
|
|
|
|
Actions.queueTask(task)
|
|
@_view.selection.clear()
|
|
|
|
_moveAndShiftBy: (offset, task) ->
|
|
layoutMode = WorkspaceStore.layoutMode()
|
|
focused = FocusedContentStore.focused('thread')
|
|
explicitOffset = if offset is "auto" then false else true
|
|
|
|
return unless focused
|
|
|
|
# Determine the current index
|
|
index = @_view.indexOfId(focused.id)
|
|
return if index is -1
|
|
|
|
# Determine the next index we want to move to
|
|
if offset is 'auto'
|
|
if @_view.get(index - 1)?.unread
|
|
offset = -1
|
|
else
|
|
offset = 1
|
|
|
|
index = Math.min(Math.max(index + offset, 0), @_view.count() - 2)
|
|
nextKeyboard = nextFocus = @_view.get(index)
|
|
|
|
# Remove the current thread from selection
|
|
@_view.selection.remove(focused)
|
|
|
|
# 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
|
|
|
|
# Remove the current thread
|
|
TaskQueueStatusStore.waitForPerformLocal(task).then =>
|
|
Actions.setFocus(collection: 'thread', item: nextFocus)
|
|
Actions.setCursorPosition(collection: 'thread', item: nextKeyboard)
|
|
Actions.queueTask(task)
|
|
|
|
module.exports = new ThreadListStore()
|