Add (s) hotkey for starring in both thread-list and message-list views

Summary:
Adding spec for message list star. Fixing multi-select in 3-pane starring

I didn't write a spec for thread-list because the thread-list-spec appears to be broken (returns immedietly at the top). I spent ~15 minutes attempting to fix but didn't make much progress

Test Plan: Added spec to message list

Reviewers: bengotow

Reviewed By: bengotow

Maniphest Tasks: T1957

Differential Revision: https://phab.nylas.com/D1697
This commit is contained in:
Robert McQueen 2015-06-26 14:06:31 -07:00
parent 51878453a3
commit f043d0e506
7 changed files with 48 additions and 14 deletions

View file

@ -2,7 +2,12 @@ _ = require 'underscore'
React = require 'react' React = require 'react'
classNames = require 'classnames' classNames = require 'classnames'
MessageItem = require "./message-item" MessageItem = require "./message-item"
{Utils, Actions, MessageStore, ComponentRegistry} = require("nylas-exports") {Utils,
Actions,
MessageStore,
ComponentRegistry,
AddRemoveTagsTask} = require("nylas-exports")
{Spinner, {Spinner,
ScrollRegion, ScrollRegion,
ResizableRegion, ResizableRegion,
@ -60,6 +65,11 @@ class MessageList extends React.Component
@_unsubscribers = [] @_unsubscribers = []
@_unsubscribers.push MessageStore.listen @_onChange @_unsubscribers.push MessageStore.listen @_onChange
commands = _.extend {},
'core:star-item': => @_onStarItem()
@command_unsubscriber = atom.commands.add('body', commands)
# We don't need to listen to ThreadStore bcause MessageStore already # We don't need to listen to ThreadStore bcause MessageStore already
# listens to thead selection changes # listens to thead selection changes
@ -68,6 +78,8 @@ class MessageList extends React.Component
componentWillUnmount: => componentWillUnmount: =>
unsubscribe() for unsubscribe in @_unsubscribers unsubscribe() for unsubscribe in @_unsubscribers
@command_unsubscriber.dispose()
window.removeEventListener("resize", @_onResize) window.removeEventListener("resize", @_onResize)
shouldComponentUpdate: (nextProps, nextState) => shouldComponentUpdate: (nextProps, nextState) =>
@ -101,6 +113,13 @@ class MessageList extends React.Component
_focusDraft: (draftElement) => _focusDraft: (draftElement) =>
draftElement.focus() draftElement.focus()
_onStarItem: =>
if @state.currentThread.isStarred()
task = new AddRemoveTagsTask(@state.currentThread, [], ['starred'])
else
task = new AddRemoveTagsTask(@state.currentThread, ['starred'], [])
Actions.queueTask(task)
render: => render: =>
if not @state.currentThread? if not @state.currentThread?
return <div className="message-list" id="message-list"></div> return <div className="message-list" id="message-list"></div>

View file

@ -13,6 +13,7 @@ TestUtils = React.addons.TestUtils
Namespace, Namespace,
MessageStore, MessageStore,
NamespaceStore, NamespaceStore,
NylasTestUtils,
ComponentRegistry} = require "nylas-exports" ComponentRegistry} = require "nylas-exports"
{InjectedComponent} = require 'nylas-component-kit' {InjectedComponent} = require 'nylas-component-kit'
@ -195,6 +196,8 @@ describe "MessageList", ->
MessageStore.trigger(MessageStore) MessageStore.trigger(MessageStore)
@messageList.setState currentThread: test_thread @messageList.setState currentThread: test_thread
NylasTestUtils.loadKeymap("keymaps/base")
it "renders all the correct number of messages", -> it "renders all the correct number of messages", ->
items = TestUtils.scryRenderedComponentsWithType(@messageList, items = TestUtils.scryRenderedComponentsWithType(@messageList,
MessageItem) MessageItem)
@ -213,6 +216,11 @@ describe "MessageList", ->
MessageParticipants) MessageParticipants)
expect(items.length).toBe 1 expect(items.length).toBe 1
it "toggles star on a thread if 's' is pressed", ->
spyOn(@messageList, "_onStarItem")
NylasTestUtils.keyPress("s", document.body)
expect(@messageList._onStarItem).toHaveBeenCalled()
it "focuses new composers when a draft is added", -> it "focuses new composers when a draft is added", ->
spyOn(@messageList, "_focusDraft") spyOn(@messageList, "_focusDraft")
msgs = @messageList.state.messages msgs = @messageList.state.messages

View file

@ -1,13 +0,0 @@
# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.
# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps
'.thread-list':
's' : 'thread-list:star-thread' # Gmail
'cmd-L' : 'thread-list:star-thread' # Mac mail
'ctrl-G': 'thread-list:star-thread' # Outlook

View file

@ -32,6 +32,7 @@ ThreadListStore = Reflux.createStore
@listenTo Actions.archive, @_onArchive @listenTo Actions.archive, @_onArchive
@listenTo Actions.toggleStarSelection, @_onToggleStarSelection @listenTo Actions.toggleStarSelection, @_onToggleStarSelection
@listenTo Actions.toggleStarFocused, @_onToggleStarFocused
@listenTo DatabaseStore, @_onDataChanged @listenTo DatabaseStore, @_onDataChanged
@listenTo FocusedTagStore, @_onTagChanged @listenTo FocusedTagStore, @_onTagChanged
@ -123,6 +124,14 @@ ThreadListStore = Reflux.createStore
task = new AddRemoveTagsTask(thread, ['starred'], []) task = new AddRemoveTagsTask(thread, ['starred'], [])
Actions.queueTask(task) Actions.queueTask(task)
_onToggleStarFocused: ->
focusedThread = FocusedContentStore.focused('thread')
if focusedThread.isStarred()
task = new AddRemoveTagsTask(focusedThread, [], ['starred'])
else
task = new AddRemoveTagsTask(focusedThread, ['starred'], [])
Actions.queueTask(task)
_onArchive: -> _onArchive: ->
@_archiveAndShiftBy('auto') @_archiveAndShiftBy('auto')

View file

@ -130,6 +130,7 @@ class ThreadList extends React.Component
@commands = @commands =
'core:remove-item': @_onArchive 'core:remove-item': @_onArchive
'core:star-item': @_onStarItem
'core:remove-and-previous': -> Actions.archiveAndPrevious() 'core:remove-and-previous': -> Actions.archiveAndPrevious()
'core:remove-and-next': -> Actions.archiveAndNext() 'core:remove-and-next': -> Actions.archiveAndNext()
'application:reply': @_onReply 'application:reply': @_onReply
@ -147,6 +148,12 @@ class ThreadList extends React.Component
componentWillUnmount: => componentWillUnmount: =>
window.removeEventListener('resize', @_onResize) window.removeEventListener('resize', @_onResize)
_onStarItem: =>
if @state.style is 'wide' or ThreadListStore.view().selection.count() > 0
Actions.toggleStarSelection()
else
Actions.toggleStarFocused()
render: => render: =>
if @state.style is 'wide' if @state.style is 'wide'
<MultiselectList <MultiselectList

View file

@ -23,6 +23,9 @@
']' : 'core:remove-and-previous' # Gmail ']' : 'core:remove-and-previous' # Gmail
'[' : 'core:remove-and-next' # Gmail '[' : 'core:remove-and-next' # Gmail
'e' : 'core:remove-item' # Gmail 'e' : 'core:remove-item' # Gmail
's' : 'core:star-item' #Gmail
'cmd-L' : 'core:star-item' # Mac mail
'ctrl-G' : 'core:star-item' # Outlook
'delete' : 'core:remove-item' # Mac mail 'delete' : 'core:remove-item' # Mac mail
'backspace': 'core:remove-item' # Outlook 'backspace': 'core:remove-item' # Outlook
'enter' : 'core:focus-item' 'enter' : 'core:focus-item'

View file

@ -319,6 +319,7 @@ class Actions
@archiveAndNext: ActionScopeWindow @archiveAndNext: ActionScopeWindow
@archiveAndPrevious: ActionScopeWindow @archiveAndPrevious: ActionScopeWindow
@toggleStarSelection: ActionScopeWindow @toggleStarSelection: ActionScopeWindow
@toggleStarFocused: ActionScopeWindow
### ###
Public: Updates the search query in the app's main search bar with the provided query text. Public: Updates the search query in the app's main search bar with the provided query text.