feat(toggle-unread): threads can now toggle their unread status. fixes T3483.

Summary:
still WIP, but functionality is there.

TODO:
[x] write tests
[x] swap out the current markasread icon for the correct markasread icon that @sdw is making
[x] figure out how to address this point by @bengotow: https://phab.nylas.com/D2024?id=19139#inline-12168

Test Plan: tested manually. still need to write tests though.

Reviewers: evan, bengotow

Reviewed By: bengotow

Subscribers: sdw

Maniphest Tasks: T3483

Differential Revision: https://phab.nylas.com/D2024
This commit is contained in:
dillon 2015-09-15 16:49:16 -07:00
parent 0289de243a
commit 4e6b4f4c9c
11 changed files with 125 additions and 4 deletions

View file

@ -7,6 +7,7 @@ SidebarThreadParticipants = require "./sidebar-thread-participants"
ThreadStarButton = require './thread-star-button'
ThreadArchiveButton = require './thread-archive-button'
ThreadToggleUnreadButton = require './thread-toggle-unread-button'
AutolinkerExtension = require './plugins/autolinker-extension'
TrackingPixelsExtension = require './plugins/tracking-pixels-extension'
@ -31,6 +32,9 @@ module.exports =
ComponentRegistry.register ThreadArchiveButton,
role: 'message:Toolbar'
ComponentRegistry.register ThreadToggleUnreadButton,
role: 'message:Toolbar'
MessageStore.registerExtension(AutolinkerExtension)
MessageStore.registerExtension(TrackingPixelsExtension)
@ -38,6 +42,7 @@ module.exports =
ComponentRegistry.unregister MessageList
ComponentRegistry.unregister ThreadStarButton
ComponentRegistry.unregister ThreadArchiveButton
ComponentRegistry.unregister ThreadToggleUnreadButton
ComponentRegistry.unregister MessageToolbarItems
ComponentRegistry.unregister SidebarThreadParticipants
MessageStore.unregisterExtension(AutolinkerExtension)

View file

@ -11,7 +11,7 @@ class StarButton extends React.Component
render: =>
selected = @props.thread? and @props.thread.starred
<button className="btn btn-toolbar btn-star"
<button className="btn btn-toolbar"
style={order: -104}
data-tooltip="Star"
onClick={@_onStarToggle}>

View file

@ -0,0 +1,29 @@
React = require 'react'
{Actions, FocusedContentStore, ChangeUnreadTask} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
class ThreadToggleUnreadButton extends React.Component
@displayName: "ThreadToggleUnreadButton"
@containerRequired: false
render: =>
fragment = if @props.thread?.unread then "read" else "unread"
<button className="btn btn-toolbar"
style={order: -106}
data-tooltip="Mark as #{fragment}"
onClick={@_onClick}>
<RetinaImg name="icon-toolbar-markas#{fragment}@2x.png"
mode={RetinaImg.Mode.ContentIsMask} />
</button>
_onClick: (e) =>
e.stopPropagation()
task = new ChangeUnreadTask
thread: @props.thread
unread: !@props.thread.unread
Actions.queueTask task
Actions.popSheet()
module.exports = ThreadToggleUnreadButton

View file

@ -1,9 +1,10 @@
React = require "react/addons"
ReactTestUtils = React.addons.TestUtils
TestUtils = React.addons.TestUtils
{Thread, FocusedContentStore, Actions} = require "nylas-exports"
{Thread, FocusedContentStore, Actions, ChangeUnreadTask} = require "nylas-exports"
StarButton = require '../lib/thread-star-button'
ThreadToggleUnreadButton = require '../lib/thread-toggle-unread-button'
test_thread = (new Thread).fromJSON({
"id" : "thread_12345"
@ -35,3 +36,28 @@ describe "MessageToolbarItem starring", ->
expect(Actions.queueTask.mostRecentCall.args[0].threads).toEqual([test_thread_starred])
expect(Actions.queueTask.mostRecentCall.args[0].starred).toEqual(false)
describe "MessageToolbarItem marking as unread", ->
thread = null
markUnreadBtn = null
beforeEach ->
thread = new Thread(id: "thread-id-lol-123")
markUnreadBtn = ReactTestUtils.renderIntoDocument(
<ThreadToggleUnreadButton thread={thread} />
)
it "queues a task to change unread status to true", ->
spyOn Actions, "queueTask"
ReactTestUtils.Simulate.click React.findDOMNode(markUnreadBtn)
changeUnreadTask = Actions.queueTask.calls[0].args[0]
expect(changeUnreadTask instanceof ChangeUnreadTask).toBe true
expect(changeUnreadTask.unread).toBe true
expect(changeUnreadTask.threads[0].id).toBe thread.id
it "returns to the thread list", ->
spyOn Actions, "popSheet"
ReactTestUtils.Simulate.click React.findDOMNode(markUnreadBtn)
expect(Actions.popSheet).toHaveBeenCalled()

View file

@ -2,7 +2,7 @@ _ = require 'underscore'
React = require "react"
{ComponentRegistry, WorkspaceStore} = require "nylas-exports"
{DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton} = require "./thread-buttons"
{DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton} = require "./thread-buttons"
{DraftDeleteButton} = require "./draft-buttons"
ThreadSelectionBar = require './thread-selection-bar'
ThreadList = require './thread-list'
@ -42,6 +42,9 @@ module.exports =
ComponentRegistry.register ThreadBulkStarButton,
role: 'thread:BulkAction'
ComponentRegistry.register ThreadBulkToggleUnreadButton,
role: 'thread:BulkAction'
ComponentRegistry.register DraftDeleteButton,
role: 'draft:BulkAction'
@ -51,6 +54,7 @@ module.exports =
ComponentRegistry.unregister ThreadList
ComponentRegistry.unregister ThreadSelectionBar
ComponentRegistry.unregister ThreadBulkArchiveButton
ComponentRegistry.unregister ThreadBulkToggleUnreadButton
ComponentRegistry.unregister DownButton
ComponentRegistry.unregister UpButton
ComponentRegistry.unregister DraftDeleteButton

View file

@ -42,6 +42,47 @@ class ThreadBulkStarButton extends React.Component
Actions.toggleStarSelection()
class ThreadBulkToggleUnreadButton extends React.Component
@displayName: 'ThreadBulkToggleUnreadButton'
@containerRequired: false
@propTypes:
selection: React.PropTypes.object.isRequired
constructor: ->
@state = @_getStateFromStores()
super
componentDidMount: =>
@unsubscribers = []
@unsubscribers.push ThreadListStore.listen @_onStoreChange
componentWillUnmount: =>
unsubscribe() for unsubscribe in @unsubscribers
render: =>
fragment = if @state.canMarkUnread then "unread" else "read"
<button style={order:-106}
className="btn btn-toolbar"
data-tooltip="Mark as #{fragment}"
onClick={@_onClick}>
<RetinaImg name="icon-toolbar-markas#{fragment}@2x.png"
mode={RetinaImg.Mode.ContentIsMask} />
</button>
_onClick: =>
Actions.toggleUnreadSelection()
_onStoreChange: =>
@setState @_getStateFromStores()
_getStateFromStores: =>
selections = ThreadListStore.view().selection.items()
canMarkUnread: not selections.every (s) -> s.unread is true
ThreadNavButtonMixin =
getInitialState: ->
@_getStateFromStores()
@ -117,4 +158,4 @@ UpButton = React.createClass
UpButton.containerRequired = false
DownButton.containerRequired = false
module.exports = {DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton}
module.exports = {DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton}

View file

@ -9,6 +9,7 @@ NylasStore = require 'nylas-store'
DatabaseStore,
AccountStore,
WorkspaceStore,
ChangeUnreadTask,
ChangeStarredTask,
FocusedContentStore,
ArchiveThreadHelper,
@ -33,6 +34,8 @@ class ThreadListStore extends NylasStore
@listenTo Actions.toggleStarSelection, @_onToggleStarSelection
@listenTo Actions.toggleStarFocused, @_onToggleStarFocused
@listenTo Actions.toggleUnreadSelection, @_onToggleUnreadSelection
@listenTo DatabaseStore, @_onDataChanged
@listenTo AccountStore, @_onAccountChanged
@listenTo FocusedMailViewStore, @_onMailViewChanged
@ -146,6 +149,15 @@ class ThreadListStore extends NylasStore
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
_onArchive: ->
@_archiveAndShiftBy('auto')

View file

@ -328,6 +328,7 @@ class Actions
@archiveAndPrevious: ActionScopeWindow
@toggleStarSelection: ActionScopeWindow
@toggleStarFocused: ActionScopeWindow
@toggleUnreadSelection: ActionScopeWindow
@deleteSelection: ActionScopeWindow
@moveThread: ActionScopeWindow

View file

@ -36,6 +36,9 @@ class ChangeUnreadTask extends ChangeMailTask
@threads = _.compact(threads)
return super
_processesNestedMessages: ->
true
_changesToModel: (model) ->
{unread: @unread}

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB