mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-14 05:41:05 +08:00
c265cf0dfa
Summary: This diff implements a behavior change described in https://github.com/nylas/N1/issues/1722. Reply buttons should prefer to focus an existing draft in reply to the same message, if one is pristine, altering it as necessary to switch between reply / reply-all. If no pristine reply is already there, it creates one. Reply keyboard shortcuts should do the same, but more strictly - the shortcuts should switch between reply / reply-all for an existing draft regardless of whether it's pristine. This diff also cleans up the DraftStore and moves all the draft creation itself to a new DraftFactory object. This makes it much easier to see what's going on in the DraftStore, and I also refactored away the "newMessageWithContext" method, which was breaking the logic for Reply vs Forward between a bunch of different helper methods and was hard to follow. Test Plan: They're all wrecked. Will fix after concept is greenlighted Reviewers: evan, juan Reviewed By: juan Differential Revision: https://phab.nylas.com/D2776
153 lines
5.2 KiB
CoffeeScript
153 lines
5.2 KiB
CoffeeScript
React = require 'react'
|
|
{remote} = require 'electron'
|
|
{Actions, NylasAPI, AccountStore} = require 'nylas-exports'
|
|
{RetinaImg, ButtonDropdown, Menu} = require 'nylas-component-kit'
|
|
|
|
class MessageControls extends React.Component
|
|
@displayName: "MessageControls"
|
|
@propTypes:
|
|
thread: React.PropTypes.object.isRequired
|
|
message: React.PropTypes.object.isRequired
|
|
|
|
constructor: (@props) ->
|
|
|
|
render: =>
|
|
items = @_items()
|
|
|
|
<div className="message-actions-wrap">
|
|
<ButtonDropdown
|
|
primaryItem={<RetinaImg name={items[0].image} mode={RetinaImg.Mode.ContentIsMask}/>}
|
|
primaryTitle={items[0].name}
|
|
primaryClick={items[0].select}
|
|
closeOnMenuClick={true}
|
|
menu={@_dropdownMenu(items[1..-1])}/>
|
|
<div className="message-actions-ellipsis" onClick={@_onShowActionsMenu}>
|
|
<RetinaImg name={"message-actions-ellipsis.png"} mode={RetinaImg.Mode.ContentIsMask}/>
|
|
</div>
|
|
</div>
|
|
|
|
_items: ->
|
|
reply =
|
|
name: 'Reply',
|
|
image: 'ic-dropdown-reply.png'
|
|
select: @_onReply
|
|
replyAll =
|
|
name: 'Reply All',
|
|
image: 'ic-dropdown-replyall.png'
|
|
select: @_onReplyAll
|
|
forward =
|
|
name: 'Forward',
|
|
image: 'ic-dropdown-forward.png'
|
|
select: @_onForward
|
|
|
|
if @props.message.canReplyAll()
|
|
defaultReplyType = NylasEnv.config.get('core.sending.defaultReplyType')
|
|
if defaultReplyType is 'reply-all'
|
|
return [replyAll, reply, forward]
|
|
else
|
|
return [reply, replyAll, forward]
|
|
else
|
|
return [reply, forward]
|
|
|
|
_account: =>
|
|
AccountStore.accountForId(@props.message.accountId)
|
|
|
|
_dropdownMenu: (items) ->
|
|
itemContent = (item) ->
|
|
<span>
|
|
<RetinaImg name={item.image} mode={RetinaImg.Mode.ContentIsMask}/>
|
|
{item.name}
|
|
</span>
|
|
|
|
<Menu items={items}
|
|
itemKey={ (item) -> item.name }
|
|
itemContent={itemContent}
|
|
onSelect={ (item) => item.select() }
|
|
/>
|
|
|
|
_onReply: =>
|
|
{thread, message} = @props
|
|
Actions.composeReply({thread, message, type: 'reply', behavior: 'prefer-existing-if-pristine'})
|
|
|
|
_onReplyAll: =>
|
|
{thread, message} = @props
|
|
Actions.composeReply({thread, message, type: 'reply-all', behavior: 'prefer-existing-if-pristine'})
|
|
|
|
_onForward: =>
|
|
Actions.composeForward(thread: @props.thread, message: @props.message)
|
|
|
|
_onShowActionsMenu: =>
|
|
SystemMenu = remote.require('menu')
|
|
SystemMenuItem = remote.require('menu-item')
|
|
|
|
# Todo: refactor this so that message actions are provided
|
|
# dynamically. Waiting to see if this will be used often.
|
|
menu = new SystemMenu()
|
|
menu.append(new SystemMenuItem({ label: 'Log Data', click: => @_onLogData()}))
|
|
menu.append(new SystemMenuItem({ label: 'Show Original', click: => @_onShowOriginal()}))
|
|
menu.append(new SystemMenuItem({ label: 'Copy Debug Info to Clipboard', click: => @_onCopyToClipboard()}))
|
|
menu.append(new SystemMenuItem({ type: 'separator'}))
|
|
menu.append(new SystemMenuItem({ label: 'Report Issue: Quoted Text', click: => @_onReport('Quoted Text')}))
|
|
menu.append(new SystemMenuItem({ label: 'Report Issue: Rendering', click: => @_onReport('Rendering')}))
|
|
menu.popup(remote.getCurrentWindow())
|
|
|
|
_onReport: (issueType) =>
|
|
{Contact, Message, DatabaseStore, AccountStore} = require 'nylas-exports'
|
|
|
|
draft = new Message
|
|
from: [@_account().me()]
|
|
to: [new Contact(name: "Nylas Team", email: "n1-support@nylas.com")]
|
|
date: (new Date)
|
|
draft: true
|
|
subject: "Feedback - Message Display Issue (#{issueType})"
|
|
accountId: @_account().id
|
|
body: @props.message.body
|
|
|
|
DatabaseStore.inTransaction (t) =>
|
|
t.persistModel(draft)
|
|
.then =>
|
|
Actions.sendDraft(draft.clientId)
|
|
|
|
dialog = remote.require('dialog')
|
|
dialog.showMessageBox remote.getCurrentWindow(), {
|
|
type: 'warning'
|
|
buttons: ['OK'],
|
|
message: "Thank you."
|
|
detail: "The contents of this message have been sent to the N1 team and will be added to a test suite."
|
|
}
|
|
|
|
_onShowOriginal: =>
|
|
fs = require 'fs'
|
|
path = require 'path'
|
|
BrowserWindow = remote.require('browser-window')
|
|
app = remote.require('app')
|
|
tmpfile = path.join(app.getPath('temp'), @props.message.id)
|
|
|
|
NylasAPI.makeRequest
|
|
headers:
|
|
Accept: 'message/rfc822'
|
|
path: "/messages/#{@props.message.id}"
|
|
accountId: @props.message.accountId
|
|
json:false
|
|
success: (body) =>
|
|
fs.writeFile tmpfile, body, =>
|
|
window = new BrowserWindow(width: 800, height: 600, title: "#{@props.message.subject} - RFC822")
|
|
window.loadURL('file://'+tmpfile)
|
|
|
|
_onLogData: =>
|
|
console.log @props.message
|
|
window.__message = @props.message
|
|
window.__thread = @props.thread
|
|
console.log "Also now available in window.__message and window.__thread"
|
|
|
|
_onCopyToClipboard: =>
|
|
clipboard = require('electron').clipboard
|
|
data = "AccountID: #{@props.message.accountId}\n"+
|
|
"Message ID: #{@props.message.serverId}\n"+
|
|
"Message Metadata: #{JSON.stringify(@props.message.pluginMetadata, null, ' ')}\n"+
|
|
"Thread ID: #{@props.thread.serverId}\n"+
|
|
"Thread Metadata: #{JSON.stringify(@props.thread.pluginMetadata, null, ' ')}\n"
|
|
|
|
clipboard.writeText(data)
|
|
|
|
module.exports = MessageControls
|