feat(signatures): add signature support

Summary:
Add signatures back in.

Extract contenteditable css to its own file instead of being bundled with
the composer.

Test Plan: manual

Reviewers: juan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2295
This commit is contained in:
Evan Morikawa 2015-11-30 11:48:24 -08:00
parent 6a4613b4a1
commit 83b0a4db5f
9 changed files with 219 additions and 243 deletions

View file

@ -24,7 +24,7 @@
font-size: @font-size-small;
}
.compose-body #contenteditable {
.compose-body .contenteditable {
code.var {
font: inherit;
padding:0;

View file

@ -6,35 +6,10 @@ module.exports =
DraftStore.registerExtension(SignatureDraftExtension)
@preferencesTab = new PreferencesUIStore.TabItem
# TODO: Fix RetinaImg to handle plugin images
icon: ->
if process.platform is "win32"
"nylas://composer-signature/images/ic-settings-signatures-win32@2x.png"
else
"nylas://composer-signature/images/ic-settings-signatures@2x.png"
tabId: "Signatures"
displayName: "Signatures"
component: require "./preferences-signatures"
# TODO Re-enable when fixed!
# PreferencesUIStore.registerPreferencesTab(@preferencesTab)
## TODO
# PreferencesUIStore.registerPreferences "composer-signatures", [
# {
# section: PreferencesUIStore.Section.Signatures
# type: "richtext"
# label: "Signature:"
# perAccount: true
# defaultValue: "- Sent from N1"
# }, {
# section: PreferencesUIStore.Section.Signatures
# type: "toggle"
# label: "Include on replies"
# defaultValue: true
# }
# ]
deactivate: ->
DraftStore.unregisterExtension(SignatureDraftExtension)
PreferencesUIStore.unregisterPreferencesTab(@preferencesTab.sectionId)

View file

@ -72,8 +72,7 @@ class PreferencesSignatures extends React.Component
ref="signatureInput"
value={@state.currentSignature}
onChange={@_onEditSignature}
spellcheck={false}
floatingToolbar={false} />
spellcheck={false} />
_onEditSignature: (event) =>
html = event.target.value
@ -97,7 +96,7 @@ class PreferencesSignatures extends React.Component
<div className="section-title">
Signature for: {@_renderAccountPicker()}
</div>
<div>
<div className="signature-wrap">
{@_renderCurrentSignature()}
</div>
</div>

View file

@ -0,0 +1,63 @@
.container-signatures {
max-width: 640px;
.signature-wrap {
position: relative;
border: 1px solid @input-border-color;
padding: 10px;
margin-top: 20px;
min-height: 200px;
display: flex;
}
.section-body {
padding: 10px 0 0 0;
.menu {
border: solid thin #CCC;
margin-right: 5px;
min-height: 200px;
.menu-items {
margin:0;
padding:0;
list-style: none;
li { padding: 6px; }
}
}
.menu-horizontal {
height: 100%;
.menu-items {
height:100%;
margin: 0;
padding: 0;
list-style: none;
li {
text-align:center;
width:40px;
display:inline-block;
padding:8px 16px 8px 16px;
border-right: solid thin #CCC;
}
}
}
.signature-area {
border: solid thin #CCC;
min-height: 200px;
}
.menu-footer {
border: solid thin #CCC;
overflow: auto;
}
.signature-footer {
border: solid thin #CCC;
overflow: auto;
.edit-html-button {
float: right;
margin: 6px;
}
}
}
}

View file

@ -21,12 +21,6 @@ body.platform-win32 {
border: 0;
}
}
.floating-toolbar {
border-radius: 0;
input, input:focus {
border: 0;
}
}
}
.composer-inner-wrap {
@ -128,7 +122,7 @@ body.platform-win32 {
padding-top: 12px;
}
input, textarea, div[contenteditable] {
input, textarea {
color: @text-color;
position: relative;
display: block;
@ -232,23 +226,9 @@ body.platform-win32 {
}
div[contenteditable] {
font-size: @font-size;
line-height: 1.4;
min-height: @compose-min-height;
padding: @spacing-standard;
padding-top: 20px;
padding-bottom: 0;
margin-bottom: 30px;
}
.contenteditable-container {
width: 100%;
position: relative;
}
spelling.misspelled {
background: linear-gradient(45deg, transparent, transparent 49%, red 49%, transparent 51%);
background-size: 2px 2px;
background-position: bottom;
background-repeat-y: no-repeat;
padding: 20px @spacing-standard 0 @spacing-standard;
}
}
@ -291,17 +271,6 @@ body.platform-win32 {
.compose-body {
margin-bottom: 0;
position: relative;
.contenteditable-container {
flex: 1;
width: 100%;
position: relative;
div[contenteditable] {
height: auto;
flex: 1;
}
}
}
}
@ -309,6 +278,8 @@ body.platform-win32 {
.compose-body {
div[contenteditable] {
min-height: @line-height-computed;
margin-bottom: 30px;
padding: 20px @spacing-standard 0 @spacing-standard;
}
}
@ -333,7 +304,6 @@ body.platform-win32 {
}
//////////////////////////////////
// participants-text-field.cjsx //
//////////////////////////////////
@ -362,123 +332,3 @@ body.platform-win32 {
}
}
}
///////////////////////////
// floating-toolbar.cjsx //
///////////////////////////
.floating-toolbar {
z-index: 10;
position: absolute;
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;
color: @text-color;
transition-duration: .15s;
transition-property: opacity, margin;
opacity: 0;
visibility: hidden;
margin-top: 3px;
&.toolbar-visible {
opacity: 1;
visibility: visible;
margin-top: 0;
}
.toolbar-pointer {
position: absolute;
width: 22.5px;
height: 10px;
background: transparent url('images/tooltip/tooltip-bg-pointer@2x.png') no-repeat;
background-size: 22.5px 9.5px;
margin-left: -11.2px;
}
&.above {
.toolbar-pointer {
transform: rotate(0deg);
bottom: -9px;
}
}
&.below {
.toolbar-pointer {
transform: rotate(180deg);
top: -9px;
}
}
.floating-toolbar-input {
display: inline;
// The hardcoded numbers here represent the widths of the various
// icons and buttons that surround the input. They are hardcoded here
// because CSS does the calculation for us that we'd otherwise have to
// do in React before the element renders to the page.
width: calc(~"100% - 62px");
&.with-remove {
width: calc(~"100% - 95px");
}
color: @text-color;
}
@padding: 0.5em;
.btn {
background: transparent;
font-size: 16px;
height: auto;
border-radius: 0;
padding: @padding*0.75 @padding;
margin: 0;
color: @text-color;
box-shadow: none;
&:first-child {
padding-left: 1.5*@padding;
}
&:last-child {
padding-right: 1.5*@padding;
}
&:hover, &:active {
color: lighten(@text-color-link, 10%);
background: transparent;
}
}
.preview-btn-icon {
position: relative;
top: 1px;
padding: 0 @padding;
}
button.btn.toolbar-btn {
@padding-top: 4px;
@padding-left: 8px;
width: 12.5px + 2*@padding-left;
height: 12.5px + 2*@padding-top;
margin: 7.5px 0;
box-shadow: none;
border: 0;
border-right: 1px solid @border-color-divider;
&:last-child { border-right: 0 }
background: no-repeat;
background-size: 12.5px 12.5px;
background-position: @padding-left @padding-top;
&.btn-bold { background-image: url("images/composer/tooltip-bold-black@2x.png") }
&.btn-italic { background-image: url("images/composer/tooltip-italic-black@2x.png") }
&.btn-underline { background-image: url("images/composer/tooltip-underline-black@2x.png") }
&.btn-link { background-image: url("images/composer/tooltip-link-black@2x.png") }
&:hover {
cursor: pointer;
background: no-repeat;
background-size: 12.5px 12.5px;
background-position: @padding-left @padding-top;
&.btn-bold { background-image: url("images/composer/tooltip-bold-blue@2x.png") }
&.btn-italic { background-image: url("images/composer/tooltip-italic-blue@2x.png") }
&.btn-underline { background-image: url("images/composer/tooltip-underline-blue@2x.png") }
&.btn-link { background-image: url("images/composer/tooltip-link-blue@2x.png") }
}
}
}

View file

@ -103,65 +103,6 @@
}
}
.container-signatures {
.contenteditable-container {
border: 1px solid @input-border-color;
padding: 10px;
margin-top: 20px;
min-height: 200px;
}
.section-body {
padding: 10px 0 0 0;
.menu {
border: solid thin #CCC;
margin-right: 5px;
min-height: 200px;
.menu-items {
margin:0;
padding:0;
list-style: none;
li { padding: 6px; }
}
}
.menu-horizontal {
height: 100%;
.menu-items {
height:100%;
margin: 0;
padding: 0;
list-style: none;
li {
text-align:center;
width:40px;
display:inline-block;
padding:8px 16px 8px 16px;
border-right: solid thin #CCC;
}
}
}
.signature-area {
border: solid thin #CCC;
min-height: 200px;
}
.menu-footer {
border: solid thin #CCC;
overflow: auto;
}
.signature-footer {
border: solid thin #CCC;
overflow: auto;
.edit-html-button {
float: right;
margin: 6px;
}
}
}
}
.appearance-mode-switch {
max-width:400px;
text-align: right;

View file

@ -131,7 +131,7 @@ class Contenteditable extends React.Component
<div className="contenteditable-container">
{@_renderFloatingToolbar()}
<div id="contenteditable"
<div className="contenteditable"
ref="contenteditable"
contentEditable
spellCheck={false}

View file

@ -0,0 +1,147 @@
.contenteditable-container {
flex: 1;
display: flex;
line-height: 1.4;
position: relative;
color: @text-color;
font-size: @font-size;
div[contenteditable], .contenteditable {
flex: 1;
}
spelling.misspelled {
background: linear-gradient(45deg, transparent, transparent 49%, red 49%, transparent 51%);
background-size: 2px 2px;
background-position: bottom;
background-repeat-y: no-repeat;
}
.floating-toolbar {
z-index: 10;
position: absolute;
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;
color: @text-color;
transition-duration: .15s;
transition-property: opacity, margin;
opacity: 0;
visibility: hidden;
margin-top: 3px;
&.toolbar-visible {
opacity: 1;
visibility: visible;
margin-top: 0;
}
.toolbar-pointer {
position: absolute;
width: 22.5px;
height: 10px;
background: transparent url('images/tooltip/tooltip-bg-pointer@2x.png') no-repeat;
background-size: 22.5px 9.5px;
margin-left: -11.2px;
}
&.above {
.toolbar-pointer {
transform: rotate(0deg);
bottom: -9px;
}
}
&.below {
.toolbar-pointer {
transform: rotate(180deg);
top: -9px;
}
}
.floating-toolbar-input {
border: 0;
display: inline;
// The hardcoded numbers here represent the widths of the various
// icons and buttons that surround the input. They are hardcoded here
// because CSS does the calculation for us that we'd otherwise have to
// do in React before the element renders to the page.
width: calc(~"100% - 62px");
&.with-remove {
width: calc(~"100% - 95px");
}
color: @text-color;
}
@padding: 0.5em;
.btn {
background: transparent;
font-size: 16px;
height: auto;
border-radius: 0;
padding: @padding*0.75 @padding;
margin: 0;
color: @text-color;
box-shadow: none;
&:first-child {
padding-left: 1.5*@padding;
}
&:last-child {
padding-right: 1.5*@padding;
}
&:hover, &:active {
color: lighten(@text-color-link, 10%);
background: transparent;
}
}
.preview-btn-icon {
position: relative;
top: 1px;
padding: 0 @padding;
}
button.btn.toolbar-btn {
@padding-top: 4px;
@padding-left: 8px;
width: 12.5px + 2*@padding-left;
height: 12.5px + 2*@padding-top;
margin: 7.5px 0;
box-shadow: none;
border: 0;
border-right: 1px solid @border-color-divider;
&:last-child { border-right: 0 }
background: no-repeat;
background-size: 12.5px 12.5px;
background-position: @padding-left @padding-top;
&.btn-bold { background-image: url("images/composer/tooltip-bold-black@2x.png") }
&.btn-italic { background-image: url("images/composer/tooltip-italic-black@2x.png") }
&.btn-underline { background-image: url("images/composer/tooltip-underline-black@2x.png") }
&.btn-link { background-image: url("images/composer/tooltip-link-black@2x.png") }
&:hover {
cursor: pointer;
background: no-repeat;
background-size: 12.5px 12.5px;
background-position: @padding-left @padding-top;
&.btn-bold { background-image: url("images/composer/tooltip-bold-blue@2x.png") }
&.btn-italic { background-image: url("images/composer/tooltip-italic-blue@2x.png") }
&.btn-underline { background-image: url("images/composer/tooltip-underline-blue@2x.png") }
&.btn-link { background-image: url("images/composer/tooltip-link-blue@2x.png") }
}
}
}
}
body.platform-win32 {
.contenteditable-container {
.floating-toolbar {
border-radius: 0;
input, input:focus {
border: 0;
}
}
}
}

View file

@ -27,3 +27,4 @@
@import "components/generated-form";
@import "components/unsafe";
@import "components/key-commands-region";
@import "components/contenteditable";