Merge branch 'master' of github.com:nylas/N1

This commit is contained in:
Jackie Luo 2016-02-24 11:32:12 -08:00
commit 75cd7af085
10 changed files with 77 additions and 34 deletions

View file

@ -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'

View file

@ -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 {

View file

@ -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) {

View file

@ -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>

View file

@ -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"
)

View file

@ -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}/>

View file

@ -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>
);
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}
}