diff --git a/internal_packages/attachments/lib/attachment-component.cjsx b/internal_packages/attachments/lib/attachment-component.cjsx index 9cd4b8b07..3aa8ae747 100644 --- a/internal_packages/attachments/lib/attachment-component.cjsx +++ b/internal_packages/attachments/lib/attachment-component.cjsx @@ -30,7 +30,7 @@ class AttachmentComponent extends React.Component - {@_fileActions()} + {@_renderFileActions()} @@ -44,18 +44,18 @@ class AttachmentComponent extends React.Component - _fileActions: => + _renderFileActions: => if @props.removable
- + {@_renderRemoveIcon()}
else if @_isDownloading() and @_canAbortDownload()
- + {@_renderRemoveIcon()}
else
- + {@_renderDownloadButton()}
_downloadProgressStyle: => @@ -68,6 +68,12 @@ class AttachmentComponent extends React.Component _canAbortDownload: -> true + _renderRemoveIcon: -> + + + _renderDownloadButton: -> + + _onClickView: => Actions.fetchAndOpenFile(@props.file) if @_canClickToView() _onClickDownload: => Actions.fetchAndSaveFile(@props.file) diff --git a/internal_packages/attachments/lib/image-attachment-component.cjsx b/internal_packages/attachments/lib/image-attachment-component.cjsx index 45eb503fa..aaca8b951 100644 --- a/internal_packages/attachments/lib/image-attachment-component.cjsx +++ b/internal_packages/attachments/lib/image-attachment-component.cjsx @@ -1,7 +1,7 @@ path = require 'path' React = require 'react' AttachmentComponent = require './attachment-component' -{Spinner, DraggableImg} = require 'nylas-component-kit' +{RetinaImg, Spinner, DraggableImg} = require 'nylas-component-kit' class ImageAttachmentComponent extends AttachmentComponent @displayName: 'ImageAttachmentComponent' @@ -13,11 +13,13 @@ class ImageAttachmentComponent extends AttachmentComponent
- +
{@_fileActions()} - +
+
+
{@props.file.filename}
{@_imgOrLoader()}
@@ -25,6 +27,12 @@ class ImageAttachmentComponent extends AttachmentComponent _canAbortDownload: -> false + _renderRemoveIcon: -> + + + _renderDownloadButton: -> + + _imgOrLoader: -> if @props.download if @props.download.percent <= 5 diff --git a/internal_packages/attachments/stylesheets/attachments.less b/internal_packages/attachments/stylesheets/attachments.less index 0a60cfa9c..102c8e685 100644 --- a/internal_packages/attachments/stylesheets/attachments.less +++ b/internal_packages/attachments/stylesheets/attachments.less @@ -16,6 +16,14 @@ width: calc(~"50% - 7.5px"); border-radius: 4px; + &.non-image-attachment { + width: calc(~"50% - 23px"); + margin-left: 15px; + &:nth-child(even) { + margin-left: 0; + } + } + &.file-upload { border-radius: 4px; padding: 13px @spacing-standard 13px @spacing-standard; @@ -53,6 +61,7 @@ .attachment-file-name { font-weight: @font-weight-medium; } + margin-left: 15px; .attachment-file-and-name { position: relative; z-index: 2; @@ -121,7 +130,7 @@ .image-attachment-file-wrap, .image-file-upload { position: relative; - margin: @spacing-standard 0; + margin: 0 0 8px 0; text-align: center; .attachment-download-progress, @@ -132,30 +141,56 @@ bottom: -2px; } + .attachment-file-actions { + position: relative; + z-index: 2; + } + &:hover { - .attachment-file-actions { + .attachment-file-actions, .attachment-name-bg, .attachment-name { display: block; } } - .attachment-file-actions { + .attachment-file-actions, .attachment-name-bg, .attachment-name { display: none; } .attachment-icon { position: absolute; z-index: 2; - right: 0; - top: 0; - background: @white; + right: -8px; + top: -8px; width: 26px; border-radius: 0 0 0 3px; } - .attachment-preview img { + .attachment-preview { position: relative; z-index: 1; - max-width: 100%; - background: @background-secondary; + + .attachment-name-bg { + position: absolute; + bottom: 0; + top: 0; + z-index: 2; + width: 100%; + background: linear-gradient(to top, rgba(0,0,0,0.75) 0%,rgba(0,0,0,0) 23%) + } + .attachment-name { + color: @white; + left: 15px; + bottom: 13px; + position: absolute; + z-index: 3; + } + + img { + position: relative; + z-index: 1; + max-width: 100%; + background: @background-secondary; + } } + } diff --git a/internal_packages/composer/lib/composer-view.cjsx b/internal_packages/composer/lib/composer-view.cjsx index a89e588b6..567754061 100644 --- a/internal_packages/composer/lib/composer-view.cjsx +++ b/internal_packages/composer/lib/composer-view.cjsx @@ -184,7 +184,9 @@ class ComposerView extends React.Component {@_renderFields()} -
+
+ onClick={@_destroyDraft}> + onClick={@_attachFile}>
- + onClick={@_sendDraft}>Send @@ -386,6 +388,12 @@ class ComposerView extends React.Component draft = @_proxy.draft() Utils.isForwardedMessage(draft) + # This lets us click outside of the `contenteditable`'s `contentBody` + # and still focus on the contenteditable + _onClickComposeBody: (event) => + if event.target is React.findDOMNode(@refs.composeBody) + @focus("contentBody") + _onDraftChanged: => return unless @_proxy draft = @_proxy.draft() diff --git a/internal_packages/composer/lib/image-file-upload.cjsx b/internal_packages/composer/lib/image-file-upload.cjsx index 27209eab8..0a957f926 100644 --- a/internal_packages/composer/lib/image-file-upload.cjsx +++ b/internal_packages/composer/lib/image-file-upload.cjsx @@ -11,13 +11,15 @@ class ImageFileUpload extends FileUpload render: =>
- +
- +
- +
+
+
{@props.uploadData.fileName}
diff --git a/internal_packages/composer/lib/main.cjsx b/internal_packages/composer/lib/main.cjsx index 4a51467ca..d3d787423 100644 --- a/internal_packages/composer/lib/main.cjsx +++ b/internal_packages/composer/lib/main.cjsx @@ -55,9 +55,10 @@ module.exports = ComponentRegistry.register ComposeButton, location: WorkspaceStore.Location.RootSidebar.Toolbar else - atom.getCurrentWindow().setMinimumSize(600, 400) + atom.getCurrentWindow().setMinimumSize(480, 400) WorkspaceStore.defineSheet 'Main', {root: true}, - list: ['Center'] + popout: ['Center'] + ComponentRegistry.register ComposerWithWindowProps, location: WorkspaceStore.Location.Center diff --git a/internal_packages/composer/stylesheets/composer.less b/internal_packages/composer/stylesheets/composer.less index d6cb3b27c..ce4d6beae 100644 --- a/internal_packages/composer/stylesheets/composer.less +++ b/internal_packages/composer/stylesheets/composer.less @@ -34,7 +34,7 @@ margin: 0 auto; flex-direction:row; max-width: @compose-width; - padding: @spacing-standard (@spacing-standard + @spacing-standard / 2) @spacing-standard*1.1; + padding: @spacing-standard; > * { margin-left: @spacing-standard / 2; @@ -51,7 +51,7 @@ max-width: @compose-width; margin: 0 auto; margin-top: @spacing-standard; - padding: 0 @spacing-standard; + padding: 0; flex: 1; display: flex; @@ -79,7 +79,7 @@ .composer-participant-actions { position: absolute; z-index: 900; - right: @spacing-double; + right: 23px; .header-action { position: relative; top: 1em; @@ -104,8 +104,8 @@ .compose-subject-wrap { position: relative; z-index: 2; - padding: 5px @spacing-standard 0 0; - margin: 0 @spacing-standard; + padding: 11px @spacing-standard 11px 0; + margin: 0 23px; border-bottom: 1px solid @border-color-divider; flex-shrink:0; @@ -119,8 +119,8 @@ input.compose-field { display: inline-block; width: calc(~"100% - 61px"); - padding: 6px 0 2px 0; - margin: 0 0 5px 5px; + padding: 0; + margin: 0 0 0 5px; min-width: 5em; background-color: transparent; border: none; @@ -139,10 +139,11 @@ cursor: text; overflow: auto; position: relative; + padding: 0 8px; .quoted-text-control { position: absolute; - bottom: -25px; + bottom: 10px; left: 15px; margin: 0; } @@ -152,11 +153,12 @@ line-height: 1.4; min-height: @compose-min-height; padding: @spacing-standard; - padding-top: @spacing-standard; + padding-top: 20px; padding-bottom: 0; margin-bottom: 30px; } .contenteditable-container { + display: flex; width: 100%; position: relative; } @@ -171,7 +173,7 @@ // TODO FIXME DRY From stylesheets/message-list.less .attachments-area { - padding: 0 15px 0 15px; + padding: 0; } .token { @@ -182,25 +184,7 @@ color: @text-color-inverse-very-subtle; } } - // &:hover { - // background: transparent; - // } - // &.selected, - // &.dragging { - // background: transparent; - // color: @text-color; - // - // .action { color: @text-color-subtle; } - // } } - - // .btn.btn-send { - // font-weight: @font-weight-semi-bold; - // color: @accent-primary-dark; - // border-top: 1px solid fade(@accent-primary, 39%); - // border-right: 1px solid fade(@accent-primary, 39%); - // border-left: 1px solid fade(@accent-primary, 39%); - // } } body.is-blurred .composer-inner-wrap .tokenizing-field .token { background: transparent; @@ -223,12 +207,15 @@ body.is-blurred .composer-inner-wrap .tokenizing-field .token { border-top:1px solid @border-color-divider; } + .composer-action-bar-content { + padding: 8px 0.5px; + } + .compose-body { margin-bottom: 0; position: relative; .contenteditable-container { - display: flex; flex: 1; width: 100%; position: relative; @@ -241,6 +228,12 @@ body.is-blurred .composer-inner-wrap .tokenizing-field .token { } } + + .compose-body { + div[contenteditable] { + min-height: @line-height-computed; + } + } } // Overrides for the composer in a message-list @@ -262,6 +255,7 @@ body.is-blurred .composer-inner-wrap .tokenizing-field .token { position: relative; z-index: 2; padding: 5px @spacing-standard 0 @spacing-standard; + margin: 0 8px; flex-shrink: 0; .participant { diff --git a/internal_packages/message-templates/lib/template-picker.cjsx b/internal_packages/message-templates/lib/template-picker.cjsx index 365ac4842..0b1700132 100644 --- a/internal_packages/message-templates/lib/template-picker.cjsx +++ b/internal_packages/message-templates/lib/template-picker.cjsx @@ -22,9 +22,10 @@ class TemplatePicker extends React.Component @unsubscribe() if @unsubscribe render: => - button = headerComponents = [ diff --git a/src/components/retina-img.cjsx b/src/components/retina-img.cjsx index 183c13f14..8edd0d5df 100644 --- a/src/components/retina-img.cjsx +++ b/src/components/retina-img.cjsx @@ -109,6 +109,7 @@ class RetinaImg extends React.Component if @props.mode is Mode.ContentIsMask style.WebkitMaskImage = "url('#{path}')" + style.WebkitMaskRepeat = "no-repeat" style.objectPosition = "10000px" className += " content-mask" else if @props.mode is Mode.ContentDark diff --git a/src/flux/stores/draft-store.coffee b/src/flux/stores/draft-store.coffee index 28e3c8575..34924cbf0 100644 --- a/src/flux/stores/draft-store.coffee +++ b/src/flux/stores/draft-store.coffee @@ -327,8 +327,11 @@ class DraftStore draft: true pristine: true namespaceId: namespace.id + DatabaseStore.persistModel(draft).then => - DatabaseStore.localIdForModel(draft).then(@_onPopoutDraftLocalId) + DatabaseStore.localIdForModel(draft).then (draftLocalId, options={}) => + options.newDraft = true + @_onPopoutDraftLocalId(draftLocalId, options) _onPopoutDraftLocalId: (draftLocalId, options = {}) => return unless NamespaceStore.current() @@ -337,9 +340,11 @@ class DraftStore if @_draftSessions[draftLocalId] save = @_draftSessions[draftLocalId].changes.commit() + title = if options.newDraft then "New Message" else "Message" + save.then => atom.newWindow - title: "Message" + title: title windowType: "composer" windowProps: _.extend(options, {draftLocalId}) diff --git a/src/sheet-container.cjsx b/src/sheet-container.cjsx index 1b200a25c..911ff8d55 100644 --- a/src/sheet-container.cjsx +++ b/src/sheet-container.cjsx @@ -34,7 +34,7 @@ class SheetContainer extends React.Component sheetElements = @_sheetElements() - + {@_toolbarContainerElement()}
@@ -96,6 +96,7 @@ class SheetContainer extends React.Component _getStateFromStores: => stack: WorkspaceStore.sheetStack() + mode: WorkspaceStore.layoutMode() module.exports = SheetContainer diff --git a/src/sheet-toolbar.cjsx b/src/sheet-toolbar.cjsx index f385f8450..2ba647f21 100644 --- a/src/sheet-toolbar.cjsx +++ b/src/sheet-toolbar.cjsx @@ -17,6 +17,21 @@ class ToolbarSpacer extends React.Component render: =>
+class WindowTitle extends React.Component + @displayName: "WindowTitle" + + constructor: (@props) -> + @state = atom.getLoadSettings() + + componentDidMount: -> + @unlisten = atom.onWindowPropsReceived (windowProps) => + @setState atom.getLoadSettings() + + componentWillUnmount: -> @unlisten() + + render: -> +
{@state.title}
+ class ToolbarBack extends React.Component @displayName: 'ToolbarBack' render: => @@ -154,6 +169,9 @@ class Toolbar extends React.Component entries = ComponentRegistry.findComponentsMatching({location: loc.Toolbar.Right, mode: state.mode}) state.columns[state.columns.length - 1]?.push(entries...) + if state.mode is "popout" + state.columns[0]?.push(WindowTitle) + state module.exports = Toolbar diff --git a/static/buttons.less b/static/buttons.less index 683e49d4f..4216482b3 100644 --- a/static/buttons.less +++ b/static/buttons.less @@ -10,11 +10,12 @@ button, html input[type="button"] { .btn { padding: 0.33em 1em; - border:1px solid rgba(0,0,0,0.18); + border:1px solid rgba(0,0,0,0.15); border-radius: @border-radius-base; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.10); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); cursor: default; display:inline-block; + background: linear-gradient(to top, rgba(241,241,241,0.75) 0%, rgba(253,253,253,0.75) 100%); height: auto; line-height: 1; @@ -55,12 +56,27 @@ button, html input[type="button"] { } &.btn-emphasis { - background-image: -webkit-gradient(linear, left top, left bottom, from(lighten(@btn-emphasis-bg-color,10%)), to(@btn-emphasis-bg-color)); - border:1px solid darken(@btn-emphasis-bg-color, 5%); + position: relative; color: @btn-emphasis-text-color; font-weight: @font-weight-medium; img.content-mask { background-color:@btn-emphasis-text-color; } + + background: linear-gradient(to bottom, #6bb1f9 0%, #0a80ff 100%); + + border: 0; + &:before { + content: ' '; + width: calc(~"100% + 2px"); + height: calc(~"100% + 2px"); + border-radius: 5px; + padding: 0; + top: -1px; + left: -1px; + position: absolute; + z-index: -1; + background: linear-gradient(to bottom, #4ca2f9 0%, #015cff 100%); + } } &.btn-emphasis:active { @@ -68,6 +84,16 @@ button, html input[type="button"] { box-shadow: 0 1px 1px rgba(0, 0, 0, 0.21); } + &.btn-text { + font-size: 13px; + padding: 2px 14px 2px 7px; + .text { + position: relative; + top: 1px; + margin-left: 6px; + } + } + &.btn-danger, .btn-destructive { color: @btn-danger-text-color; background: @btn-danger-bg-color; @@ -76,7 +102,8 @@ button, html input[type="button"] { } .btn-toolbar { - min-height:34px; + min-height: 24px; + padding: 2px 13px; } .btn-gradient { diff --git a/static/images/attachments/icon-attachment-download-@1x.png b/static/images/attachments/icon-attachment-download-@1x.png new file mode 100644 index 000000000..e93c4793f Binary files /dev/null and b/static/images/attachments/icon-attachment-download-@1x.png differ diff --git a/static/images/attachments/icon-attachment-download-@2x.png b/static/images/attachments/icon-attachment-download-@2x.png new file mode 100644 index 000000000..5dba32f4d Binary files /dev/null and b/static/images/attachments/icon-attachment-download-@2x.png differ diff --git a/static/images/attachments/image-cancel-button@2x.png b/static/images/attachments/image-cancel-button@2x.png new file mode 100644 index 000000000..1945de8a4 Binary files /dev/null and b/static/images/attachments/image-cancel-button@2x.png differ diff --git a/static/images/attachments/image-download-button@2x.png b/static/images/attachments/image-download-button@2x.png new file mode 100644 index 000000000..c510f841c Binary files /dev/null and b/static/images/attachments/image-download-button@2x.png differ diff --git a/static/images/composer/icon-composer-attachment@2x.png b/static/images/composer/icon-composer-attachment@2x.png new file mode 100644 index 000000000..a3e6462c2 Binary files /dev/null and b/static/images/composer/icon-composer-attachment@2x.png differ diff --git a/static/images/composer/icon-composer-dropdown@2x.png b/static/images/composer/icon-composer-dropdown@2x.png new file mode 100644 index 000000000..c0aae9445 Binary files /dev/null and b/static/images/composer/icon-composer-dropdown@2x.png differ diff --git a/static/images/composer/icon-composer-send@2x.png b/static/images/composer/icon-composer-send@2x.png new file mode 100644 index 000000000..e89f9c897 Binary files /dev/null and b/static/images/composer/icon-composer-send@2x.png differ diff --git a/static/images/composer/icon-composer-templates@2x.png b/static/images/composer/icon-composer-templates@2x.png new file mode 100644 index 000000000..bf138b936 Binary files /dev/null and b/static/images/composer/icon-composer-templates@2x.png differ diff --git a/static/images/composer/icon-composer-trash@2x.png b/static/images/composer/icon-composer-trash@2x.png new file mode 100644 index 000000000..0dbf6ba08 Binary files /dev/null and b/static/images/composer/icon-composer-trash@2x.png differ diff --git a/static/workspace.less b/static/workspace.less index cc8df69f3..b0a021bd7 100644 --- a/static/workspace.less +++ b/static/workspace.less @@ -124,6 +124,22 @@ body.is-blurred { .sheet-toolbar-container { background: @toolbar-background-color; + + &.mode-popout { + background: transparent; + } +} + +.layout-mode-popout { + .sheet-toolbar { + background: @background-primary; + height: 35px; + min-height: 35px; + max-height: 35px; + } + .toolbar-window-controls { + margin-top: 7px; + } } .sheet-toolbar { @@ -149,6 +165,20 @@ body.is-blurred { .item-spacer { -webkit-app-region: drag; } + + .item-container { + .window-title { + flex: 2; + text-align: center; + margin-top: 6px; + margin-left: -80px; /* width of ToolbarWindowControls */ + -webkit-app-region: drag; + &:hover { + cursor: default; + } + } + } + .item-back { order:-999; padding-top: 5px; @@ -265,3 +295,4 @@ body.platform-win32 { cursor:ew-resize; } } +