mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-12-29 20:04:59 +08:00
feat(selection): add selection of read, unread, starred, etc
Summary: Can select all, deselect-all, read, unread, starred, unstarred. Yes, it's not REALLY select "all", but it uses the items in the current `retainedRange`. This is actually similar to what gmail does (only selects on the first page of a 100). Test Plan: new test Reviewers: juan, bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D2241
This commit is contained in:
parent
32ffc7123a
commit
119da453e1
5 changed files with 47 additions and 2 deletions
|
@ -23,6 +23,12 @@ class ThreadListStore extends NylasStore
|
|||
@listenTo AccountStore, @_onAccountChanged
|
||||
@listenTo FocusedMailViewStore, @_onMailViewChanged
|
||||
|
||||
atom.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
|
||||
|
@ -81,6 +87,22 @@ class ThreadListStore extends NylasStore
|
|||
|
||||
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: ->
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
'g l' : 'navigation:go-to-label'
|
||||
|
||||
### Threadlist selection ###
|
||||
'* a': 'thread-list:select-all'
|
||||
'* n': 'thread-list:deselect-all'
|
||||
'* a': 'multiselect-list:select-all'
|
||||
'* n': 'multiselect-list:deselect-all'
|
||||
'* r': 'thread-list:select-read'
|
||||
'* u': 'thread-list:select-unread'
|
||||
'* s': 'thread-list:select-starred'
|
||||
|
|
|
@ -33,6 +33,14 @@ describe "ModelView", ->
|
|||
beforeEach ->
|
||||
@view = new TestModelView()
|
||||
|
||||
describe "itemsCurrentlyInViewMatching", ->
|
||||
it "returns matching items", ->
|
||||
@view.stubFillPage(0)
|
||||
items = @view.itemsCurrentlyInViewMatching (item) ->
|
||||
item.id == "A55"
|
||||
expect(items.length).toBe 1
|
||||
expect(items[0].id).toBe "A55"
|
||||
|
||||
describe "setRetainedRange", ->
|
||||
it "should perform basic bounds checks to avoid fetching non-existent pages", ->
|
||||
@view.setRetainedRange({start: -100, end: 15000})
|
||||
|
|
|
@ -83,6 +83,9 @@ class MultiselectList extends React.Component
|
|||
'core:list-page-up': => @_onScrollByPage(-1)
|
||||
'core:list-page-down': => @_onScrollByPage(1)
|
||||
'application:pop-sheet': => @_onDeselect()
|
||||
'multiselect-list:select-all': @_onSelectAll
|
||||
'core:select-all': @_onSelectAll
|
||||
'multiselect-list:deselect-all': => @_onDeselect()
|
||||
|
||||
render: =>
|
||||
# IMPORTANT: DO NOT pass inline functions as props. _.isEqual thinks these
|
||||
|
@ -152,6 +155,11 @@ class MultiselectList extends React.Component
|
|||
return unless @state.handler
|
||||
@state.handler.onSelect()
|
||||
|
||||
_onSelectAll: =>
|
||||
return unless @state.handler
|
||||
items = @state.dataView.itemsCurrentlyInViewMatching -> true
|
||||
@state.dataView.selection.set(items)
|
||||
|
||||
_onDeselect: =>
|
||||
return unless @_visible() and @state.dataView
|
||||
@state.dataView.selection.clear()
|
||||
|
|
|
@ -73,6 +73,13 @@ class ModelView
|
|||
pagesRetained: ->
|
||||
[Math.floor(@_retainedRange.start / @_pageSize)..Math.floor(@_retainedRange.end / @_pageSize)]
|
||||
|
||||
itemsCurrentlyInViewMatching: (matchFn) ->
|
||||
matchedItems = []
|
||||
for index, page of @_pages
|
||||
for item in (page.items ? [])
|
||||
matchedItems.push item if matchFn(item)
|
||||
return matchedItems
|
||||
|
||||
setRetainedRange: ({start, end}) ->
|
||||
{start, end} = @padRetainedRange({start, end})
|
||||
start = Math.max(0, Math.min(@count(), start))
|
||||
|
|
Loading…
Reference in a new issue