mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-12 12:40:08 +08:00
abcf2b7dad
Summary: consolidate all the "untitled" stuff into a convenience method on the File itself. Previously it'd show "Unnamed Attachment", download as "Untitled" and open as "<file.id>". Now it's consistent everywhere and chooses names based on the contenttype (Event.ics). Rewrite CSS rules for uploads and attachments to be simpler - remove container divs and classnames from things that have no CSS - switch to using Flexbox so it's not necesary to have so many containers - remove zIndex hacks, apply overflow rules to name div only, so long filenames don't make action button unclickable - consolidate CSS classnames for uploads/attachments - Other style fixes - cursor "default" instead of text insertion on image attachments - cursor "default" on action buttons - image uplaods / attachments with long filenames truncate with ellpsis - attachments are not indented by an extra 15px in message bodies Prevent progress bar overflow (was ending above 100%, 100.12315%...) Update FileDownloadStore so it never creates Download objects when file is downloaded already - Previously, the download itself decided if it would be a no-op, but this meant the download was around for a split second and you'd see progress indicators flash for a moment when opening/saving an attachment. Upgrade FileDownloadStore use of promises Restore Image attachment drag and drop - was broken because the name gradient thing was covering the entire drag region. Allow file attachments to be drag and dropped to the finder and other applications 😍😍😍 Test Plan: Tests still pass Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D1745
121 lines
4.1 KiB
CoffeeScript
121 lines
4.1 KiB
CoffeeScript
_ = require 'underscore'
|
|
path = require 'path'
|
|
React = require 'react'
|
|
{RetinaImg, Flexbox} = require 'nylas-component-kit'
|
|
{Actions, Utils, FileDownloadStore} = require 'nylas-exports'
|
|
|
|
# Passed in as props from MessageItem and FileDownloadStore
|
|
# This is empty if the attachment isn't downloading.
|
|
# @props.download is a FileDownloadStore.Download object
|
|
# @props.file is a File object
|
|
{DragDropMixin} = require 'react-dnd'
|
|
|
|
AttachmentDragContainer = React.createClass
|
|
displayName: "AttachmentDragContainer"
|
|
mixins: [DragDropMixin]
|
|
statics:
|
|
configureDragDrop: (registerType) =>
|
|
registerType('attachment', {
|
|
dragSource:
|
|
beginDrag: (component) =>
|
|
# Why is event defined in this scope? Magic. We need to use react-dnd
|
|
# because otherwise it's global onDragStart listener will cancel the
|
|
# drag. We don't actually intend to do a react-dnd drag/drop, but we
|
|
# can use this hook to populate the event.dataTransfer
|
|
DownloadURL = component.props.downloadUrl
|
|
event.dataTransfer.setData("DownloadURL", DownloadURL)
|
|
event.dataTransfer.setData("text/nylas-file-url", DownloadURL)
|
|
|
|
# This is bogus we don't care about the rest of the react-dnd lifecycle.
|
|
return {item: {DownloadURL}}
|
|
})
|
|
|
|
render: ->
|
|
<div {...@dragSourceFor('attachment')} draggable="true">
|
|
{@props.children}
|
|
</div>
|
|
|
|
class AttachmentComponent extends React.Component
|
|
@displayName: 'AttachmentComponent'
|
|
|
|
@propTypes:
|
|
file: React.PropTypes.object.isRequired
|
|
download: React.PropTypes.object
|
|
removable: React.PropTypes.bool
|
|
targetPath: React.PropTypes.string
|
|
messageLocalId: React.PropTypes.string
|
|
|
|
constructor: (@props) ->
|
|
@state = progressPercent: 0
|
|
|
|
render: =>
|
|
<AttachmentDragContainer downloadUrl={@_getDragDownloadURL()}>
|
|
<div className="inner" onClick={@_onClickView}>
|
|
<span className={"progress-bar-wrap state-#{@props.download?.state ? ""}"}>
|
|
<span className="progress-background"></span>
|
|
<span className="progress-foreground" style={@_downloadProgressStyle()}></span>
|
|
</span>
|
|
|
|
<Flexbox direction="row" style={alignItems: 'center'}>
|
|
<RetinaImg className="file-icon"
|
|
fallback="file-fallback.png"
|
|
name="file-#{@_extension()}.png"/>
|
|
<span className="file-name">{@props.file.displayName()}</span>
|
|
{@_renderFileActions()}
|
|
</Flexbox>
|
|
</div>
|
|
</AttachmentDragContainer>
|
|
|
|
_renderFileActions: =>
|
|
if @props.removable
|
|
<div className="file-action-icon" onClick={@_onClickRemove}>
|
|
{@_renderRemoveIcon()}
|
|
</div>
|
|
else if @_isDownloading() and @_canAbortDownload()
|
|
<div className="file-action-icon" onClick={@_onClickAbort}>
|
|
{@_renderRemoveIcon()}
|
|
</div>
|
|
else
|
|
<div className="file-action-icon" onClick={@_onClickDownload}>
|
|
{@_renderDownloadButton()}
|
|
</div>
|
|
|
|
_downloadProgressStyle: =>
|
|
width: "#{@props.download?.percent ? 0}%"
|
|
|
|
_canAbortDownload: -> true
|
|
|
|
_canClickToView: => not @props.removable and not @_isDownloading()
|
|
|
|
_isDownloading: => @props.download?.state is "downloading"
|
|
|
|
_renderRemoveIcon: ->
|
|
<RetinaImg name="remove-attachment.png"/>
|
|
|
|
_renderDownloadButton: ->
|
|
<RetinaImg name="icon-attachment-download.png"/>
|
|
|
|
_getDragDownloadURL: (event) =>
|
|
path = FileDownloadStore.pathForFile(@props.file)
|
|
return "#{@props.file.contentType}:#{@props.file.displayName()}:file://#{path}"
|
|
|
|
_onClickView: => Actions.fetchAndOpenFile(@props.file) if @_canClickToView()
|
|
|
|
_onClickRemove: (event) =>
|
|
Actions.removeFile
|
|
file: @props.file
|
|
messageLocalId: @props.messageLocalId
|
|
event.stopPropagation() # Prevent 'onClickView'
|
|
|
|
_onClickDownload: (event) =>
|
|
Actions.fetchAndSaveFile(@props.file)
|
|
event.stopPropagation() # Prevent 'onClickView'
|
|
|
|
_onClickAbort: (event) =>
|
|
Actions.abortDownload(@props.file, @props.download)
|
|
event.stopPropagation() # Prevent 'onClickView'
|
|
|
|
_extension: -> @props.file.filename.split('.').pop()
|
|
|
|
|
|
module.exports = AttachmentComponent
|