mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-11-08 07:21:18 +08:00
Merge branch 'master' of github.com:nylas/N1
This commit is contained in:
commit
75cd7af085
10 changed files with 77 additions and 34 deletions
|
|
@ -5,6 +5,7 @@ _str = require 'underscore.string'
|
|||
FocusedPerspectiveStore,
|
||||
SyncbackCategoryTask,
|
||||
DestroyCategoryTask,
|
||||
CategoryStore,
|
||||
Actions,
|
||||
Utils} = require 'nylas-exports'
|
||||
{OutlineViewItem} = require 'nylas-component-kit'
|
||||
|
|
@ -107,6 +108,19 @@ class SidebarItem
|
|||
opts.contextMenuLabel = contextMenuLabel
|
||||
@forPerspective(id, perspective, opts)
|
||||
|
||||
@forSnoozed: (accountIds, opts = {}) ->
|
||||
# TODO This constant should be available elsewhere
|
||||
displayName = require('../../thread-snooze/lib/snooze-constants').SNOOZE_CATEGORY_NAME
|
||||
id = displayName
|
||||
id += "-#{opts.name}" if opts.name
|
||||
opts.name = "Snoozed" unless opts.name
|
||||
opts.iconName= 'snooze.png'
|
||||
categories = accountIds.map (accId) =>
|
||||
_.findWhere CategoryStore.userCategories(accId), {displayName}
|
||||
|
||||
perspective = MailboxPerspective.forCategories(categories)
|
||||
@forPerspective(id, perspective, opts)
|
||||
|
||||
@forStarred: (accountIds, opts = {}) ->
|
||||
perspective = MailboxPerspective.forStarred(accountIds)
|
||||
id = 'Starred'
|
||||
|
|
|
|||
|
|
@ -39,9 +39,10 @@ class SidebarSection
|
|||
|
||||
starredItem = SidebarItem.forStarred([account.id])
|
||||
draftsItem = SidebarItem.forDrafts([account.id])
|
||||
snoozedItem = SidebarItem.forSnoozed([account.id])
|
||||
|
||||
# Order correctly: Inbox, Starred, rest... , Drafts
|
||||
items.splice(1, 0, starredItem)
|
||||
items.splice(1, 0, starredItem, snoozedItem)
|
||||
items.push(draftsItem)
|
||||
|
||||
return {
|
||||
|
|
@ -77,15 +78,20 @@ class SidebarSection
|
|||
|
||||
items.push SidebarItem.forCategories(categories, {children, editable: false, deletable: false})
|
||||
|
||||
starredItem = SidebarItem.forStarred(_.pluck(accounts, 'id'),
|
||||
accountIds = _.pluck(accounts, 'id')
|
||||
|
||||
starredItem = SidebarItem.forStarred(accountIds,
|
||||
children: accounts.map (acc) -> SidebarItem.forStarred([acc.id], name: acc.label)
|
||||
)
|
||||
draftsItem = SidebarItem.forDrafts(_.pluck(accounts, 'id'),
|
||||
draftsItem = SidebarItem.forDrafts(accountIds,
|
||||
children: accounts.map (acc) -> SidebarItem.forDrafts([acc.id], name: acc.label)
|
||||
)
|
||||
snoozedItem = SidebarItem.forSnoozed(accountIds,
|
||||
children: accounts.map (acc) -> SidebarItem.forSnoozed([acc.id], name: acc.label)
|
||||
)
|
||||
|
||||
# Order correctly: Inbox, Starred, rest... , Drafts
|
||||
items.splice(1, 0, starredItem)
|
||||
items.splice(1, 0, starredItem, snoozedItem)
|
||||
items.push(draftsItem)
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class EmojisComposerExtension extends ContenteditableExtension {
|
|||
locationRefNode: locationRefNode,
|
||||
width: EmojisComposerExtension._emojiPickerWidth(emojiOptions),
|
||||
height: EmojisComposerExtension._emojiPickerHeight(emojiOptions),
|
||||
hidePointer: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -171,7 +172,7 @@ class EmojisComposerExtension extends ContenteditableExtension {
|
|||
}
|
||||
}
|
||||
const WIDTH_PER_CHAR = 8;
|
||||
return (maxLength + 6) * WIDTH_PER_CHAR;
|
||||
return (maxLength + 8) * WIDTH_PER_CHAR;
|
||||
}
|
||||
|
||||
static _emojiPickerHeight(emojiOptions) {
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ class SendLaterPopover extends Component {
|
|||
return (
|
||||
<div key="custom" className="custom-time-section">
|
||||
<input
|
||||
tabIndex={1}
|
||||
tabIndex="1"
|
||||
type="text"
|
||||
placeholder="Or type a time..."
|
||||
placeholder="e.g. 'Sunday at 2PM'"
|
||||
onChange={event=> updateInputDateValue(event.target.value)}/>
|
||||
{dateInterpretation}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,10 @@ class ThreadList extends React.Component
|
|||
element = document.querySelector("[data-item-id=\"#{item.id}\"]")
|
||||
rect = element.getBoundingClientRect()
|
||||
Actions.openPopover(
|
||||
<SnoozePopoverBody threads={[item]} swipeCallback={callback}/>,
|
||||
<SnoozePopoverBody
|
||||
threads={[item]}
|
||||
swipeCallback={callback}
|
||||
closePopover={Actions.closePopover}/>,
|
||||
rect,
|
||||
"right"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/** @babel */
|
||||
import _ from 'underscore';
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import {Actions, DateUtils} from 'nylas-exports'
|
||||
import {DateUtils} from 'nylas-exports'
|
||||
import {RetinaImg} from 'nylas-component-kit';
|
||||
import SnoozeActions from './snooze-actions'
|
||||
import {DATE_FORMAT_LONG} from './snooze-constants'
|
||||
|
|
@ -45,10 +45,12 @@ class SnoozePopoverBody extends Component {
|
|||
static propTypes = {
|
||||
threads: PropTypes.array.isRequired,
|
||||
swipeCallback: PropTypes.func,
|
||||
closePopover: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
swipeCallback: ()=> {},
|
||||
closePopover: ()=> {},
|
||||
};
|
||||
|
||||
constructor() {
|
||||
|
|
@ -62,8 +64,8 @@ class SnoozePopoverBody extends Component {
|
|||
const utcDate = dateGenerator().utc()
|
||||
const formatted = DateUtils.format(utcDate)
|
||||
SnoozeActions.snoozeThreads(this.props.threads, formatted);
|
||||
this.props.swipeCallback(true);
|
||||
Actions.closePopover();
|
||||
this.props.swipeCallback(true)
|
||||
this.props.closePopover()
|
||||
}
|
||||
|
||||
onBlur = ()=> {
|
||||
|
|
@ -72,18 +74,18 @@ class SnoozePopoverBody extends Component {
|
|||
return;
|
||||
}
|
||||
this.props.swipeCallback(false);
|
||||
Actions.closePopover();
|
||||
this.props.closePopover();
|
||||
};
|
||||
|
||||
onKeyDown = (event)=> {
|
||||
if (event.key === "Escape") {
|
||||
this.props.swipeCallback(false);
|
||||
Actions.closePopover()
|
||||
this.props.closePopover();
|
||||
}
|
||||
};
|
||||
|
||||
onInputChange = (event)=> {
|
||||
this.updateInputDateValue(event.target.value)
|
||||
this.updateInputDateValue(event.target.value);
|
||||
};
|
||||
|
||||
onInputKeyDown = (event)=> {
|
||||
|
|
@ -137,7 +139,7 @@ class SnoozePopoverBody extends Component {
|
|||
<input
|
||||
type="text"
|
||||
tabIndex="1"
|
||||
placeholder="Or type a time, e.g. Next monday at 2pm"
|
||||
placeholder="Or type a time, like 'next monday at 2PM'"
|
||||
onMouseDown={this.onInputMouseDown}
|
||||
onKeyDown={this.onInputKeyDown}
|
||||
onChange={this.onInputChange}/>
|
||||
|
|
|
|||
|
|
@ -15,17 +15,22 @@ class SnoozePopover extends Component {
|
|||
popoverStyle: PropTypes.object,
|
||||
};
|
||||
|
||||
closePopover = ()=> {
|
||||
this.refs.popover.close();
|
||||
};
|
||||
|
||||
render() {
|
||||
const {buttonComponent, direction, popoverStyle, pointerStyle, threads} = this.props
|
||||
|
||||
return (
|
||||
<Popover
|
||||
ref="popover"
|
||||
className="snooze-popover"
|
||||
direction={direction || 'down-align-left'}
|
||||
buttonComponent={buttonComponent}
|
||||
popoverStyle={popoverStyle}
|
||||
pointerStyle={pointerStyle}>
|
||||
<SnoozePopoverBody threads={threads}/>
|
||||
<SnoozePopoverBody threads={threads} closePopover={this.closePopover}/>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class FloatingToolbar extends React.Component
|
|||
toolbarComponent: null
|
||||
toolbarLocationRef: null
|
||||
toolbarComponentProps: {}
|
||||
hidePointer: false
|
||||
@innerProps = FloatingToolbar.defaultInnerProps
|
||||
|
||||
shouldComponentUpdate: (nextProps, nextState) ->
|
||||
|
|
@ -95,8 +96,8 @@ class FloatingToolbar extends React.Component
|
|||
<div ref="floatingToolbar"
|
||||
className={@_toolbarClasses()}
|
||||
style={@_toolbarStyles()}>
|
||||
<div className="toolbar-pointer"
|
||||
style={@_toolbarPointerStyles()}></div>
|
||||
|
||||
{@_renderPointer()}
|
||||
<ToolbarComponent {...@state.toolbarComponentProps} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -116,6 +117,7 @@ class FloatingToolbar extends React.Component
|
|||
toolbarWidth = 0
|
||||
toolbarHeight = 0
|
||||
toolbarLocationRef = null
|
||||
hidePointer = false
|
||||
toolbarComponentProps = {}
|
||||
|
||||
for extension in props.extensions
|
||||
|
|
@ -127,13 +129,15 @@ class FloatingToolbar extends React.Component
|
|||
toolbarLocationRef = params.locationRefNode
|
||||
toolbarWidth = params.width
|
||||
toolbarHeight = params.height
|
||||
if params.hidePointer
|
||||
hidePointer = params.hidePointer
|
||||
catch error
|
||||
NylasEnv.reportError(error)
|
||||
|
||||
if toolbarComponent and not toolbarLocationRef
|
||||
throw new Error("You must provide a locationRefNode for #{toolbarComponent.displayName}. It must be either a DOM Element or a Range.")
|
||||
|
||||
return {toolbarComponent, toolbarComponentProps, toolbarLocationRef, toolbarWidth, toolbarHeight}
|
||||
return {toolbarComponent, toolbarComponentProps, toolbarLocationRef, toolbarWidth, toolbarHeight, hidePointer}
|
||||
|
||||
@CONTENT_PADDING: 15
|
||||
|
||||
|
|
@ -158,9 +162,13 @@ class FloatingToolbar extends React.Component
|
|||
calcLeft = Math.min(Math.max(calcLeft, FloatingToolbar.CONTENT_PADDING+BORDER_RADIUS_PADDING), editArea.width - BORDER_RADIUS_PADDING)
|
||||
|
||||
calcTop = referenceRect.top - editArea.top - toolbarHeight - 14
|
||||
if @state.hidePointer
|
||||
calcTop += 10
|
||||
toolbarPos = "above"
|
||||
if calcTop < TOP_PADDING
|
||||
calcTop = referenceRect.top - editArea.top + referenceRect.height + TOP_PADDING + 4
|
||||
if @state.hidePointer
|
||||
calcTop -= 10
|
||||
toolbarPos = "below"
|
||||
|
||||
maxWidth = editArea.width - FloatingToolbar.CONTENT_PADDING * 2
|
||||
|
|
@ -206,4 +214,8 @@ class FloatingToolbar extends React.Component
|
|||
left: left
|
||||
return styles
|
||||
|
||||
_renderPointer: =>
|
||||
unless @state.hidePointer
|
||||
return <div className="toolbar-pointer" style={@_toolbarPointerStyles()}></div>
|
||||
|
||||
module.exports = FloatingToolbar
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
background: #fff;
|
||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), inset 0 0 1px rgba(0,0,0,0.5);
|
||||
border-radius: @border-radius-base;
|
||||
border-radius: @border-radius-large;
|
||||
color: @text-color;
|
||||
|
||||
transition-duration: .15s;
|
||||
|
|
|
|||
|
|
@ -31,21 +31,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
border: 1px solid darken(@background-secondary, 10%);
|
||||
border-radius: 3px;
|
||||
background-color: @background-primary;
|
||||
box-shadow: inset 0 1px 0 rgba(0,0,0,0.05), 0 1px 0 rgba(0,0,0,0.05);
|
||||
color: @text-color;
|
||||
}
|
||||
input[type=text] {
|
||||
border: 1px solid darken(@background-secondary, 10%);
|
||||
border-radius: 3px;
|
||||
background-color: @background-primary;
|
||||
box-shadow: inset 0 1px 0 rgba(0,0,0,0.05), 0 1px 0 rgba(0,0,0,0.05);
|
||||
color: @text-color;
|
||||
|
||||
&.search {
|
||||
padding-left: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("../static/images/search/searchloupe@2x.png");
|
||||
background-size: 15px 15px;
|
||||
background-position: 7px 4px;
|
||||
text-indent: 31px;
|
||||
}
|
||||
&.search {
|
||||
padding-left: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("../static/images/search/searchloupe@2x.png");
|
||||
background-size: 15px 15px;
|
||||
background-position: 7px 4px;
|
||||
text-indent: 31px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue